Pre Merge pull request !83 from ShikiSuen/upd/1.9.3
This commit is contained in:
commit
ddc55efb2d
|
@ -1 +1 @@
|
|||
Subproject commit 3cb476e7c884198fe91ce7d7ccc1ac0e082e007e
|
||||
Subproject commit b5e6f15c198f87c4cf0227bc6d9b4346e86228a0
|
|
@ -18,6 +18,7 @@ import Cocoa
|
|||
|
||||
/// KeyHandler 委任協定
|
||||
protocol KeyHandlerDelegate {
|
||||
var clientBundleIdentifier: String { get }
|
||||
func ctlCandidate() -> ctlCandidateProtocol
|
||||
func keyHandler(
|
||||
_: KeyHandler, didSelectCandidateAt index: Int,
|
||||
|
|
|
@ -347,6 +347,18 @@ extension KeyHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - Flipping pages by using symbol menu keys (when they are not occupied).
|
||||
|
||||
if input.isSymbolMenuPhysicalKey {
|
||||
let updated: Bool =
|
||||
input.isShiftHold ? ctlCandidateCurrent.showPreviousPage() : ctlCandidateCurrent.showNextPage()
|
||||
if !updated {
|
||||
IME.prtDebugIntel("66F3477B")
|
||||
errorCallback()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
IME.prtDebugIntel("172A0F81")
|
||||
errorCallback()
|
||||
return true
|
||||
|
|
|
@ -347,7 +347,7 @@ extension KeyHandler {
|
|||
composingBuffer = Tekkon.cnvPhonaToHanyuPinyin(target: composingBuffer) // 注音轉拼音
|
||||
}
|
||||
|
||||
if !IME.areWeUsingOurOwnPhraseEditor {
|
||||
if let delegate = delegate, !delegate.clientBundleIdentifier.contains("vChewingPhraseEditor") {
|
||||
composingBuffer = composingBuffer.replacingOccurrences(of: "-", with: " ")
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,16 @@ class ctlInputMethod: IMKInputController {
|
|||
/// 當前這個 ctlInputMethod 副本是否處於英數輸入模式。
|
||||
var isASCIIMode: Bool = false
|
||||
|
||||
/// 記錄當前輸入環境是縱排輸入還是橫排輸入。
|
||||
public var isVerticalTyping: Bool {
|
||||
guard let client = client() else { return false }
|
||||
var textFrame = NSRect.zero
|
||||
let attributes: [AnyHashable: Any]? = client.attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
return (attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
}
|
||||
|
||||
/// 切換當前 ctlInputMethod 副本的英數輸入模式開關。
|
||||
func toggleASCIIMode() -> Bool {
|
||||
resetKeyHandler()
|
||||
|
@ -54,7 +64,9 @@ class ctlInputMethod: IMKInputController {
|
|||
|
||||
/// 指定鍵盤佈局。
|
||||
func setKeyLayout() {
|
||||
client().overrideKeyboard(withKeyboardNamed: mgrPrefs.basicKeyboardLayout)
|
||||
if let client = client() {
|
||||
client.overrideKeyboard(withKeyboardNamed: mgrPrefs.basicKeyboardLayout)
|
||||
}
|
||||
}
|
||||
|
||||
/// 重設按鍵調度模組,會將當前尚未遞交的內容遞交出去。
|
||||
|
@ -95,23 +107,28 @@ class ctlInputMethod: IMKInputController {
|
|||
// 因為偶爾會收到與 activateServer 有關的以「強制拆 nil」為理由的報錯,
|
||||
// 所以這裡添加這句、來試圖應對這種情況。
|
||||
if keyHandler.delegate == nil { keyHandler.delegate = self }
|
||||
setValue(IME.currentInputMode.rawValue, forTag: 114_514, client: client())
|
||||
guard let client = client() else { return }
|
||||
setValue(IME.currentInputMode.rawValue, forTag: 114_514, client: client)
|
||||
keyHandler.clear() // 這句不要砍,因為後面 handle State.Empty() 不一定執行。
|
||||
keyHandler.ensureParser()
|
||||
|
||||
if isASCIIMode {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n",
|
||||
isASCIIMode
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")
|
||||
))
|
||||
if mgrPrefs.disableShiftTogglingAlphanumericalMode {
|
||||
isASCIIMode = false
|
||||
} else {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n",
|
||||
isASCIIMode
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// 必須加上下述條件,否則會在每次切換至輸入法本體的視窗(比如偏好設定視窗)時會卡死。
|
||||
/// 這是很多 macOS 副廠輸入法的常見失誤之處。
|
||||
if client().bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
if client.bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
// 強制重設當前鍵盤佈局、使其與偏好設定同步。
|
||||
setKeyLayout()
|
||||
handle(state: InputState.Empty())
|
||||
|
@ -152,7 +169,7 @@ class ctlInputMethod: IMKInputController {
|
|||
keyHandler.inputMode = newInputMode
|
||||
/// 必須加上下述條件,否則會在每次切換至輸入法本體的視窗(比如偏好設定視窗)時會卡死。
|
||||
/// 這是很多 macOS 副廠輸入法的常見失誤之處。
|
||||
if client().bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
if let client = client(), client.bundleIdentifier() != Bundle.main.bundleIdentifier {
|
||||
// 強制重設當前鍵盤佈局、使其與偏好設定同步。這裡的這一步也不能省略。
|
||||
setKeyLayout()
|
||||
handle(state: InputState.Empty())
|
||||
|
@ -189,9 +206,12 @@ class ctlInputMethod: IMKInputController {
|
|||
_ = sender // 防止格式整理工具毀掉與此對應的參數。
|
||||
|
||||
// 用 Shift 開關半形英數模式,僅對 macOS 10.15 及之後的 macOS 有效。
|
||||
let shouldUseHandle =
|
||||
(IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
|
||||
|| mgrPrefs.shouldAlwaysUseShiftKeyAccommodation)
|
||||
if #available(macOS 10.15, *) {
|
||||
if ShiftKeyUpChecker.check(event) {
|
||||
if !rencentKeyHandledByKeyHandler {
|
||||
if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode {
|
||||
if !shouldUseHandle || (!rencentKeyHandledByKeyHandler && shouldUseHandle) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n",
|
||||
|
@ -201,7 +221,9 @@ class ctlInputMethod: IMKInputController {
|
|||
)
|
||||
)
|
||||
}
|
||||
rencentKeyHandledByKeyHandler = false
|
||||
if shouldUseHandle {
|
||||
rencentKeyHandledByKeyHandler = false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -221,24 +243,7 @@ class ctlInputMethod: IMKInputController {
|
|||
// 準備修飾鍵,用來判定要新增的詞彙是否需要賦以非常低的權重。
|
||||
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
|
||||
|
||||
var textFrame = NSRect.zero
|
||||
|
||||
let attributes: [AnyHashable: Any]? = client().attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
|
||||
let isTypingVertical =
|
||||
(attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
|
||||
if client().bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
{
|
||||
IME.areWeUsingOurOwnPhraseEditor = true
|
||||
} else {
|
||||
IME.areWeUsingOurOwnPhraseEditor = false
|
||||
}
|
||||
|
||||
var input = InputSignal(event: event, isVerticalTyping: isTypingVertical)
|
||||
var input = InputSignal(event: event, isVerticalTyping: isVerticalTyping)
|
||||
input.isASCIIModeInput = isASCIIMode
|
||||
|
||||
// 無法列印的訊號輸入,一概不作處理。
|
||||
|
@ -254,7 +259,9 @@ class ctlInputMethod: IMKInputController {
|
|||
} errorCallback: {
|
||||
clsSFX.beep()
|
||||
}
|
||||
rencentKeyHandledByKeyHandler = result
|
||||
if shouldUseHandle {
|
||||
rencentKeyHandledByKeyHandler = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -267,34 +274,59 @@ class ctlInputMethod: IMKInputController {
|
|||
resetKeyHandler()
|
||||
}
|
||||
|
||||
// MARK: - IMKCandidates 功能擴充
|
||||
|
||||
/// 生成 IMK 選字窗專用的候選字串陣列。
|
||||
/// - Parameter sender: 呼叫了該函式的客體(無須使用)。
|
||||
/// - Returns: IMK 選字窗專用的候選字串陣列。
|
||||
override func candidates(_ sender: Any!) -> [Any]! {
|
||||
_ = sender // 防止格式整理工具毀掉與此對應的參數。
|
||||
var arrResult = [String]()
|
||||
// 你沒看錯,三個狀態下的處理流程都是雷同的。
|
||||
if let state = state as? InputState.AssociatedPhrases {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
for theCandidate in state.candidates {
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
if arrResult.contains(result) {
|
||||
result = "\(result)(\(theCandidate.0))"
|
||||
}
|
||||
arrResult.append(result)
|
||||
}
|
||||
} else if let state = state as? InputState.SymbolTable {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
for theCandidate in state.candidates {
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
if arrResult.contains(result) {
|
||||
result = "\(result)(\(theCandidate.0))"
|
||||
}
|
||||
arrResult.append(result)
|
||||
}
|
||||
} else if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
for theCandidate in state.candidates {
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
if arrResult.contains(result) {
|
||||
result = "\(result)(\(theCandidate.0))"
|
||||
}
|
||||
arrResult.append(result)
|
||||
}
|
||||
}
|
||||
return .init()
|
||||
return arrResult
|
||||
}
|
||||
|
||||
/// IMK 選字窗限定函式,只要選字窗內的高亮內容選擇出現變化了、就會呼叫這個函式。
|
||||
/// - Parameter _: 已經高亮選中的候選字詞內容。
|
||||
override open func candidateSelectionChanged(_: NSAttributedString!) {
|
||||
// 暫時不需要擴充這個函數。
|
||||
// 暫時不需要擴充這個函式。但有些幹話還是要講的:
|
||||
// 在這個函式當中試圖(無論是否拿著傳入的參數)從 ctlCandidateIMK 找 identifier 的話,
|
||||
// 只會找出 NSNotFound。你想 NSLog 列印看 identifier 是多少,輸入法直接崩潰。
|
||||
// 而且會他媽的崩得連 console 內的 ips 錯誤報告都沒有。
|
||||
// 在下文的 candidateSelected() 試圖看每個候選字的 identifier 的話,永遠都只能拿到 NSNotFound。
|
||||
// 衰洨 IMK 真的看上去就像是沒有做過單元測試的東西,賈伯斯有檢查過的話會被氣得從棺材裡爬出來。
|
||||
}
|
||||
|
||||
/// IMK 選字窗限定函式,只要選字窗確認了某個候選字詞的選擇、就會呼叫這個函式。
|
||||
/// - Parameter candidateString: 已經確認的候選字詞內容。
|
||||
override open func candidateSelected(_ candidateString: NSAttributedString!) {
|
||||
if state is InputState.AssociatedPhrases {
|
||||
if !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter {
|
||||
|
@ -305,28 +337,44 @@ class ctlInputMethod: IMKInputController {
|
|||
}
|
||||
|
||||
var indexDeducted = 0
|
||||
// 你沒看錯,三個狀態下的處理流程都是雷同的。
|
||||
if let state = state as? InputState.AssociatedPhrases {
|
||||
for (i, neta) in state.candidates.map(\.1).enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta)
|
||||
let netaShown = (neta == theConverted) ? neta : "\(theConverted)(\(neta))"
|
||||
for (i, neta) in state.candidates.enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta.1)
|
||||
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)(\(neta.1))"
|
||||
let netaShownWithPronunciation = "\(theConverted)(\(neta.0))"
|
||||
if candidateString.string == netaShownWithPronunciation {
|
||||
indexDeducted = i
|
||||
break
|
||||
}
|
||||
if candidateString.string == netaShown {
|
||||
indexDeducted = i
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if let state = state as? InputState.SymbolTable {
|
||||
for (i, neta) in state.candidates.map(\.1).enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta)
|
||||
let netaShown = (neta == theConverted) ? neta : "\(theConverted)(\(neta))"
|
||||
for (i, neta) in state.candidates.enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta.1)
|
||||
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)(\(neta.1))"
|
||||
let netaShownWithPronunciation = "\(theConverted)(\(neta.0))"
|
||||
if candidateString.string == netaShownWithPronunciation {
|
||||
indexDeducted = i
|
||||
break
|
||||
}
|
||||
if candidateString.string == netaShown {
|
||||
indexDeducted = i
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if let state = state as? InputState.ChoosingCandidate {
|
||||
for (i, neta) in state.candidates.map(\.1).enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta)
|
||||
let netaShown = (neta == theConverted) ? neta : "\(theConverted)(\(neta))"
|
||||
for (i, neta) in state.candidates.enumerated() {
|
||||
let theConverted = IME.kanjiConversionIfRequired(neta.1)
|
||||
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)(\(neta.1))"
|
||||
let netaShownWithPronunciation = "\(theConverted)(\(neta.0))"
|
||||
if candidateString.string == netaShownWithPronunciation {
|
||||
indexDeducted = i
|
||||
break
|
||||
}
|
||||
if candidateString.string == netaShown {
|
||||
indexDeducted = i
|
||||
break
|
||||
|
|
|
@ -13,6 +13,8 @@ import Cocoa
|
|||
// MARK: - KeyHandler Delegate
|
||||
|
||||
extension ctlInputMethod: KeyHandlerDelegate {
|
||||
var clientBundleIdentifier: String { client()?.bundleIdentifier() ?? "" }
|
||||
|
||||
func ctlCandidate() -> ctlCandidateProtocol { ctlInputMethod.ctlCandidateCurrent }
|
||||
|
||||
func keyHandler(
|
||||
|
@ -50,11 +52,20 @@ extension ctlInputMethod: KeyHandlerDelegate {
|
|||
// MARK: - Candidate Controller Delegate
|
||||
|
||||
extension ctlInputMethod: ctlCandidateDelegate {
|
||||
var isAssociatedPhrasesMode: Bool { state is InputState.AssociatedPhrases }
|
||||
|
||||
/// 與 handle() 完全雷同,但去掉了與 IMK 選字窗有關的判斷語句。
|
||||
/// 這兩個函數最好分開處理,不然 handle() 函數會陷入無限迴圈。
|
||||
/// - Parameter event: 由 IMK 選字窗接收的裝置操作輸入事件。
|
||||
/// - Returns: 回「`true`」以將該案件已攔截處理的訊息傳遞給 IMK;回「`false`」則放行、不作處理。
|
||||
func handleDelegateEvent(_ event: NSEvent!) -> Bool {
|
||||
// 用 Shift 開關半形英數模式,僅對 macOS 10.15 及之後的 macOS 有效。
|
||||
let shouldUseHandle =
|
||||
(IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
|
||||
|| mgrPrefs.shouldAlwaysUseShiftKeyAccommodation)
|
||||
if #available(macOS 10.15, *) {
|
||||
if ShiftKeyUpChecker.check(event) {
|
||||
if !rencentKeyHandledByKeyHandler {
|
||||
if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode {
|
||||
if !shouldUseHandle || (!rencentKeyHandledByKeyHandler && shouldUseHandle) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Alphanumerical Mode", comment: ""), "\n",
|
||||
|
@ -64,7 +75,9 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
)
|
||||
)
|
||||
}
|
||||
rencentKeyHandledByKeyHandler = false
|
||||
if shouldUseHandle {
|
||||
rencentKeyHandledByKeyHandler = false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -78,24 +91,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
// 準備修飾鍵,用來判定要新增的詞彙是否需要賦以非常低的權重。
|
||||
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
|
||||
|
||||
var textFrame = NSRect.zero
|
||||
|
||||
let attributes: [AnyHashable: Any]? = client().attributes(
|
||||
forCharacterIndex: 0, lineHeightRectangle: &textFrame
|
||||
)
|
||||
|
||||
let isTypingVertical =
|
||||
(attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false
|
||||
|
||||
if client().bundleIdentifier()
|
||||
== "org.atelierInmu.vChewing.vChewingPhraseEditor"
|
||||
{
|
||||
IME.areWeUsingOurOwnPhraseEditor = true
|
||||
} else {
|
||||
IME.areWeUsingOurOwnPhraseEditor = false
|
||||
}
|
||||
|
||||
var input = InputSignal(event: event, isVerticalTyping: isTypingVertical)
|
||||
var input = InputSignal(event: event, isVerticalTyping: isVerticalTyping)
|
||||
input.isASCIIModeInput = isASCIIMode
|
||||
|
||||
// 無法列印的訊號輸入,一概不作處理。
|
||||
|
@ -106,12 +102,15 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
|
||||
/// 將按鍵行為與當前輸入法狀態結合起來、交給按鍵調度模組來處理。
|
||||
/// 再根據返回的 result bool 數值來告知 IMK「這個按鍵事件是被處理了還是被放行了」。
|
||||
let result = keyHandler.handleCandidate(state: state, input: input) { newState in
|
||||
/// 這裡不用 keyHandler.handleCandidate() 是因為需要針對聯想詞輸入狀態做額外處理。
|
||||
let result = keyHandler.handle(input: input, state: state) { newState in
|
||||
self.handle(state: newState)
|
||||
} errorCallback: {
|
||||
clsSFX.beep()
|
||||
}
|
||||
rencentKeyHandledByKeyHandler = result
|
||||
if shouldUseHandle {
|
||||
rencentKeyHandledByKeyHandler = result
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,14 @@ import Foundation
|
|||
|
||||
extension ctlInputMethod {
|
||||
func show(tooltip: String, composingBuffer: String, cursorIndex: Int) {
|
||||
guard let client = client() else { return }
|
||||
var lineHeightRect = NSRect(x: 0.0, y: 0.0, width: 16.0, height: 16.0)
|
||||
var cursor = cursorIndex
|
||||
if cursor == composingBuffer.count, cursor != 0 {
|
||||
cursor -= 1
|
||||
}
|
||||
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 {
|
||||
client().attributes(
|
||||
client.attributes(
|
||||
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect
|
||||
)
|
||||
cursor -= 1
|
||||
|
@ -30,6 +31,7 @@ extension ctlInputMethod {
|
|||
}
|
||||
|
||||
func show(candidateWindowWith state: InputStateProtocol) {
|
||||
guard let client = client() else { return }
|
||||
var isTypingVertical: Bool {
|
||||
if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.isTypingVertical
|
||||
|
@ -153,7 +155,7 @@ extension ctlInputMethod {
|
|||
}
|
||||
|
||||
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 {
|
||||
client().attributes(
|
||||
client.attributes(
|
||||
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect
|
||||
)
|
||||
cursor -= 1
|
||||
|
|
|
@ -47,8 +47,9 @@ extension ctlInputMethod {
|
|||
|
||||
/// 針對受 .NotEmpty() 管轄的非空狀態,在組字區內顯示游標。
|
||||
private func setInlineDisplayWithCursor() {
|
||||
guard let client = client() else { return }
|
||||
if let state = state as? InputState.AssociatedPhrases {
|
||||
client().setMarkedText(
|
||||
client.setMarkedText(
|
||||
state.attributedString, selectionRange: NSRange(location: 0, length: 0),
|
||||
replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
|
@ -94,7 +95,7 @@ extension ctlInputMethod {
|
|||
/// 所謂選區「selectionRange」,就是「可見游標位置」的位置,只不過長度
|
||||
/// 是 0 且取代範圍(replacementRange)為「NSNotFound」罷了。
|
||||
/// 也就是說,內文組字區該在哪裡出現,得由客體軟體來作主。
|
||||
client().setMarkedText(
|
||||
client.setMarkedText(
|
||||
state.attributedString, selectionRange: NSRange(location: state.cursorIndex, length: 0),
|
||||
replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
|
@ -113,12 +114,12 @@ extension ctlInputMethod {
|
|||
/// 遞交組字區內容。
|
||||
/// 注意:必須在 IMK 的 commitComposition 函式當中也間接或者直接執行這個處理。
|
||||
private func commit(text: String) {
|
||||
guard let client = client() else { return }
|
||||
let buffer = IME.kanjiConversionIfRequired(text)
|
||||
if buffer.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
client().insertText(
|
||||
client.insertText(
|
||||
buffer, replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,18 @@ public enum IME {
|
|||
static let arrSupportedLocales = ["en", "zh-Hant", "zh-Hans", "ja"]
|
||||
static let dlgOpenPath = NSOpenPanel()
|
||||
|
||||
// MARK: - 瀏覽器 Bundle Identifier 關鍵詞匹配黑名單
|
||||
|
||||
/// 瀏覽器 Bundle Identifier 關鍵詞匹配黑名單,匹配到的瀏覽器會做出特殊的 Shift 鍵擊劍判定處理。
|
||||
static let arrClientShiftHandlingExceptionList = [
|
||||
"com.avast.browser", "com.brave.Browser", "com.brave.Browser.beta", "com.coccoc.Coccoc", "com.fenrir-inc.Sleipnir",
|
||||
"com.google.Chrome", "com.google.Chrome.beta", "com.google.Chrome.canary", "com.hiddenreflex.Epic",
|
||||
"com.maxthon.Maxthon", "com.microsoft.edgemac", "com.microsoft.edgemac.Canary", "com.microsoft.edgemac.Dev",
|
||||
"com.naver.Whale", "com.operasoftware.Opera", "com.valvesoftware.steam", "com.vivaldi.Vivaldi",
|
||||
"net.qihoo.360browser", "org.blisk.Blisk", "org.chromium.Chromium", "org.qt-project.Qt.QtWebEngineCore",
|
||||
"ru.yandex.desktop.yandex-browser",
|
||||
]
|
||||
|
||||
// MARK: - 輸入法的當前的簡繁體中文模式是?
|
||||
|
||||
static var currentInputMode: InputMode = .init(rawValue: mgrPrefs.mostRecentInputMode) ?? .imeModeNULL
|
||||
|
@ -40,10 +52,6 @@ public enum IME {
|
|||
return text
|
||||
}
|
||||
|
||||
// MARK: - 開關判定當前應用究竟是?
|
||||
|
||||
static var areWeUsingOurOwnPhraseEditor: Bool = false
|
||||
|
||||
// MARK: - 自 ctlInputMethod 讀取當前輸入法的簡繁體模式
|
||||
|
||||
static func getInputMode(isReversed: Bool = false) -> InputMode {
|
||||
|
|
|
@ -49,8 +49,11 @@ public enum UserDef: String, CaseIterable {
|
|||
case kKeepReadingUponCompositionError = "KeepReadingUponCompositionError"
|
||||
case kTogglingAlphanumericalModeWithLShift = "TogglingAlphanumericalModeWithLShift"
|
||||
case kUpperCaseLetterKeyBehavior = "UpperCaseLetterKeyBehavior"
|
||||
|
||||
case kUseIMKCandidateWindow = "UseIMKCandidateWindow"
|
||||
case kHandleDefaultCandidateFontsByLangIdentifier = "HandleDefaultCandidateFontsByLangIdentifier"
|
||||
case kShouldAlwaysUseShiftKeyAccommodation = "ShouldAlwaysUseShiftKeyAccommodation"
|
||||
case kDisableShiftTogglingAlphanumericalMode = "DisableShiftTogglingAlphanumericalMode"
|
||||
|
||||
case kCandidateTextFontName = "CandidateTextFontName"
|
||||
case kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
|
||||
|
@ -277,6 +280,9 @@ public enum mgrPrefs {
|
|||
UserDefaults.standard.setDefault(
|
||||
mgrPrefs.upperCaseLetterKeyBehavior, forKey: UserDef.kUpperCaseLetterKeyBehavior.rawValue
|
||||
)
|
||||
|
||||
// -----
|
||||
|
||||
UserDefaults.standard.setDefault(
|
||||
mgrPrefs.useIMKCandidateWindow, forKey: UserDef.kUseIMKCandidateWindow.rawValue
|
||||
)
|
||||
|
@ -284,6 +290,11 @@ public enum mgrPrefs {
|
|||
mgrPrefs.handleDefaultCandidateFontsByLangIdentifier,
|
||||
forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue
|
||||
)
|
||||
UserDefaults.standard.setDefault(
|
||||
mgrPrefs.shouldAlwaysUseShiftKeyAccommodation, forKey: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue
|
||||
)
|
||||
|
||||
// -----
|
||||
|
||||
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeySCPC, forKey: UserDef.kUsingHotKeySCPC.rawValue)
|
||||
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyAssociates, forKey: UserDef.kUsingHotKeyAssociates.rawValue)
|
||||
|
@ -388,6 +399,8 @@ public enum mgrPrefs {
|
|||
@UserDefault(key: UserDef.kUpperCaseLetterKeyBehavior.rawValue, defaultValue: 0)
|
||||
static var upperCaseLetterKeyBehavior: Int
|
||||
|
||||
// MARK: - Settings (Tier 2)
|
||||
|
||||
@UserDefault(key: UserDef.kUseIMKCandidateWindow.rawValue, defaultValue: false)
|
||||
static var useIMKCandidateWindow: Bool {
|
||||
didSet {
|
||||
|
@ -399,7 +412,13 @@ public enum mgrPrefs {
|
|||
@UserDefault(key: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue, defaultValue: false)
|
||||
static var handleDefaultCandidateFontsByLangIdentifier: Bool
|
||||
|
||||
// MARK: - Settings (Tier 2)
|
||||
@UserDefault(key: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue, defaultValue: false)
|
||||
static var shouldAlwaysUseShiftKeyAccommodation: Bool
|
||||
|
||||
@UserDefault(key: UserDef.kDisableShiftTogglingAlphanumericalMode.rawValue, defaultValue: false)
|
||||
static var disableShiftTogglingAlphanumericalMode: Bool
|
||||
|
||||
// MARK: - Settings (Tier 3)
|
||||
|
||||
@UserDefault(key: UserDef.kTogglingAlphanumericalModeWithLShift.rawValue, defaultValue: true)
|
||||
static var togglingAlphanumericalModeWithLShift: Bool
|
||||
|
|
|
@ -57,7 +57,7 @@ extension Megrez.Compositor {
|
|||
|
||||
/// 返回在當前位置的所有候選字詞(以詞音配對的形式)。如果組字器內有幅位、且游標
|
||||
/// 位於組字器的(文字輸入順序的)最前方(也就是游標位置的數值是最大合規數值)的
|
||||
/// 話,那麼這裡會用到 location - 1、以免去在呼叫該函數後再處理的麻煩。
|
||||
/// 話,那麼這裡會用到 location - 1、以免去在呼叫該函式後再處理的麻煩。
|
||||
/// - Parameter location: 游標位置。
|
||||
/// - Returns: 候選字音配對陣列。
|
||||
public func fetchCandidates(at location: Int, filter: CandidateFetchFilter = .all) -> [Candidate] {
|
||||
|
@ -105,7 +105,7 @@ extension Megrez.Compositor {
|
|||
|
||||
/// 使用給定的候選字詞字串,將給定位置的節點的候選字詞改為與之一致的候選字詞。
|
||||
///
|
||||
/// 注意:如果有多個「單元圖資料值雷同、卻讀音不同」的節點的話,該函數的行為結果不可控。
|
||||
/// 注意:如果有多個「單元圖資料值雷同、卻讀音不同」的節點的話,該函式的行為結果不可控。
|
||||
/// - Parameters:
|
||||
/// - candidate: 指定用來覆寫為的候選字(字串)。
|
||||
/// - location: 游標位置。
|
||||
|
|
|
@ -17,20 +17,20 @@ extension Megrez.Compositor {
|
|||
/// [("a", -114), ("b", -514), ("c", -1919)] 的話,指定該覆寫行為則會導致該節
|
||||
/// 點返回的結果為 ("c", -114)。該覆寫行為多用於諸如使用者半衰記憶模組的建議
|
||||
/// 行為。被覆寫的這個節點的狀態可能不會再被爬軌行為擅自改回。該覆寫行為無法
|
||||
/// 防止其它節點被爬軌函數所支配。這種情況下就需要用到 kOverridingScore
|
||||
/// - withHighScore: 將該節點權重覆寫為 kOverridingScore,使其被爬軌函數所青睞。
|
||||
/// 防止其它節點被爬軌函式所支配。這種情況下就需要用到 kOverridingScore
|
||||
/// - withHighScore: 將該節點權重覆寫為 kOverridingScore,使其被爬軌函式所青睞。
|
||||
public enum OverrideType: Int {
|
||||
case withNoOverrides = 0
|
||||
case withTopUnigramScore = 1
|
||||
case withHighScore = 2
|
||||
}
|
||||
|
||||
/// 一個用以覆寫權重的數值。該數值之高足以改變爬軌函數對該節點的讀取結果。這裡用
|
||||
/// 「0」可能看似足夠了,但仍會使得該節點的覆寫狀態有被爬軌函數忽視的可能。比方說
|
||||
/// 一個用以覆寫權重的數值。該數值之高足以改變爬軌函式對該節點的讀取結果。這裡用
|
||||
/// 「0」可能看似足夠了,但仍會使得該節點的覆寫狀態有被爬軌函式忽視的可能。比方說
|
||||
/// 要針對索引鍵「a b c」複寫的資料值為「A B C」,使用大寫資料值來覆寫節點。這時,
|
||||
/// 如果這個獨立的 c 有一個可以拮抗權重的詞「bc」的話,可能就會導致爬軌函數的算法
|
||||
/// 如果這個獨立的 c 有一個可以拮抗權重的詞「bc」的話,可能就會導致爬軌函式的算法
|
||||
/// 找出「A->bc」的爬軌途徑(尤其是當 A 和 B 使用「0」作為複寫數值的情況下)。這樣
|
||||
/// 一來,「A-B」就不一定始終會是爬軌函數的青睞結果了。所以,這裡一定要用大於 0 的
|
||||
/// 一來,「A-B」就不一定始終會是爬軌函式的青睞結果了。所以,這裡一定要用大於 0 的
|
||||
/// 數(比如野獸常數),以讓「c」更容易單獨被選中。
|
||||
public static let kOverridingScore: Double = 114_514
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public class CandidateKeyLabel: NSObject {
|
|||
}
|
||||
|
||||
public protocol ctlCandidateDelegate: AnyObject {
|
||||
var isAssociatedPhrasesMode: Bool { get }
|
||||
func handleDelegateEvent(_ event: NSEvent!) -> Bool
|
||||
func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int
|
||||
func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)]
|
|
@ -11,7 +11,9 @@ import InputMethodKit
|
|||
|
||||
public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
|
||||
public var currentLayout: CandidateLayout = .horizontal
|
||||
|
||||
private let defaultIMKSelectionKey: [UInt16: String] = [
|
||||
18: "1", 19: "2", 20: "3", 21: "4", 23: "5", 22: "6", 26: "7", 28: "8", 25: "9",
|
||||
]
|
||||
public weak var delegate: ctlCandidateDelegate? {
|
||||
didSet {
|
||||
reloadData()
|
||||
|
@ -70,6 +72,9 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
|
|||
super.init(server: theServer, panelType: kIMKScrollingGridCandidatePanel)
|
||||
specifyLayout(layout)
|
||||
visible = false
|
||||
// guard let currentTISInputSource = currentTISInputSource else { return } // 下面兩句都沒用,所以註釋掉。
|
||||
// setSelectionKeys([18, 19, 20, 21, 23, 22, 26, 28, 25]) // 這句是壞的,用了反而沒有選字鍵。
|
||||
// setSelectionKeysKeylayout(currentTISInputSource) // 這句也是壞的,沒有卵用。
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
|
@ -110,7 +115,12 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
|
|||
currentPageIndex = (currentPageIndex + 1 >= pageCount) ? 0 : currentPageIndex + 1
|
||||
if selectedCandidateIndex == candidates(self).count - 1 { return false }
|
||||
selectedCandidateIndex = min(selectedCandidateIndex + keyCount, candidates(self).count - 1)
|
||||
pageDownAndModifySelection(self)
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
moveDown(self)
|
||||
case .vertical:
|
||||
moveRight(self)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -121,7 +131,12 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
|
|||
currentPageIndex = (currentPageIndex == 0) ? pageCount - 1 : currentPageIndex - 1
|
||||
if selectedCandidateIndex == 0 { return true }
|
||||
selectedCandidateIndex = max(selectedCandidateIndex - keyCount, 0)
|
||||
pageUpAndModifySelection(self)
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
moveUp(self)
|
||||
case .vertical:
|
||||
moveLeft(self)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -226,14 +241,97 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
|
|||
}
|
||||
|
||||
override public func interpretKeyEvents(_ eventArray: [NSEvent]) {
|
||||
// 鬼知道為什麼這個函式接收的參數是陣列,但經過測試卻發現這個函式收到的陣列往往內容只有一個。
|
||||
// 這也可能是 Objective-C 當中允許接收內容為 nil 的一種方式。
|
||||
guard !eventArray.isEmpty else { return }
|
||||
var eventArray = eventArray
|
||||
let event = eventArray[0]
|
||||
let input = InputSignal(event: event)
|
||||
guard let delegate = delegate else { return }
|
||||
if input.isEsc || input.isBackSpace || input.isDelete || input.isShiftHold {
|
||||
if input.isEsc || input.isBackSpace || input.isDelete || (input.isShiftHold && !input.isSpace) {
|
||||
_ = delegate.handleDelegateEvent(event)
|
||||
} else if input.isSymbolMenuPhysicalKey || input.isSpace {
|
||||
if input.isShiftHold {
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
moveUp(self)
|
||||
case .vertical:
|
||||
moveLeft(self)
|
||||
}
|
||||
} else {
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
moveDown(self)
|
||||
case .vertical:
|
||||
moveRight(self)
|
||||
}
|
||||
}
|
||||
} else if input.isTab {
|
||||
switch currentLayout {
|
||||
case .horizontal:
|
||||
if input.isShiftHold {
|
||||
moveLeft(self)
|
||||
} else {
|
||||
moveRight(self)
|
||||
}
|
||||
case .vertical:
|
||||
if input.isShiftHold {
|
||||
moveUp(self)
|
||||
} else {
|
||||
moveDown(self)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let newChar = defaultIMKSelectionKey[event.keyCode] {
|
||||
/// 根據 KeyCode 重新換算一下選字鍵的 NSEvent,糾正其 Character 數值。
|
||||
/// 反正 IMK 選字窗目前也沒辦法修改選字鍵。
|
||||
let newEvent = NSEvent.keyEvent(
|
||||
with: event.type,
|
||||
location: event.locationInWindow,
|
||||
modifierFlags: event.modifierFlags,
|
||||
timestamp: event.timestamp,
|
||||
windowNumber: event.windowNumber,
|
||||
context: nil,
|
||||
characters: newChar,
|
||||
charactersIgnoringModifiers: event.charactersIgnoringModifiers ?? event.characters ?? "",
|
||||
isARepeat: event.isARepeat,
|
||||
keyCode: event.keyCode
|
||||
)
|
||||
if let newEvent = newEvent {
|
||||
/// 這裡不用診斷了,檢出的內容都是經過轉換之後的正確 NSEvent。
|
||||
eventArray = Array(eventArray.dropFirst(0))
|
||||
eventArray.insert(newEvent, at: 0)
|
||||
}
|
||||
}
|
||||
if delegate.isAssociatedPhrasesMode,
|
||||
!input.isPageUp, !input.isPageDown, !input.isCursorForward, !input.isCursorBackward,
|
||||
!input.isCursorClockLeft, !input.isCursorClockRight, !input.isSpace,
|
||||
!input.isEnter || !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter
|
||||
{
|
||||
_ = delegate.handleDelegateEvent(event)
|
||||
return
|
||||
}
|
||||
super.interpretKeyEvents(eventArray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Generate TISInputSource Object
|
||||
|
||||
/// 該參數只用來獲取 "com.apple.keylayout.ABC" 對應的 TISInputSource,
|
||||
/// 所以少寫了很多在這裡用不到的東西。
|
||||
/// 想參考完整版的話,請洽該專案內的 IME.swift。
|
||||
var currentTISInputSource: TISInputSource? {
|
||||
var result: TISInputSource?
|
||||
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
|
||||
let matchedTISString = "com.apple.keylayout.ABC"
|
||||
for source in list {
|
||||
guard let ptrCat = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) else { continue }
|
||||
let category = Unmanaged<CFString>.fromOpaque(ptrCat).takeUnretainedValue()
|
||||
guard category == kTISCategoryKeyboardInputSource else { continue }
|
||||
guard let ptrSourceID = TISGetInputSourceProperty(source, kTISPropertyInputSourceID) else { continue }
|
||||
let sourceID = String(Unmanaged<CFString>.fromOpaque(ptrSourceID).takeUnretainedValue())
|
||||
if sourceID == matchedTISString { result = source }
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -13,7 +13,10 @@ import Cocoa
|
|||
// 將之前 Zonble 重寫的 Voltaire 選字窗隔的橫向版本與縱向版本合併到同一個型別實體內。
|
||||
|
||||
private class vwrCandidateUniversal: NSView {
|
||||
var highlightedIndex: Int = 0 { didSet { highlightedIndex = max(highlightedIndex, 0) } }
|
||||
var highlightedIndex: Int = 0 {
|
||||
didSet { highlightedIndex = min(max(highlightedIndex, 0), dispCandidatesWithLabels.count - 1) }
|
||||
}
|
||||
|
||||
var action: Selector?
|
||||
weak var target: AnyObject?
|
||||
var isVerticalLayout: Bool = false
|
||||
|
@ -181,8 +184,8 @@ private class vwrCandidateUniversal: NSView {
|
|||
.withAlphaComponent(0.84)
|
||||
// Highlightened phrase text color
|
||||
activeCandidateAttr[.foregroundColor] = NSColor.selectedMenuItemTextColor
|
||||
} else {
|
||||
NSColor.controlBackgroundColor.setFill()
|
||||
let path: NSBezierPath = .init(roundedRect: rctCandidateArea, xRadius: 6, yRadius: 6)
|
||||
path.fill()
|
||||
}
|
||||
if mgrPrefs.handleDefaultCandidateFontsByLangIdentifier {
|
||||
switch IME.currentInputMode {
|
||||
|
@ -200,8 +203,6 @@ private class vwrCandidateUniversal: NSView {
|
|||
break
|
||||
}
|
||||
}
|
||||
let path: NSBezierPath = .init(roundedRect: rctCandidateArea, xRadius: 5, yRadius: 5)
|
||||
path.fill()
|
||||
(keyLabels[index] as NSString).draw(
|
||||
in: rctLabel, withAttributes: activeCandidateIndexAttr
|
||||
)
|
||||
|
@ -254,8 +255,8 @@ private class vwrCandidateUniversal: NSView {
|
|||
.withAlphaComponent(0.84)
|
||||
// Highlightened phrase text color
|
||||
activeCandidateAttr[.foregroundColor] = NSColor.selectedMenuItemTextColor
|
||||
} else {
|
||||
NSColor.controlBackgroundColor.setFill()
|
||||
let path: NSBezierPath = .init(roundedRect: rctCandidateArea, xRadius: 6, yRadius: 6)
|
||||
path.fill()
|
||||
}
|
||||
if mgrPrefs.handleDefaultCandidateFontsByLangIdentifier {
|
||||
switch IME.currentInputMode {
|
||||
|
@ -273,8 +274,6 @@ private class vwrCandidateUniversal: NSView {
|
|||
break
|
||||
}
|
||||
}
|
||||
let path: NSBezierPath = .init(roundedRect: rctCandidateArea, xRadius: 5, yRadius: 5)
|
||||
path.fill()
|
||||
(keyLabels[index] as NSString).draw(
|
||||
in: rctLabel, withAttributes: activeCandidateIndexAttr
|
||||
)
|
||||
|
@ -379,11 +378,10 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
candidateView = vwrCandidateUniversal(frame: contentRect)
|
||||
|
||||
candidateView.wantsLayer = true
|
||||
candidateView.layer?.borderColor =
|
||||
NSColor.selectedMenuItemTextColor.withAlphaComponent(0.20).cgColor
|
||||
candidateView.layer?.borderWidth = 1.0
|
||||
// candidateView.layer?.borderColor = NSColor.selectedMenuItemTextColor.withAlphaComponent(0.20).cgColor
|
||||
// candidateView.layer?.borderWidth = 1.0
|
||||
if #available(macOS 10.13, *) {
|
||||
candidateView.layer?.cornerRadius = 8.0
|
||||
candidateView.layer?.cornerRadius = 9.0
|
||||
}
|
||||
|
||||
panel.contentView?.addSubview(candidateView)
|
||||
|
@ -462,7 +460,10 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
if pageCount == 1 { return highlightNextCandidate() }
|
||||
if currentPageIndex + 1 >= pageCount { clsSFX.beep() }
|
||||
currentPageIndex = (currentPageIndex + 1 >= pageCount) ? 0 : currentPageIndex + 1
|
||||
candidateView.highlightedIndex = 0
|
||||
if currentPageIndex == pageCount - 1 {
|
||||
candidateView.highlightedIndex = min(lastPageContentCount - 1, candidateView.highlightedIndex)
|
||||
}
|
||||
// candidateView.highlightedIndex = 0
|
||||
layoutCandidateView()
|
||||
return true
|
||||
}
|
||||
|
@ -472,7 +473,10 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
if pageCount == 1 { return highlightPreviousCandidate() }
|
||||
if currentPageIndex == 0 { clsSFX.beep() }
|
||||
currentPageIndex = (currentPageIndex == 0) ? pageCount - 1 : currentPageIndex - 1
|
||||
candidateView.highlightedIndex = 0
|
||||
if currentPageIndex == pageCount - 1 {
|
||||
candidateView.highlightedIndex = min(lastPageContentCount - 1, candidateView.highlightedIndex)
|
||||
}
|
||||
// candidateView.highlightedIndex = 0
|
||||
layoutCandidateView()
|
||||
return true
|
||||
}
|
||||
|
@ -530,6 +534,15 @@ extension ctlCandidateUniversal {
|
|||
return totalCount / keyLabelCount + ((totalCount % keyLabelCount) != 0 ? 1 : 0)
|
||||
}
|
||||
|
||||
private var lastPageContentCount: Int {
|
||||
guard let delegate = delegate else {
|
||||
return 0
|
||||
}
|
||||
let totalCount = delegate.candidateCountForController(self)
|
||||
let keyLabelCount = keyLabels.count
|
||||
return totalCount % keyLabelCount
|
||||
}
|
||||
|
||||
private func layoutCandidateView() {
|
||||
guard let delegate = delegate else {
|
||||
return
|
|
@ -14,6 +14,10 @@ struct suiPrefPaneDevZone: View {
|
|||
forKey: UserDef.kUseIMKCandidateWindow.rawValue)
|
||||
@State private var selHandleDefaultCandidateFontsByLangIdentifier: Bool = UserDefaults.standard.bool(
|
||||
forKey: UserDef.kHandleDefaultCandidateFontsByLangIdentifier.rawValue)
|
||||
@State private var selShouldAlwaysUseShiftKeyAccommodation: Bool = UserDefaults.standard.bool(
|
||||
forKey: UserDef.kShouldAlwaysUseShiftKeyAccommodation.rawValue)
|
||||
@State private var selDisableShiftTogglingAlphanumericalMode: Bool = UserDefaults.standard.bool(
|
||||
forKey: UserDef.kDisableShiftTogglingAlphanumericalMode.rawValue)
|
||||
private let contentWidth: Double = {
|
||||
switch mgrPrefs.appleLanguages[0] {
|
||||
case "ja":
|
||||
|
@ -56,6 +60,24 @@ struct suiPrefPaneDevZone: View {
|
|||
)
|
||||
)
|
||||
.preferenceDescription().fixedSize(horizontal: false, vertical: true)
|
||||
Toggle(
|
||||
LocalizedStringKey("Use Shift Key Accommodation in all cases"),
|
||||
isOn: $selShouldAlwaysUseShiftKeyAccommodation.onChange {
|
||||
mgrPrefs.shouldAlwaysUseShiftKeyAccommodation = selShouldAlwaysUseShiftKeyAccommodation
|
||||
}
|
||||
)
|
||||
Text(
|
||||
LocalizedStringKey(
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on."
|
||||
)
|
||||
)
|
||||
.preferenceDescription().fixedSize(horizontal: false, vertical: true)
|
||||
Toggle(
|
||||
LocalizedStringKey("Completely disable using Shift key to toggling alphanumerical mode"),
|
||||
isOn: $selDisableShiftTogglingAlphanumericalMode.onChange {
|
||||
mgrPrefs.disableShiftTogglingAlphanumericalMode = selDisableShiftTogglingAlphanumericalMode
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -162,7 +162,7 @@ struct suiPrefPaneExperience: View {
|
|||
mgrPrefs.useSCPCTypingMode = selEnableSCPCTypingMode
|
||||
}
|
||||
)
|
||||
Text(LocalizedStringKey("An accomodation for elder computer users."))
|
||||
Text(LocalizedStringKey("An accommodation for elder computer users."))
|
||||
.preferenceDescription()
|
||||
}
|
||||
}
|
|
@ -93,7 +93,7 @@
|
|||
"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection";
|
||||
"Also toggle alphanumerical mode with Left-Shift" = "Also toggle alphanumerical mode with Left-Shift";
|
||||
"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.";
|
||||
"An accommodation for elder computer users." = "An accommodation for elder computer users.";
|
||||
"Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)";
|
||||
"Apple Chewing - Dachen" = "Apple Chewing - Dachen";
|
||||
"Apple Chewing - Eten Traditional" = "Apple Chewing - Eten Traditional";
|
||||
|
@ -164,6 +164,7 @@
|
|||
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip";
|
||||
"Show page buttons in candidate window" = "Show page buttons in candidate window";
|
||||
"Simplified Chinese" = "Simplified Chinese";
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on.";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates";
|
||||
"Starlight" = "Starlight";
|
||||
|
@ -177,6 +178,7 @@
|
|||
"Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window";
|
||||
"Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer";
|
||||
"Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)";
|
||||
"Use Shift Key Accommodation in all cases" = "Use Shift Key Accommodation in all cases";
|
||||
"Vertical" = "Vertical";
|
||||
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected.";
|
||||
"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation";
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection";
|
||||
"Also toggle alphanumerical mode with Left-Shift" = "Also toggle alphanumerical mode with Left-Shift";
|
||||
"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.";
|
||||
"An accommodation for elder computer users." = "An accommodation for elder computer users.";
|
||||
"Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)";
|
||||
"Apple Chewing - Dachen" = "Apple Chewing - Dachen";
|
||||
"Apple Chewing - Eten Traditional" = "Apple Chewing - Eten Traditional";
|
||||
|
@ -119,6 +119,7 @@
|
|||
"Choose the phonetic layout for Mandarin parser." = "Choose the phonetic layout for Mandarin parser.";
|
||||
"Choose your desired user data folder path. Will be omitted if invalid." = "Choose your desired user data folder path. Will be omitted if invalid.";
|
||||
"Choose your preferred layout of the candidate window." = "Choose your preferred layout of the candidate window.";
|
||||
"Completely disable using Shift key to toggling alphanumerical mode" = "Completely disable using Shift key to toggling alphanumerical mode";
|
||||
"Cursor Selection:" = "Cursor Selection:";
|
||||
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "Dachen (Microsoft Standard / Wang / 01, etc.)";
|
||||
"Dachen 26 (libChewing)" = "Dachen 26 (libChewing)";
|
||||
|
@ -164,6 +165,7 @@
|
|||
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip";
|
||||
"Show page buttons in candidate window" = "Show page buttons in candidate window";
|
||||
"Simplified Chinese" = "Simplified Chinese";
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on.";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates";
|
||||
"Starlight" = "Starlight";
|
||||
|
@ -177,6 +179,7 @@
|
|||
"Use .langIdentifier to handle UI fonts in candidate window" = "Use .langIdentifier to handle UI fonts in candidate window";
|
||||
"Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer";
|
||||
"Use IMK Candidate Window instead (will reboot the IME)" = "Use IMK Candidate Window instead (will reboot the IME)";
|
||||
"Use Shift Key Accommodation in all cases" = "Use Shift Key Accommodation in all cases";
|
||||
"Vertical" = "Vertical";
|
||||
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "Warning: This page is for testing future features. \nFeatures listed here may not work as expected.";
|
||||
"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation";
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
"Allow using Enter key to confirm associated candidate selection" = "Enter キーを連想語彙候補の確認のために使う";
|
||||
"Also toggle alphanumerical mode with Left-Shift" = "左側の Shift キーでも英数入力モードの切り替え";
|
||||
"Always use fixed listing order in candidate window" = "候補文字を固定順番で陳列する";
|
||||
"An accomodation for elder computer users." = "年配なるユーザーのために提供した機能である。";
|
||||
"An accommodation for elder computer users." = "年配なるユーザーのために提供した機能である。";
|
||||
"Apple ABC (equivalent to English US)" = "Apple ABC (Apple U.S. キーボードと同じ)";
|
||||
"Apple Chewing - Dachen" = "Apple 大千注音キーボード";
|
||||
"Apple Chewing - Eten Traditional" = "Apple 倚天傳統キーボード";
|
||||
|
@ -119,6 +119,7 @@
|
|||
"Choose the phonetic layout for Mandarin parser." = "共通語分析器の注音配列をご指定ください。";
|
||||
"Choose your desired user data folder path. Will be omitted if invalid." = "欲しがるユーザー辞書保存先をご指定ください。無効なる保存先設定は省かれる。";
|
||||
"Choose your preferred layout of the candidate window." = "入力候補陳列の仕様をご指定ください。";
|
||||
"Completely disable using Shift key to toggling alphanumerical mode" = "Shift キーの英数入力モードの切り替え機能を徹底的に禁ず";
|
||||
"Cursor Selection:" = "カーソル候補呼出:";
|
||||
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千配列 (Microsoft 標準・王安・零壹など)";
|
||||
"Dachen 26 (libChewing)" = "酷音大千 26 キー配列";
|
||||
|
@ -164,6 +165,7 @@
|
|||
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "弁音合併入力(入力緩衝列とヒントで音読みを漢語弁音に)";
|
||||
"Show page buttons in candidate window" = "入力候補陳列の側にページボタンを表示";
|
||||
"Simplified Chinese" = "簡体中国語";
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "いくつかのアプリ(例えば MS Edge や Google Chrome などのような Chromium 系ブラウザー)には「Shift キーの入力イベントを複数化してしまう」という支障があり、そしてアプリそれぞれの開発元に修復される可能性はほぼゼロだと言える。威注音入力アプリは対策用の特殊措置を普段に起用している。別のアプリにも同じ特殊措置が欲しければ、これをチェックしてください。";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+Space で次のページ、Space で次の候補文字を";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "Space で次のページ、Shift+Space で次の候補文字を";
|
||||
"Starlight" = "星光配列";
|
||||
|
@ -177,6 +179,7 @@
|
|||
"Use .langIdentifier to handle UI fonts in candidate window" = "「.langIdentifier」を使って候補陳列ウィンドウのフォントを取り扱う";
|
||||
"Use ESC key to clear the entire input buffer" = "ESC キーで入力緩衝列を消す";
|
||||
"Use IMK Candidate Window instead (will reboot the IME)" = "IMK 候補陳列ウィンドウを起用(入力アプリは自動的に再起動)";
|
||||
"Use Shift Key Accommodation in all cases" = "いずれの客体アプリにも Shift キーの互換性措置を起用";
|
||||
"Vertical" = "縦型陳列";
|
||||
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:これからの新機能テストのために作ったページですから、\nここで陳列されている諸機能は予想通り動けるだと思わないでください。";
|
||||
"Yale Pinyin with Numeral Intonation" = "イェール弁音 (ローマ字+数字音調)";
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
"Allow using Enter key to confirm associated candidate selection" = "允许使用 Enter 确认当前选中的联想词";
|
||||
"Also toggle alphanumerical mode with Left-Shift" = "也允许使用左侧的 Shift 键盘切换英数输入模式";
|
||||
"Always use fixed listing order in candidate window" = "以固定顺序来陈列选字窗内的候选字";
|
||||
"An accomodation for elder computer users." = "针对年长使用者的习惯而提供。";
|
||||
"An accommodation for elder computer users." = "针对年长使用者的习惯而提供。";
|
||||
"Apple ABC (equivalent to English US)" = "Apple ABC (与 Apple 美规键盘等价)";
|
||||
"Apple Chewing - Dachen" = "Apple 大千注音键盘排列";
|
||||
"Apple Chewing - Eten Traditional" = "Apple 倚天传统键盘排列";
|
||||
|
@ -119,6 +119,7 @@
|
|||
"Choose the phonetic layout for Mandarin parser." = "请指定普通话/国音分析器所使用的注音排列。";
|
||||
"Choose your desired user data folder path. Will be omitted if invalid." = "请在此指定您想指定的使用者语汇档案目录。无效值会被忽略。";
|
||||
"Choose your preferred layout of the candidate window." = "选择您所偏好的候选字窗布局。";
|
||||
"Completely disable using Shift key to toggling alphanumerical mode" = "彻底禁止使用 Shift 键切换英数模式";
|
||||
"Cursor Selection:" = "选字游标:";
|
||||
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微软标准/王安/零壹/仲鼎/国乔)";
|
||||
"Dachen 26 (libChewing)" = "酷音大千二十六键排列";
|
||||
|
@ -144,7 +145,6 @@
|
|||
"Horizontal" = "横向布局";
|
||||
"Hsu" = "许氏国音自然排列";
|
||||
"Hualuo Pinyin with Numeral Intonation" = "华罗拼音+数字标调";
|
||||
"Hualuo Pinyin with Numeral Intonation" = "華羅拼音+数字标调";
|
||||
"IBM" = "IBM 排列";
|
||||
"IMK candidate window is plagued with issues like failed selection keys." = "IMK 选字窗目前暂时无法正常使用选字键,并具其它未知故障。";
|
||||
"in front of the phrase (like macOS built-in Zhuyin IME)" = "将游标置于词语前方 // macOS 内建注音风格";
|
||||
|
@ -165,8 +165,9 @@
|
|||
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音并击(组字区与工具提示内显示汉语拼音)";
|
||||
"Show page buttons in candidate window" = "在选字窗内显示翻页按钮";
|
||||
"Simplified Chinese" = "简体中文";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格键 换下一页,空格键 换选下一个后选字";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格键 换下一页,Shift+空格键 换选下一个后选字";
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "某些应用(比如像是 MS Edge 或者 Chrome 这样的 Chromium 核心的浏览器)可能会使输入的 Shift 按键讯号被重复输入,且其有关研发方很可能不打算修复这些产品缺陷。威注音针对这些应用预设启用了相容措施。如果您希望在任何应用当中都启用该措施的话,请勾选之。";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格键 换下一页,空格键 换选下一个候选字";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格键 换下一页,Shift+空格键 换选下一个候选字";
|
||||
"Starlight" = "星光排列";
|
||||
"Stop farting (when typed phonetic combination is invalid, etc.)" = "廉耻模式 // 取消勾选的话,敲错字时会有异音";
|
||||
"This only works since macOS 12 with non-IMK candidate window as an alternative wordaround of Apple Bug Report #FB10978412. Apple should patch that for macOS 11 and later." = "该方法是 Apple Bug Report #FB10978412 的保守治疗方案,用来仅针对 macOS 12 开始的系统,且仅对非 IMK 选字窗起作用。Apple 应该对 macOS 11 开始的系统修复这个 Bug。";
|
||||
|
@ -175,10 +176,10 @@
|
|||
"Typing Style:" = "输入风格:";
|
||||
"UI Language:" = "介面语言:";
|
||||
"Universal Pinyin with Numeral Intonation" = "通用拼音+数字标调";
|
||||
"Universal Pinyin with Numeral Intonation" = "通用拼音+数字标调";
|
||||
"Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 来管理选字窗的预设介面字型";
|
||||
"Use ESC key to clear the entire input buffer" = "敲 ESC 键以清空整个组字缓冲区";
|
||||
"Use IMK Candidate Window instead (will reboot the IME)" = "启用 IMK 选字窗(会自动重启输入法)";
|
||||
"Use Shift Key Accommodation in all cases" = "对任何客体应用均启用 Shift 键相容性措施";
|
||||
"Vertical" = "纵向布局";
|
||||
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:该页面仅作未来功能测试所用。\n在此列出的功能并非处于完全可用之状态。";
|
||||
"Yale Pinyin with Numeral Intonation" = "耶鲁拼音+数字标调";
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
"Allow using Enter key to confirm associated candidate selection" = "允許使用 Enter 確認當前選中的聯想詞";
|
||||
"Also toggle alphanumerical mode with Left-Shift" = "也允許使用左側的 Shift 鍵盤切換英數輸入模式";
|
||||
"Always use fixed listing order in candidate window" = "以固定順序來陳列選字窗內的候選字";
|
||||
"An accomodation for elder computer users." = "針對年長使用者的習慣而提供。";
|
||||
"An accommodation for elder computer users." = "針對年長使用者的習慣而提供。";
|
||||
"Apple ABC (equivalent to English US)" = "Apple ABC (與 Apple 美規鍵盤等價)";
|
||||
"Apple Chewing - Dachen" = "Apple 大千注音鍵盤佈局";
|
||||
"Apple Chewing - Eten Traditional" = "Apple 倚天傳統鍵盤佈局";
|
||||
|
@ -119,6 +119,7 @@
|
|||
"Choose the phonetic layout for Mandarin parser." = "請指定普通話/國音分析器所使用的注音排列。";
|
||||
"Choose your desired user data folder path. Will be omitted if invalid." = "請在此指定您想指定的使用者語彙檔案目錄。無效值會被忽略。";
|
||||
"Choose your preferred layout of the candidate window." = "選擇您所偏好的候選字窗佈局。";
|
||||
"Completely disable using Shift key to toggling alphanumerical mode" = "徹底禁止使用 Shift 鍵切換英數模式";
|
||||
"Cursor Selection:" = "選字游標:";
|
||||
"Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微軟標準/王安/零壹/仲鼎/國喬)";
|
||||
"Dachen 26 (libChewing)" = "酷音大千二十六鍵排列";
|
||||
|
@ -164,8 +165,9 @@
|
|||
"Show Hanyu-Pinyin in the inline composition buffer & tooltip" = "拼音並擊(組字區與工具提示內顯示漢語拼音)";
|
||||
"Show page buttons in candidate window" = "在選字窗內顯示翻頁按鈕";
|
||||
"Simplified Chinese" = "簡體中文";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格鍵 換下一頁,空格鍵 換選下一個後選字";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格鍵 換下一頁,Shift+空格鍵 換選下一個後選字";
|
||||
"Some client apps (like Chromium-cored browsers: MS Edge, Google Chrome, etc.) may duplicate Shift-key inputs due to their internal bugs, and their devs are less likely to fix their bugs of such. vChewing has its accommodation procedures enabled by default for known Chromium-cored browsers. If you want the same accommodation for other client apps, please tick this checkbox on." = "某些應用(比如像是 MS Edge 或者 Chrome 這樣的 Chromium 核心的瀏覽器)可能會使輸入的 Shift 按鍵訊號被重複輸入,且其有關研發方很可能不打算修復這些產品缺陷。威注音針對這些應用預設啟用了相容措施。如果您希望在任何應用當中都啟用該措施的話,請勾選之。";
|
||||
"Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格鍵 換下一頁,空格鍵 換選下一個候選字";
|
||||
"Space to +cycle pages, Shift+Space to +cycle candidates" = "空格鍵 換下一頁,Shift+空格鍵 換選下一個候選字";
|
||||
"Starlight" = "星光排列";
|
||||
"Stop farting (when typed phonetic combination is invalid, etc.)" = "廉恥模式 // 取消勾選的話,敲錯字時會有異音";
|
||||
"This only works since macOS 12 with non-IMK candidate window as an alternative wordaround of Apple Bug Report #FB10978412. Apple should patch that for macOS 11 and later." = "該方法是 Apple Bug Report #FB10978412 的保守治療方案,用來僅針對 macOS 12 開始的系統,且僅對非 IMK 選字窗起作用。Apple 應該對 macOS 11 開始的系統修復這個 Bug。";
|
||||
|
@ -177,6 +179,7 @@
|
|||
"Use .langIdentifier to handle UI fonts in candidate window" = "使用 .langIdentifier 來管理選字窗的預設介面字型";
|
||||
"Use ESC key to clear the entire input buffer" = "敲 ESC 鍵以清空整個組字緩衝區";
|
||||
"Use IMK Candidate Window instead (will reboot the IME)" = "啟用 IMK 選字窗(會自動重啟輸入法)";
|
||||
"Use Shift Key Accommodation in all cases" = "對任何客體應用均啟用 Shift 鍵相容性措施";
|
||||
"Vertical" = "縱向佈局";
|
||||
"Warning: This page is for testing future features. \nFeatures listed here may not work as expected." = "警告:該頁面僅作未來功能測試所用。\n在此列出的功能並非處於完全可用之狀態。";
|
||||
"Yale Pinyin with Numeral Intonation" = "耶魯拼音+數字標調";
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.2</string>
|
||||
<string>1.9.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1992</string>
|
||||
<string>1993</string>
|
||||
<key>UpdateInfoEndpoint</key>
|
||||
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
|
||||
<key>UpdateInfoSite</key>
|
||||
|
|
|
@ -726,7 +726,7 @@
|
|||
<key>USE_HFS+_COMPRESSION</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.9.2</string>
|
||||
<string>1.9.3</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
|
|
|
@ -544,7 +544,7 @@
|
|||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B62A33927AE7C6700A19448 /* UI */ = {
|
||||
5B62A33927AE7C6700A19448 /* UIModules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B62A33E27AE7CD900A19448 /* CandidateUI */,
|
||||
|
@ -552,7 +552,7 @@
|
|||
5BA9FD0927FED9F3002DE248 /* PrefUI */,
|
||||
5B62A34227AE7CD900A19448 /* TooltipUI */,
|
||||
);
|
||||
path = UI;
|
||||
path = UIModules;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B62A33A27AE7C7500A19448 /* WindowControllers */ = {
|
||||
|
@ -792,7 +792,6 @@
|
|||
5B62A30127AE732800A19448 /* 3rdParty */,
|
||||
6A0D4F1215FC0EB100ABF4B3 /* Modules */,
|
||||
5B62A33027AE78E500A19448 /* Resources */,
|
||||
5B62A33927AE7C6700A19448 /* UI */,
|
||||
5B62A33A27AE7C7500A19448 /* WindowControllers */,
|
||||
5B62A33B27AE7C7F00A19448 /* WindowNIBs */,
|
||||
);
|
||||
|
@ -818,6 +817,7 @@
|
|||
5B62A32427AE757300A19448 /* LangModelRelated */,
|
||||
5B62A32327AE756800A19448 /* LanguageParsers */,
|
||||
5B62A31E27AE74E400A19448 /* SFX */,
|
||||
5B62A33927AE7C6700A19448 /* UIModules */,
|
||||
);
|
||||
path = Modules;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1417,7 +1417,7 @@
|
|||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
@ -1427,7 +1427,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
|
||||
|
@ -1456,13 +1456,13 @@
|
|||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
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.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
|
||||
|
@ -1493,7 +1493,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -1514,7 +1514,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1543,7 +1543,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
|
@ -1560,7 +1560,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1674,7 +1674,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1702,7 +1702,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1729,7 +1729,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1751,7 +1751,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1773,7 +1773,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
@ -1793,7 +1793,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1815,7 +1815,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1992;
|
||||
CURRENT_PROJECT_VERSION = 1993;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
@ -1829,7 +1829,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.9.2;
|
||||
MARKETING_VERSION = 1.9.3;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|
Loading…
Reference in New Issue