diff --git a/Source/Data b/Source/Data index 91a12bb5..94b215d4 160000 --- a/Source/Data +++ b/Source/Data @@ -1 +1 @@ -Subproject commit 91a12bb5a355b56456beceec42cb001dea036b2b +Subproject commit 94b215d444e1c43e81ad173e9c28e6769f74c330 diff --git a/Source/Modules/ControllerModules/InputSignal.swift b/Source/Modules/ControllerModules/InputSignal.swift index 4bf8309a..621475d4 100644 --- a/Source/Modules/ControllerModules/InputSignal.swift +++ b/Source/Modules/ControllerModules/InputSignal.swift @@ -34,7 +34,7 @@ enum KeyCode: UInt16 { case kCarriageReturn = 36 // Renamed from "kReturn" to avoid nomenclatural confusions. case kTab = 48 case kSpace = 49 - case kSymbolMenuPhysicalKey = 50 // vChewing Specific + case kSymbolMenuPhysicalKeyIntl = 50 // vChewing Specific (Non-JIS) case kBackSpace = 51 // Renamed from "kDelete" to avoid nomenclatural confusions. case kEscape = 53 case kCommand = 55 @@ -54,6 +54,7 @@ enum KeyCode: UInt16 { case kF18 = 79 case kF19 = 80 case kF20 = 90 + case kSymbolMenuPhysicalKeyJIS = 94 // vChewing Specific (JIS) case kF5 = 96 case kF6 = 97 case kF7 = 98 @@ -109,6 +110,11 @@ enum KeyCodeBlackListed: UInt16 { case kF1 = 122 } +/// 數字小鍵盤區域的按鍵的 KeyCode。 +/// +/// 注意:第 95 號 Key Code(逗號)為 JIS 佈局特有的數字小鍵盤按鍵。 +let arrNumpadKeyCodes: [UInt16] = [65, 67, 69, 71, 75, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 95] + // CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html enum CharCode: UInt16 { case yajuusenpaiA = 114 @@ -255,6 +261,11 @@ struct InputSignal: CustomStringConvertible { return code.rawValue != KeyCode.kNone.rawValue } + /// 單獨用 flags 來判定數字小鍵盤輸入的方法已經失效了,所以必須再增補用 KeyCode 判定的方法。 + var isNumericPadAreaKey: Bool { + arrNumpadKeyCodes.contains(keyCode) + } + var isTab: Bool { KeyCode(rawValue: keyCode) == KeyCode.kTab } @@ -338,13 +349,13 @@ struct InputSignal: CustomStringConvertible { var isUpperCaseASCIILetterKey: Bool { // 這裡必須加上「flags == .shift」,否則會出現某些情況下輸入法「誤判當前鍵入的非 Shift 字符為大寫」的問題。 - charCode >= 65 && charCode <= 90 && flags == .shift + (65...90).contains(charCode) && flags == .shift } var isSymbolMenuPhysicalKey: Bool { // 這裡必須用 KeyCode,這樣才不會受隨 macOS 版本更動的 Apple 動態注音鍵盤排列內容的影響。 // 只是必須得與 ![input isShift] 搭配使用才可以(也就是僅判定 Shift 沒被摁下的情形)。 - KeyCode(rawValue: keyCode) == KeyCode.kSymbolMenuPhysicalKey + [KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode)) } } diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index d1147792..bc25f26d 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -188,7 +188,7 @@ class KeyHandler { // 這個過程會讓半衰引擎根據當前上下文生成三元圖索引鍵。 currentUOM.observe( walkedAnchors: walkedAnchors, cursorIndex: adjustedCursor, candidate: theCandidate.value, - timestamp: NSDate().timeIntervalSince1970 + timestamp: NSDate().timeIntervalSince1970, saveCallback: { mgrLangModel.saveUserOverrideModelData() } ) } } @@ -236,7 +236,7 @@ class KeyHandler { // 選字窗的內容的康熙轉換 / JIS 轉換不能放在這裡處理,會影響選字有效性。 // 選字的原理是拿著具體的候選字詞的字串去當前的節錨下找出對應的候選字詞(X元圖)。 // 一旦在這裡轉換了,節錨內的某些元圖就無法被選中。 - arrCandidates.append(.init(key: currentCandidate.key, value: currentCandidate.value)) + arrCandidates.append(currentCandidate) } // 決定是否根據半衰記憶模組的建議來調整候選字詞的順序。 if !mgrPrefs.fetchSuggestionsFromUserOverrideModel || mgrPrefs.useSCPCTypingMode || fixOrder { diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift index 0b512e4b..f8e6a067 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleCandidate.swift @@ -78,7 +78,12 @@ extension KeyHandler { // MARK: Enter if input.isEnter { - delegate!.keyHandler( + if state is InputState.AssociatedPhrases, !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter { + clear() + stateCallback(InputState.EmptyIgnoringPreviousState()) + return true + } + delegate?.keyHandler( self, didSelectCandidateAt: ctlCandidateCurrent.selectedCandidateIndex, ctlCandidate: ctlCandidateCurrent @@ -271,6 +276,7 @@ extension KeyHandler { } else { ctlCandidateCurrent.selectedCandidateIndex = candidates.count - 1 } + return true } } @@ -297,7 +303,7 @@ extension KeyHandler { if index != NSNotFound { let candidateIndex = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(index) if candidateIndex != Int.max { - delegate!.keyHandler( + delegate?.keyHandler( self, didSelectCandidateAt: candidateIndex, ctlCandidate: ctlCandidateCurrent ) return true @@ -337,7 +343,7 @@ extension KeyHandler { if shouldAutoSelectCandidate { let candidateIndex = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(0) if candidateIndex != Int.max { - delegate!.keyHandler( + delegate?.keyHandler( self, didSelectCandidateAt: candidateIndex, ctlCandidate: ctlCandidateCurrent diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift index 25fbf97f..c801d32f 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift @@ -108,9 +108,12 @@ extension KeyHandler { // MARK: 處理數字小鍵盤 (Numeric Pad Processing) - if input.isNumericPad { - if !input.isLeft, !input.isRight, !input.isDown, - !input.isUp, !input.isSpace, charCode.isPrintableASCII + // 這裡必須用「isNumericPadAreaKey」這個以 KeyCode 判定數字鍵區輸入的方法來鎖定按鍵範圍。 + // 不然的話,會誤傷到在主鍵盤區域的功能鍵。 + // 我們先規定允許小鍵盤區域操縱選字窗,其餘場合一律直接放行。 + if input.isNumericPadAreaKey { + if !(state is InputState.ChoosingCandidate || state is InputState.AssociatedPhrases + || state is InputState.SymbolTable) { clear() stateCallback(InputState.Empty()) @@ -184,12 +187,12 @@ extension KeyHandler { // 小麥注音因為使用 OVMandarin,所以不需要這樣補。但鐵恨引擎對所有聲調一視同仁。 composer.receiveKey(fromString: " ") } - let reading = composer.getComposition() // 拿取用來進行索引檢索用的注音。 + let readingKey = composer.getComposition() // 拿取用來進行索引檢索用的注音。 // 如果輸入法的辭典索引是漢語拼音的話,要注意上一行拿到的內容得是漢語拼音。 // 向語言模型詢問是否有對應的記錄。 - if !currentLM.hasUnigramsFor(key: reading) { - IME.prtDebugIntel("B49C0979:語彙庫內無「\(reading)」的匹配記錄。") + if !currentLM.hasUnigramsFor(key: readingKey) { + IME.prtDebugIntel("B49C0979:語彙庫內無「\(readingKey)」的匹配記錄。") errorCallback() composer.clear() // 根據「組字器是否為空」來判定回呼哪一種狀態。 @@ -198,7 +201,7 @@ extension KeyHandler { } // 將該讀音插入至組字器內的軌格當中。 - compositor.insertReading(reading) + compositor.insertReading(readingKey) // 讓組字器反爬軌格。 let textToCommit = commitOverflownCompositionAndWalk @@ -359,7 +362,8 @@ extension KeyHandler { return handleInlineCandidateRotation( state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback ) - } else if input.isExtraChooseCandidateKeyReverse { + } + if input.isExtraChooseCandidateKeyReverse { return handleInlineCandidateRotation( state: state, reverseModifier: true, stateCallback: stateCallback, errorCallback: errorCallback ) @@ -471,6 +475,17 @@ extension KeyHandler { } } + // MARK: 全形/半形空白 (Full-Width / Half-Width Space) + + /// 該功能僅可在當前組字區沒有任何內容的時候使用。 + if state is InputState.Empty { + if input.isSpace, !input.isOptionHold, !input.isFunctionKeyHold, !input.isControlHold, !input.isCommandHold { + stateCallback(InputState.Committing(textToCommit: input.isShiftHold ? " " : " ")) + } + stateCallback(InputState.Empty()) + return true + } + // MARK: - 終末處理 (Still Nothing) /// 對剩下的漏網之魚做攔截處理、直接將當前狀態繼續回呼給 ctlInputMethod。 diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index 6ed1b3e1..4bd97370 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -77,6 +77,7 @@ extension KeyHandler { /// 這裡先計算一下要用在工具提示當中的顯示參數的內容。 switch compositor.cursor { case compositor.readings.count...: + // 這裡的 compositor.cursor 數值不可能大於 readings.count,因為會被 Megrez 自動糾正。 tooltipParameterRef[0] = compositor.readings[compositor.cursor - 1] case 0: tooltipParameterRef[1] = compositor.readings[compositor.cursor] @@ -328,7 +329,7 @@ extension KeyHandler { ) if candidateState.candidates.count == 1 { clear() - if let candidateToCommit: (String, String) = candidateState.candidates.first { + if let candidateToCommit: (String, String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty { stateCallback(InputState.Committing(textToCommit: candidateToCommit.1)) stateCallback(InputState.Empty()) } else { diff --git a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift index b772cbe5..0c5f78a4 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift @@ -151,6 +151,9 @@ extension ctlInputMethod { { commit(text: previous.composingBuffer) } + // 在這裡手動再取消一次選字窗與工具提示的顯示,可謂雙重保險。 + ctlInputMethod.ctlCandidateCurrent.visible = false + ctlInputMethod.tooltipController.hide() clearInlineDisplay() } diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 1a8b9e4d..e2e0ff2b 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -59,6 +59,7 @@ struct UserDef { static let kFetchSuggestionsFromUserOverrideModel = "FetchSuggestionsFromUserOverrideModel" static let kUseFixecCandidateOrderOnSelection = "UseFixecCandidateOrderOnSelection" static let kAutoCorrectReadingCombination = "AutoCorrectReadingCombination" + static let kAlsoConfirmAssociatedCandidatesByEnter = "AlsoConfirmAssociatedCandidatesByEnter" static let kCandidateTextFontName = "CandidateTextFontName" static let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName" @@ -282,6 +283,9 @@ public enum mgrPrefs { UserDefaults.standard.setDefault( mgrPrefs.autoCorrectReadingCombination, forKey: UserDef.kAutoCorrectReadingCombination ) + UserDefaults.standard.setDefault( + mgrPrefs.alsoConfirmAssociatedCandidatesByEnter, forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter + ) UserDefaults.standard.setDefault(mgrPrefs.usingHotKeySCPC, forKey: UserDef.kUsingHotKeySCPC) UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyAssociates, forKey: UserDef.kUsingHotKeyAssociates) @@ -367,6 +371,9 @@ public enum mgrPrefs { @UserDefault(key: UserDef.kAutoCorrectReadingCombination, defaultValue: true) static var autoCorrectReadingCombination: Bool + @UserDefault(key: UserDef.kAlsoConfirmAssociatedCandidatesByEnter, defaultValue: true) + static var alsoConfirmAssociatedCandidatesByEnter: Bool + static var minCandidateLength: Int { mgrPrefs.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2 } @@ -601,6 +608,7 @@ extension mgrPrefs { UserDef.kAssociatedPhrasesEnabled, UserDef.kPhraseReplacementEnabled, UserDef.kUsingHotKeySCPC, UserDef.kUsingHotKeyAssociates, UserDef.kUsingHotKeyCNS, UserDef.kUsingHotKeyKangXi, UserDef.kUsingHotKeyJIS, UserDef.kUsingHotKeyHalfWidthASCII, UserDef.kUseFixecCandidateOrderOnSelection, + UserDef.kAutoCorrectReadingCombination, UserDef.kAlsoConfirmAssociatedCandidatesByEnter, ] } diff --git a/Source/Modules/LangModelRelated/LMInstantiator.swift b/Source/Modules/LangModelRelated/LMInstantiator.swift index 96e2bf07..21b4164d 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.swift +++ b/Source/Modules/LangModelRelated/LMInstantiator.swift @@ -248,14 +248,6 @@ extension vChewing { return !unigramsFor(key: key).isEmpty } - public func associatedPhrasesFor(key: String) -> [String] { - lmAssociates.valuesFor(key: key) - } - - public func hasAssociatedPhrasesFor(key: String) -> Bool { - lmAssociates.hasValuesFor(key: key) - } - public func associatedPhrasesFor(pair: Megrez.KeyValuePaired) -> [String] { lmAssociates.valuesFor(pair: pair) } diff --git a/Source/Modules/LangModelRelated/LMSymbolNode.swift b/Source/Modules/LangModelRelated/LMSymbolNode.swift index fa6c51f9..e7270e83 100644 --- a/Source/Modules/LangModelRelated/LMSymbolNode.swift +++ b/Source/Modules/LangModelRelated/LMSymbolNode.swift @@ -100,6 +100,7 @@ class SymbolNode { private static let defaultSymbolRoot: SymbolNode = .init( "/", [ + SymbolNode(" "), SymbolNode("`"), SymbolNode(catCommonSymbols, symbols: ",、。.?!;:‧‥﹐﹒˙·‘’“”〝〞‵′〃~$%@&#*"), SymbolNode(catHoriBrackets, symbols: "()「」〔〕{}〈〉『』《》【】﹙﹚﹝﹞﹛﹜"), diff --git a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift index e69b4935..47f15b8c 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift @@ -42,7 +42,7 @@ extension vChewing { !rangeMap.isEmpty } - internal func cnvNgramKeyFromPinyinToPhona(target: String) -> String { + internal func cnvNGramKeyFromPinyinToPhona(target: String) -> String { guard target.contains("("), target.contains(","), target.contains(")") else { return target } @@ -69,7 +69,7 @@ extension vChewing { if !theKey.isEmpty, theKey.first != "#" { for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() { if i == 0 { continue } - rangeMap[cnvNgramKeyFromPinyinToPhona(target: theKey), default: []].append(($0, i)) + rangeMap[cnvNGramKeyFromPinyinToPhona(target: theKey), default: []].append(($0, i)) } } } @@ -94,22 +94,6 @@ extension vChewing { // This function will be implemented only if further hard-necessity comes. } - public func valuesFor(key: String) -> [String] { - var pairs: [String] = [] - if let arrRangeRecords: [(Range, Int)] = rangeMap[key] { - for (netaRange, index) in arrRangeRecords { - let neta = strData[netaRange].split(separator: " ") - let theValue: String = .init(neta[index]) - pairs.append(theValue) - } - } - return pairs - } - - public func hasValuesFor(key: String) -> Bool { - rangeMap[key] != nil - } - public func valuesFor(pair: Megrez.KeyValuePaired) -> [String] { var pairs: [String] = [] if let arrRangeRecords: [(Range, Int)] = rangeMap[pair.toNGramKey] { diff --git a/Source/Modules/LangModelRelated/SubLMs/lmCoreEX.swift b/Source/Modules/LangModelRelated/SubLMs/lmCoreEX.swift index eb049aea..19ed60ad 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmCoreEX.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmCoreEX.swift @@ -51,10 +51,10 @@ extension vChewing { /// 初期化該語言模型。 /// /// - parameters: - /// - reverse: 聲明原始檔案內第一、二縱列的內容是否彼此顛倒 - /// - consolidate: 請且僅請對使用者語言模組啟用該參數:是否自動整理格式 - /// - defaultScore: 當某一筆資料內的權重資料毀損時,要施加的預設權重 - /// - forceDefaultScore: 啟用該選項的話,會強制施加預設權重、而無視原始權重資料 + /// - reverse: 聲明原始檔案內第一、二縱列的內容是否彼此顛倒。 + /// - consolidate: 請且僅請對使用者語言模組啟用該參數:是否自動整理格式。 + /// - defaultScore: 當某一筆資料內的權重資料毀損時,要施加的預設權重。 + /// - forceDefaultScore: 啟用該選項的話,會強制施加預設權重、而無視原始權重資料。 public init( reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0, forceDefaultScore: Bool = false @@ -73,7 +73,7 @@ extension vChewing { /// 將資料從檔案讀入至資料庫辭典內。 /// - parameters: - /// - path: 給定路徑 + /// - path: 給定路徑。 @discardableResult public mutating func open(_ path: String) -> Bool { if isLoaded() { return false @@ -135,8 +135,8 @@ extension vChewing { /// /// 威注音輸入法尚未引入雙元圖支援,所以該函式並未擴充相關功能,自然不會起作用。 /// - parameters: - /// - precedingKey: 前述讀音索引鍵 - /// - key: 當前讀音索引鍵 + /// - precedingKey: 前述讀音索引鍵。 + /// - key: 當前讀音索引鍵。 public func bigramsFor(precedingKey: String, key: String) -> [Megrez.Bigram] { // 這裡用了點廢話處理,不然函式構建體會被 Swift 格式整理工具給毀掉。 // 其實只要一句「[Megrez.Bigram]()」就夠了。 @@ -145,7 +145,7 @@ extension vChewing { /// 根據給定的讀音索引鍵,來獲取資料庫辭典內的對應資料陣列的字串首尾範圍資料、據此自 strData 取得字串形式的資料、生成單元圖陣列。 /// - parameters: - /// - key: 讀音索引鍵 + /// - key: 讀音索引鍵。 public func unigramsFor(key: String) -> [Megrez.Unigram] { var grams: [Megrez.Unigram] = [] if let arrRangeRecords: [Range] = rangeMap[key] { @@ -168,7 +168,7 @@ extension vChewing { /// 根據給定的讀音索引鍵來確認資料庫辭典內是否存在對應的資料。 /// - parameters: - /// - key: 讀音索引鍵 + /// - key: 讀音索引鍵。 public func hasUnigramsFor(key: String) -> Bool { rangeMap[key] != nil } diff --git a/Source/Modules/LangModelRelated/SubLMs/lmCoreNS.swift b/Source/Modules/LangModelRelated/SubLMs/lmCoreNS.swift index da250eee..6224e0ad 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmCoreNS.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmCoreNS.swift @@ -52,10 +52,10 @@ extension vChewing { /// 某些參數在 LMCoreNS 內已作廢,但仍保留、以方便那些想用該專案源碼做實驗的人群。 /// /// - parameters: - /// - reverse: 已作廢:聲明原始檔案內第一、二縱列的內容是否彼此顛倒 - /// - consolidate: 請且僅請對使用者語言模組啟用該參數:是否自動整理格式 - /// - defaultScore: 當某一筆資料內的權重資料毀損時,要施加的預設權重 - /// - forceDefaultScore: 啟用該選項的話,會強制施加預設權重、而無視原始權重資料 + /// - reverse: 已作廢:聲明原始檔案內第一、二縱列的內容是否彼此顛倒。 + /// - consolidate: 請且僅請對使用者語言模組啟用該參數:是否自動整理格式。 + /// - defaultScore: 當某一筆資料內的權重資料毀損時,要施加的預設權重。 + /// - forceDefaultScore: 啟用該選項的話,會強制施加預設權重、而無視原始權重資料。 public init( reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0, forceDefaultScore: Bool = false @@ -74,7 +74,7 @@ extension vChewing { /// 將資料從檔案讀入至資料庫辭典內。 /// - parameters: - /// - path: 給定路徑 + /// - path: 給定路徑。 @discardableResult public mutating func open(_ path: String) -> Bool { if isLoaded() { return false @@ -128,8 +128,8 @@ extension vChewing { /// /// 威注音輸入法尚未引入雙元圖支援,所以該函式並未擴充相關功能,自然不會起作用。 /// - parameters: - /// - precedingKey: 前述讀音索引鍵 - /// - key: 當前讀音索引鍵 + /// - precedingKey: 前述讀音索引鍵。 + /// - key: 當前讀音索引鍵。 public func bigramsFor(precedingKey: String, key: String) -> [Megrez.Bigram] { // 這裡用了點廢話處理,不然函式構建體會被 Swift 格式整理工具給毀掉。 // 其實只要一句「[Megrez.Bigram]()」就夠了。 @@ -138,7 +138,7 @@ extension vChewing { /// 根據給定的讀音索引鍵,來獲取資料庫辭典內的對應資料陣列的 UTF8 資料、就地分析、生成單元圖陣列。 /// - parameters: - /// - key: 讀音索引鍵 + /// - key: 讀音索引鍵。 public func unigramsFor(key: String) -> [Megrez.Unigram] { var grams: [Megrez.Unigram] = [] if let arrRangeRecords: [Data] = rangeMap[cnvPhonabetToASCII(key)] { @@ -162,7 +162,7 @@ extension vChewing { /// 根據給定的讀音索引鍵來確認資料庫辭典內是否存在對應的資料。 /// - parameters: - /// - key: 讀音索引鍵 + /// - key: 讀音索引鍵。 public func hasUnigramsFor(key: String) -> Bool { rangeMap[cnvPhonabetToASCII(key)] != nil } @@ -173,7 +173,7 @@ extension vChewing { /// /// 如果傳入的字串當中包含 ASCII 下畫線符號的話,則表明該字串並非注音讀音字串,會被忽略處理。 /// - parameters: - /// - incoming: 傳入的未加密注音讀音字串 + /// - incoming: 傳入的未加密注音讀音字串。 func cnvPhonabetToASCII(_ incoming: String) -> String { let dicPhonabet2ASCII = [ "ㄅ": "b", "ㄆ": "p", "ㄇ": "m", "ㄈ": "f", "ㄉ": "d", "ㄊ": "t", "ㄋ": "n", "ㄌ": "l", "ㄍ": "g", "ㄎ": "k", "ㄏ": "h", @@ -194,7 +194,7 @@ extension vChewing { /// /// 如果傳入的字串當中包含 ASCII 下畫線符號的話,則表明該字串並非注音讀音字串,會被忽略處理。 /// - parameters: - /// - incoming: 傳入的已加密注音讀音字串 + /// - incoming: 傳入的已加密注音讀音字串。 func restorePhonabetFromASCII(_ incoming: String) -> String { let dicPhonabet4ASCII = [ "b": "ㄅ", "p": "ㄆ", "m": "ㄇ", "f": "ㄈ", "d": "ㄉ", "t": "ㄊ", "n": "ㄋ", "l": "ㄌ", "g": "ㄍ", "k": "ㄎ", "h": "ㄏ", diff --git a/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift b/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift index e08003e4..96da627d 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift @@ -33,9 +33,11 @@ extension vChewing { var mutDecayExponent: Double var mutLRUList: [KeyObservationPair] = [] var mutLRUMap: [String: KeyObservationPair] = [:] - let kDecayThreshold: Double = 1.0 / 1_048_576.0 + let kDecayThreshold: Double = 1.0 / 1_048_576.0 // 衰減二十次之後差不多就失效了。 - public init(capacity: Int = 500, decayConstant: Double = 5400.0) { + public static let kObservedOverrideHalfLife: Double = 3600.0 * 6 // 6 小時半衰一次,能持續不到六天的記憶。 + + public init(capacity: Int = 500, decayConstant: Double = LMUserOverride.kObservedOverrideHalfLife) { mutCapacity = max(capacity, 1) // Ensures that this integer value is always > 0. mutDecayExponent = log(0.5) / decayConstant } @@ -44,7 +46,8 @@ extension vChewing { walkedAnchors: [Megrez.NodeAnchor], cursorIndex: Int, candidate: String, - timestamp: Double + timestamp: Double, + saveCallback: @escaping () -> Void ) { let key = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex) guard !key.isEmpty else { return } @@ -64,24 +67,35 @@ extension vChewing { mutLRUList.removeLast() } IME.prtDebugIntel("UOM: Observation finished with new observation: \(key)") - mgrLangModel.saveUserOverrideModelData() + saveCallback() return } + // 降低磁碟寫入次數。唯有失憶的情況下才會更新觀察且記憶。 if var theNeta = mutLRUMap[key] { - theNeta.observation.update(candidate: candidate, timestamp: timestamp) - mutLRUList.insert(theNeta, at: 0) - mutLRUMap[key] = theNeta - IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)") - mgrLangModel.saveUserOverrideModelData() + _ = suggest( + walkedAnchors: walkedAnchors, cursorIndex: cursorIndex, timestamp: timestamp, + decayCallback: { + theNeta.observation.update(candidate: candidate, timestamp: timestamp) + self.mutLRUList.insert(theNeta, at: 0) + self.mutLRUMap[key] = theNeta + IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)") + saveCallback() + } + ) } } public func suggest( walkedAnchors: [Megrez.NodeAnchor], cursorIndex: Int, - timestamp: Double + timestamp: Double, + decayCallback: @escaping () -> Void = {} ) -> [Megrez.Unigram] { let key = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex) + guard !key.isEmpty else { + IME.prtDebugIntel("UOM: Blank key generated on suggestion, aborting suggestion.") + return .init() + } let currentReadingKey = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex, readingOnly: true) guard let koPair = mutLRUMap[key] else { IME.prtDebugIntel("UOM: mutLRUMap[key] is nil, throwing blank suggestion for key: \(key).") @@ -94,6 +108,7 @@ extension vChewing { var currentHighScore = 0.0 for overrideNeta in Array(observation.overrides) { let override: Override = overrideNeta.value + let overrideScore: Double = getScore( eventCount: override.count, totalCount: observation.count, @@ -102,6 +117,16 @@ extension vChewing { lambda: mutDecayExponent ) if (0...currentHighScore).contains(overrideScore) { continue } + + let overrideDetectionScore: Double = getScore( + eventCount: override.count, + totalCount: observation.count, + eventTimestamp: override.timestamp, + timestamp: timestamp, + lambda: mutDecayExponent * 2 + ) + if (0...currentHighScore).contains(overrideDetectionScore) { decayCallback() } + let newUnigram = Megrez.Unigram( keyValue: .init(key: currentReadingKey, value: overrideNeta.key), score: overrideScore ) @@ -270,13 +295,13 @@ extension vChewing.LMUserOverride { extension vChewing.LMUserOverride { /// 自 LRU 辭典內移除所有的單元圖。 - public func bleachUnigrams() { + public func bleachUnigrams(saveCallback: @escaping () -> Void) { for key in mutLRUMap.keys { if !key.contains("(),()") { continue } mutLRUMap.removeValue(forKey: key) } resetMRUList() - mgrLangModel.saveUserOverrideModelData() + saveCallback() } internal func resetMRUList() { diff --git a/Source/Modules/LangModelRelated/mgrLangModel.swift b/Source/Modules/LangModelRelated/mgrLangModel.swift index e79eda30..ed901684 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.swift +++ b/Source/Modules/LangModelRelated/mgrLangModel.swift @@ -325,7 +325,8 @@ enum mgrLangModel { if !ensureFileExists(userPhrasesDataURL(mode), populateWithTemplate: kTemplateNameUserPhrases) || !ensureFileExists( userAssociatesDataURL(mode), - populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT) + populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT + ) || !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions) || !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements) || !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases) @@ -480,16 +481,20 @@ enum mgrLangModel { } static func saveUserOverrideModelData() { - gUserOverrideModelCHT.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHT)) - gUserOverrideModelCHS.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHS)) + DispatchQueue.main.async { + gUserOverrideModelCHT.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHT)) + } + DispatchQueue.main.async { + gUserOverrideModelCHS.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHS)) + } } static func removeUnigramsFromUserOverrideModel(_ mode: InputMode) { switch mode { case .imeModeCHS: - gUserOverrideModelCHT.bleachUnigrams() + gUserOverrideModelCHT.bleachUnigrams(saveCallback: { mgrLangModel.saveUserOverrideModelData() }) case .imeModeCHT: - gUserOverrideModelCHS.bleachUnigrams() + gUserOverrideModelCHS.bleachUnigrams(saveCallback: { mgrLangModel.saveUserOverrideModelData() }) case .imeModeNULL: break } diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index a1f1968f..bdb8adb1 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -85,6 +85,7 @@ // SwiftUI Preferences "(Shift+)Space:" = "(Shift+)Space:"; "Allow boosting / excluding a candidate of single kanji" = "Allow boosting / excluding a candidate of single kanji"; +"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection"; "Always use fixed listing order in candidate window" = "Always use fixed listing order in candidate window"; "An accomodation for elder computer users." = "An accomodation for elder computer users."; "Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)"; @@ -118,7 +119,7 @@ "Debug Mode" = "Debug Mode"; "Dictionary" = "Dictionary"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; -"Enable CNS11643 Support (2022-06-15)" = "Enable CNS11643 Support (2022-06-15)"; +"Enable CNS11643 Support (2022-07-20)" = "Enable CNS11643 Support (2022-07-20)"; "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"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index a1f1968f..bdb8adb1 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -85,6 +85,7 @@ // SwiftUI Preferences "(Shift+)Space:" = "(Shift+)Space:"; "Allow boosting / excluding a candidate of single kanji" = "Allow boosting / excluding a candidate of single kanji"; +"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection"; "Always use fixed listing order in candidate window" = "Always use fixed listing order in candidate window"; "An accomodation for elder computer users." = "An accomodation for elder computer users."; "Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)"; @@ -118,7 +119,7 @@ "Debug Mode" = "Debug Mode"; "Dictionary" = "Dictionary"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; -"Enable CNS11643 Support (2022-06-15)" = "Enable CNS11643 Support (2022-06-15)"; +"Enable CNS11643 Support (2022-07-20)" = "Enable CNS11643 Support (2022-07-20)"; "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"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index 3c77f330..b5dd73aa 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -85,6 +85,7 @@ // SwiftUI Preferences "(Shift+)Space:" = "(Shift+)Space:"; "Allow boosting / excluding a candidate of single kanji" = "即排除/即最優先にできる候補の文字数の最低限は1字とする"; +"Allow using Enter key to confirm associated candidate selection" = "Enter キーを連想語彙候補の確認のために使う"; "Always use fixed listing order in candidate window" = "候補文字を固定順番で陳列する"; "An accomodation for elder computer users." = "年配なるユーザーのために提供した機能である。"; "Apple ABC (equivalent to English US)" = "Apple ABC (Apple U.S. キーボードと同じ)"; @@ -118,7 +119,7 @@ "Debug Mode" = "欠陥辿着モード"; "Dictionary" = "辞書設定"; "Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード"; -"Enable CNS11643 Support (2022-06-15)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-06-15)"; +"Enable CNS11643 Support (2022-07-20)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-07-20)"; "Enable Space key for calling candidate window" = "Space キーで入力候補を呼び出す"; "Enable symbol input support (incl. certain emoji symbols)" = "僅かなる絵文字も含む符号入力サポートを起用"; "English" = "英語"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 653d52fa..d3520bb3 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -85,6 +85,7 @@ // SwiftUI Preferences "(Shift+)Space:" = "(Shift+)空格键:"; "Allow boosting / excluding a candidate of single kanji" = "将可以就地升权/排除的候选字词的最短词长设为单个汉字"; +"Allow using Enter key to confirm associated candidate selection" = "允许使用 Enter 确认当前选中的联想词"; "Always use fixed listing order in candidate window" = "以固定顺序来陈列选字窗内的候选字"; "An accomodation for elder computer users." = "针对年长使用者的习惯而提供。"; "Apple ABC (equivalent to English US)" = "Apple ABC (与 Apple 美规键盘等价)"; @@ -118,7 +119,7 @@ "Debug Mode" = "侦错模式"; "Dictionary" = "辞典"; "Emulating select-candidate-per-character mode" = "模拟 90 年代前期注音逐字选字输入风格"; -"Enable CNS11643 Support (2022-06-15)" = "启用 CNS11643 全字库支援 (2022-06-15)"; +"Enable CNS11643 Support (2022-07-20)" = "启用 CNS11643 全字库支援 (2022-07-20)"; "Enable Space key for calling candidate window" = "敲空格键以呼出候选字窗"; "Enable symbol input support (incl. certain emoji symbols)" = "启用包括少许绘文字在内的符号输入支援"; "English" = "英语"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index 45698072..fb3b989e 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -85,6 +85,7 @@ // SwiftUI Preferences "(Shift+)Space:" = "(Shift+)空格鍵:"; "Allow boosting / excluding a candidate of single kanji" = "將可以就地升權/排除的候選字詞的最短詞長設為單個漢字"; +"Allow using Enter key to confirm associated candidate selection" = "允許使用 Enter 確認當前選中的聯想詞"; "Always use fixed listing order in candidate window" = "以固定順序來陳列選字窗內的候選字"; "An accomodation for elder computer users." = "針對年長使用者的習慣而提供。"; "Apple ABC (equivalent to English US)" = "Apple ABC (與 Apple 美規鍵盤等價)"; @@ -118,7 +119,7 @@ "Debug Mode" = "偵錯模式"; "Dictionary" = "辭典"; "Emulating select-candidate-per-character mode" = "模擬 90 年代前期注音逐字選字輸入風格"; -"Enable CNS11643 Support (2022-06-15)" = "啟用 CNS11643 全字庫支援 (2022-06-15)"; +"Enable CNS11643 Support (2022-07-20)" = "啟用 CNS11643 全字庫支援 (2022-07-20)"; "Enable Space key for calling candidate window" = "敲空格鍵以呼出候選字窗"; "Enable symbol input support (incl. certain emoji symbols)" = "啟用包括少許繪文字在內的符號輸入支援"; "English" = "英語"; diff --git a/Source/UI/PrefUI/suiPrefPaneDictionary.swift b/Source/UI/PrefUI/suiPrefPaneDictionary.swift index acd69b3b..922b77f1 100644 --- a/Source/UI/PrefUI/suiPrefPaneDictionary.swift +++ b/Source/UI/PrefUI/suiPrefPaneDictionary.swift @@ -101,7 +101,7 @@ struct suiPrefPaneDictionary: View { return } } - } // End If self.window != nil + } } label: { Text("...") } @@ -120,7 +120,7 @@ struct suiPrefPaneDictionary: View { } Divider() Toggle( - LocalizedStringKey("Enable CNS11643 Support (2022-06-15)"), + LocalizedStringKey("Enable CNS11643 Support (2022-07-20)"), isOn: $selEnableCNS11643 ) .onChange(of: selEnableCNS11643) { value in diff --git a/Source/UI/PrefUI/suiPrefPaneExperience.swift b/Source/UI/PrefUI/suiPrefPaneExperience.swift index 43f46668..3271a587 100644 --- a/Source/UI/PrefUI/suiPrefPaneExperience.swift +++ b/Source/UI/PrefUI/suiPrefPaneExperience.swift @@ -48,6 +48,8 @@ struct suiPrefPaneExperience: View { @State private var selComposingBufferSize = UserDefaults.standard.integer(forKey: UserDef.kComposingBufferSize) @State private var selAutoCorrectReadingCombination = UserDefaults.standard.bool( forKey: UserDef.kAutoCorrectReadingCombination) + @State private var selAlsoConfirmAssociatedCandidatesByEnter = UserDefaults.standard.bool( + forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter) private let contentWidth: Double = { switch mgrPrefs.appleLanguages[0] { case "ja": @@ -180,6 +182,12 @@ struct suiPrefPaneExperience: View { } Text(LocalizedStringKey("An accomodation for elder computer users.")) .preferenceDescription() + Toggle( + LocalizedStringKey("Allow using Enter key to confirm associated candidate selection"), + isOn: $selAlsoConfirmAssociatedCandidatesByEnter + ).onChange(of: selAlsoConfirmAssociatedCandidatesByEnter) { value in + mgrPrefs.alsoConfirmAssociatedCandidatesByEnter = value + } } } } diff --git a/Source/WindowControllers/ctlAboutWindow.swift b/Source/WindowControllers/ctlAboutWindow.swift index f653e09d..47b767b0 100644 --- a/Source/WindowControllers/ctlAboutWindow.swift +++ b/Source/WindowControllers/ctlAboutWindow.swift @@ -57,8 +57,14 @@ class ctlAboutWindow: NSWindowController { ) } - @IBAction func btnWiki(_: NSButton) { - if let url = URL(string: "https://gitee.com/vchewing/vChewing-macOS/wikis") { + @IBAction func btnBugReport(_ sender: NSButton) { + if let url = URL(string: "https://vchewing.github.io/BUGREPORT.html") { + NSWorkspace.shared.open(url) + } + } + + @IBAction func btnWebsite(_ sender: NSButton) { + if let url = URL(string: "https://vchewing.github.io/") { NSWorkspace.shared.open(url) } } diff --git a/Source/WindowControllers/ctlPrefWindow.swift b/Source/WindowControllers/ctlPrefWindow.swift index d7de5183..41791725 100644 --- a/Source/WindowControllers/ctlPrefWindow.swift +++ b/Source/WindowControllers/ctlPrefWindow.swift @@ -27,9 +27,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import Carbon import Cocoa +private let kWindowTitleHeight: CGFloat = 78 + +extension NSToolbarItem.Identifier { + fileprivate static let ofGeneral = NSToolbarItem.Identifier(rawValue: "tabGeneral") + fileprivate static let ofExperience = NSToolbarItem.Identifier(rawValue: "tabExperience") + fileprivate static let ofDictionary = NSToolbarItem.Identifier(rawValue: "tabDictionary") + fileprivate static let ofKeyboard = NSToolbarItem.Identifier(rawValue: "tabKeyboard") +} + // Please note that the class should be exposed using the same class name // in Objective-C in order to let IMK to see the same class name as // the "InputMethodServerPreferencesWindowControllerClass" in Info.plist. +@objc(ctlPrefWindow) class ctlPrefWindow: NSWindowController { @IBOutlet var fontSizePopUpButton: NSPopUpButton! @IBOutlet var uiLanguageButton: NSPopUpButton! @@ -39,11 +49,34 @@ class ctlPrefWindow: NSWindowController { @IBOutlet var chkTrad2JISShinjitai: NSButton! @IBOutlet var lblCurrentlySpecifiedUserDataFolder: NSTextFieldCell! + @IBOutlet var vwrGeneral: NSView! + @IBOutlet var vwrExperience: NSView! + @IBOutlet var vwrDictionary: NSView! + @IBOutlet var vwrKeyboard: NSView! + var currentLanguageSelectItem: NSMenuItem? override func windowDidLoad() { super.windowDidLoad() + var preferencesTitleName = NSLocalizedString("vChewing Preferences…", comment: "") + preferencesTitleName.removeLast() + + let toolbar = NSToolbar(identifier: "preference toolbar") + toolbar.allowsUserCustomization = false + toolbar.autosavesConfiguration = false + toolbar.sizeMode = .default + toolbar.delegate = self + toolbar.selectedItemIdentifier = .ofGeneral + toolbar.showsBaselineSeparator = true + window?.titlebarAppearsTransparent = false + if #available(macOS 11.0, *) { + window?.toolbarStyle = .preference + } + window?.toolbar = toolbar + window?.title = preferencesTitleName + use(view: vwrGeneral) + lblCurrentlySpecifiedUserDataFolder.placeholderString = mgrLangModel.dataFolderPath( isDefaultFolder: true) @@ -254,6 +287,7 @@ class ctlPrefWindow: NSWindowController { } @IBAction func chooseUserDataFolderToSpecify(_: Any) { + guard let window = window else { return } IME.dlgOpenPath.title = NSLocalizedString( "Choose your desired user data folder.", comment: "" ) @@ -265,33 +299,136 @@ class ctlPrefWindow: NSWindowController { let bolPreviousFolderValidity = mgrLangModel.checkIfSpecifiedUserDataFolderValid( mgrPrefs.userDataFolderSpecified.expandingTildeInPath) - if window != nil { - IME.dlgOpenPath.beginSheetModal(for: window!) { result in - if result == NSApplication.ModalResponse.OK { - if IME.dlgOpenPath.url != nil { - // CommonDialog 讀入的路徑沒有結尾斜槓,這會導致檔案目錄合規性判定失準。 - // 所以要手動補回來。 - var newPath = IME.dlgOpenPath.url!.path - newPath.ensureTrailingSlash() - if mgrLangModel.checkIfSpecifiedUserDataFolderValid(newPath) { - mgrPrefs.userDataFolderSpecified = newPath - IME.initLangModels(userOnly: true) - (NSApplication.shared.delegate as! AppDelegate).updateStreamHelperPath() - } else { - clsSFX.beep() - if !bolPreviousFolderValidity { - mgrPrefs.resetSpecifiedUserDataFolder() - } - return + IME.dlgOpenPath.beginSheetModal(for: window) { result in + if result == NSApplication.ModalResponse.OK { + if IME.dlgOpenPath.url != nil { + // CommonDialog 讀入的路徑沒有結尾斜槓,這會導致檔案目錄合規性判定失準。 + // 所以要手動補回來。 + var newPath = IME.dlgOpenPath.url!.path + newPath.ensureTrailingSlash() + if mgrLangModel.checkIfSpecifiedUserDataFolderValid(newPath) { + mgrPrefs.userDataFolderSpecified = newPath + IME.initLangModels(userOnly: true) + (NSApplication.shared.delegate as! AppDelegate).updateStreamHelperPath() + } else { + clsSFX.beep() + if !bolPreviousFolderValidity { + mgrPrefs.resetSpecifiedUserDataFolder() } + return } - } else { - if !bolPreviousFolderValidity { - mgrPrefs.resetSpecifiedUserDataFolder() - } - return } + } else { + if !bolPreviousFolderValidity { + mgrPrefs.resetSpecifiedUserDataFolder() + } + return } - } // End If self.window != nil + } } // End IBAction } + +extension ctlPrefWindow: NSToolbarDelegate { + func use(view: NSView) { + guard let window = window else { + return + } + window.contentView?.subviews.first?.removeFromSuperview() + let viewFrame = view.frame + var windowRect = window.frame + windowRect.size.height = kWindowTitleHeight + viewFrame.height + windowRect.size.width = viewFrame.width + windowRect.origin.y = window.frame.maxY - (viewFrame.height + kWindowTitleHeight) + window.setFrame(windowRect, display: true, animate: true) + window.contentView?.frame = view.bounds + window.contentView?.addSubview(view) + } + + func toolbarDefaultItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { + [.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard] + } + + func toolbarAllowedItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { + [.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard] + } + + func toolbarSelectableItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { + [.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard] + } + + @objc func showGeneralView(_: Any?) { + use(view: vwrGeneral) + window?.toolbar?.selectedItemIdentifier = .ofGeneral + } + + @objc func showExperienceView(_: Any?) { + use(view: vwrExperience) + window?.toolbar?.selectedItemIdentifier = .ofExperience + } + + @objc func showDictionaryView(_: Any?) { + use(view: vwrDictionary) + window?.toolbar?.selectedItemIdentifier = .ofDictionary + } + + @objc func showKeyboardView(_: Any?) { + use(view: vwrKeyboard) + window?.toolbar?.selectedItemIdentifier = .ofKeyboard + } + + func toolbar( + _: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, + willBeInsertedIntoToolbar _: Bool + ) -> NSToolbarItem? { + let item = NSToolbarItem(itemIdentifier: itemIdentifier) + item.target = self + switch itemIdentifier { + case .ofGeneral: + let title = NSLocalizedString("General", comment: "") + item.label = title + if #available(macOS 11.0, *) { + item.image = NSImage( + systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences") + } else { + item.image = NSImage(named: NSImage.homeTemplateName) + } + item.action = #selector(showGeneralView(_:)) + + case .ofExperience: + let title = NSLocalizedString("Experience", comment: "") + item.label = title + if #available(macOS 11.0, *) { + item.image = NSImage( + systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences") + } else { + item.image = NSImage(named: NSImage.flowViewTemplateName) + } + item.action = #selector(showExperienceView(_:)) + + case .ofDictionary: + let title = NSLocalizedString("Dictionary", comment: "") + item.label = title + if #available(macOS 11.0, *) { + item.image = NSImage( + systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences") + } else { + item.image = NSImage(named: NSImage.bookmarksTemplateName) + } + item.action = #selector(showDictionaryView(_:)) + + case .ofKeyboard: + let title = NSLocalizedString("Keyboard", comment: "") + item.label = title + if #available(macOS 11.0, *) { + item.image = NSImage(systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences") + } else { + item.image = NSImage(named: NSImage.slideshowTemplateName) + } + item.action = #selector(showKeyboardView(_:)) + + default: + return nil + } + return item + } +} diff --git a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib index 78825465..5d5f6351 100644 --- a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib @@ -1,8 +1,8 @@ - + - + @@ -155,12 +155,22 @@ DQ + @@ -174,6 +184,8 @@ DQ + + @@ -190,6 +202,7 @@ DQ + diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index ef7de2c3..758a4f72 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -15,6 +15,10 @@ + + + + @@ -28,1057 +32,994 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Item 1 - Item 2 - Item 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %{value1}@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Item 1 + Item 2 + Item 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %{value1}@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings index 2bb44275..f10309f3 100644 --- a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings @@ -25,3 +25,7 @@ /* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ "lblCredits.title" = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; + +"xCD-lx-zY7.title" = "Website"; + +"7SW-k9-sId.title" = "Bug Report"; diff --git a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index a41eb394..20fce96f 100644 --- a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -20,7 +20,7 @@ "29.title" = "Candidate UI font size:"; "2iG-Ic-gbl.label" = "Dictionary"; "2pS-nv-te4.title" = "Choose which keys you prefer for selecting candidates."; -"2Y6-Am-WM1.title" = "General Settings"; +"xibGeneralSettings.title" = "General Settings"; "5.title" = "OtherViews"; "6.title" = "Microsoft, Dachen, Wang, etc."; "62u-jY-BRh.title" = "Stop farting (when typed phonetic combination is invalid, etc.)"; @@ -41,6 +41,7 @@ "BSK-bH-Gct.title" = "Auto-convert traditional Chinese glyphs to KangXi characters"; "cf2-se-PDO.title" = "Dictionary and Language Models"; "chkAllowBoostingSingleKanjiAsUserPhrase.title" = "Allow boosting / excluding a candidate of single kanji"; +"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "Allow using Enter key to confirm associated candidate selection"; "chkAutoCorrectReadingCombination.title" = "Automatically correct reading combinations when typing"; "chkFetchSuggestionsFromUserOverrideModel.title" = "Applying typing suggestions from half-life user override model"; "chkUseFixecCandidateOrderOnSelection.title" = "Always use fixed listing order in candidate window"; @@ -73,8 +74,8 @@ "sZx-18-8dO.title" = "Debug Mode"; "TXr-FF-ehw.title" = "Traditional Chinese"; "ueU-Rz-a1C.title" = "Choose the behavior of (Shift+)Tab key in the candidate window."; -"Uyz-xL-TVN.title" = "Output Settings"; -"W24-T4-cg0.title" = "Enable CNS11643 Support (2022-06-15)"; +"xibOutputSettings.title" = "Output Settings"; +"W24-T4-cg0.title" = "Enable CNS11643 Support (2022-07-20)"; "wFR-zX-M8H.title" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip"; "wN3-k3-b2a.title" = "Choose your desired user data folder path. Will be omitted if invalid."; "wQ9-px-b07.title" = "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional."; diff --git a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings index 2f25f6b2..8e97e752 100644 --- a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings @@ -25,3 +25,7 @@ /* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ "lblCredits.title" = "macOS 版威注音の開発:Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。"; + +"xCD-lx-zY7.title" = "公式HP"; + +"7SW-k9-sId.title" = "支障を報告"; diff --git a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index e14990c9..0cdb3dfc 100644 --- a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -20,7 +20,7 @@ "29.title" = "候補文字の字号:"; "2iG-Ic-gbl.label" = "辞書"; "2pS-nv-te4.title" = "お好きなる言選り用キー陣列をお選びください。"; -"2Y6-Am-WM1.title" = "全般設定"; +"xibGeneralSettings.title" = "全般設定"; "5.title" = "OtherViews"; "6.title" = "大千配列(Microsoft 標準・王安など)"; "62u-jY-BRh.title" = "マナーモード // 外すと入力間違の時に変な音が出る"; @@ -41,6 +41,7 @@ "BSK-bH-Gct.title" = "入力した繁体字を康熙字体と自動変換"; "cf2-se-PDO.title" = "辞書と言語モデル"; "chkAllowBoostingSingleKanjiAsUserPhrase.title" = "即排除/即最優先にできる候補の文字数の最低限は1字とする"; +"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "Enter キーを連想語彙候補の確認のために使う"; "chkAutoCorrectReadingCombination.title" = "入力中で打ち間違った発音組み合わせを自動的に訂正する"; "chkFetchSuggestionsFromUserOverrideModel.title" = "入力中で臨時記憶モジュールからお薦めの候補を自動的に選ぶ"; "chkUseFixecCandidateOrderOnSelection.title" = "候補文字を固定順番で陳列する"; @@ -73,8 +74,8 @@ "sZx-18-8dO.title" = "欠陥辿着モード"; "TXr-FF-ehw.title" = "繁体中国語"; "ueU-Rz-a1C.title" = "入力候補陳列での (Shift+)Tab キーの輪番切替対象をご指定ください。"; -"Uyz-xL-TVN.title" = "出力設定"; -"W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-06-15)"; +"xibOutputSettings.title" = "出力設定"; +"W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-07-20)"; "wFR-zX-M8H.title" = "弁音合併入力(入力緩衝列とヒントで音読みを漢語弁音に)"; "wN3-k3-b2a.title" = "欲しがるユーザー辞書保存先をご指定ください。無効の保存先設定は効かぬ。"; "wQ9-px-b07.title" = "Apple 動態注音キーボード (大千と倚天伝統) を使うには、共通語分析器の注音配列を大千と設定すべきである。"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings index 234a4a42..03d086a7 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings @@ -25,3 +25,7 @@ /* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ "lblCredits.title" = "威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。"; + +"xCD-lx-zY7.title" = "网站"; + +"7SW-k9-sId.title" = "故障提报"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index 930f0ec1..13328caa 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -20,7 +20,7 @@ "29.title" = "字型大小设定:"; "2iG-Ic-gbl.label" = "辞典"; "2pS-nv-te4.title" = "选择您所偏好的用来选字的按键组合。"; -"2Y6-Am-WM1.title" = "一般设定"; +"xibGeneralSettings.title" = "一般设定"; "5.title" = "OtherViews"; "6.title" = "微软/大千/王安/国乔/零壹/仲鼎"; "62u-jY-BRh.title" = "廉耻模式 // 取消勾选的话,敲错字时会有异音"; @@ -35,12 +35,13 @@ "96.title" = "18"; "98.title" = "24"; "99.title" = "32"; -"9DS-Rc-TXq.title" = "接口语言设定:"; +"9DS-Rc-TXq.title" = "界面语言设定:"; "akC-2g-ybz.title" = "简体中文"; "ArK-Vk-OoT.title" = "仿真 90 年代前期注音逐字选字输入风格"; "BSK-bH-Gct.title" = "自动将繁体中文字转换为康熙正体字"; "cf2-se-PDO.title" = "辞典&語言模型"; "chkAllowBoostingSingleKanjiAsUserPhrase.title" = "将可以就地升权/排除的候选字词的最短词长设为单个汉字"; +"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允许使用 Enter 确认当前选中的联想词"; "chkAutoCorrectReadingCombination.title" = "敲字时自动纠正读音组合"; "chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字时自动套用来自半衰记忆模组的建议"; "chkUseFixecCandidateOrderOnSelection.title" = "以固定顺序来陈列选字窗内的候选字"; @@ -73,8 +74,8 @@ "sZx-18-8dO.title" = "侦错模式"; "TXr-FF-ehw.title" = "繁体中文"; "ueU-Rz-a1C.title" = "指定 (Shift+)Tab 热键在选字窗内的轮替操作对象。"; -"Uyz-xL-TVN.title" = "输出设定"; -"W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-06-15)"; +"xibOutputSettings.title" = "输出设定"; +"W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-07-20)"; "wFR-zX-M8H.title" = "拼音并击(组字区与工具提示内显示汉语拼音)"; "wN3-k3-b2a.title" = "请在此指定您想指定的使用者语汇档案目录。无效值会被忽略。"; "wQ9-px-b07.title" = "Apple 动态注音键盘布局(大千与倚天)要求普通话/国音分析器的注音排列得配置为大千排列。"; @@ -92,4 +93,4 @@ "XqL-rf-X6d.title" = "Space 换下一页,Shift+Space 换选下一个候选字。"; "xrE-8T-WKO.label" = "进阶"; "Z9t-P0-BLF.title" = "自动检查软件更新"; -"ZEv-Q2-mYL.title" = "变更使用者接口语言,会自动重新启动输入法。"; +"ZEv-Q2-mYL.title" = "变更使用者界面语言,会自动重新启动输入法。"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings index 248929f1..ea056ee2 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings @@ -25,3 +25,7 @@ /* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ "lblCredits.title" = "威注音 macOS 程式研发:Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。"; + +"xCD-lx-zY7.title" = "網站"; + +"7SW-k9-sId.title" = "故障提報"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index c25db2ec..d3338f64 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -20,7 +20,7 @@ "29.title" = "字型大小設定:"; "2iG-Ic-gbl.label" = "辭典"; "2pS-nv-te4.title" = "選擇您所偏好的用來選字的按鍵組合。"; -"2Y6-Am-WM1.title" = "一般設定"; +"xibGeneralSettings.title" = "一般設定"; "5.title" = "OtherViews"; "6.title" = "微軟/大千/王安/國喬/零壹/仲鼎"; "62u-jY-BRh.title" = "廉恥模式 // 取消勾選的話,敲錯字時會有異音"; @@ -41,6 +41,7 @@ "BSK-bH-Gct.title" = "自動將繁體中文字轉換為康熙正體字"; "cf2-se-PDO.title" = "辭典&語言模型"; "chkAllowBoostingSingleKanjiAsUserPhrase.title" = "將可以就地升權/排除的候選字詞的最短詞長設為單個漢字"; +"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允許使用 Enter 確認當前選中的聯想詞"; "chkAutoCorrectReadingCombination.title" = "敲字時自動糾正讀音組合"; "chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字時自動套用來自半衰記憶模組的建議"; "chkUseFixecCandidateOrderOnSelection.title" = "以固定順序來陳列選字窗內的候選字"; @@ -48,7 +49,7 @@ "E1l-m8-xgb.title" = "進階設定"; "eia-1F-Do0.title" = "自動將繁體中文字轉換為日本簡化字(JIS 新字體)"; "f2j-xD-4xK.title" = "敲 ESC 鍵以清空整個輸入緩衝區"; -"f8i-69-zxm.title" = "自動重新載入變更過的使用者數據內容"; +"f8i-69-zxm.title" = "自動重新載入變更過的使用者資料內容"; "FnD-oH-El5.title" = "選字鍵:"; "FSG-lN-CJO.title" = "英文"; "FVC-br-H57.title" = "輪替候選字"; @@ -73,8 +74,8 @@ "sZx-18-8dO.title" = "偵錯模式"; "TXr-FF-ehw.title" = "繁體中文"; "ueU-Rz-a1C.title" = "指定 (Shift+)Tab 熱鍵在選字窗內的輪替操作對象。"; -"Uyz-xL-TVN.title" = "輸出設定"; -"W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-06-15)"; +"xibOutputSettings.title" = "輸出設定"; +"W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-07-20)"; "wFR-zX-M8H.title" = "拼音並擊(組字區與工具提示內顯示漢語拼音)"; "wN3-k3-b2a.title" = "請在此指定您想指定的使用者語彙檔案目錄。無效值會被忽略。"; "wQ9-px-b07.title" = "Apple 動態注音鍵盤佈局(大千與倚天)要求普通話/國音分析器的注音排列得配置為大千排列。"; diff --git a/Update-Info.plist b/Update-Info.plist index 06df0777..2c436890 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -3,9 +3,9 @@ CFBundleShortVersionString - 1.8.3 + 1.8.4 CFBundleVersion - 1983 + 1984 UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite diff --git a/UserPhraseEditor/Resources/Base.lproj/frmAboutWindow.xib b/UserPhraseEditor/Resources/Base.lproj/frmAboutWindow.xib index 19a706ea..6cea96de 100644 --- a/UserPhraseEditor/Resources/Base.lproj/frmAboutWindow.xib +++ b/UserPhraseEditor/Resources/Base.lproj/frmAboutWindow.xib @@ -157,10 +157,13 @@ DQ diff --git a/UserPhraseEditor/Resources/en.lproj/frmAboutWindow.strings b/UserPhraseEditor/Resources/en.lproj/frmAboutWindow.strings index b99c9b11..562c4a07 100644 --- a/UserPhraseEditor/Resources/en.lproj/frmAboutWindow.strings +++ b/UserPhraseEditor/Resources/en.lproj/frmAboutWindow.strings @@ -25,3 +25,5 @@ /* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */ "ttlAboutWindow.title" = "About vChewing Phrase Editor for macOS"; + +"ImH-h2-3FG.title" = "Website"; diff --git a/UserPhraseEditor/Resources/ja.lproj/frmAboutWindow.strings b/UserPhraseEditor/Resources/ja.lproj/frmAboutWindow.strings index eecfe7a2..5c8a9576 100644 --- a/UserPhraseEditor/Resources/ja.lproj/frmAboutWindow.strings +++ b/UserPhraseEditor/Resources/ja.lproj/frmAboutWindow.strings @@ -25,3 +25,5 @@ /* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */ "ttlAboutWindow.title" = "macOS 版威注音辞書データ編集アプリについて"; + +"ImH-h2-3FG.title" = "公式HP"; diff --git a/UserPhraseEditor/Resources/zh-Hans.lproj/frmAboutWindow.strings b/UserPhraseEditor/Resources/zh-Hans.lproj/frmAboutWindow.strings index d39ffa46..6f918468 100644 --- a/UserPhraseEditor/Resources/zh-Hans.lproj/frmAboutWindow.strings +++ b/UserPhraseEditor/Resources/zh-Hans.lproj/frmAboutWindow.strings @@ -25,3 +25,5 @@ /* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */ "ttlAboutWindow.title" = "关于 macOS 版「威注音语汇编辑器」"; + +"ImH-h2-3FG.title" = "网站"; diff --git a/UserPhraseEditor/Resources/zh-Hant.lproj/frmAboutWindow.strings b/UserPhraseEditor/Resources/zh-Hant.lproj/frmAboutWindow.strings index ee36f51a..1be83bd6 100644 --- a/UserPhraseEditor/Resources/zh-Hant.lproj/frmAboutWindow.strings +++ b/UserPhraseEditor/Resources/zh-Hant.lproj/frmAboutWindow.strings @@ -25,3 +25,5 @@ /* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */ "ttlAboutWindow.title" = "關於 macOS 版「威注音語彙編輯器」"; + +"ImH-h2-3FG.title" = "網站"; diff --git a/UserPhraseEditor/ctlAboutWindow.swift b/UserPhraseEditor/ctlAboutWindow.swift index c4c9fee4..e8c00e5c 100644 --- a/UserPhraseEditor/ctlAboutWindow.swift +++ b/UserPhraseEditor/ctlAboutWindow.swift @@ -57,8 +57,8 @@ import Cocoa ) } - @IBAction func btnWiki(_: NSButton) { - if let url = URL(string: "https://gitee.com/vchewing/vChewing-macOS/wikis") { + @IBAction func btnWebsite(_ sender: NSButton) { + if let url = URL(string: "https://vchewing.github.io/") { NSWorkspace.shared.open(url) } } diff --git a/vChewing.pkgproj b/vChewing.pkgproj index 7b11ff18..46430362 100644 --- a/vChewing.pkgproj +++ b/vChewing.pkgproj @@ -726,7 +726,7 @@ USE_HFS+_COMPRESSION VERSION - 1.8.3 + 1.8.4 TYPE 0 diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 5ea47912..12257b27 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1389,7 +1389,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -1399,7 +1399,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; @@ -1428,13 +1428,13 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; @@ -1465,7 +1465,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; @@ -1486,7 +1486,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1515,7 +1515,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1532,7 +1532,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1646,7 +1646,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1674,7 +1674,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1701,7 +1701,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1723,7 +1723,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1745,7 +1745,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1765,7 +1765,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1787,7 +1787,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1983; + CURRENT_PROJECT_VERSION = 1984; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1801,7 +1801,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.8.3; + MARKETING_VERSION = 1.8.4; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/vChewingTests/KeyHandlerTestsNormalCHS.swift b/vChewingTests/KeyHandlerTestsNormalCHS.swift index 15e48e11..c6e14668 100644 --- a/vChewingTests/KeyHandlerTestsNormalCHS.swift +++ b/vChewingTests/KeyHandlerTestsNormalCHS.swift @@ -337,7 +337,7 @@ class KeyHandlerTestsNormalCHS: XCTestCase { let enabled = mgrPrefs.halfWidthPunctuationEnabled mgrPrefs.halfWidthPunctuationEnabled = false let input = InputSignal( - inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: [], + inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: [], isVerticalTyping: false ) var state: InputStateProtocol = InputState.Empty() @@ -354,7 +354,7 @@ class KeyHandlerTestsNormalCHS: XCTestCase { let enabled = mgrPrefs.halfWidthPunctuationEnabled mgrPrefs.halfWidthPunctuationEnabled = false let input = InputSignal( - inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: .option, + inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: .option, isVerticalTyping: false ) var state: InputStateProtocol = InputState.Empty() diff --git a/vChewingTests/KeyHandlerTestsSCPCCHT.swift b/vChewingTests/KeyHandlerTestsSCPCCHT.swift index 5753ccd2..edcdbcbc 100644 --- a/vChewingTests/KeyHandlerTestsSCPCCHT.swift +++ b/vChewingTests/KeyHandlerTestsSCPCCHT.swift @@ -75,7 +75,7 @@ class KeyHandlerTestsSCPCCHT: XCTestCase { func testPunctuationTable() { let input = InputSignal( - inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: .option + inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: .option ) var state: InputStateProtocol = InputState.Empty() _ = handler.handle(input: input, state: state) { newState in