!35 1.6.0 // Bug fixes. Merge Gitee PR!35 from upd/1.6.0

This commit is contained in:
ShikiSuen 2022-05-21 10:02:58 +00:00 committed by Gitee
commit 96453d0478
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
40 changed files with 842 additions and 654 deletions

View File

@ -2,12 +2,11 @@
威注音輸入法歡迎有熱心的志願者們參與。 威注音輸入法歡迎有熱心的志願者們參與。
威注音目前的 codebase 更能代表一個先進的 macOS 輸入法雛形專案的形態。目前的 dev 分支除了 Mandarin 模組(以及其與 KeyHandler 的對接的部分)以外被威注音使用的部分全都是清一色的 Swift codebase一目了然方便他人參與比某些其它開源品牌旗下的專案更具程式方面的生命力。為什麼這樣講呢那些傳統開源品牌的專案主要使用 C++ 這門不太友好的語言Mandarin 模組現在對我而言仍舊是天書,一大堆針對記憶體指針的操作完全看不懂。搞不清楚在這一層之上的功能邏輯的話,就無法制定 Swift 版的 coding 策略),這也是我這次用 Swift 重寫了語言模型引擎的原因(也是為後來者行方便)。 威注音目前的 codebase 更能代表一個先進的 macOS 輸入法雛形專案的形態。目前的 dev 分支除了第三方 OpenCC 模組以外被威注音使用的部分全都是清一色的 Swift codebase一目了然方便他人參與比某些其它開源品牌旗下的專案更具程式方面的生命力。為什麼這樣講呢那些傳統開源品牌的專案主要使用 C++ 這門不太友好的語言Mandarin 模組現在對我而言仍舊是天書,一大堆針對記憶體指針的操作完全看不懂。搞不清楚在這一層之上的功能邏輯的話,就無法制定 Swift 版的 coding 策略),這也是我這次用 Swift 重寫了語言模型引擎與注音拼音並擊處理引擎、來換掉 Gramambular 與 OVMandarin 的原因(也是為後來者行方便)。
為了不讓參與者們浪費各自的熱情,特設此文以說明該專案目前最需要協助的地方。 為了不讓參與者們浪費各自的熱情,特設此文以說明該專案目前最需要協助的地方。
1. 讓 Alt+波浪鍵選單能夠在諸如 MS Word 以及終端機內正常工作(可以用方向鍵控制高亮候選內容,等)。 1. 將選字窗換成 IMK 內建的矩陣選字窗。
- 原理上而言恐怕得欺騙當前正在接受輸入的應用、使其誤以為當前有組字區。這只是推測。
除了上述各項以外的貢獻,除非特邀、或者有足夠的說服理由與吸引力(比如語法錯誤或更好的重構方法等),否則敝專案可能會無視或者拒絕。 除了上述各項以外的貢獻,除非特邀、或者有足夠的說服理由與吸引力(比如語法錯誤或更好的重構方法等),否則敝專案可能會無視或者拒絕。

View File

@ -7,6 +7,8 @@
威注音輸入法基於小麥注音二次開發,是**原生簡體中文、原生繁體中文注音輸入法** 威注音輸入法基於小麥注音二次開發,是**原生簡體中文、原生繁體中文注音輸入法**
- 威注音是業界現階段支援注音排列種類數量與輸入用拼音種類數量最多的注音輸入法。
- 受威注音自家的鐵恨注音並擊引擎加持。
- 威注音的原廠詞庫內不存在任何可以妨礙該輸入法在世界上任何地方傳播的內容。 - 威注音的原廠詞庫內不存在任何可以妨礙該輸入法在世界上任何地方傳播的內容。
- 相比中州韻(鼠須管)而言,威注音能夠做到真正的大千聲韻並擊。 - 相比中州韻(鼠須管)而言,威注音能夠做到真正的大千聲韻並擊。
@ -14,7 +16,7 @@
>- 支援 macOS 螢幕模擬鍵盤(僅傳統大千與傳統倚天佈局)。 >- 支援 macOS 螢幕模擬鍵盤(僅傳統大千與傳統倚天佈局)。
>- 可以將自己打的繁體中文自動轉成日本 JIS 新字體來輸出(包括基礎的字詞轉換)、也可以轉成康熙繁體來輸出。 >- 可以將自己打的繁體中文自動轉成日本 JIS 新字體來輸出(包括基礎的字詞轉換)、也可以轉成康熙繁體來輸出。
>- 簡繁體中文語料庫彼此分離,徹底杜絕任何繁簡轉換過程可能造成的失誤。 >- 簡繁體中文語料庫彼此分離,徹底杜絕任何繁簡轉換過程可能造成的失誤。
>- 支援最新的全字型檔漢字輸入。 >- 支援近年的全字庫漢字輸入。
>- 可以自動整理使用者語彙檔案格式、自訂聯想詞。 >- 可以自動整理使用者語彙檔案格式、自訂聯想詞。
>- …… >- ……
@ -96,8 +98,14 @@
請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案。 請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案。
## 特殊勸告 ## 其他
為了您的精神衛生,任何使用威注音輸入法時遇到的產品問題、請勿提報至小麥注音,除非您確信小麥注音也有該問題。即便如此,也請在他們那邊不要提及威注音。 為了您的精神衛生,任何使用威注音輸入法時遇到的產品問題、請勿提報至小麥注音,除非您確信小麥注音也有該問題。即便如此,也請在他們那邊不要提及威注音。
濫用沉默權來浪費對方的時間與熱情,也是一種暴力。 濫用沉默權來浪費對方的時間與熱情,也是一種暴力。**當對方最最最開始就把你當敵人的時候,你連呼吸都是錯的**。
其實我滿懷念上游專案還沒被 Lukhnos Liu 接管收入 OpenVanilla 的那個年代。MJHsieh 主導開發小麥注音的時候且不討論他立場怎樣但基礎的技術交流是完全沒問題的。LibChewing 那邊也是,正常交流完全沒問題。
有些事情,繼續爭論下去也沒用。本來我想著重寫 ctlInputMethod 撤掉 zonble 的狀態管理引擎的,畢竟有大陸同鄉寫的火山五筆輸入法的框架套上我的鐵恨注音並擊引擎可以直接用。但這樣賭氣對誰都沒好處。眼下,威注音 macOS 版還需要一些小維護。之後我就得開始考慮用 Rust 重寫鐵恨注音並擊引擎與天權星語彙引擎、方便接下來威注音的 Windows 版本的研發。能將 Lukhnos 的 C++ 內容全部換掉、徹底砸碎套在威注音身上的名為 C++ 的枷鎖、讓威注音有一個自由的未來,我已經知足了。讓更多的人用上好用的輸入法,才是最重要的。**這個重要性,不是 zonble 用「私人需求」這種帽子扣過來、就可以泯滅了的**。
$ EOF.

@ -1 +1 @@
Subproject commit 4e5f1dc11a9b477b7907f5e59594e636a8830ce8 Subproject commit 6c4d659d148ef5be3255427bfd4429fa8690631d

View File

@ -105,11 +105,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega
NSApp.setActivationPolicy(.accessory) NSApp.setActivationPolicy(.accessory)
} }
func checkForUpdate() { func checkForUpdate(forced: Bool = false) {
checkForUpdate(forced: false)
}
func checkForUpdate(forced: Bool) {
if checkTask != nil { if checkTask != nil {
// busy // busy
return return

View File

@ -117,7 +117,7 @@ enum CharCode: UInt /* 16 */ {
// ... but only focuses on which physical key is pressed. // ... but only focuses on which physical key is pressed.
} }
class InputHandler: NSObject { struct InputSignal: CustomStringConvertible {
private(set) var useVerticalMode: Bool private(set) var useVerticalMode: Bool
private(set) var inputText: String? private(set) var inputText: String?
private(set) var inputTextIgnoringModifiers: String? private(set) var inputTextIgnoringModifiers: String?
@ -125,15 +125,15 @@ class InputHandler: NSObject {
private(set) var keyCode: UInt16 private(set) var keyCode: UInt16
private var isFlagChanged: Bool private var isFlagChanged: Bool
private var flags: NSEvent.ModifierFlags private var flags: NSEvent.ModifierFlags
private var cursorForwardKey: KeyCode private var cursorForwardKey: KeyCode = .kNone
private var cursorBackwardKey: KeyCode private var cursorBackwardKey: KeyCode = .kNone
private var extraChooseCandidateKey: KeyCode private var extraChooseCandidateKey: KeyCode = .kNone
private var extraChooseCandidateKeyReverse: KeyCode private var extraChooseCandidateKeyReverse: KeyCode = .kNone
private var absorbedArrowKey: KeyCode private var absorbedArrowKey: KeyCode = .kNone
private var verticalModeOnlyChooseCandidateKey: KeyCode private var verticalModeOnlyChooseCandidateKey: KeyCode = .kNone
private(set) var emacsKey: vChewingEmacsKey private(set) var emacsKey: vChewingEmacsKey
init( public init(
inputText: String?, keyCode: UInt16, charCode: UInt16, flags: NSEvent.ModifierFlags, inputText: String?, keyCode: UInt16, charCode: UInt16, flags: NSEvent.ModifierFlags,
isVerticalMode: Bool, inputTextIgnoringModifiers: String? = nil isVerticalMode: Bool, inputTextIgnoringModifiers: String? = nil
) { ) {
@ -150,17 +150,11 @@ class InputHandler: NSObject {
emacsKey = EmacsKeyHelper.detect( emacsKey = EmacsKeyHelper.detect(
charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags
) )
// Define Arrow Keys // Define Arrow Keys in the same way above.
cursorForwardKey = useVerticalMode ? .kDownArrow : .kRightArrow defineArrowKeys()
cursorBackwardKey = useVerticalMode ? .kUpArrow : .kLeftArrow
extraChooseCandidateKey = useVerticalMode ? .kLeftArrow : .kDownArrow
extraChooseCandidateKeyReverse = useVerticalMode ? .kRightArrow : .kUpArrow
absorbedArrowKey = useVerticalMode ? .kRightArrow : .kUpArrow
verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .kNone
super.init()
} }
init(event: NSEvent, isVerticalMode: Bool) { public init(event: NSEvent, isVerticalMode: Bool) {
inputText = AppleKeyboardConverter.cnvStringApple2ABC(event.characters ?? "") inputText = AppleKeyboardConverter.cnvStringApple2ABC(event.characters ?? "")
inputTextIgnoringModifiers = AppleKeyboardConverter.cnvStringApple2ABC( inputTextIgnoringModifiers = AppleKeyboardConverter.cnvStringApple2ABC(
event.charactersIgnoringModifiers ?? "") event.charactersIgnoringModifiers ?? "")
@ -181,22 +175,20 @@ class InputHandler: NSObject {
charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags charCode: AppleKeyboardConverter.cnvApple2ABC(charCode), flags: flags
) )
// Define Arrow Keys in the same way above. // Define Arrow Keys in the same way above.
defineArrowKeys()
}
mutating func defineArrowKeys() {
cursorForwardKey = useVerticalMode ? .kDownArrow : .kRightArrow cursorForwardKey = useVerticalMode ? .kDownArrow : .kRightArrow
cursorBackwardKey = useVerticalMode ? .kUpArrow : .kLeftArrow cursorBackwardKey = useVerticalMode ? .kUpArrow : .kLeftArrow
extraChooseCandidateKey = useVerticalMode ? .kLeftArrow : .kDownArrow extraChooseCandidateKey = useVerticalMode ? .kLeftArrow : .kDownArrow
extraChooseCandidateKeyReverse = useVerticalMode ? .kRightArrow : .kUpArrow extraChooseCandidateKeyReverse = useVerticalMode ? .kRightArrow : .kUpArrow
absorbedArrowKey = useVerticalMode ? .kRightArrow : .kUpArrow absorbedArrowKey = useVerticalMode ? .kRightArrow : .kUpArrow
verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .kNone verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .kNone
super.init()
} }
override var description: String { var description: String {
charCode = AppleKeyboardConverter.cnvApple2ABC(charCode) "<inputText:\(String(describing: inputText)), inputTextIgnoringModifiers:\(String(describing: inputTextIgnoringModifiers)) charCode:\(charCode), keyCode:\(keyCode), flags:\(flags), cursorForwardKey:\(cursorForwardKey), cursorBackwardKey:\(cursorBackwardKey), extraChooseCandidateKey:\(extraChooseCandidateKey), extraChooseCandidateKeyReverse:\(extraChooseCandidateKeyReverse), absorbedArrowKey:\(absorbedArrowKey), verticalModeOnlyChooseCandidateKey:\(verticalModeOnlyChooseCandidateKey), emacsKey:\(emacsKey), useVerticalMode:\(useVerticalMode)>"
inputText = AppleKeyboardConverter.cnvStringApple2ABC(inputText ?? "")
inputTextIgnoringModifiers = AppleKeyboardConverter.cnvStringApple2ABC(
inputTextIgnoringModifiers ?? "")
return
"<\(super.description) inputText:\(String(describing: inputText)), inputTextIgnoringModifiers:\(String(describing: inputTextIgnoringModifiers)) charCode:\(charCode), keyCode:\(keyCode), flags:\(flags), cursorForwardKey:\(cursorForwardKey), cursorBackwardKey:\(cursorBackwardKey), extraChooseCandidateKey:\(extraChooseCandidateKey), extraChooseCandidateKeyReverse:\(extraChooseCandidateKeyReverse), absorbedArrowKey:\(absorbedArrowKey), verticalModeOnlyChooseCandidateKey:\(verticalModeOnlyChooseCandidateKey), emacsKey:\(emacsKey), useVerticalMode:\(useVerticalMode)>"
} }
// ANSI charCode Swift KeyHandler // ANSI charCode Swift KeyHandler
@ -365,7 +357,7 @@ enum vChewingEmacsKey: UInt16 {
case nextPage = 22 // V case nextPage = 22 // V
} }
class EmacsKeyHelper: NSObject { enum EmacsKeyHelper {
static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> vChewingEmacsKey { static func detect(charCode: UniChar, flags: NSEvent.ModifierFlags) -> vChewingEmacsKey {
let charCode = AppleKeyboardConverter.cnvApple2ABC(charCode) let charCode = AppleKeyboardConverter.cnvApple2ABC(charCode)
if flags.contains(.control) { if flags.contains(.control) {

View File

@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import Cocoa import Cocoa
// InputState 使 Struct Struct
/// Represents the states for the input method controller. /// Represents the states for the input method controller.
/// ///
/// An input method is actually a finite state machine. It receives the inputs /// An input method is actually a finite state machine. It receives the inputs
@ -44,10 +46,10 @@ import Cocoa
/// create a new state object to replace the current state instead of modifying /// create a new state object to replace the current state instead of modifying
/// the existing one. /// the existing one.
/// ///
/// vChewing's input controller has following possible states: /// The input controller has following possible states:
/// ///
/// - Deactivated: The user is not using vChewing yet. /// - Deactivated: The user is not using the input method yet.
/// - Empty: The user has switched to vChewing but did not input anything yet, /// - Empty: The user has switched to this input method but inputted nothing yet,
/// or, he or she has committed text into the client apps and starts a new /// or, he or she has committed text into the client apps and starts a new
/// input phase. /// input phase.
/// - Committing: The input controller is sending text to the client apps. /// - Committing: The input controller is sending text to the client apps.
@ -136,14 +138,14 @@ class InputState {
} }
var attributedString: NSAttributedString { var attributedString: NSAttributedString {
let attributedSting = NSAttributedString( let attributedString = NSAttributedString(
string: composingBuffer, string: composingBuffer,
attributes: [ attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue, .underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0, .markedClauseSegment: 0,
] ]
) )
return attributedSting return attributedString
} }
override var description: String { override var description: String {
@ -257,22 +259,22 @@ class InputState {
} }
var attributedString: NSAttributedString { var attributedString: NSAttributedString {
let attributedSting = NSMutableAttributedString(string: composingBuffer) let attributedString = NSMutableAttributedString(string: composingBuffer)
let end = markedRange.location + markedRange.length let end = markedRange.location + markedRange.length
attributedSting.setAttributes( attributedString.setAttributes(
[ [
.underlineStyle: NSUnderlineStyle.single.rawValue, .underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0, .markedClauseSegment: 0,
], range: NSRange(location: 0, length: markedRange.location) ], range: NSRange(location: 0, length: markedRange.location)
) )
attributedSting.setAttributes( attributedString.setAttributes(
[ [
.underlineStyle: NSUnderlineStyle.thick.rawValue, .underlineStyle: NSUnderlineStyle.thick.rawValue,
.markedClauseSegment: 1, .markedClauseSegment: 1,
], range: markedRange ], range: markedRange
) )
attributedSting.setAttributes( attributedString.setAttributes(
[ [
.underlineStyle: NSUnderlineStyle.single.rawValue, .underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 2, .markedClauseSegment: 2,
@ -282,21 +284,21 @@ class InputState {
length: (composingBuffer as NSString).length - end length: (composingBuffer as NSString).length - end
) )
) )
return attributedSting return attributedString
} }
override var description: String { override var description: String {
"<InputState.Marking, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex), markedRange:\(markedRange)>" "<InputState.Marking, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex), markedRange:\(markedRange)>"
} }
func convertToInputting() -> Inputting { var convertedToInputting: Inputting {
let state = Inputting(composingBuffer: composingBuffer, cursorIndex: cursorIndex) let state = Inputting(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
state.tooltip = tooltipForInputting state.tooltip = tooltipForInputting
return state return state
} }
var validToWrite: Bool { var validToWrite: Bool {
/// vChewing allows users to input a string whose length differs /// The input method allows users to input a string whose length differs
/// from the amount of Bopomofo readings. In this case, the range /// from the amount of Bopomofo readings. In this case, the range
/// in the composing buffer and the readings could not match, so /// in the composing buffer and the readings could not match, so
/// we disable the function to write user phrases in this case. /// we disable the function to write user phrases in this case.
@ -370,14 +372,14 @@ class InputState {
} }
var attributedString: NSAttributedString { var attributedString: NSAttributedString {
let attributedSting = NSAttributedString( let attributedString = NSAttributedString(
string: composingBuffer, string: composingBuffer,
attributes: [ attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue, .underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0, .markedClauseSegment: 0,
] ]
) )
return attributedSting return attributedString
} }
override var description: String { override var description: String {
@ -415,6 +417,22 @@ class InputState {
) )
} }
// InputState.SymbolTable
// MS Word
//
//
// Crediting Qwertyyb: https://github.com/qwertyyb/Fire/issues/55#issuecomment-1133497700
override var attributedString: NSAttributedString {
let attributedString = NSAttributedString(
string: " ",
attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0,
]
)
return attributedString
}
override var description: String { override var description: String {
"<InputState.SymbolTable, candidates:\(candidates), useVerticalMode:\(useVerticalMode), composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex)>" "<InputState.SymbolTable, candidates:\(candidates), useVerticalMode:\(useVerticalMode), composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex)>"
} }

View File

@ -68,13 +68,35 @@ class KeyHandler {
return InputMode.imeModeNULL return InputMode.imeModeNULL
} }
} }
set { setInputMode(newValue.rawValue) } set {
let isCHS: Bool = (newValue == InputMode.imeModeCHS)
// ctlInputMethod:
ctlInputMethod.currentInputMode = isCHS ? InputMode.imeModeCHS.rawValue : InputMode.imeModeCHT.rawValue
mgrPrefs.mostRecentInputMode = ctlInputMethod.currentInputMode
// _inputMode ctlInputMethod
if _inputMode != ctlInputMethod.currentInputMode {
// Reinitiate language models if necessary
_languageModel = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT
_userOverrideModel = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT
// Synchronize the sub-languageModel state settings to the new LM.
syncBaseLMPrefs()
// Create new grid builder and clear the composer.
createNewBuilder()
_composer.clear()
}
//
_inputMode = ctlInputMethod.currentInputMode
}
} }
public init() { public init() {
_builder = Megrez.BlockReadingBuilder(lm: _languageModel) _builder = Megrez.BlockReadingBuilder(lm: _languageModel, separator: "-")
ensureParser() ensureParser()
setInputMode(ctlInputMethod.currentInputMode) inputMode = InputMode(rawValue: ctlInputMethod.currentInputMode) ?? InputMode.imeModeNULL
} }
func clear() { func clear() {
@ -83,34 +105,6 @@ class KeyHandler {
_walkedNodes.removeAll() _walkedNodes.removeAll()
} }
func setInputMode(_ value: String) {
// isKindOfClass
// plist
let isCHS: Bool = (value == InputMode.imeModeCHS.rawValue)
// ctlInputMethod:
ctlInputMethod.currentInputMode = isCHS ? InputMode.imeModeCHS.rawValue : InputMode.imeModeCHT.rawValue
mgrPrefs.mostRecentInputMode = ctlInputMethod.currentInputMode
// _inputMode ctlInputMethod
if _inputMode != ctlInputMethod.currentInputMode {
// Reinitiate language models if necessary
setInputModesToLM(isCHS: isCHS)
// Synchronize the sub-languageModel state settings to the new LM.
syncBaseLMPrefs()
// Create new grid builder.
createNewBuilder()
if !_composer.isEmpty {
_composer.clear()
}
}
//
_inputMode = ctlInputMethod.currentInputMode
}
// MARK: - Functions dealing with Megrez. // MARK: - Functions dealing with Megrez.
func walk() { func walk() {
@ -118,12 +112,10 @@ class KeyHandler {
// 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 Megrez library. // using the Viterbi algorithm implemented in the Megrez library.
// The walk() traces the grid to the end, hence no need to use .reversed() here. // The walk() traces the grid to the end, hence no need to use .reversed() here.
_walkedNodes = Megrez.Walker( _walkedNodes = _builder.walk(at: _builder.grid.width, nodesLimit: 10, balanced: true)
grid: _builder.grid()
).walk(at: _builder.grid().width(), nodesLimit: 3, balanced: true)
} }
func popOverflowComposingTextAndWalk() -> String { var popOverflowComposingTextAndWalk: String {
// In ideal situations we can allow users to type infinitely in a buffer. // In ideal situations we can allow users to type infinitely in a buffer.
// However, Viberti algorithm has a complexity of O(N^2), the walk will // However, Viberti algorithm has a complexity of O(N^2), the walk will
// become slower as the number of nodes increase. Therefore, we need to // become slower as the number of nodes increase. Therefore, we need to
@ -133,11 +125,11 @@ class KeyHandler {
// (i.e. popped out.) // (i.e. popped out.)
var poppedText = "" var poppedText = ""
if _builder.grid().width() > mgrPrefs.composingBufferSize { if _builder.grid.width > mgrPrefs.composingBufferSize {
if _walkedNodes.count > 0 { if _walkedNodes.count > 0 {
let anchor: Megrez.NodeAnchor = _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
} }
_builder.removeHeadReadings(count: anchor.spanningLength) _builder.removeHeadReadings(count: anchor.spanningLength)
} }
@ -155,8 +147,8 @@ class KeyHandler {
} }
func fixNode(value: String) { func fixNode(value: String) {
let cursorIndex: Int = getActualCandidateCursorIndex() let cursorIndex: Int = actualCandidateCursorIndex
let selectedNode: Megrez.NodeAnchor = _builder.grid().fixNodeSelectedCandidate( let selectedNode: Megrez.NodeAnchor = _builder.grid.fixNodeSelectedCandidate(
location: cursorIndex, value: value location: cursorIndex, value: value
) )
// //
@ -194,16 +186,16 @@ class KeyHandler {
if nextPosition >= cursorIndex { break } if nextPosition >= cursorIndex { break }
nextPosition += node.spanningLength nextPosition += node.spanningLength
} }
if nextPosition <= getBuilderLength() { if nextPosition <= builderLength {
setBuilderCursorIndex(value: nextPosition) builderCursorIndex = nextPosition
} }
} }
} }
func getCandidatesArray() -> [String] { var candidatesArray: [String] {
var arrCandidates: [String] = [] var arrCandidates: [String] = []
var arrNodes: [Megrez.NodeAnchor] = [] var arrNodes: [Megrez.NodeAnchor] = []
arrNodes.append(contentsOf: getRawNodes()) arrNodes.append(contentsOf: rawNodes)
/// nodes /// nodes
/// ///
@ -216,7 +208,7 @@ class KeyHandler {
// then use the Swift trick to retrieve the candidates for each node at/crossing the cursor // then use the Swift trick to retrieve the candidates for each node at/crossing the cursor
for currentNodeAnchor in arrNodes { for currentNodeAnchor in arrNodes {
if let currentNode = currentNodeAnchor.node { if let currentNode = currentNodeAnchor.node {
for currentCandidate in currentNode.candidates() { for currentCandidate in currentNode.candidates {
arrCandidates.append(currentCandidate.value) arrCandidates.append(currentCandidate.value)
} }
} }
@ -230,17 +222,17 @@ class KeyHandler {
mgrPrefs.useSCPCTypingMode mgrPrefs.useSCPCTypingMode
? "" ? ""
: _userOverrideModel.suggest( : _userOverrideModel.suggest(
walkedNodes: _walkedNodes, cursorIndex: getBuilderCursorIndex(), walkedNodes: _walkedNodes, cursorIndex: builderCursorIndex,
timestamp: NSDate().timeIntervalSince1970 timestamp: NSDate().timeIntervalSince1970
) )
if !overrideValue.isEmpty { if !overrideValue.isEmpty {
IME.prtDebugIntel( IME.prtDebugIntel(
"UOM: Suggestion retrieved, overriding the node score of the selected candidate.") "UOM: Suggestion retrieved, overriding the node score of the selected candidate.")
_builder.grid().overrideNodeScoreForSelectedCandidate( _builder.grid.overrideNodeScoreForSelectedCandidate(
location: getActualCandidateCursorIndex(), location: actualCandidateCursorIndex,
value: overrideValue, value: overrideValue,
overridingScore: findHighestScore(nodes: getRawNodes(), epsilon: kEpsilon) overridingScore: findHighestScore(nodes: rawNodes, epsilon: kEpsilon)
) )
} else { } else {
IME.prtDebugIntel("UOM: Blank suggestion retrieved, dismissing.") IME.prtDebugIntel("UOM: Blank suggestion retrieved, dismissing.")
@ -251,7 +243,7 @@ class KeyHandler {
var highestScore: Double = 0 var highestScore: Double = 0
for currentAnchor in nodes { for currentAnchor in nodes {
if let theNode = currentAnchor.node { if let theNode = currentAnchor.node {
let score = theNode.highestUnigramScore() let score = theNode.highestUnigramScore
if score > highestScore { if score > highestScore {
highestScore = score highestScore = score
} }
@ -260,70 +252,6 @@ class KeyHandler {
return highestScore + epsilon return highestScore + epsilon
} }
// MARK: - Extracted methods and functions (Megrez).
func isBuilderEmpty() -> Bool { _builder.grid().width() == 0 }
func getRawNodes() -> [Megrez.NodeAnchor] {
/// 使 nodesCrossing macOS
/// nodeCrossing Megrez
/// Windows
mgrPrefs.setRearCursorMode
? _builder.grid().nodesCrossingOrEndingAt(location: getActualCandidateCursorIndex())
: _builder.grid().nodesEndingAt(location: getActualCandidateCursorIndex())
}
func setInputModesToLM(isCHS: Bool) {
_languageModel = isCHS ? mgrLangModel.lmCHS : mgrLangModel.lmCHT
_userOverrideModel = isCHS ? mgrLangModel.uomCHS : mgrLangModel.uomCHT
}
func syncBaseLMPrefs() {
_languageModel.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled
_languageModel.isCNSEnabled = mgrPrefs.cns11643Enabled
_languageModel.isSymbolEnabled = mgrPrefs.symbolInputEnabled
}
func createNewBuilder() {
_builder = Megrez.BlockReadingBuilder(lm: _languageModel)
// Each Mandarin syllable is separated by a hyphen.
_builder.setJoinSeparator(separator: "-")
}
func currentReadings() -> [String] { _builder.readings() }
func ifLangModelHasUnigrams(forKey reading: String) -> Bool {
_languageModel.hasUnigramsFor(key: reading)
}
func insertReadingToBuilderAtCursor(reading: String) {
_builder.insertReadingAtCursor(reading: reading)
}
func setBuilderCursorIndex(value: Int) {
_builder.setCursorIndex(newIndex: value)
}
func getBuilderCursorIndex() -> Int {
_builder.cursorIndex()
}
func getBuilderLength() -> Int {
_builder.length()
}
func deleteBuilderReadingInFrontOfCursor() {
_builder.deleteReadingAtTheRearOfCursor()
}
func deleteBuilderReadingToTheFrontOfCursor() {
_builder.deleteReadingToTheFrontOfCursor()
}
func getKeyLengthAtIndexZero() -> Int {
_walkedNodes[0].node?.currentKeyValue().value.count ?? 0
}
// MARK: - Extracted methods and functions (Tekkon). // MARK: - Extracted methods and functions (Tekkon).
func ensureParser() { func ensureParser() {
@ -360,4 +288,59 @@ class KeyHandler {
} }
_composer.clear() _composer.clear()
} }
// MARK: - Extracted methods and functions (Megrez).
var isBuilderEmpty: Bool { _builder.grid.width == 0 }
var rawNodes: [Megrez.NodeAnchor] {
/// 使 nodesCrossing macOS
/// nodeCrossing Megrez
/// Windows
mgrPrefs.setRearCursorMode
? _builder.grid.nodesCrossingOrEndingAt(location: actualCandidateCursorIndex)
: _builder.grid.nodesEndingAt(location: actualCandidateCursorIndex)
}
func syncBaseLMPrefs() {
_languageModel.isPhraseReplacementEnabled = mgrPrefs.phraseReplacementEnabled
_languageModel.isCNSEnabled = mgrPrefs.cns11643Enabled
_languageModel.isSymbolEnabled = mgrPrefs.symbolInputEnabled
}
func createNewBuilder() {
// Each Mandarin syllable is separated by a hyphen.
_builder = Megrez.BlockReadingBuilder(lm: _languageModel, separator: "-")
}
var currentReadings: [String] { _builder.readings }
func ifLangModelHasUnigrams(forKey reading: String) -> Bool {
_languageModel.hasUnigramsFor(key: reading)
}
func insertReadingToBuilderAtCursor(reading: String) {
_builder.insertReadingAtCursor(reading: reading)
}
var builderCursorIndex: Int {
get { _builder.cursorIndex }
set { _builder.cursorIndex = newValue }
}
var builderLength: Int {
_builder.length
}
func deleteBuilderReadingInFrontOfCursor() {
_builder.deleteReadingAtTheRearOfCursor()
}
func deleteBuilderReadingToTheFrontOfCursor() {
_builder.deleteReadingToTheFrontOfCursor()
}
var keyLengthAtIndexZero: Int {
_walkedNodes[0].node?.currentKeyValue.value.count ?? 0
}
} }

View File

@ -31,7 +31,7 @@ import Cocoa
extension KeyHandler { extension KeyHandler {
func handleCandidate( func handleCandidate(
state: InputState, state: InputState,
input: InputHandler, input: InputSignal,
stateCallback: @escaping (InputState) -> Void, stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -47,16 +47,16 @@ extension KeyHandler {
if cancelCandidateKey { if cancelCandidateKey {
if (state is InputState.AssociatedPhrases) if (state is InputState.AssociatedPhrases)
|| mgrPrefs.useSCPCTypingMode || mgrPrefs.useSCPCTypingMode
|| isBuilderEmpty() || isBuilderEmpty
{ {
// //
// //
// 使 BackSpace // 使 BackSpace
// isBuilderEmpty() // isBuilderEmpty
clear() clear()
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
} else { } else {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} }
return true return true
} }
@ -320,7 +320,7 @@ extension KeyHandler {
punctuationNamePrefix = "_punctuation_" punctuationNamePrefix = "_punctuation_"
} }
let parser = getCurrentMandarinParser() let parser = currentMandarinParser
let arrCustomPunctuations: [String] = [ let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)), punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),

View File

@ -30,7 +30,7 @@ import Cocoa
extension KeyHandler { extension KeyHandler {
func handle( func handle(
input: InputHandler, input: InputSignal,
state: InputState, state: InputState,
stateCallback: @escaping (InputState) -> Void, stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
@ -135,7 +135,7 @@ extension KeyHandler {
) { ) {
return true return true
} }
state = marking.convertToInputting() state = marking.convertedToInputting
stateCallback(state) stateCallback(state)
} }
@ -154,7 +154,7 @@ extension KeyHandler {
// update the composing buffer. // update the composing buffer.
let composeReading = _composer.hasToneMarker() let composeReading = _composer.hasToneMarker()
if !composeReading { if !composeReading {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
return true return true
} }
} }
@ -166,7 +166,7 @@ extension KeyHandler {
// However, Swift does not support "|=". // However, Swift does not support "|=".
composeReading = composeReading || (!_composer.isEmpty && (input.isSpace || input.isEnter)) composeReading = composeReading || (!_composer.isEmpty && (input.isSpace || input.isEnter))
if composeReading { if composeReading {
if input.isSpace && !_composer.hasToneMarker() { if input.isSpace, !_composer.hasToneMarker() {
_composer.receiveKey(fromString: " ") // _composer.receiveKey(fromString: " ") //
} }
let reading = _composer.getComposition() let reading = _composer.getComposition()
@ -176,7 +176,7 @@ extension KeyHandler {
IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。") IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。")
errorCallback() errorCallback()
_composer.clear() _composer.clear()
stateCallback((getBuilderLength() == 0) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState()) stateCallback((builderLength == 0) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState)
return true return true
} }
@ -184,7 +184,7 @@ extension KeyHandler {
insertReadingToBuilderAtCursor(reading: reading) insertReadingToBuilderAtCursor(reading: reading)
// ... then walk the grid... // ... then walk the grid...
let poppedText = popOverflowComposingTextAndWalk() let poppedText = popOverflowComposingTextAndWalk
// ... get and tweak override model suggestion if possible... // ... get and tweak override model suggestion if possible...
dealWithOverrideModelSuggestions() dealWithOverrideModelSuggestions()
@ -192,7 +192,7 @@ extension KeyHandler {
// ... then update the text. // ... then update the text.
_composer.clear() _composer.clear()
let inputting = buildInputtingState() let inputting = buildInputtingState
inputting.poppedText = poppedText inputting.poppedText = poppedText
stateCallback(inputting) stateCallback(inputting)
@ -233,7 +233,7 @@ extension KeyHandler {
// but does not compose. Only sequences such as "ˊ", "ˊˊ", "ˊˇ", or "ˊ " // but does not compose. Only sequences such as "ˊ", "ˊˊ", "ˊˇ", or "ˊ "
// would compose. // would compose.
if keyConsumedByReading { if keyConsumedByReading {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
return true return true
} }
@ -247,7 +247,7 @@ extension KeyHandler {
if input.isSpace { if input.isSpace {
// If the Space key is NOT set to be a selection key // If the Space key is NOT set to be a selection key
if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace { if input.isShiftHold || !mgrPrefs.chooseCandidateUsingSpace {
if getBuilderCursorIndex() >= getBuilderLength() { if builderCursorIndex >= builderLength {
let composingBuffer = currentState.composingBuffer let composingBuffer = currentState.composingBuffer
if !composingBuffer.isEmpty { if !composingBuffer.isEmpty {
stateCallback(InputState.Committing(poppedText: composingBuffer)) stateCallback(InputState.Committing(poppedText: composingBuffer))
@ -257,8 +257,8 @@ extension KeyHandler {
stateCallback(InputState.Empty()) stateCallback(InputState.Empty())
} else if ifLangModelHasUnigrams(forKey: " ") { } else if ifLangModelHasUnigrams(forKey: " ") {
insertReadingToBuilderAtCursor(reading: " ") insertReadingToBuilderAtCursor(reading: " ")
let poppedText = popOverflowComposingTextAndWalk() let poppedText = popOverflowComposingTextAndWalk
let inputting = buildInputtingState() let inputting = buildInputtingState
inputting.poppedText = poppedText inputting.poppedText = poppedText
stateCallback(inputting) stateCallback(inputting)
} }
@ -351,12 +351,12 @@ extension KeyHandler {
// MARK: Punctuation list // MARK: Punctuation list
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 _composer.isEmpty { if _composer.isEmpty {
insertReadingToBuilderAtCursor(reading: "_punctuation_list") insertReadingToBuilderAtCursor(reading: "_punctuation_list")
let poppedText: String! = popOverflowComposingTextAndWalk() let poppedText: String! = popOverflowComposingTextAndWalk
let inputting = buildInputtingState() let inputting = buildInputtingState
inputting.poppedText = poppedText inputting.poppedText = poppedText
stateCallback(inputting) stateCallback(inputting)
stateCallback(buildCandidate(state: inputting, useVerticalMode: input.useVerticalMode)) stateCallback(buildCandidate(state: inputting, useVerticalMode: input.useVerticalMode))
@ -392,7 +392,7 @@ extension KeyHandler {
punctuationNamePrefix = "_punctuation_" punctuationNamePrefix = "_punctuation_"
} }
let parser = getCurrentMandarinParser() let parser = currentMandarinParser
let arrCustomPunctuations: [String] = [ let arrCustomPunctuations: [String] = [
punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)), punctuationNamePrefix, parser, String(format: "%c", CChar(charCode)),
] ]

View File

@ -29,22 +29,22 @@ import Cocoa
// MARK: - § Misc functions. // MARK: - § Misc functions.
extension KeyHandler { extension KeyHandler {
func getCurrentMandarinParser() -> String { var currentMandarinParser: String {
mgrPrefs.mandarinParserName + "_" mgrPrefs.mandarinParserName + "_"
} }
func getActualCandidateCursorIndex() -> Int { var actualCandidateCursorIndex: Int {
var cursorIndex = getBuilderCursorIndex() var cursorIndex = builderCursorIndex
// Windows Yahoo Kimo IME style, phrase is *at the rear of* the cursor. // Windows Yahoo Kimo IME style, phrase is *at the rear of* the cursor.
// (i.e. the cursor is always *before* the phrase.) // (i.e. the cursor is always *before* the phrase.)
// This is different from MS Phonetics IME style ... // This is different from MS Phonetics IME style ...
// ... since Windows Yahoo Kimo allows "node crossing". // ... since Windows Yahoo Kimo allows "node crossing".
if (mgrPrefs.setRearCursorMode if (mgrPrefs.setRearCursorMode
&& (cursorIndex < getBuilderLength())) && (cursorIndex < builderLength))
|| cursorIndex == 0 || cursorIndex == 0
{ {
if cursorIndex == 0, !mgrPrefs.setRearCursorMode { if cursorIndex == 0, !mgrPrefs.setRearCursorMode {
cursorIndex += getKeyLengthAtIndexZero() cursorIndex += keyLengthAtIndexZero
} else { } else {
cursorIndex += 1 cursorIndex += 1
} }

View File

@ -31,42 +31,47 @@ import Cocoa
extension KeyHandler { extension KeyHandler {
// MARK: - State Building // MARK: - State Building
func buildInputtingState() -> InputState.Inputting { var buildInputtingState: InputState.Inputting {
// "Updating the composing buffer" means to request the client // "Updating the composing buffer" means to request the client
// to "refresh" the text input buffer with our "composing text" // to "refresh" the text input buffer with our "composing text"
var composingBuffer = "" var composingBuffer = ""
var composedStringCursorIndex = 0 var composedStringCursorIndex = 0
var readingCursorIndex = 0 var readingCursorIndex = 0
let builderCursorIndex = getBuilderCursorIndex() // 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
for theAnchor in _walkedNodes { // locations. These processes are inherited from the ObjC++ version of this class and might be
guard let node = theAnchor.node else { // unnecessary in Swift, but this deduction requires further experiments.
continue for walkedNode in _walkedNodes {
} if let theNode = walkedNode.node {
let strNodeValue = theNode.currentKeyValue.value
let valueString = node.currentKeyValue().value composingBuffer += strNodeValue
composingBuffer += valueString let arrSplit: [NSString] = (strNodeValue as NSString).split()
let codepointCount = valueString.count let codepointCount = arrSplit.count
// This re-aligns the cursor index in the composed string
let spanningLength = theAnchor.spanningLength // (the actual cursor on the screen) with the builder's logical
if readingCursorIndex + spanningLength <= builderCursorIndex { // cursor (reading) cursor; each built node has a "spanning length"
composedStringCursorIndex += valueString.count // (e.g. two reading blocks has a spanning length of 2), and we
readingCursorIndex += spanningLength // accumulate those lengths to calculate the displayed cursor
} else { // index.
if codepointCount == spanningLength { let spanningLength: Int = walkedNode.spanningLength
for _ in 0..<codepointCount { if readingCursorIndex + spanningLength <= builderCursorIndex {
if readingCursorIndex < builderCursorIndex { composedStringCursorIndex += (strNodeValue as NSString).length
composedStringCursorIndex += 1 readingCursorIndex += spanningLength
readingCursorIndex += 1
}
}
} else { } else {
if readingCursorIndex < builderCursorIndex { if codepointCount == spanningLength {
composedStringCursorIndex += valueString.count var i = 0
readingCursorIndex += spanningLength while i < codepointCount, readingCursorIndex < builderCursorIndex {
if readingCursorIndex > builderCursorIndex { composedStringCursorIndex += arrSplit[i].length
readingCursorIndex = builderCursorIndex readingCursorIndex += 1
i += 1
}
} else {
if readingCursorIndex < builderCursorIndex {
composedStringCursorIndex += (strNodeValue as NSString).length
readingCursorIndex += spanningLength
if readingCursorIndex > builderCursorIndex {
readingCursorIndex = builderCursorIndex
}
} }
} }
} }
@ -76,21 +81,9 @@ extension KeyHandler {
// Now, we gather all the intel, separate the composing buffer to two parts (head and tail), // Now, we gather all the intel, separate the composing buffer to two parts (head and tail),
// and insert the reading text (the Mandarin syllable) in between them. // and insert the reading text (the Mandarin syllable) in between them.
// 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))
var rawHead = ""
var rawEnd = ""
for (i, n) in composingBuffer.enumerated() {
if i < composedStringCursorIndex {
rawHead += String(n)
} else {
rawEnd += String(n)
}
}
let head = rawHead
let reading = _composer.getInlineCompositionForIMK(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer) let reading = _composer.getInlineCompositionForIMK(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer)
let tail = rawEnd 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
@ -106,7 +99,7 @@ extension KeyHandler {
InputState.ChoosingCandidate( InputState.ChoosingCandidate(
composingBuffer: currentState.composingBuffer, composingBuffer: currentState.composingBuffer,
cursorIndex: currentState.cursorIndex, cursorIndex: currentState.cursorIndex,
candidates: getCandidatesArray(), candidates: candidatesArray,
useVerticalMode: useVerticalMode useVerticalMode: useVerticalMode
) )
} }
@ -115,7 +108,7 @@ extension KeyHandler {
// buildAssociatePhraseStateWithKey // buildAssociatePhraseStateWithKey
// 使 // 使
// ObjC buildAssociatePhraseArray // Core buildAssociatePhraseArray
// String Swift // String Swift
// nil // nil
// //
@ -134,12 +127,12 @@ extension KeyHandler {
func handleMarkingState( func handleMarkingState(
_ state: InputState.Marking, _ state: InputState.Marking,
input: InputHandler, input: InputSignal,
stateCallback: @escaping (InputState) -> Void, stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
if input.isESC { if input.isESC {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
return true return true
} }
@ -152,7 +145,7 @@ extension KeyHandler {
return true return true
} }
} }
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
return true return true
} }
@ -168,7 +161,7 @@ extension KeyHandler {
readings: state.readings readings: state.readings
) )
marking.tooltipForInputting = state.tooltipForInputting marking.tooltipForInputting = state.tooltipForInputting
stateCallback(marking.markedRange.length == 0 ? marking.convertToInputting() : marking) stateCallback(marking.markedRange.length == 0 ? marking.convertedToInputting : marking)
} else { } else {
IME.prtDebugIntel("1149908D") IME.prtDebugIntel("1149908D")
errorCallback() errorCallback()
@ -191,7 +184,7 @@ extension KeyHandler {
readings: state.readings readings: state.readings
) )
marking.tooltipForInputting = state.tooltipForInputting marking.tooltipForInputting = state.tooltipForInputting
stateCallback(marking.markedRange.length == 0 ? marking.convertToInputting() : marking) stateCallback(marking.markedRange.length == 0 ? marking.convertedToInputting : marking)
} else { } else {
IME.prtDebugIntel("9B51408D") IME.prtDebugIntel("9B51408D")
errorCallback() errorCallback()
@ -217,8 +210,8 @@ extension KeyHandler {
if _composer.isEmpty { if _composer.isEmpty {
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)
@ -273,7 +266,7 @@ extension KeyHandler {
) -> Bool { ) -> Bool {
guard state is InputState.Inputting else { return false } guard state is InputState.Inputting else { return false }
var composingBuffer = currentReadings().joined(separator: "-") var composingBuffer = currentReadings.joined(separator: "-")
if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin { if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin {
composingBuffer = restoreToneOneInZhuyinKey(target: composingBuffer) // composingBuffer = restoreToneOneInZhuyinKey(target: composingBuffer) //
composingBuffer = Tekkon.cnvPhonaToHanyuPinyin(target: composingBuffer) // composingBuffer = Tekkon.cnvPhonaToHanyuPinyin(target: composingBuffer) //
@ -303,7 +296,7 @@ extension KeyHandler {
for theAnchor in _walkedNodes { for theAnchor in _walkedNodes {
if let node = theAnchor.node { if let node = theAnchor.node {
var key = node.currentKeyValue().key var key = node.currentKeyValue.key
if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin { if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin {
key = restoreToneOneInZhuyinKey(target: key) // key = restoreToneOneInZhuyinKey(target: key) //
key = Tekkon.cnvPhonaToHanyuPinyin(target: key) // key = Tekkon.cnvPhonaToHanyuPinyin(target: key) //
@ -313,7 +306,7 @@ extension KeyHandler {
key = cnvZhuyinKeyToTextbookReading(target: key, newSeparator: " ") key = cnvZhuyinKeyToTextbookReading(target: key, newSeparator: " ")
} }
let value = node.currentKeyValue().value let value = node.currentKeyValue.value
if key.contains("_") { // if key.contains("_") { //
composed += value composed += value
} else { } else {
@ -341,7 +334,7 @@ extension KeyHandler {
if _composer.hasToneMarker(withNothingElse: true) { if _composer.hasToneMarker(withNothingElse: true) {
_composer.clear() _composer.clear()
} else if _composer.isEmpty { } else if _composer.isEmpty {
if getBuilderCursorIndex() >= 0 { if builderCursorIndex >= 0 {
deleteBuilderReadingInFrontOfCursor() deleteBuilderReadingInFrontOfCursor()
walk() walk()
} else { } else {
@ -354,10 +347,10 @@ extension KeyHandler {
_composer.doBackSpace() _composer.doBackSpace()
} }
if _composer.isEmpty, getBuilderLength() == 0 { if _composer.isEmpty, builderLength == 0 {
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
} else { } else {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} }
return true return true
} }
@ -372,10 +365,10 @@ extension KeyHandler {
guard state is InputState.Inputting else { return false } guard state is InputState.Inputting else { return false }
if _composer.isEmpty { if _composer.isEmpty {
if getBuilderCursorIndex() != getBuilderLength() { if builderCursorIndex != builderLength {
deleteBuilderReadingToTheFrontOfCursor() deleteBuilderReadingToTheFrontOfCursor()
walk() walk()
let inputting = buildInputtingState() let inputting = buildInputtingState
// count > 0!isEmpty滿 // count > 0!isEmpty滿
if inputting.composingBuffer.isEmpty { if inputting.composingBuffer.isEmpty {
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
@ -428,9 +421,9 @@ extension KeyHandler {
return true return true
} }
if getBuilderCursorIndex() != 0 { if builderCursorIndex != 0 {
setBuilderCursorIndex(value: 0) builderCursorIndex = 0
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} else { } else {
IME.prtDebugIntel("66D97F90") IME.prtDebugIntel("66D97F90")
errorCallback() errorCallback()
@ -456,9 +449,9 @@ extension KeyHandler {
return true return true
} }
if getBuilderCursorIndex() != getBuilderLength() { if builderCursorIndex != builderLength {
setBuilderCursorIndex(value: getBuilderLength()) builderCursorIndex = builderLength
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} else { } else {
IME.prtDebugIntel("9B69908E") IME.prtDebugIntel("9B69908E")
errorCallback() errorCallback()
@ -490,10 +483,10 @@ extension KeyHandler {
// If reading is not empty, we cancel the reading. // If reading is not empty, we cancel the reading.
if !_composer.isEmpty { if !_composer.isEmpty {
_composer.clear() _composer.clear()
if getBuilderLength() == 0 { if builderLength == 0 {
stateCallback(InputState.EmptyIgnoringPreviousState()) stateCallback(InputState.EmptyIgnoringPreviousState())
} else { } else {
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} }
} }
} }
@ -504,7 +497,7 @@ extension KeyHandler {
func handleForward( func handleForward(
state: InputState, state: InputState,
input: InputHandler, input: InputSignal,
stateCallback: @escaping (InputState) -> Void, stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -526,7 +519,7 @@ extension KeyHandler {
composingBuffer: currentState.composingBuffer, composingBuffer: currentState.composingBuffer,
cursorIndex: currentState.cursorIndex, cursorIndex: currentState.cursorIndex,
markerIndex: UInt(nextPosition), markerIndex: UInt(nextPosition),
readings: currentReadings() readings: currentReadings
) )
marking.tooltipForInputting = currentState.tooltip marking.tooltipForInputting = currentState.tooltip
stateCallback(marking) stateCallback(marking)
@ -536,9 +529,9 @@ extension KeyHandler {
stateCallback(state) stateCallback(state)
} }
} else { } else {
if getBuilderCursorIndex() < getBuilderLength() { if builderCursorIndex < builderLength {
setBuilderCursorIndex(value: getBuilderCursorIndex() + 1) builderCursorIndex += 1
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} else { } else {
IME.prtDebugIntel("A96AAD58") IME.prtDebugIntel("A96AAD58")
errorCallback() errorCallback()
@ -553,7 +546,7 @@ extension KeyHandler {
func handleBackward( func handleBackward(
state: InputState, state: InputState,
input: InputHandler, input: InputSignal,
stateCallback: @escaping (InputState) -> Void, stateCallback: @escaping (InputState) -> Void,
errorCallback: @escaping () -> Void errorCallback: @escaping () -> Void
) -> Bool { ) -> Bool {
@ -575,7 +568,7 @@ extension KeyHandler {
composingBuffer: currentState.composingBuffer, composingBuffer: currentState.composingBuffer,
cursorIndex: currentState.cursorIndex, cursorIndex: currentState.cursorIndex,
markerIndex: UInt(previousPosition), markerIndex: UInt(previousPosition),
readings: currentReadings() readings: currentReadings
) )
marking.tooltipForInputting = currentState.tooltip marking.tooltipForInputting = currentState.tooltip
stateCallback(marking) stateCallback(marking)
@ -585,9 +578,9 @@ extension KeyHandler {
stateCallback(state) stateCallback(state)
} }
} else { } else {
if getBuilderCursorIndex() > 0 { if builderCursorIndex > 0 {
setBuilderCursorIndex(value: getBuilderCursorIndex() - 1) builderCursorIndex -= 1
stateCallback(buildInputtingState()) stateCallback(buildInputtingState)
} else { } else {
IME.prtDebugIntel("7045E6F3") IME.prtDebugIntel("7045E6F3")
errorCallback() errorCallback()

View File

@ -96,7 +96,7 @@ public struct Tekkon {
] ]
/// ///
public static let allowedsemivowels = ["", "", ""] public static let allowedSemivowels = ["", "", ""]
/// ///
public static let allowedVowels = [ public static let allowedVowels = [
@ -109,7 +109,7 @@ public struct Tekkon {
/// 調 /// 調
public static var allowedPhonabets: [String] { public static var allowedPhonabets: [String] {
allowedConsonants + allowedsemivowels + allowedVowels + allowedIntonations allowedConsonants + allowedSemivowels + allowedVowels + allowedIntonations
} }
// MARK: - Phonabet Structure // MARK: - Phonabet Structure
@ -132,18 +132,7 @@ public struct Tekkon {
if !input.isEmpty { if !input.isEmpty {
if allowedPhonabets.contains(String(input.reversed()[0])) { if allowedPhonabets.contains(String(input.reversed()[0])) {
valueStorage = String(input.reversed()[0]) valueStorage = String(input.reversed()[0])
if Tekkon.allowedConsonants.contains(value) { ensureType()
type = .consonant
} else if Tekkon.allowedsemivowels.contains(value) {
type = .semivowel
} else if Tekkon.allowedVowels.contains(value) {
type = .vowel
} else if Tekkon.allowedIntonations.contains(value) {
type = .intonation
} else {
type = .null
valueStorage = ""
}
} }
} }
} }
@ -159,6 +148,23 @@ public struct Tekkon {
/// - strWith: /// - strWith:
mutating func selfReplace(_ strOf: String, _ strWith: String = "") { mutating func selfReplace(_ strOf: String, _ strWith: String = "") {
valueStorage = valueStorage.replacingOccurrences(of: strOf, with: strWith) valueStorage = valueStorage.replacingOccurrences(of: strOf, with: strWith)
ensureType()
}
///
mutating func ensureType() {
if Tekkon.allowedConsonants.contains(value) {
type = .consonant
} else if Tekkon.allowedSemivowels.contains(value) {
type = .semivowel
} else if Tekkon.allowedVowels.contains(value) {
type = .vowel
} else if Tekkon.allowedIntonations.contains(value) {
type = .intonation
} else {
type = .null
valueStorage = ""
}
} }
// MARK: - Misc Definitions // MARK: - Misc Definitions
@ -192,7 +198,7 @@ public struct Tekkon {
/// Syllable Composer /// Syllable Composer
/// 使 Struct /// 使 Struct
/// 調 /// 調
/// @--DISCUSSION--@ ///
/// String Literal @input /// String Literal @input
/// @arrange .ofDachen /// @arrange .ofDachen
@frozen public struct Composer: Equatable, Hashable, ExpressibleByStringLiteral { @frozen public struct Composer: Equatable, Hashable, ExpressibleByStringLiteral {
@ -303,7 +309,7 @@ public struct Tekkon {
// MARK: - Public Functions // MARK: - Public Functions
/// ///
/// @--DISCUSSION--@ ///
/// parser /// parser
/// - Parameters: /// - Parameters:
/// - key: UniChar /// - key: UniChar
@ -338,7 +344,7 @@ public struct Tekkon {
/// String /// String
/// UniChar /// UniChar
/// @--DISCUSSION--@ ///
/// 調 /// 調
/// - Parameters: /// - Parameters:
/// - fromString: String /// - fromString: String
@ -364,7 +370,7 @@ public struct Tekkon {
/// UniChar /// UniChar
/// UniChar String /// UniChar String
/// @--DISCUSSION--@ ///
/// 調 /// 調
/// - Parameters: /// - Parameters:
/// - fromCharCode: UniChar /// - fromCharCode: UniChar
@ -446,7 +452,7 @@ public struct Tekkon {
/// 使 BackSpace /// 使 BackSpace
/// 調 /// 調
/// @--DISCUSSION--@ ///
/// ///
public mutating func doBackSpace() { public mutating func doBackSpace() {
if [.ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin].contains(parser), if [.ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin].contains(parser),
@ -490,7 +496,7 @@ public struct Tekkon {
// //
/// String /// String
/// @--DISCUSSION--@ ///
/// ///
/// - Parameters: /// - Parameters:
/// - key: String /// - key: String
@ -521,7 +527,7 @@ public struct Tekkon {
} }
/// ///
/// @--DISCUSSION--@ ///
/// ///
/// - Parameters: /// - Parameters:
/// - key: String /// - key: String
@ -605,7 +611,7 @@ public struct Tekkon {
} }
/// ///
/// @--DISCUSSION--@ ///
/// ///
/// - Parameters: /// - Parameters:
/// - key: String /// - key: String
@ -726,7 +732,7 @@ public struct Tekkon {
} }
/// ///
/// @--DISCUSSION--@ ///
/// ///
/// - Parameters: /// - Parameters:
/// - key: String /// - key: String
@ -1237,7 +1243,7 @@ public struct Tekkon {
// MARK: - Maps for Keyboard-to-Phonabet parsers // MARK: - Maps for Keyboard-to-Phonabet parsers
/// ///
/// @--DISCUSSION--@ ///
/// macOS 使 Ukelele /// macOS 使 Ukelele
/// 使 /// 使
static let mapQwertyDachen: [String: String] = [ static let mapQwertyDachen: [String: String] = [
@ -1248,7 +1254,7 @@ public struct Tekkon {
] ]
/// ///
/// @--DISCUSSION--@ ///
/// 便 validity check /// 便 validity check
/// ///
static let mapDachenCP26StaticKeys: [String: String] = [ static let mapDachenCP26StaticKeys: [String: String] = [
@ -1258,7 +1264,7 @@ public struct Tekkon {
] ]
/// ///
/// @--DISCUSSION--@ ///
/// 便 validity check /// 便 validity check
/// ///
static let mapHsuStaticKeys: [String: String] = [ static let mapHsuStaticKeys: [String: String] = [
@ -1268,7 +1274,7 @@ public struct Tekkon {
] ]
/// ///
/// @--DISCUSSION--@ ///
/// 便 validity check /// 便 validity check
/// //// /// ////
static let mapEten26StaticKeys: [String: String] = [ static let mapEten26StaticKeys: [String: String] = [

View File

@ -51,7 +51,7 @@ class ctlInputMethod: IMKInputController {
// KeyHandler 調 KeyHandler // KeyHandler 調 KeyHandler
// InputState ctlInputMethod // InputState ctlInputMethod
// keyHandler InputHandler // keyHandler InputSignal
// currentKeyHandler KeyHandler // currentKeyHandler KeyHandler
// currentKeyHandler // currentKeyHandler
static var currentKeyHandler: KeyHandler = .init() static var currentKeyHandler: KeyHandler = .init()
@ -77,9 +77,11 @@ class ctlInputMethod: IMKInputController {
// MARK: - KeyHandler Reset Command // MARK: - KeyHandler Reset Command
func resetKeyHandler() { func resetKeyHandler(client sender: Any? = nil) {
if let currentClient = currentClient { keyHandler.clear()
keyHandler.clear() if let client = sender as? IMKTextInput {
handle(state: InputState.Empty(), client: client)
} else if let currentClient = currentClient {
handle(state: InputState.Empty(), client: currentClient) handle(state: InputState.Empty(), client: currentClient)
} }
} }
@ -112,7 +114,8 @@ class ctlInputMethod: IMKInputController {
handle(state: .Deactivated(), client: client) handle(state: .Deactivated(), client: client)
} }
override func setValue(_ value: Any!, forTag _: Int, client: Any!) { override func setValue(_ value: Any!, forTag tag: Int, client: Any!) {
_ = tag // Stop clang-format from ruining the parameters of this function.
var newInputMode = InputMode(rawValue: value as? String ?? "") ?? InputMode.imeModeNULL var newInputMode = InputMode(rawValue: value as? String ?? "") ?? InputMode.imeModeNULL
switch newInputMode { switch newInputMode {
case InputMode.imeModeCHS: case InputMode.imeModeCHS:
@ -143,7 +146,8 @@ class ctlInputMethod: IMKInputController {
// MARK: - IMKServerInput protocol methods // MARK: - IMKServerInput protocol methods
override func recognizedEvents(_: Any!) -> Int { override func recognizedEvents(_ sender: Any!) -> Int {
_ = sender // Stop clang-format from ruining the parameters of this function.
let events: NSEvent.EventTypeMask = [.keyDown, .flagsChanged] let events: NSEvent.EventTypeMask = [.keyDown, .flagsChanged]
return Int(events.rawValue) return Int(events.rawValue)
} }
@ -180,7 +184,7 @@ class ctlInputMethod: IMKInputController {
IME.areWeUsingOurOwnPhraseEditor = false IME.areWeUsingOurOwnPhraseEditor = false
} }
let input = InputHandler(event: event, isVerticalMode: useVerticalMode) let input = InputSignal(event: event, isVerticalMode: useVerticalMode)
// //
// KeyHandler // KeyHandler
@ -195,6 +199,19 @@ class ctlInputMethod: IMKInputController {
} }
return result return result
} }
// App Ctrl+Enter / Shift+Enter
// handle(event:) Event
// commitComposition
override func commitComposition(_ sender: Any!) {
resetKeyHandler(client: sender)
}
//
override func composedString(_ sender: Any!) -> Any! {
_ = sender // Stop clang-format from ruining the parameters of this function.
return (state as? InputState.NotEmpty)?.composingBuffer ?? ""
}
} }
// MARK: - State Handling // MARK: - State Handling
@ -220,6 +237,8 @@ extension ctlInputMethod {
handle(state: newState, previous: previous, client: client) handle(state: newState, previous: previous, client: client)
} else if let newState = newState as? InputState.AssociatedPhrases { } else if let newState = newState as? InputState.AssociatedPhrases {
handle(state: newState, previous: previous, client: client) handle(state: newState, previous: previous, client: client)
} else if let newState = newState as? InputState.SymbolTable {
handle(state: newState, previous: previous, client: client)
} }
} }
@ -246,12 +265,25 @@ extension ctlInputMethod {
if buffer.isEmpty { if buffer.isEmpty {
return return
} }
var bufferOutput = ""
//
for theChar in buffer {
if let charCode = theChar.utf16.first {
if !(theChar.isASCII && !(charCode.isPrintable())) {
bufferOutput += String(theChar)
}
}
}
(client as? IMKTextInput)?.insertText( (client as? IMKTextInput)?.insertText(
buffer, replacementRange: NSRange(location: NSNotFound, length: NSNotFound) bufferOutput, replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
) )
} }
private func handle(state _: InputState.Deactivated, previous: InputState, client: Any?) { private func handle(state: InputState.Deactivated, previous: InputState, client: Any?) {
_ = state // Stop clang-format from ruining the parameters of this function.
currentClient = nil currentClient = nil
ctlCandidateCurrent?.delegate = nil ctlCandidateCurrent?.delegate = nil
@ -267,7 +299,8 @@ extension ctlInputMethod {
) )
} }
private func handle(state _: InputState.Empty, previous: InputState, client: Any?) { private func handle(state: InputState.Empty, previous: InputState, client: Any?) {
_ = state // Stop clang-format from ruining the parameters of this function.
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
hideTooltip() hideTooltip()
@ -285,8 +318,10 @@ extension ctlInputMethod {
} }
private func handle( private func handle(
state _: InputState.EmptyIgnoringPreviousState, previous _: InputState, client: Any! state: InputState.EmptyIgnoringPreviousState, previous: InputState, client: Any!
) { ) {
_ = state // Stop clang-format from ruining the parameters of this function.
_ = previous // Stop clang-format from ruining the parameters of this function.
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
hideTooltip() hideTooltip()
@ -300,7 +335,8 @@ extension ctlInputMethod {
) )
} }
private func handle(state: InputState.Committing, previous _: InputState, client: Any?) { private func handle(state: InputState.Committing, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
hideTooltip() hideTooltip()
@ -318,7 +354,8 @@ extension ctlInputMethod {
) )
} }
private func handle(state: InputState.Inputting, previous _: InputState, client: Any?) { private func handle(state: InputState.Inputting, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
hideTooltip() hideTooltip()
@ -345,7 +382,8 @@ extension ctlInputMethod {
} }
} }
private func handle(state: InputState.Marking, previous _: InputState, client: Any?) { private func handle(state: InputState.Marking, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
guard let client = client as? IMKTextInput else { guard let client = client as? IMKTextInput else {
hideTooltip() hideTooltip()
@ -369,7 +407,8 @@ extension ctlInputMethod {
} }
} }
private func handle(state: InputState.ChoosingCandidate, previous _: InputState, client: Any?) { private func handle(state: InputState.ChoosingCandidate, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
hideTooltip() hideTooltip()
guard let client = client as? IMKTextInput else { guard let client = client as? IMKTextInput else {
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
@ -385,7 +424,25 @@ extension ctlInputMethod {
show(candidateWindowWith: state, client: client) show(candidateWindowWith: state, client: client)
} }
private func handle(state: InputState.AssociatedPhrases, previous _: InputState, client: Any?) { private func handle(state: InputState.SymbolTable, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
hideTooltip()
guard let client = client as? IMKTextInput else {
ctlCandidateCurrent?.visible = false
return
}
// the selection range is where the cursor is, with the length being 0 and replacement range NSNotFound,
// i.e. the client app needs to take care of where to put this composing buffer
client.setMarkedText(
state.attributedString, selectionRange: NSRange(location: Int(state.cursorIndex), length: 0),
replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
)
show(candidateWindowWith: state, client: client)
}
private func handle(state: InputState.AssociatedPhrases, previous: InputState, client: Any?) {
_ = previous // Stop clang-format from ruining the parameters of this function.
hideTooltip() hideTooltip()
guard let client = client as? IMKTextInput else { guard let client = client as? IMKTextInput else {
ctlCandidateCurrent?.visible = false ctlCandidateCurrent?.visible = false
@ -547,14 +604,16 @@ extension ctlInputMethod {
// MARK: - // MARK: -
extension ctlInputMethod: KeyHandlerDelegate { extension ctlInputMethod: KeyHandlerDelegate {
func ctlCandidate(for _: KeyHandler) -> Any { func ctlCandidate(for keyHandler: KeyHandler) -> Any {
ctlCandidateCurrent ?? .vertical _ = keyHandler // Stop clang-format from ruining the parameters of this function.
return ctlCandidateCurrent ?? .vertical
} }
func keyHandler( func keyHandler(
_: KeyHandler, didSelectCandidateAt index: Int, _ keyHandler: KeyHandler, didSelectCandidateAt index: Int,
ctlCandidate controller: Any ctlCandidate controller: Any
) { ) {
_ = keyHandler // Stop clang-format from ruining the parameters of this function.
if let controller = controller as? ctlCandidate { if let controller = controller as? ctlCandidate {
ctlCandidate(controller, didSelectCandidateAtIndex: UInt(index)) ctlCandidate(controller, didSelectCandidateAtIndex: UInt(index))
} }
@ -592,7 +651,8 @@ extension ctlInputMethod: KeyHandlerDelegate {
// MARK: - // MARK: -
extension ctlInputMethod: ctlCandidateDelegate { extension ctlInputMethod: ctlCandidateDelegate {
func candidateCountForController(_: ctlCandidate) -> UInt { func candidateCountForController(_ controller: ctlCandidate) -> UInt {
_ = controller // Stop clang-format from ruining the parameters of this function.
if let state = state as? InputState.ChoosingCandidate { if let state = state as? InputState.ChoosingCandidate {
return UInt(state.candidates.count) return UInt(state.candidates.count)
} else if let state = state as? InputState.AssociatedPhrases { } else if let state = state as? InputState.AssociatedPhrases {
@ -601,9 +661,10 @@ extension ctlInputMethod: ctlCandidateDelegate {
return 0 return 0
} }
func ctlCandidate(_: ctlCandidate, candidateAtIndex index: UInt) func ctlCandidate(_ controller: ctlCandidate, candidateAtIndex index: UInt)
-> String -> String
{ {
_ = controller // Stop clang-format from ruining the parameters of this function.
if let state = state as? InputState.ChoosingCandidate { if let state = state as? InputState.ChoosingCandidate {
return state.candidates[Int(index)] return state.candidates[Int(index)]
} else if let state = state as? InputState.AssociatedPhrases { } else if let state = state as? InputState.AssociatedPhrases {
@ -612,7 +673,8 @@ extension ctlInputMethod: ctlCandidateDelegate {
return "" return ""
} }
func ctlCandidate(_: ctlCandidate, didSelectCandidateAtIndex index: UInt) { func ctlCandidate(_ controller: ctlCandidate, didSelectCandidateAtIndex index: UInt) {
_ = controller // Stop clang-format from ruining the parameters of this function.
let client = currentClient let client = currentClient
if let state = state as? InputState.SymbolTable, if let state = state as? InputState.SymbolTable,
@ -634,7 +696,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
let selectedValue = state.candidates[Int(index)] let selectedValue = state.candidates[Int(index)]
keyHandler.fixNode(value: selectedValue) keyHandler.fixNode(value: selectedValue)
let inputting = keyHandler.buildInputtingState() let inputting = keyHandler.buildInputtingState
if mgrPrefs.useSCPCTypingMode { if mgrPrefs.useSCPCTypingMode {
keyHandler.clear() keyHandler.clear()

View File

@ -302,7 +302,7 @@ extension ctlInputMethod {
} }
@objc func openUserDataFolder(_: Any?) { @objc func openUserDataFolder(_: Any?) {
if !mgrLangModel.checkIfUserDataFolderExists() { if !mgrLangModel.userDataFolderExists {
return return
} }
NSWorkspace.shared.openFile( NSWorkspace.shared.openFile(

View File

@ -186,7 +186,7 @@ extension vChewing {
var strPrevious = "()" var strPrevious = "()"
var strAnterior = "()" var strAnterior = "()"
guard let kvCurrent = arrNodesReversed[0].node?.currentKeyValue(), guard let kvCurrent = arrNodesReversed[0].node?.currentKeyValue,
!arrEndingPunctuation.contains(kvCurrent.value) !arrEndingPunctuation.contains(kvCurrent.value)
else { else {
return "" return ""
@ -196,14 +196,14 @@ extension vChewing {
strCurrent = kvCurrent.key strCurrent = kvCurrent.key
if arrNodesReversed.count >= 2, if arrNodesReversed.count >= 2,
let kvPrevious = arrNodesReversed[1].node?.currentKeyValue(), let kvPrevious = arrNodesReversed[1].node?.currentKeyValue,
!arrEndingPunctuation.contains(kvPrevious.value) !arrEndingPunctuation.contains(kvPrevious.value)
{ {
strPrevious = "(\(kvPrevious.key),\(kvPrevious.value))" strPrevious = "(\(kvPrevious.key),\(kvPrevious.value))"
} }
if arrNodesReversed.count >= 3, if arrNodesReversed.count >= 3,
let kvAnterior = arrNodesReversed[2].node?.currentKeyValue(), let kvAnterior = arrNodesReversed[2].node?.currentKeyValue,
!arrEndingPunctuation.contains(kvAnterior.value) !arrEndingPunctuation.contains(kvAnterior.value)
{ {
strAnterior = "(\(kvAnterior.key),\(kvAnterior.value))" strAnterior = "(\(kvAnterior.key),\(kvAnterior.value))"

View File

@ -271,7 +271,7 @@ enum mgrLangModel {
} }
static func chkUserLMFilesExist(_ mode: InputMode) -> Bool { static func chkUserLMFilesExist(_ mode: InputMode) -> Bool {
if !checkIfUserDataFolderExists() { if !userDataFolderExists {
return false return false
} }
if !ensureFileExists(userPhrasesDataPath(mode)) if !ensureFileExists(userPhrasesDataPath(mode))
@ -309,9 +309,8 @@ enum mgrLangModel {
return true return true
} }
// //
// static var userDataFolderExists: Bool {
static func checkIfUserDataFolderExists() -> Bool {
let folderPath = mgrLangModel.dataFolderPath(isDefaultFolder: false) let folderPath = mgrLangModel.dataFolderPath(isDefaultFolder: false)
var isFolder = ObjCBool(false) var isFolder = ObjCBool(false)
var folderExist = FileManager.default.fileExists(atPath: folderPath, isDirectory: &isFolder) var folderExist = FileManager.default.fileExists(atPath: folderPath, isDirectory: &isFolder)

View File

@ -24,33 +24,55 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
///
public class BlockReadingBuilder { public class BlockReadingBuilder {
var mutMaximumBuildSpanLength = 10 ///
var mutCursorIndex: Int = 0 private var mutMaximumBuildSpanLength = 10
var mutReadings: [String] = [] ///
var mutGrid: Grid = .init() private var mutCursorIndex: Int = 0
var mutLM: LanguageModel ///
var mutJoinSeparator: String = "" private var mutReadings: [String] = []
///
private var mutGrid: Grid = .init()
/// 使
private var mutLM: LanguageModel
public init(lm: LanguageModel, length: Int = 10) { ///
mutLM = lm public var joinSeparator: String = ""
mutMaximumBuildSpanLength = length ///
public var cursorIndex: Int {
get { mutCursorIndex }
set { mutCursorIndex = (newValue < 0) ? 0 : min(newValue, mutReadings.count) }
} }
///
public var grid: Grid { mutGrid }
///
public var length: Int { mutReadings.count }
///
public var readings: [String] { mutReadings }
///
/// - Parameters:
/// - lm: Megrez.LanguageModel
/// - length: 10
/// - separator:
public init(lm: LanguageModel, length: Int = 10, separator: String = "") {
mutLM = lm
mutMaximumBuildSpanLength = length
joinSeparator = separator
}
///
public func clear() { public func clear() {
mutCursorIndex = 0 mutCursorIndex = 0
mutReadings.removeAll() mutReadings.removeAll()
mutGrid.clear() mutGrid.clear()
} }
public func length() -> Int { mutReadings.count } ///
/// - Parameters:
public func cursorIndex() -> Int { mutCursorIndex } /// - reading:
public func setCursorIndex(newIndex: Int) {
mutCursorIndex = min(newIndex, mutReadings.count)
}
public func insertReadingAtCursor(reading: String) { public func insertReadingAtCursor(reading: String) {
mutReadings.insert(reading, at: mutCursorIndex) mutReadings.insert(reading, at: mutCursorIndex)
mutGrid.expandGridByOneAt(location: mutCursorIndex) mutGrid.expandGridByOneAt(location: mutCursorIndex)
@ -58,8 +80,8 @@ extension Megrez {
mutCursorIndex += 1 mutCursorIndex += 1
} }
public func readings() -> [String] { mutReadings } ///
/// Rear
@discardableResult public func deleteReadingAtTheRearOfCursor() -> Bool { @discardableResult public func deleteReadingAtTheRearOfCursor() -> Bool {
if mutCursorIndex == 0 { if mutCursorIndex == 0 {
return false return false
@ -72,6 +94,8 @@ extension Megrez {
return true return true
} }
///
/// Front
@discardableResult public func deleteReadingToTheFrontOfCursor() -> Bool { @discardableResult public func deleteReadingToTheFrontOfCursor() -> Bool {
if mutCursorIndex == mutReadings.count { if mutCursorIndex == mutReadings.count {
return false return false
@ -83,8 +107,12 @@ extension Megrez {
return true return true
} }
///
///
///
///
@discardableResult public func removeHeadReadings(count: Int) -> Bool { @discardableResult public func removeHeadReadings(count: Int) -> Bool {
if count > length() { if count > length {
return false return false
} }
@ -100,17 +128,108 @@ extension Megrez {
return true return true
} }
public func setJoinSeparator(separator: String) { // MARK: - Walker
mutJoinSeparator = separator
///
///
/// 使
/// - Parameters:
/// - at:
/// - score: 0
/// - nodesLimit:
/// - balanced:
public func walk(
at location: Int,
score accumulatedScore: Double = 0.0,
nodesLimit: Int = 0,
balanced: Bool = false
) -> [NodeAnchor] {
Array(
reverseWalk(
at: location, score: accumulatedScore,
nodesLimit: nodesLimit, balanced: balanced
).reversed())
} }
public func joinSeparator() -> String { mutJoinSeparator } ///
/// - Parameters:
/// - at:
/// - score: 0
/// - nodesLimit:
/// - balanced:
public func reverseWalk(
at location: Int,
score accumulatedScore: Double = 0.0,
nodesLimit: Int = 0,
balanced: Bool = false
) -> [NodeAnchor] {
if location == 0 || location > mutGrid.width {
return [] as [NodeAnchor]
}
public func grid() -> Grid { mutGrid } var paths: [[NodeAnchor]] = []
var nodes: [NodeAnchor] = mutGrid.nodesEndingAt(location: location)
public func build() { if balanced {
// if (mutLM == nil) { return } // nil nodes.sort {
$0.balancedScore > $1.balancedScore
}
}
for (i, n) in nodes.enumerated() {
// X NodeAnchor node
// abs
if abs(nodesLimit) > 0, i == abs(nodesLimit) - 1 {
break
}
var n = n
guard let nNode = n.node else {
continue
}
n.accumulatedScore = accumulatedScore + nNode.score
//
//
if balanced {
let weightedScore: Double = (Double(n.spanningLength) - 1) * 2
n.accumulatedScore += weightedScore
}
var path: [NodeAnchor] = reverseWalk(
at: location - n.spanningLength,
score: n.accumulatedScore
)
path.insert(n, at: 0)
paths.append(path)
// 使
if balanced, nNode.score >= 0 {
break
}
}
if !paths.isEmpty {
if var result = paths.first {
for value in paths {
if let vLast = value.last, let rLast = result.last {
if vLast.accumulatedScore > rLast.accumulatedScore {
result = value
}
}
}
return result
}
}
return [] as [NodeAnchor]
}
// MARK: - Private functions
private func build() {
let itrBegin: Int = let itrBegin: Int =
(mutCursorIndex < mutMaximumBuildSpanLength) ? 0 : mutCursorIndex - mutMaximumBuildSpanLength (mutCursorIndex < mutMaximumBuildSpanLength) ? 0 : mutCursorIndex - mutMaximumBuildSpanLength
let itrEnd: Int = min(mutCursorIndex + mutMaximumBuildSpanLength, mutReadings.count) let itrEnd: Int = min(mutCursorIndex + mutMaximumBuildSpanLength, mutReadings.count)
@ -121,7 +240,7 @@ extension Megrez {
break break
} }
let strSlice = mutReadings[p..<(p + q)] let strSlice = mutReadings[p..<(p + q)]
let combinedReading: String = join(slice: strSlice, separator: mutJoinSeparator) let combinedReading: String = join(slice: strSlice, separator: joinSeparator)
if !mutGrid.hasMatchedNode(location: p, spanningLength: q, key: combinedReading) { if !mutGrid.hasMatchedNode(location: p, spanningLength: q, key: combinedReading) {
let unigrams: [Unigram] = mutLM.unigramsFor(key: combinedReading) let unigrams: [Unigram] = mutLM.unigramsFor(key: combinedReading)
@ -134,7 +253,7 @@ extension Megrez {
} }
} }
public func join(slice strSlice: ArraySlice<String>, separator: String) -> String { private func join(slice strSlice: ArraySlice<String>, separator: String) -> String {
var arrResult: [String] = [] var arrResult: [String] = []
for value in strSlice { for value in strSlice {
arrResult.append(value) arrResult.append(value)

View File

@ -1,123 +0,0 @@
// Swiftified by (c) 2022 and onwards The vChewing Project (MIT-NTL License).
// Rebranded from (c) Lukhnos Liu's C++ library "Gramambular" (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.
*/
extension Megrez {
public class Walker {
var mutGrid: Grid
public init(grid: Megrez.Grid = Megrez.Grid()) {
mutGrid = grid
}
public func walk(
at location: Int,
score accumulatedScore: Double = 0.0,
nodesLimit: Int = 0,
balanced: Bool = false
) -> [NodeAnchor] {
var arrReturn: [NodeAnchor] = []
let arrReversedSource = reverseWalk(
at: location, score: accumulatedScore,
nodesLimit: nodesLimit, balanced: balanced
).reversed()
for neta in arrReversedSource {
arrReturn.append(neta)
}
return arrReturn
}
public func reverseWalk(
at location: Int,
score accumulatedScore: Double = 0.0,
nodesLimit: Int = 0,
balanced: Bool = false
) -> [NodeAnchor] {
if location == 0 || location > mutGrid.width() {
return [] as [NodeAnchor]
}
var paths: [[NodeAnchor]] = []
var nodes: [NodeAnchor] = mutGrid.nodesEndingAt(location: location)
if balanced {
nodes.sort {
$0.balancedScore > $1.balancedScore
}
}
for (i, n) in nodes.enumerated() {
// X NodeAnchor node
// abs
if abs(nodesLimit) > 0, i == abs(nodesLimit) - 1 {
break
}
var n = n
guard let nNode = n.node else {
continue
}
n.accumulatedScore = accumulatedScore + nNode.score()
// Spanning Length
//
if balanced {
let weightedScore: Double = (Double(n.spanningLength) - 1) * 2
n.accumulatedScore += weightedScore
}
var path: [NodeAnchor] = reverseWalk(
at: location - n.spanningLength,
score: n.accumulatedScore
)
path.insert(n, at: 0)
paths.append(path)
// 使
if balanced, nNode.score() >= 0 {
break
}
}
if !paths.isEmpty {
if var result = paths.first {
for value in paths {
if let vLast = value.last, let rLast = result.last {
if vLast.accumulatedScore > rLast.accumulatedScore {
result = value
}
}
}
return result
}
}
return [] as [NodeAnchor]
}
}
}

View File

@ -24,17 +24,28 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
///
public class Grid { public class Grid {
var mutSpans: [Megrez.Span] ///
private var mutSpans: [Megrez.Span]
///
var width: Int { mutSpans.count }
public init() { public init() {
mutSpans = [Megrez.Span]() mutSpans = [Megrez.Span]()
} }
///
public func clear() { public func clear() {
mutSpans = [Megrez.Span]() mutSpans = [Megrez.Span]()
} }
///
/// - Parameters:
/// - node:
/// - location:
/// - spanningLength:
public func insertNode(node: Node, location: Int, spanningLength: Int) { public func insertNode(node: Node, location: Int, spanningLength: Int) {
if location >= mutSpans.count { if location >= mutSpans.count {
let diff = location - mutSpans.count + 1 let diff = location - mutSpans.count + 1
@ -45,15 +56,23 @@ extension Megrez {
mutSpans[location].insert(node: node, length: spanningLength) mutSpans[location].insert(node: node, length: spanningLength)
} }
///
/// - Parameters:
/// - location:
/// - spanningLength:
/// - key:
public func hasMatchedNode(location: Int, spanningLength: Int, key: String) -> Bool { public func hasMatchedNode(location: Int, spanningLength: Int, key: String) -> Bool {
if location > mutSpans.count { if location > mutSpans.count {
return false return false
} }
let n = mutSpans[location].node(length: spanningLength) let n = mutSpans[location].node(length: spanningLength)
return n == nil ? false : key == n?.key() return n == nil ? false : key == n?.key
} }
///
/// - Parameters:
/// - location:
public func expandGridByOneAt(location: Int) { public func expandGridByOneAt(location: Int) {
// abs // abs
mutSpans.insert(Span(), at: abs(location)) mutSpans.insert(Span(), at: abs(location))
@ -65,6 +84,9 @@ extension Megrez {
} }
} }
///
/// - Parameters:
/// - location:
public func shrinkGridByOneAt(location: Int) { public func shrinkGridByOneAt(location: Int) {
if location >= mutSpans.count { if location >= mutSpans.count {
return return
@ -77,8 +99,9 @@ extension Megrez {
} }
} }
public func width() -> Int { mutSpans.count } ///
/// - Parameters:
/// - location:
public func nodesEndingAt(location: Int) -> [NodeAnchor] { public func nodesEndingAt(location: Int) -> [NodeAnchor] {
var results: [NodeAnchor] = [] var results: [NodeAnchor] = []
if !mutSpans.isEmpty, location <= mutSpans.count { if !mutSpans.isEmpty, location <= mutSpans.count {
@ -100,6 +123,9 @@ extension Megrez {
return results return results
} }
///
/// - Parameters:
/// - location:
public func nodesCrossingOrEndingAt(location: Int) -> [NodeAnchor] { public func nodesCrossingOrEndingAt(location: Int) -> [NodeAnchor] {
var results: [NodeAnchor] = [] var results: [NodeAnchor] = []
if !mutSpans.isEmpty, location <= mutSpans.count { if !mutSpans.isEmpty, location <= mutSpans.count {
@ -126,14 +152,18 @@ extension Megrez {
return results return results
} }
public func fixNodeSelectedCandidate(location: Int, value: String) -> NodeAnchor { ///
/// - Parameters:
/// - location:
/// - value:
@discardableResult public func fixNodeSelectedCandidate(location: Int, value: String) -> NodeAnchor {
var node = NodeAnchor() var node = NodeAnchor()
for nodeAnchor in nodesCrossingOrEndingAt(location: location) { for nodeAnchor in nodesCrossingOrEndingAt(location: location) {
guard let theNode = nodeAnchor.node else { guard let theNode = nodeAnchor.node else {
continue continue
} }
let candidates = theNode.candidates() let candidates = theNode.candidates
// Reset the candidate-fixed state of every node at the location. //
theNode.resetCandidate() theNode.resetCandidate()
for (i, candidate) in candidates.enumerated() { for (i, candidate) in candidates.enumerated() {
if candidate.value == value { if candidate.value == value {
@ -146,13 +176,18 @@ extension Megrez {
return node return node
} }
///
/// - Parameters:
/// - location:
/// - value:
/// - overridingScore:
public func overrideNodeScoreForSelectedCandidate(location: Int, value: String, overridingScore: Double) { public func overrideNodeScoreForSelectedCandidate(location: Int, value: String, overridingScore: Double) {
for nodeAnchor in nodesCrossingOrEndingAt(location: location) { for nodeAnchor in nodesCrossingOrEndingAt(location: location) {
guard let theNode = nodeAnchor.node else { guard let theNode = nodeAnchor.node else {
continue continue
} }
let candidates = theNode.candidates() let candidates = theNode.candidates
// Reset the candidate-fixed state of every node at the location. //
theNode.resetCandidate() theNode.resetCandidate()
for (i, candidate) in candidates.enumerated() { for (i, candidate) in candidates.enumerated() {
if candidate.value == value { if candidate.value == value {
@ -164,3 +199,38 @@ extension Megrez {
} }
} }
} }
// MARK: - DumpDOT-related functions.
extension Megrez.Grid {
public var dumpDOT: String {
var sst = "digraph {\ngraph [ rankdir=LR ];\nBOS;\n"
for (p, span) in mutSpans.enumerated() {
for ni in 0...(span.maximumLength) {
guard let np: Megrez.Node = span.node(length: ni) else {
continue
}
if p == 0 {
sst += "BOS -> \(np.currentKeyValue.value);\n"
}
sst += "\(np.currentKeyValue.value);\n"
if (p + ni) < mutSpans.count {
let dstSpan = mutSpans[p + ni]
for q in 0...(dstSpan.maximumLength) {
if let dn = dstSpan.node(length: q) {
sst += np.currentKeyValue.value + " -> " + dn.currentKeyValue.value + ";\n"
}
}
}
if (p + ni) == mutSpans.count {
sst += np.currentKeyValue.value + " -> EOS;\n"
}
}
}
sst += "EOS;\n}\n"
return sst
}
}

View File

@ -24,19 +24,52 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
@frozen public struct NodeAnchor { ///
@frozen public struct NodeAnchor: CustomStringConvertible {
///
public var node: Node? public var node: Node?
///
public var location: Int = 0 public var location: Int = 0
///
public var spanningLength: Int = 0 public var spanningLength: Int = 0
///
public var accumulatedScore: Double = 0.0 public var accumulatedScore: Double = 0.0
///
public var keyLength: Int { public var keyLength: Int {
node?.key().count ?? 0 node?.key.count ?? 0
} }
///
public var description: String {
var stream = ""
stream += "{@(" + String(location) + "," + String(spanningLength) + "),"
if let node = node {
stream += node.description
} else {
stream += "null"
}
stream += "}"
return stream
}
///
public var balancedScore: Double { public var balancedScore: Double {
let weightedScore: Double = (Double(spanningLength) - 1) * 2 let weightedScore: Double = (Double(spanningLength) - 1) * 2
let nodeScore: Double = node?.score() ?? 0 let nodeScore: Double = node?.score ?? 0
return weightedScore + nodeScore return weightedScore + nodeScore
} }
} }
} }
// MARK: - DumpDOT-related functions.
extension Array where Element == Megrez.NodeAnchor {
///
public var description: String {
var arrOutputContent = [""]
for anchor in self {
arrOutputContent.append(anchor.description)
}
return arrOutputContent.joined(separator: "<-")
}
}

View File

@ -24,23 +24,28 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
///
@frozen public struct Span { @frozen public struct Span {
private var mutLengthNodeMap: [Int: Megrez.Node] ///
private var mutMaximumLength: Int private var mutLengthNodeMap: [Int: Megrez.Node] = [:]
///
private var mutMaximumLength: Int = 0
///
var maximumLength: Int { var maximumLength: Int {
mutMaximumLength mutMaximumLength
} }
public init() { ///
mutLengthNodeMap = [:]
mutMaximumLength = 0
}
mutating func clear() { mutating func clear() {
mutLengthNodeMap.removeAll() mutLengthNodeMap.removeAll()
mutMaximumLength = 0 mutMaximumLength = 0
} }
///
/// - Parameters:
/// - node:
/// - length:
mutating func insert(node: Node, length: Int) { mutating func insert(node: Node, length: Int) {
mutLengthNodeMap[length] = node mutLengthNodeMap[length] = node
if length > mutMaximumLength { if length > mutMaximumLength {
@ -48,6 +53,9 @@ extension Megrez {
} }
} }
///
/// - Parameters:
/// - length:
mutating func removeNodeOfLengthGreaterThan(_ length: Int) { mutating func removeNodeOfLengthGreaterThan(_ length: Int) {
if length > mutMaximumLength { return } if length > mutMaximumLength { return }
var max = 0 var max = 0
@ -67,6 +75,9 @@ extension Megrez {
mutMaximumLength = max mutMaximumLength = max
} }
///
/// - Parameters:
/// - length:
public func node(length: Int) -> Node? { public func node(length: Int) -> Node? {
mutLengthNodeMap[length] mutLengthNodeMap[length]
} }

View File

@ -24,55 +24,69 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
public class Node { ///
let mutLM: LanguageModel public class Node: CustomStringConvertible {
var mutKey: String ///
var mutScore: Double = 0 private let mutLM: LanguageModel = .init()
var mutUnigrams: [Unigram] ///
var mutCandidates: [KeyValuePair] private var mutKey: String = ""
var mutValueUnigramIndexMap: [String: Int] ///
var mutPrecedingBigramMap: [KeyValuePair: [Megrez.Bigram]] private var mutScore: Double = 0
///
var mutCandidateFixed: Bool = false private var mutUnigrams: [Unigram]
var mutSelectedUnigramIndex: Int = 0 ///
private var mutBigrams: [Bigram]
let kSelectedCandidateScore: Double = 99 ///
private var mutCandidates: [KeyValuePair] = []
public init(key: String, unigrams: [Megrez.Unigram], bigrams: [Megrez.Bigram] = []) { /// 調
mutLM = LanguageModel() private var mutValueUnigramIndexMap: [String: Int] = [:]
///
mutKey = key private var mutPrecedingBigramMap: [KeyValuePair: [Megrez.Bigram]] = [:]
mutScore = 0 ///
private var mutCandidateFixed: Bool = false
mutUnigrams = unigrams ///
mutCandidates = [] private var mutSelectedUnigramIndex: Int = 0
mutValueUnigramIndexMap = [:] ///
mutPrecedingBigramMap = [:] private let kSelectedCandidateScore: Double = 99
///
mutCandidateFixed = false public var description: String {
mutSelectedUnigramIndex = 0 "(node,key:\(mutKey),fixed:\(mutCandidateFixed ? "true" : "false"),selected:\(mutSelectedUnigramIndex),\(mutUnigrams))"
if bigrams == [] {
node(key: key, unigrams: unigrams, bigrams: bigrams)
} else {
node(key: key, unigrams: unigrams)
}
} }
public func node(key: String, unigrams: [Megrez.Unigram], bigrams: [Megrez.Bigram] = []) { ///
var unigrams = unigrams var candidates: [KeyValuePair] { mutCandidates }
///
var isCandidateFixed: Bool { mutCandidateFixed }
///
var key: String { mutKey }
///
var score: Double { mutScore }
///
var currentKeyValue: KeyValuePair {
mutSelectedUnigramIndex >= mutUnigrams.count ? KeyValuePair() : mutCandidates[mutSelectedUnigramIndex]
}
///
var highestUnigramScore: Double { mutUnigrams.isEmpty ? 0.0 : mutUnigrams[0].score }
///
/// - Parameters:
/// - key:
/// - unigrams:
/// - bigrams:
public init(key: String, unigrams: [Megrez.Unigram], bigrams: [Megrez.Bigram] = []) {
mutKey = key mutKey = key
unigrams.sort { mutUnigrams = unigrams
mutBigrams = bigrams
mutUnigrams.sort {
$0.score > $1.score $0.score > $1.score
} }
if !mutUnigrams.isEmpty { for (i, gram) in mutUnigrams.enumerated() {
mutScore = mutUnigrams[0].score mutValueUnigramIndexMap[gram.keyValue.value] = i
} mutCandidates.append(gram.keyValue)
for (i, theGram) in unigrams.enumerated() {
mutValueUnigramIndexMap[theGram.keyValue.value] = i
mutCandidates.append(theGram.keyValue)
} }
for gram in bigrams { for gram in bigrams {
@ -80,11 +94,14 @@ extension Megrez {
} }
} }
///
/// - Parameters:
/// - precedingKeyValues:
public func primeNodeWith(precedingKeyValues: [KeyValuePair]) { public func primeNodeWith(precedingKeyValues: [KeyValuePair]) {
var newIndex = mutSelectedUnigramIndex var newIndex = mutSelectedUnigramIndex
var max = mutScore var max = mutScore
if !isCandidateFixed() { if !isCandidateFixed {
for neta in precedingKeyValues { for neta in precedingKeyValues {
let bigrams = mutPrecedingBigramMap[neta] ?? [] let bigrams = mutPrecedingBigramMap[neta] ?? []
for bigram in bigrams { for bigram in bigrams {
@ -107,16 +124,17 @@ extension Megrez {
} }
} }
public func isCandidateFixed() -> Bool { mutCandidateFixed } ///
/// - Parameters:
public func candidates() -> [KeyValuePair] { mutCandidates } /// - index:
/// - fix:
public func selectCandidateAt(index: Int = 0, fix: Bool = false) { public func selectCandidateAt(index: Int = 0, fix: Bool = false) {
mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index
mutCandidateFixed = fix mutCandidateFixed = fix
mutScore = kSelectedCandidateScore mutScore = kSelectedCandidateScore
} }
///
public func resetCandidate() { public func resetCandidate() {
mutSelectedUnigramIndex = 0 mutSelectedUnigramIndex = 0
mutCandidateFixed = false mutCandidateFixed = false
@ -125,16 +143,19 @@ extension Megrez {
} }
} }
///
/// - Parameters:
/// - index:
/// - score:
public func selectFloatingCandidateAt(index: Int, score: Double) { public func selectFloatingCandidateAt(index: Int, score: Double) {
mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index mutSelectedUnigramIndex = index >= mutUnigrams.count ? 0 : index
mutCandidateFixed = false mutCandidateFixed = false
mutScore = score mutScore = score
} }
public func key() -> String { mutKey } ///
/// - Parameters:
public func score() -> Double { mutScore } /// - candidate:
public func scoreFor(candidate: String) -> Double { public func scoreFor(candidate: String) -> Double {
for unigram in mutUnigrams { for unigram in mutUnigrams {
if unigram.keyValue.value == candidate { if unigram.keyValue.value == candidate {
@ -144,14 +165,6 @@ extension Megrez {
return 0.0 return 0.0
} }
public func currentKeyValue() -> KeyValuePair {
mutSelectedUnigramIndex >= mutUnigrams.count ? KeyValuePair() : mutCandidates[mutSelectedUnigramIndex]
}
public func highestUnigramScore() -> Double {
mutUnigrams.isEmpty ? 0.0 : mutUnigrams[0].score
}
public static func == (lhs: Node, rhs: Node) -> Bool { public static func == (lhs: Node, rhs: Node) -> Bool {
lhs.mutUnigrams == rhs.mutUnigrams && lhs.mutCandidates == rhs.mutCandidates lhs.mutUnigrams == rhs.mutUnigrams && lhs.mutCandidates == rhs.mutCandidates
&& lhs.mutValueUnigramIndexMap == rhs.mutValueUnigramIndexMap && lhs.mutValueUnigramIndexMap == rhs.mutValueUnigramIndexMap

View File

@ -24,19 +24,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
// 使 /// 使
// Swift
open class LanguageModel { open class LanguageModel {
public init() {} public init() {}
// Swift
///
open func unigramsFor(key: String) -> [Megrez.Unigram] { open func unigramsFor(key: String) -> [Megrez.Unigram] {
key.isEmpty ? [Megrez.Unigram]() : [Megrez.Unigram]() key.isEmpty ? [Megrez.Unigram]() : [Megrez.Unigram]()
} }
///
open func bigramsForKeys(precedingKey: String, key: String) -> [Megrez.Bigram] { open func bigramsForKeys(precedingKey: String, key: String) -> [Megrez.Bigram] {
precedingKey == key ? [Megrez.Bigram]() : [Megrez.Bigram]() precedingKey == key ? [Megrez.Bigram]() : [Megrez.Bigram]()
} }
///
open func hasUnigramsFor(key: String) -> Bool { open func hasUnigramsFor(key: String) -> Bool {
key.count != 0 key.count != 0
} }

View File

@ -24,17 +24,28 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
@frozen public struct Bigram: Equatable { ///
@frozen public struct Bigram: Equatable, CustomStringConvertible {
///
public var keyValue: KeyValuePair public var keyValue: KeyValuePair
///
public var precedingKeyValue: KeyValuePair public var precedingKeyValue: KeyValuePair
///
public var score: Double public var score: Double
// var paired: String ///
public var description: String {
"(" + keyValue.description + "|" + precedingKeyValue.description + "," + String(score) + ")"
}
///
/// - Parameters:
/// - precedingKeyValue:
/// - keyValue:
/// - score:
public init(precedingKeyValue: KeyValuePair, keyValue: KeyValuePair, score: Double) { public init(precedingKeyValue: KeyValuePair, keyValue: KeyValuePair, score: Double) {
self.keyValue = keyValue self.keyValue = keyValue
self.precedingKeyValue = precedingKeyValue self.precedingKeyValue = precedingKeyValue
self.score = score self.score = score
// paired = "(" + keyValue.paired + "|" + precedingKeyValue.paired + "," + String(score) + ")"
} }
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
@ -44,16 +55,6 @@ extension Megrez {
// hasher.combine(paired) // hasher.combine(paired)
} }
// static func getPairedBigrams(grams: [Bigram]) -> String {
// var arrOutputContent = [""]
// var index = 0
// for gram in grams {
// arrOutputContent.append(contentsOf: [String(index) + "=>" + gram.paired])
// index += 1
// }
// return "[" + String(grams.count) + "]=>{" + arrOutputContent.joined(separator: ",") + "}"
// }
public static func == (lhs: Bigram, rhs: Bigram) -> Bool { public static func == (lhs: Bigram, rhs: Bigram) -> Bool {
lhs.precedingKeyValue == rhs.precedingKeyValue && lhs.keyValue == rhs.keyValue && lhs.score == rhs.score lhs.precedingKeyValue == rhs.precedingKeyValue && lhs.keyValue == rhs.keyValue && lhs.score == rhs.score
} }
@ -62,13 +63,18 @@ extension Megrez {
lhs.precedingKeyValue < rhs.precedingKeyValue lhs.precedingKeyValue < rhs.precedingKeyValue
|| (lhs.keyValue < rhs.keyValue || (lhs.keyValue == rhs.keyValue && lhs.keyValue < rhs.keyValue)) || (lhs.keyValue < rhs.keyValue || (lhs.keyValue == rhs.keyValue && lhs.keyValue < rhs.keyValue))
} }
}
var description: String { }
"\(keyValue):\(score)"
} // MARK: - DumpDOT-related functions.
var debugDescription: String { extension Array where Element == Megrez.Bigram {
"Bigram(keyValue: \(keyValue), score: \(score))" ///
} public var description: String {
var arrOutputContent = [""]
for (index, gram) in enumerated() {
arrOutputContent.append(contentsOf: [String(index) + "=>" + gram.description])
}
return "[" + String(count) + "]=>{" + arrOutputContent.joined(separator: ",") + "}"
} }
} }

View File

@ -24,21 +24,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
@frozen public struct Unigram: Equatable { ///
@frozen public struct Unigram: Equatable, CustomStringConvertible {
///
public var keyValue: KeyValuePair public var keyValue: KeyValuePair
///
public var score: Double public var score: Double
// var paired: String ///
public var description: String {
"(" + keyValue.description + "," + String(score) + ")"
}
///
/// - Parameters:
/// - keyValue:
/// - score:
public init(keyValue: KeyValuePair, score: Double) { public init(keyValue: KeyValuePair, score: Double) {
self.keyValue = keyValue self.keyValue = keyValue
self.score = score self.score = score
// paired = "(" + keyValue.paired + "," + String(score) + ")"
} }
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
hasher.combine(keyValue) hasher.combine(keyValue)
hasher.combine(score) hasher.combine(score)
// hasher.combine(paired)
} }
// //
@ -46,16 +54,6 @@ extension Megrez {
a.score > b.score a.score > b.score
} }
// static func getPairedUnigrams(grams: [Unigram]) -> String {
// var arrOutputContent = [""]
// var index = 0
// for gram in grams {
// arrOutputContent.append(contentsOf: [String(index) + "=>" + gram.paired])
// index += 1
// }
// return "[" + String(grams.count) + "]=>{" + arrOutputContent.joined(separator: ",") + "}"
// }
public static func == (lhs: Unigram, rhs: Unigram) -> Bool { public static func == (lhs: Unigram, rhs: Unigram) -> Bool {
lhs.keyValue == rhs.keyValue && lhs.score == rhs.score lhs.keyValue == rhs.keyValue && lhs.score == rhs.score
} }
@ -63,13 +61,18 @@ extension Megrez {
public static func < (lhs: Unigram, rhs: Unigram) -> Bool { public static func < (lhs: Unigram, rhs: Unigram) -> Bool {
lhs.keyValue < rhs.keyValue || (lhs.keyValue == rhs.keyValue && lhs.keyValue < rhs.keyValue) lhs.keyValue < rhs.keyValue || (lhs.keyValue == rhs.keyValue && lhs.keyValue < rhs.keyValue)
} }
}
var description: String { }
"\(keyValue):\(score)"
} // MARK: - DumpDOT-related functions.
var debugDescription: String { extension Array where Element == Megrez.Unigram {
"Unigram(keyValue: \(keyValue), score: \(score))" ///
} public var description: String {
var arrOutputContent = [""]
for (index, gram) in enumerated() {
arrOutputContent.append(contentsOf: [String(index) + "=>" + gram.description])
}
return "[" + String(count) + "]=>{" + arrOutputContent.joined(separator: ",") + "}"
} }
} }

View File

@ -24,21 +24,29 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
extension Megrez { extension Megrez {
@frozen public struct KeyValuePair: Equatable, Hashable, Comparable { ///
@frozen public struct KeyValuePair: Equatable, Hashable, Comparable, CustomStringConvertible {
///
public var key: String public var key: String
///
public var value: String public var value: String
// public var paired: String ///
public var description: String {
"(" + key + "," + value + ")"
}
///
/// - Parameters:
/// - key:
/// - value:
public init(key: String = "", value: String = "") { public init(key: String = "", value: String = "") {
self.key = key self.key = key
self.value = value self.value = value
// paired = "(" + key + "," + value + ")"
} }
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
hasher.combine(key) hasher.combine(key)
hasher.combine(value) hasher.combine(value)
// hasher.combine(paired)
} }
public static func == (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool { public static func == (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
@ -60,13 +68,5 @@ extension Megrez {
public static func >= (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool { public static func >= (lhs: KeyValuePair, rhs: KeyValuePair) -> Bool {
(lhs.key.count >= rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value >= rhs.value) (lhs.key.count >= rhs.key.count) || (lhs.key.count == rhs.key.count && lhs.value >= rhs.value)
} }
public var description: String {
"(\(key), \(value))"
}
public var debugDescription: String {
"KeyValuePair(key: \(key), value: \(value))"
}
} }
} }

View File

@ -109,7 +109,7 @@
"Debug Mode" = "Debug Mode"; "Debug Mode" = "Debug Mode";
"Dictionary" = "Dictionary"; "Dictionary" = "Dictionary";
"Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode";
"Enable CNS11643 Support (2022-01-27)" = "Enable CNS11643 Support (2022-01-27)"; "Enable CNS11643 Support (2022-04-27)" = "Enable CNS11643 Support (2022-04-27)";
"Enable Space key for calling candidate window" = "Enable Space key for calling candidate window"; "Enable Space key for calling candidate window" = "Enable Space key for calling candidate window";
"Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)"; "Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)";
"English" = "English"; "English" = "English";

View File

@ -109,7 +109,7 @@
"Debug Mode" = "Debug Mode"; "Debug Mode" = "Debug Mode";
"Dictionary" = "Dictionary"; "Dictionary" = "Dictionary";
"Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode";
"Enable CNS11643 Support (2022-01-27)" = "Enable CNS11643 Support (2022-01-27)"; "Enable CNS11643 Support (2022-04-27)" = "Enable CNS11643 Support (2022-04-27)";
"Enable Space key for calling candidate window" = "Enable Space key for calling candidate window"; "Enable Space key for calling candidate window" = "Enable Space key for calling candidate window";
"Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)"; "Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)";
"English" = "English"; "English" = "English";

View File

@ -109,7 +109,7 @@
"Debug Mode" = "欠陥辿着モード"; "Debug Mode" = "欠陥辿着モード";
"Dictionary" = "辞書設定"; "Dictionary" = "辞書設定";
"Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード"; "Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード";
"Enable CNS11643 Support (2022-01-27)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-01-07)"; "Enable CNS11643 Support (2022-04-27)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-04-27)";
"Enable Space key for calling candidate window" = "Space キーで入力候補を呼び出す"; "Enable Space key for calling candidate window" = "Space キーで入力候補を呼び出す";
"Enable symbol input support (incl. certain emoji symbols)" = "僅かなる絵文字も含む符号入力サポートを起用"; "Enable symbol input support (incl. certain emoji symbols)" = "僅かなる絵文字も含む符号入力サポートを起用";
"English" = "英語"; "English" = "英語";

View File

@ -105,11 +105,11 @@
"Choose your preferred layout of the candidate window." = "选择您所偏好的候选字窗布局。"; "Choose your preferred layout of the candidate window." = "选择您所偏好的候选字窗布局。";
"Cursor Selection:" = "选字游标:"; "Cursor Selection:" = "选字游标:";
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微软标准/王安/零壹/仲鼎/国乔)"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微软标准/王安/零壹/仲鼎/国乔)";
"Dachen 26 (libChewing)" = "酷音大千二十六键"; "Dachen 26 (libChewing)" = "酷音大千二十六键排列";
"Debug Mode" = "侦错模式"; "Debug Mode" = "侦错模式";
"Dictionary" = "辞典"; "Dictionary" = "辞典";
"Emulating select-candidate-per-character mode" = "模拟 90 年代前期注音逐字选字输入风格"; "Emulating select-candidate-per-character mode" = "模拟 90 年代前期注音逐字选字输入风格";
"Enable CNS11643 Support (2022-01-27)" = "启用 CNS11643 全字库支援 (2022-01-07)"; "Enable CNS11643 Support (2022-04-27)" = "启用 CNS11643 全字库支援 (2022-04-27)";
"Enable Space key for calling candidate window" = "敲空格键以呼出候选字窗"; "Enable Space key for calling candidate window" = "敲空格键以呼出候选字窗";
"Enable symbol input support (incl. certain emoji symbols)" = "启用包括少许绘文字在内的符号输入支援"; "Enable symbol input support (incl. certain emoji symbols)" = "启用包括少许绘文字在内的符号输入支援";
"English" = "英语"; "English" = "英语";

View File

@ -105,11 +105,11 @@
"Choose your preferred layout of the candidate window." = "選擇您所偏好的候選字窗佈局。"; "Choose your preferred layout of the candidate window." = "選擇您所偏好的候選字窗佈局。";
"Cursor Selection:" = "選字游標:"; "Cursor Selection:" = "選字游標:";
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微軟標準/王安/零壹/仲鼎/國喬)"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微軟標準/王安/零壹/仲鼎/國喬)";
"Dachen 26 (libChewing)" = "酷音大千二十六鍵"; "Dachen 26 (libChewing)" = "酷音大千二十六鍵排列";
"Debug Mode" = "偵錯模式"; "Debug Mode" = "偵錯模式";
"Dictionary" = "辭典"; "Dictionary" = "辭典";
"Emulating select-candidate-per-character mode" = "模擬 90 年代前期注音逐字選字輸入風格"; "Emulating select-candidate-per-character mode" = "模擬 90 年代前期注音逐字選字輸入風格";
"Enable CNS11643 Support (2022-01-27)" = "啟用 CNS11643 全字庫支援 (2022-01-07)"; "Enable CNS11643 Support (2022-04-27)" = "啟用 CNS11643 全字庫支援 (2022-04-27)";
"Enable Space key for calling candidate window" = "敲空格鍵以呼出候選字窗"; "Enable Space key for calling candidate window" = "敲空格鍵以呼出候選字窗";
"Enable symbol input support (incl. certain emoji symbols)" = "啟用包括少許繪文字在內的符號輸入支援"; "Enable symbol input support (incl. certain emoji symbols)" = "啟用包括少許繪文字在內的符號輸入支援";
"English" = "英語"; "English" = "英語";

View File

@ -113,7 +113,7 @@ struct suiPrefPaneDictionary: View {
mgrPrefs.shouldAutoReloadUserDataFiles = value mgrPrefs.shouldAutoReloadUserDataFiles = value
} }
Divider() Divider()
Toggle(LocalizedStringKey("Enable CNS11643 Support (2022-01-27)"), isOn: $selEnableCNS11643) Toggle(LocalizedStringKey("Enable CNS11643 Support (2022-04-27)"), isOn: $selEnableCNS11643)
.onChange(of: selEnableCNS11643) { value in .onChange(of: selEnableCNS11643) { value in
mgrPrefs.cns11643Enabled = value mgrPrefs.cns11643Enabled = value
mgrLangModel.setCNSEnabled(value) mgrLangModel.setCNSEnabled(value)

View File

@ -682,7 +682,7 @@
<constraints> <constraints>
<constraint firstAttribute="height" constant="16" id="KdE-Vd-Y50"/> <constraint firstAttribute="height" constant="16" id="KdE-Vd-Y50"/>
</constraints> </constraints>
<buttonCell key="cell" type="check" title="Enable CNS11643 Support (2022-01-07)" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="W24-T4-cg0"> <buttonCell key="cell" type="check" title="Enable CNS11643 Support (2022-04-27)" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="W24-T4-cg0">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="cellTitle"/> <font key="font" metaFont="cellTitle"/>
</buttonCell> </buttonCell>

View File

@ -152,8 +152,8 @@
/* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */ /* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */
"Uyz-xL-TVN.title" = "Output Settings"; "Uyz-xL-TVN.title" = "Output Settings";
/* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-01-07)"; ObjectID = "W24-T4-cg0"; */ /* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-04-27)"; ObjectID = "W24-T4-cg0"; */
"W24-T4-cg0.title" = "Enable CNS11643 Support (2022-01-07)"; "W24-T4-cg0.title" = "Enable CNS11643 Support (2022-04-27)";
/* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */ /* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */
"Wvt-HE-LOv.title" = "Keyboard Layout"; "Wvt-HE-LOv.title" = "Keyboard Layout";

View File

@ -152,8 +152,8 @@
/* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */ /* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */
"Uyz-xL-TVN.title" = "出力設定"; "Uyz-xL-TVN.title" = "出力設定";
/* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-01-07)"; ObjectID = "W24-T4-cg0"; */ /* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-04-27)"; ObjectID = "W24-T4-cg0"; */
"W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-01-07)"; "W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-04-27)";
/* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */ /* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */
"Wvt-HE-LOv.title" = "キーボード"; "Wvt-HE-LOv.title" = "キーボード";

View File

@ -152,8 +152,8 @@
/* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */ /* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */
"Uyz-xL-TVN.title" = "输出设定"; "Uyz-xL-TVN.title" = "输出设定";
/* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-01-07)"; ObjectID = "W24-T4-cg0"; */ /* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-04-27)"; ObjectID = "W24-T4-cg0"; */
"W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-01-07)"; "W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-04-27)";
/* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */ /* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */
"Wvt-HE-LOv.title" = "键盘布局"; "Wvt-HE-LOv.title" = "键盘布局";

View File

@ -152,8 +152,8 @@
/* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */ /* Class = "NSBox"; title = "Output Settings"; ObjectID = "Uyz-xL-TVN"; */
"Uyz-xL-TVN.title" = "輸出設定"; "Uyz-xL-TVN.title" = "輸出設定";
/* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-01-07)"; ObjectID = "W24-T4-cg0"; */ /* Class = "NSButtonCell"; title = "Enable CNS11643 Support (2022-04-27)"; ObjectID = "W24-T4-cg0"; */
"W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-01-07)"; "W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-04-27)";
/* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */ /* Class = "NSBox"; title = "Keyboard Layout"; ObjectID = "Wvt-HE-LOv"; */
"Wvt-HE-LOv.title" = "鍵盤佈局"; "Wvt-HE-LOv.title" = "鍵盤佈局";

View File

@ -3,9 +3,9 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.5.9</string> <string>1.6.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1959</string> <string>1960</string>
<key>UpdateInfoEndpoint</key> <key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string> <string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key> <key>UpdateInfoSite</key>

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key> <key>USE_HFS+_COMPRESSION</key>
<false/> <false/>
<key>VERSION</key> <key>VERSION</key>
<string>1.5.9</string> <string>1.6.0</string>
</dict> </dict>
<key>TYPE</key> <key>TYPE</key>
<integer>0</integer> <integer>0</integer>

View File

@ -20,7 +20,6 @@
5B38F59D281E2E49007D5F5D /* 4_Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1A15FC0EB100ABF4B3 /* 4_Node.swift */; }; 5B38F59D281E2E49007D5F5D /* 4_Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1A15FC0EB100ABF4B3 /* 4_Node.swift */; };
5B38F59E281E2E49007D5F5D /* 6_Bigram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1415FC0EB100ABF4B3 /* 6_Bigram.swift */; }; 5B38F59E281E2E49007D5F5D /* 6_Bigram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1415FC0EB100ABF4B3 /* 6_Bigram.swift */; };
5B38F59F281E2E49007D5F5D /* 3_NodeAnchor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */; }; 5B38F59F281E2E49007D5F5D /* 3_NodeAnchor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */; };
5B38F5A0281E2E49007D5F5D /* 1_Walker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1E15FC0EB100ABF4B3 /* 1_Walker.swift */; };
5B38F5A1281E2E49007D5F5D /* 1_BlockReadingBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1515FC0EB100ABF4B3 /* 1_BlockReadingBuilder.swift */; }; 5B38F5A1281E2E49007D5F5D /* 1_BlockReadingBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4F1515FC0EB100ABF4B3 /* 1_BlockReadingBuilder.swift */; };
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 */; };
@ -107,7 +106,7 @@
6ACA41FD15FC1D9000935EF6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6ACA41F015FC1D9000935EF6 /* MainMenu.xib */; }; 6ACA41FD15FC1D9000935EF6 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6ACA41F015FC1D9000935EF6 /* MainMenu.xib */; };
6ACA420215FC1E5200935EF6 /* vChewing.app in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */; }; 6ACA420215FC1E5200935EF6 /* vChewing.app in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */; };
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; }; D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; };
D456576E279E4F7B00DF6BC9 /* InputHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* InputHandler.swift */; }; D456576E279E4F7B00DF6BC9 /* InputSignal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* InputSignal.swift */; };
D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; }; D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; };
D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; }; D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; };
D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */; }; D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */; };
@ -300,7 +299,6 @@
6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_NodeAnchor.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_NodeAnchor.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_Span.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 3_Span.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
6A0D4F1D15FC0EB100ABF4B3 /* 6_Unigram.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 6_Unigram.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 6A0D4F1D15FC0EB100ABF4B3 /* 6_Unigram.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 6_Unigram.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
6A0D4F1E15FC0EB100ABF4B3 /* 1_Walker.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = 1_Walker.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
6A15B32421A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; }; 6A15B32421A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
6A15B32521A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; }; 6A15B32521A51F2300B92CD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
6A225A1E23679F2600F685C6 /* NotarizedArchives */ = {isa = PBXFileReference; lastKnownFileType = folder; path = NotarizedArchives; sourceTree = "<group>"; }; 6A225A1E23679F2600F685C6 /* NotarizedArchives */ = {isa = PBXFileReference; lastKnownFileType = folder; path = NotarizedArchives; sourceTree = "<group>"; };
@ -313,7 +311,7 @@
6ACA41F315FC1D9000935EF6 /* Installer-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Installer-Prefix.pch"; path = "Installer/Installer-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 6ACA41F315FC1D9000935EF6 /* Installer-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Installer-Prefix.pch"; path = "Installer/Installer-Prefix.pch"; sourceTree = SOURCE_ROOT; };
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; }; D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D427F76B278CA1BA004A2160 /* AppDelegate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D456576D279E4F7B00DF6BC9 /* InputHandler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputHandler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D456576D279E4F7B00DF6BC9 /* InputSignal.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputSignal.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputState.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = InputState.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
@ -413,7 +411,7 @@
5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */, 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */,
D4E569DA27A34CC100AC2CEF /* CTools.h */, D4E569DA27A34CC100AC2CEF /* CTools.h */,
D4E569DB27A34CC100AC2CEF /* CTools.m */, D4E569DB27A34CC100AC2CEF /* CTools.m */,
D456576D279E4F7B00DF6BC9 /* InputHandler.swift */, D456576D279E4F7B00DF6BC9 /* InputSignal.swift */,
D461B791279DAC010070E734 /* InputState.swift */, D461B791279DAC010070E734 /* InputState.swift */,
5BD0113C2818543900609769 /* KeyHandler_Core.swift */, 5BD0113C2818543900609769 /* KeyHandler_Core.swift */,
5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */, 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */,
@ -769,7 +767,6 @@
children = ( children = (
6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */, 6A0D4F1615FC0EB100ABF4B3 /* 0_Megrez.swift */,
6A0D4F1515FC0EB100ABF4B3 /* 1_BlockReadingBuilder.swift */, 6A0D4F1515FC0EB100ABF4B3 /* 1_BlockReadingBuilder.swift */,
6A0D4F1E15FC0EB100ABF4B3 /* 1_Walker.swift */,
6A0D4F1715FC0EB100ABF4B3 /* 2_Grid.swift */, 6A0D4F1715FC0EB100ABF4B3 /* 2_Grid.swift */,
6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */, 6A0D4F1B15FC0EB100ABF4B3 /* 3_NodeAnchor.swift */,
6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */, 6A0D4F1C15FC0EB100ABF4B3 /* 3_Span.swift */,
@ -1054,7 +1051,7 @@
D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */, D47F7DD0278C0897002F9DD7 /* ctlNonModalAlertWindow.swift in Sources */,
5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */, 5B38F5A2281E2E49007D5F5D /* 0_Megrez.swift in Sources */,
5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */, 5B949BD92816DC5400D87B5D /* LineReader.swift in Sources */,
D456576E279E4F7B00DF6BC9 /* InputHandler.swift in Sources */, D456576E279E4F7B00DF6BC9 /* InputSignal.swift in Sources */,
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */, 5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */, 5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */, 5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
@ -1086,7 +1083,6 @@
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */, 5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */, 5B61B0CA280BEFD4002E3CFA /* KeyHandler_Misc.swift in Sources */,
5B38F59A281E2E49007D5F5D /* 6_Unigram.swift in Sources */, 5B38F59A281E2E49007D5F5D /* 6_Unigram.swift in Sources */,
5B38F5A0281E2E49007D5F5D /* 1_Walker.swift in Sources */,
5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */, 5B62A34827AE7CD900A19448 /* ctlCandidateVertical.swift in Sources */,
5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */, 5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */,
5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */, 5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */,
@ -1296,7 +1292,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
@ -1319,7 +1315,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1352,7 +1348,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1371,7 +1367,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1486,7 +1482,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1521,7 +1517,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1553,7 +1549,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1583,7 +1579,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -1666,7 +1662,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
@ -1691,7 +1687,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1718,7 +1714,7 @@
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1959; CURRENT_PROJECT_VERSION = 1960;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1738,7 +1734,7 @@
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MACOSX_DEPLOYMENT_TARGET = 10.11.5; MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.5.9; MARKETING_VERSION = 1.6.0;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";