1.8.7 // Rescue. Merge Gitee PR!73 from dev/bleed

This commit is contained in:
ShikiSuen 2022-08-02 13:49:01 +00:00 committed by Gitee
commit d5f0ed4b6f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
43 changed files with 781 additions and 411 deletions

View File

@ -97,7 +97,7 @@
- 天權星語彙處理引擎Shiki Suen (MIT-NTL License)。
- 威注音詞庫由 Shiki Suen 維護,以 3-Clause BSD License 授權釋出。其中的詞頻數據[由 NAER 授權用於非商業用途](https://twitter.com/ShikiSuen/status/1479329302713831424)。
使用者可自由使用、散播本軟體,惟散播時必須完整保留版權聲明及軟體授權、且一旦經過修改便不可以再繼續使用威注音的產品名稱。
使用者可自由使用、散播本軟體,惟散播時必須完整保留版權聲明及軟體授權、且一旦經過修改便不可以再繼續使用威注音的產品名稱」。換言之,這條相對上游 MIT 而言新增的規定就是:你 Fork 可以,但 Fork 成單獨發行的產品名稱時就必須修改產品名稱。這條新增規定對 OpenVanilla 與威注音雙方都有益,免得各自的旗號被盜版下載販子等挪用做意外用途
## 資料來源

View File

@ -97,7 +97,7 @@
- 天权星语汇处理引擎Shiki Suen (MIT-NTL License)。
- 威注音词库由 Shiki Suen 维护,以 3-Clause BSD License 授权释出。其中的词频数据[由 NAER 授权用于非商业用途](https://twitter.com/ShikiSuen/status/1479329302713831424)。
使用者可自由使用、散播本软件,惟散播时必须完整保留版权声明及软件授权、且一旦经过修改便不可以再继续使用威注音的产品名称。
使用者可自由使用、散播本软件,惟散播时必须完整保留版权声明及软件授权、且一旦经过修改便不可以再继续使用威注音的产品名称」。换言之,这条相对上游 MIT 而言新增的规定就是:你 Fork 可以,但 Fork 成单独发行的产品名称时就必须修改产品名称。这条新增规定对 OpenVanilla 与威注音双方都有益,免得各自的旗号被盗版下载贩子等挪用做意外用途
## 资料来源

@ -1 +1 @@
Subproject commit 30a5bc773a21d67c3f117eef5346d3b35433bbaa
Subproject commit 144db528de84caff0fa20802b144421bcc58419f

View File

@ -29,7 +29,7 @@ import InputMethodKit
@objc(AppDelegate)
class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate,
FSEventStreamHelperDelegate
FSEventStreamHelperDelegate, NSUserNotificationCenterDelegate
{
func helper(_: FSEventStreamHelper, didReceive _: [FSEventStreamHelper.Event]) {
// 100ms 使使
@ -63,7 +63,25 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega
fsStreamHelper.delegate = nil
}
func userNotificationCenter(_: NSUserNotificationCenter, shouldPresent _: NSUserNotification) -> Bool {
return true
}
func applicationDidFinishLaunching(_: Notification) {
NSUserNotificationCenter.default.delegate = self
// 使
if mgrPrefs.failureFlagForUOMObservation {
mgrLangModel.clearUserOverrideModelData(.imeModeCHS)
mgrLangModel.clearUserOverrideModelData(.imeModeCHT)
mgrPrefs.failureFlagForUOMObservation = false
let userNotification = NSUserNotification()
userNotification.title = NSLocalizedString("vChewing", comment: "")
userNotification.informativeText =
"\(NSLocalizedString("vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability.", comment: ""))"
userNotification.soundName = NSUserNotificationDefaultSoundName
NSUserNotificationCenter.default.deliver(userNotification)
}
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
IME.initLangModels(userOnly: false)
}

View File

@ -29,7 +29,7 @@ import Cocoa
// InputState 使 Struct Struct
// enum
enum StateType {
public enum StateType {
case ofDeactivated
case ofAssociatedPhrases
case ofEmpty
@ -38,12 +38,12 @@ enum StateType {
case ofNotEmpty
case ofInputting
case ofMarking
case ofChooseCandidate
case ofChoosingCandidate
case ofSymbolTable
}
// InputState
protocol InputStateProtocol {
public protocol InputStateProtocol {
var type: StateType { get }
}
@ -79,7 +79,7 @@ protocol InputStateProtocol {
///
/// - .ChoosingCandidate: 使
/// - .SymbolTable:
enum InputState {
public enum InputState {
/// .Deactivated: 使使
class Deactivated: InputStateProtocol {
public var type: StateType { .ofDeactivated }
@ -175,6 +175,8 @@ enum InputState {
public var type: StateType { .ofNotEmpty }
private(set) var composingBuffer: String
private(set) var cursorIndex: Int = 0 { didSet { cursorIndex = max(cursorIndex, 0) } }
private(set) var reading: String = ""
private(set) var nodeValuesArray = [String]()
public var composingBufferConverted: String {
let converted = IME.kanjiConversionIfRequired(composingBuffer)
if converted.utf16.count != composingBuffer.utf16.count
@ -185,23 +187,41 @@ enum InputState {
return converted
}
init(composingBuffer: String, cursorIndex: Int) {
init(composingBuffer: String, cursorIndex: Int, reading: String = "", nodeValuesArray: [String] = []) {
self.composingBuffer = composingBuffer
self.reading = reading
self.nodeValuesArray = nodeValuesArray
defer { self.cursorIndex = cursorIndex }
}
var attributedString: NSMutableAttributedString {
///
/// JIS
guard reading.isEmpty else {
let attributedString = NSMutableAttributedString(
string: composingBufferConverted,
attributes: [
/// .thick
.underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0,
]
)
return attributedString
}
let attributedString = NSMutableAttributedString(string: composingBufferConverted)
var newBegin = 0
for (i, neta) in nodeValuesArray.enumerated() {
attributedString.setAttributes(
[
/// .thick
.underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: i,
], range: NSRange(location: newBegin, length: neta.utf16.count)
)
newBegin += neta.utf16.count
}
return attributedString
}
var description: String {
"<InputState.NotEmpty, composingBuffer:\(composingBuffer), cursorIndex:\(cursorIndex)>"
@ -216,8 +236,9 @@ enum InputState {
var textToCommit: String = ""
var tooltip: String = ""
override init(composingBuffer: String, cursorIndex: Int) {
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
override init(composingBuffer: String, cursorIndex: Int, reading: String = "", nodeValuesArray: [String] = []) {
super.init(
composingBuffer: composingBuffer, cursorIndex: cursorIndex, reading: reading, nodeValuesArray: nodeValuesArray)
}
override var description: String {
@ -264,9 +285,9 @@ enum InputState {
private var deleteTargetExists = false
var tooltip: String {
if composingBuffer.count != readings.count {
ctlInputMethod.tooltipController.setColor(state: .redAlert)
ctlInputMethod.tooltipController.setColor(state: .denialOverflow)
return NSLocalizedString(
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match.", comment: ""
"⚠︎ Beware: Chars and Readings in buffer doesn't match.", comment: ""
)
}
if mgrPrefs.phraseReplacementEnabled {
@ -376,14 +397,9 @@ enum InputState {
}
var validToWrite: Bool {
/// The input method allows users to input a string whose length differs
/// from the amount of Bopomofo readings. In this case, the range
/// in the composing buffer and the readings could not match, so
/// we disable the function to write user phrases in this case.
/// deleteTargetExists 使
/// 使
((composingBuffer.count != readings.count)
|| (ctlInputMethod.areWeDeleting && !deleteTargetExists))
///
/// deleteTargetExists 使
(ctlInputMethod.areWeDeleting && !deleteTargetExists)
? false
: allowedMarkRange.contains(literalMarkedRange.count)
}
@ -418,7 +434,7 @@ enum InputState {
/// .ChoosingCandidate: 使
class ChoosingCandidate: NotEmpty {
override public var type: StateType { .ofChooseCandidate }
override public var type: StateType { .ofChoosingCandidate }
private(set) var candidates: [(String, String)]
private(set) var isTypingVertical: Bool

View File

@ -34,10 +34,10 @@ import Cocoa
/// KeyHandler
protocol KeyHandlerDelegate {
func ctlCandidate() -> ctlCandidate
func ctlCandidate() -> ctlCandidateProtocol
func keyHandler(
_: KeyHandler, didSelectCandidateAt index: Int,
ctlCandidate controller: ctlCandidate
ctlCandidate controller: ctlCandidateProtocol
)
func keyHandler(_ keyHandler: KeyHandler, didRequestWriteUserPhraseWith state: InputStateProtocol)
-> Bool
@ -46,9 +46,11 @@ protocol KeyHandlerDelegate {
// MARK: - (Kernel).
/// KeyHandler 調
class KeyHandler {
public class KeyHandler {
///
let kEpsilon: Double = 0.000001
///
var isCursorCuttingChar = false
///
let kMaxComposingBufferNeedsToWalkSize = Int(max(12, ceil(Double(mgrPrefs.composingBufferSize) / 2)))
@ -182,14 +184,20 @@ class KeyHandler {
addToUserOverrideModel = false
}
}
if addToUserOverrideModel {
if addToUserOverrideModel, mgrPrefs.fetchSuggestionsFromUserOverrideModel {
IME.prtDebugIntel("UOM: Start Observation.")
// 使
//
// AppDelegate
mgrPrefs.failureFlagForUOMObservation = true
//
//
currentUOM.observe(
walkedAnchors: walkedAnchors, cursorIndex: adjustedCursor, candidate: theCandidate.value,
timestamp: NSDate().timeIntervalSince1970, saveCallback: { mgrLangModel.saveUserOverrideModelData() }
)
//
mgrPrefs.failureFlagForUOMObservation = false
}
}

View File

@ -46,7 +46,7 @@ extension KeyHandler {
) -> Bool {
let inputText = input.inputText
let charCode: UniChar = input.charCode
guard let ctlCandidateCurrent = delegate?.ctlCandidate() else {
guard var ctlCandidateCurrent = delegate?.ctlCandidate() else {
IME.prtDebugIntel("06661F6E")
errorCallback()
return true
@ -69,6 +69,7 @@ extension KeyHandler {
// compositor.isEmpty
clear()
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
} else {
stateCallback(buildInputtingState)
}
@ -84,6 +85,7 @@ extension KeyHandler {
if state is InputState.AssociatedPhrases, !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter {
clear()
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
return true
}
delegate?.keyHandler(
@ -293,14 +295,12 @@ extension KeyHandler {
let match: String =
(state is InputState.AssociatedPhrases) ? input.inputTextIgnoringModifiers ?? "" : inputText
var j = 0
while j < ctlCandidateCurrent.keyLabels.count {
for j in 0..<ctlCandidateCurrent.keyLabels.count {
let label: CandidateKeyLabel = ctlCandidateCurrent.keyLabels[j]
if match.compare(label.key, options: .caseInsensitive, range: nil, locale: .current) == .orderedSame {
index = j
break
}
j += 1
}
if index != NSNotFound {
@ -352,10 +352,10 @@ extension KeyHandler {
ctlCandidate: ctlCandidateCurrent
)
clear()
let empty = InputState.EmptyIgnoringPreviousState()
stateCallback(empty)
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
return handle(
input: input, state: empty, stateCallback: stateCallback, errorCallback: errorCallback
input: input, state: InputState.Empty(), stateCallback: stateCallback, errorCallback: errorCallback
)
}
return true

View File

@ -30,17 +30,14 @@ extension KeyHandler {
/// KeyHandler.HandleInput()
/// - Parameters:
/// - input:
/// - state:
/// - stateCallback:
/// - errorCallback:
/// - Returns: IMK
func handleComposition(
input: InputSignal,
state: InputStateProtocol,
stateCallback: @escaping (InputStateProtocol) -> Void,
errorCallback: @escaping () -> Void
) -> Bool? {
// MARK: (Handle BPMF Keys)
var keyConsumedByReading = false
@ -63,7 +60,7 @@ extension KeyHandler {
}
}
var composeReading = composer.hasToneMarker() //
var composeReading = composer.hasToneMarker() && composer.inputValidityCheck(key: input.charCode) //
// Enter Space _composer
// |=
@ -81,9 +78,21 @@ extension KeyHandler {
if !currentLM.hasUnigramsFor(key: readingKey) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(readingKey)」的匹配記錄。")
errorCallback()
if mgrPrefs.keepReadingUponCompositionError {
composer.intonation.clear() // 調
stateCallback(buildInputtingState)
return true
}
composer.clear()
//
stateCallback((compositor.isEmpty) ? InputState.EmptyIgnoringPreviousState() : buildInputtingState)
switch compositor.isEmpty {
case false: stateCallback(buildInputtingState)
case true:
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
}
return true // IMK
}
@ -141,9 +150,7 @@ extension KeyHandler {
return true
}
/// true 調調
/// 6jˊˊ調
/// 調ˊˊˊˊˇˊ
/// 調
if keyConsumedByReading {
// updateClientComposingBuffer()
stateCallback(buildInputtingState)

View File

@ -159,8 +159,8 @@ extension KeyHandler {
// MARK: (Handle BPMF Keys)
if let compositionHandled = handleComposition(
input: input, state: state, stateCallback: stateCallback, errorCallback: errorCallback)
{
input: input, stateCallback: stateCallback, errorCallback: errorCallback
) {
return compositionHandled
}

View File

@ -38,7 +38,7 @@ extension KeyHandler {
/// (Update the composing buffer)
/// NSAttributeString
var tooltipParameterRef: [String] = ["", ""]
var composingBuffer = ""
let nodeValuesArray: [String] = walkedAnchors.map(\.node.currentPair.value)
var composedStringCursorIndex = 0
var readingCursorIndex = 0
/// IMK UTF8 emoji
@ -47,7 +47,6 @@ extension KeyHandler {
for theAnchor in walkedAnchors {
let theNode = theAnchor.node
let strNodeValue = theNode.currentPair.value
composingBuffer += strNodeValue
let arrSplit: [String] = Array(strNodeValue).map { String($0) }
let codepointCount = arrSplit.count
///
@ -57,16 +56,17 @@ extension KeyHandler {
if readingCursorIndex + spanningLength <= compositor.cursor {
composedStringCursorIndex += strNodeValue.utf16.count
readingCursorIndex += spanningLength
} else {
continue
}
if codepointCount == spanningLength {
var i = 0
while i < codepointCount, readingCursorIndex < compositor.cursor {
for i in 0..<codepointCount {
guard readingCursorIndex < compositor.cursor else { continue }
composedStringCursorIndex += arrSplit[i].utf16.count
readingCursorIndex += 1
i += 1
}
} else {
if readingCursorIndex < compositor.cursor {
continue
}
guard readingCursorIndex < compositor.cursor else { continue }
composedStringCursorIndex += strNodeValue.utf16.count
readingCursorIndex += spanningLength
readingCursorIndex = min(readingCursorIndex, compositor.cursor)
@ -85,29 +85,16 @@ extension KeyHandler {
tooltipParameterRef[0] = compositor.readings[compositor.cursor - 1]
tooltipParameterRef[1] = compositor.readings[compositor.cursor]
}
///
for (i, _) in tooltipParameterRef.enumerated() {
if tooltipParameterRef[i].isEmpty { continue }
if tooltipParameterRef[i].contains("_") { continue }
if mgrPrefs.showHanyuPinyinInCompositionBuffer { // ->->調
tooltipParameterRef[i] = Tekkon.restoreToneOneInZhuyinKey(target: tooltipParameterRef[i])
tooltipParameterRef[i] = Tekkon.cnvPhonaToHanyuPinyin(target: tooltipParameterRef[i])
tooltipParameterRef[i] = Tekkon.cnvHanyuPinyinToTextbookStyle(target: tooltipParameterRef[i])
} else {
tooltipParameterRef[i] = Tekkon.cnvZhuyinChainToTextbookReading(target: tooltipParameterRef[i])
}
}
}
}
}
}
isCursorCuttingChar = !tooltipParameterRef[0].isEmpty || !tooltipParameterRef[1].isEmpty
///
/// 便 composer
var arrHead = [String.UTF16View.Element]()
var arrTail = [String.UTF16View.Element]()
for (i, n) in composingBuffer.utf16.enumerated() {
for (i, n) in nodeValuesArray.joined().utf16.enumerated() {
if i < composedStringCursorIndex {
arrHead.append(n)
} else {
@ -126,42 +113,16 @@ extension KeyHandler {
//
var cleanedComposition = ""
for theChar in composedText {
if let charCode = theChar.utf16.first {
guard let charCode = theChar.utf16.first else { continue }
if !(theChar.isASCII && !(charCode.isPrintable)) {
cleanedComposition += String(theChar)
}
}
}
/// 使
let stateResult = InputState.Inputting(composingBuffer: cleanedComposition, cursorIndex: cursorIndex)
///
switch (tooltipParameterRef[0].isEmpty, tooltipParameterRef[1].isEmpty) {
case (true, true): stateResult.tooltip.removeAll()
case (true, false):
stateResult.tooltip = String(
format: NSLocalizedString("Cursor is to the rear of \"%@\".", comment: ""),
tooltipParameterRef[1]
return InputState.Inputting(
composingBuffer: cleanedComposition, cursorIndex: cursorIndex, reading: reading, nodeValuesArray: nodeValuesArray
)
case (false, true):
stateResult.tooltip = String(
format: NSLocalizedString("Cursor is in front of \"%@\".", comment: ""),
tooltipParameterRef[0]
)
case (false, false):
stateResult.tooltip = String(
format: NSLocalizedString("Cursor is between \"%@\" and \"%@\".", comment: ""),
tooltipParameterRef[0], tooltipParameterRef[1]
)
}
///
if !stateResult.tooltip.isEmpty {
ctlInputMethod.tooltipController.setColor(state: .denialOverflow)
}
return stateResult
}
// MARK: -
@ -459,8 +420,12 @@ extension KeyHandler {
composer.doBackSpace()
}
stateCallback(
composer.isEmpty && compositor.isEmpty ? InputState.EmptyIgnoringPreviousState() : buildInputtingState)
switch composer.isEmpty && compositor.isEmpty {
case false: stateCallback(buildInputtingState)
case true:
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
}
return true
}
@ -497,7 +462,12 @@ extension KeyHandler {
walk()
let inputting = buildInputtingState
// count > 0!isEmpty滿
stateCallback(inputting.composingBuffer.isEmpty ? InputState.EmptyIgnoringPreviousState() : inputting)
switch inputting.composingBuffer.isEmpty {
case false: stateCallback(inputting)
case true:
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
}
return true
}
@ -609,11 +579,17 @@ extension KeyHandler {
/// macOS Windows 使
clear()
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
} else {
if composer.isEmpty { return true }
///
composer.clear()
stateCallback(compositor.isEmpty ? InputState.EmptyIgnoringPreviousState() : buildInputtingState)
switch compositor.isEmpty {
case false: stateCallback(buildInputtingState)
case true:
stateCallback(InputState.EmptyIgnoringPreviousState())
stateCallback(InputState.Empty())
}
}
return true
}
@ -661,6 +637,7 @@ extension KeyHandler {
stateCallback(state)
}
} else if input.isOptionHold {
isCursorCuttingChar = false
if input.isControlHold {
return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
}
@ -675,7 +652,12 @@ extension KeyHandler {
} else {
if compositor.cursor < compositor.length {
compositor.cursor += 1
stateCallback(buildInputtingState)
var inputtingState = buildInputtingState
if isCursorCuttingChar == true {
compositor.jumpCursorBySpan(to: .front)
inputtingState = buildInputtingState
}
stateCallback(inputtingState)
} else {
IME.prtDebugIntel("A96AAD58")
errorCallback()
@ -729,6 +711,7 @@ extension KeyHandler {
stateCallback(state)
}
} else if input.isOptionHold {
isCursorCuttingChar = false
if input.isControlHold {
return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
}
@ -743,7 +726,12 @@ extension KeyHandler {
} else {
if compositor.cursor > 0 {
compositor.cursor -= 1
stateCallback(buildInputtingState)
var inputtingState = buildInputtingState
if isCursorCuttingChar == true {
compositor.jumpCursorBySpan(to: .rear)
inputtingState = buildInputtingState
}
stateCallback(inputtingState)
} else {
IME.prtDebugIntel("7045E6F3")
errorCallback()

View File

@ -41,7 +41,7 @@ class ctlInputMethod: IMKInputController {
static var areWeDeleting = false
///
static var ctlCandidateCurrent = ctlCandidateUniversal.init(.horizontal)
static var ctlCandidateCurrent: ctlCandidateProtocol = ctlCandidateUniversal.init(.horizontal)
///
static let tooltipController = TooltipController()
@ -85,6 +85,7 @@ class ctlInputMethod: IMKInputController {
keyHandler.delegate = self
//
activateServer(inputClient)
keyHandler.ensureParser()
resetKeyHandler()
}
@ -99,7 +100,7 @@ class ctlInputMethod: IMKInputController {
// activateServer nil
//
if keyHandler.delegate == nil { keyHandler.delegate = self }
setValue(IME.currentInputMode.rawValue, forTag: 114514, client: client())
keyHandler.clear()
keyHandler.ensureParser()
@ -236,4 +237,30 @@ class ctlInputMethod: IMKInputController {
_ = sender //
resetKeyHandler()
}
/// IMK
/// - Parameter sender: 使
/// - Returns: IMK
override func candidates(_ sender: Any!) -> [Any]! {
_ = sender //
if let state = state as? InputState.AssociatedPhrases {
return state.candidates.map { theCandidate -> String in
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
}
}
if let state = state as? InputState.ChoosingCandidate {
return state.candidates.map { theCandidate -> String in
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
}
}
if let state = state as? InputState.SymbolTable {
return state.candidates.map { theCandidate -> String in
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
}
}
return .init()
}
}

View File

@ -24,16 +24,16 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import Foundation
import Cocoa
// MARK: - KeyHandler Delegate
extension ctlInputMethod: KeyHandlerDelegate {
func ctlCandidate() -> ctlCandidate { ctlInputMethod.ctlCandidateCurrent }
func ctlCandidate() -> ctlCandidateProtocol { ctlInputMethod.ctlCandidateCurrent }
func keyHandler(
_: KeyHandler, didSelectCandidateAt index: Int,
ctlCandidate controller: ctlCandidate
ctlCandidate controller: ctlCandidateProtocol
) {
ctlCandidate(controller, didSelectCandidateAtIndex: index)
}
@ -70,7 +70,54 @@ extension ctlInputMethod: KeyHandlerDelegate {
// MARK: - Candidate Controller Delegate
extension ctlInputMethod: ctlCandidateDelegate {
func candidateCountForController(_ controller: ctlCandidate) -> Int {
func handleDelegateEvent(_ event: NSEvent!) -> Bool {
/// flags使 KeyHandler
/// flags
/// event.type == .flagsChanged return false
/// NSInternalInconsistencyException
if event.type == .flagsChanged {
return false
}
// Enter
ctlInputMethod.areWeDeleting = 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
}
let input = InputSignal(event: event, isVerticalTyping: isTypingVertical)
//
// KeyHandler
if !input.charCode.isPrintable {
return false
}
/// 調
/// result bool IMK
let result = keyHandler.handleCandidate(state: state, input: input) { newState in
self.handle(state: newState)
} errorCallback: {
clsSFX.beep()
}
return result
}
func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int {
_ = controller //
if let state = state as? InputState.ChoosingCandidate {
return state.candidates.count
@ -80,7 +127,20 @@ extension ctlInputMethod: ctlCandidateDelegate {
return 0
}
func ctlCandidate(_ controller: ctlCandidate, candidateAtIndex index: Int)
///
/// - Parameter controller:
/// - Returns:
func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)] {
_ = controller //
if let state = state as? InputState.ChoosingCandidate {
return state.candidates
} else if let state = state as? InputState.AssociatedPhrases {
return state.candidates
}
return .init()
}
func ctlCandidate(_ controller: ctlCandidateProtocol, candidateAtIndex index: Int)
-> (String, String)
{
_ = controller //
@ -92,7 +152,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
return ("", "")
}
func ctlCandidate(_ controller: ctlCandidate, didSelectCandidateAtIndex index: Int) {
func ctlCandidate(_ controller: ctlCandidateProtocol, didSelectCandidateAtIndex index: Int) {
_ = controller //
if let state = state as? InputState.SymbolTable,

View File

@ -81,11 +81,11 @@ extension ctlInputMethod {
/// macOS 10.x SwiftUI
if isCandidateWindowVertical { // 使
ctlInputMethod.ctlCandidateCurrent = .init(.vertical)
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.vertical)
} else if mgrPrefs.useHorizontalCandidateList {
ctlInputMethod.ctlCandidateCurrent = .init(.horizontal)
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.horizontal)
} else {
ctlInputMethod.ctlCandidateCurrent = .init(.vertical)
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.vertical)
}
// set the attributes for the candidate panel (which uses NSAttributedString)
@ -100,12 +100,22 @@ extension ctlInputMethod {
}
func candidateFont(name: String?, size: CGFloat) -> NSFont {
let currentMUIFont =
(keyHandler.inputMode == InputMode.imeModeCHS)
? "Sarasa Term Slab SC" : "Sarasa Term Slab TC"
var finalReturnFont =
NSFont(name: currentMUIFont, size: size) ?? NSFont.systemFont(ofSize: size)
// macOS 11 Big Sur macOS 12 Monterey 使
var finalReturnFont: NSFont =
{
switch IME.currentInputMode {
case InputMode.imeModeCHS:
return CTFontCreateUIFontForLanguage(.system, size, "zh-Hans" as CFString)
case InputMode.imeModeCHT:
return (mgrPrefs.shiftJISShinjitaiOutputEnabled || mgrPrefs.chineseConversionEnabled)
? CTFontCreateUIFontForLanguage(.system, size, "ja" as CFString)
: CTFontCreateUIFontForLanguage(.system, size, "zh-Hant" as CFString)
default:
return CTFontCreateUIFontForLanguage(.system, size, nil)
}
}()
?? NSFont.systemFont(ofSize: size)
// macOS 10.11-10.15 macOS 12 Monterey Bug
// macOS 12 Monterey ctlCandidateUniversal
if #available(macOS 12.0, *) { finalReturnFont = NSFont.systemFont(ofSize: size) }
if let name = name {
return NSFont(name: name, size: size) ?? finalReturnFont

View File

@ -26,56 +26,58 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import Cocoa
struct UserDef {
static let kIsDebugModeEnabled = "_DebugMode"
static let kMostRecentInputMode = "MostRecentInputMode"
static let kUserDataFolderSpecified = "UserDataFolderSpecified"
static let kCheckUpdateAutomatically = "CheckUpdateAutomatically"
static let kMandarinParser = "MandarinParser"
static let kBasicKeyboardLayout = "BasicKeyboardLayout"
static let kShowPageButtonsInCandidateWindow = "ShowPageButtonsInCandidateWindow"
static let kCandidateListTextSize = "CandidateListTextSize"
static let kAppleLanguages = "AppleLanguages"
static let kShouldAutoReloadUserDataFiles = "ShouldAutoReloadUserDataFiles"
static let kuseRearCursorMode = "useRearCursorMode"
static let kUseHorizontalCandidateList = "UseHorizontalCandidateList"
static let kComposingBufferSize = "ComposingBufferSize"
static let kChooseCandidateUsingSpace = "ChooseCandidateUsingSpace"
static let kCNS11643Enabled = "CNS11643Enabled"
static let kSymbolInputEnabled = "SymbolInputEnabled"
static let kChineseConversionEnabled = "ChineseConversionEnabled"
static let kShiftJISShinjitaiOutputEnabled = "ShiftJISShinjitaiOutputEnabled"
static let kCurrencyNumeralsEnabled = "CurrencyNumeralsEnabled"
static let kHalfWidthPunctuationEnabled = "HalfWidthPunctuationEnable"
static let kMoveCursorAfterSelectingCandidate = "MoveCursorAfterSelectingCandidate"
static let kEscToCleanInputBuffer = "EscToCleanInputBuffer"
static let kSpecifyShiftTabKeyBehavior = "SpecifyShiftTabKeyBehavior"
static let kSpecifyShiftSpaceKeyBehavior = "SpecifyShiftSpaceKeyBehavior"
static let kAllowBoostingSingleKanjiAsUserPhrase = "AllowBoostingSingleKanjiAsUserPhrase"
static let kUseSCPCTypingMode = "UseSCPCTypingMode"
static let kMaxCandidateLength = "MaxCandidateLength"
static let kShouldNotFartInLieuOfBeep = "ShouldNotFartInLieuOfBeep"
static let kShowHanyuPinyinInCompositionBuffer = "ShowHanyuPinyinInCompositionBuffer"
static let kInlineDumpPinyinInLieuOfZhuyin = "InlineDumpPinyinInLieuOfZhuyin"
static let kFetchSuggestionsFromUserOverrideModel = "FetchSuggestionsFromUserOverrideModel"
static let kUseFixecCandidateOrderOnSelection = "UseFixecCandidateOrderOnSelection"
static let kAutoCorrectReadingCombination = "AutoCorrectReadingCombination"
static let kAlsoConfirmAssociatedCandidatesByEnter = "AlsoConfirmAssociatedCandidatesByEnter"
public enum UserDef: String, CaseIterable {
case kIsDebugModeEnabled = "_DebugMode"
case kFailureFlagForUOMObservation = "_FailureFlag_UOMObservation"
case kMostRecentInputMode = "MostRecentInputMode"
case kUserDataFolderSpecified = "UserDataFolderSpecified"
case kCheckUpdateAutomatically = "CheckUpdateAutomatically"
case kMandarinParser = "MandarinParser"
case kBasicKeyboardLayout = "BasicKeyboardLayout"
case kShowPageButtonsInCandidateWindow = "ShowPageButtonsInCandidateWindow"
case kCandidateListTextSize = "CandidateListTextSize"
case kAppleLanguages = "AppleLanguages"
case kShouldAutoReloadUserDataFiles = "ShouldAutoReloadUserDataFiles"
case kUseRearCursorMode = "useRearCursorMode"
case kUseHorizontalCandidateList = "UseHorizontalCandidateList"
case kComposingBufferSize = "ComposingBufferSize"
case kChooseCandidateUsingSpace = "ChooseCandidateUsingSpace"
case kCNS11643Enabled = "CNS11643Enabled"
case kSymbolInputEnabled = "SymbolInputEnabled"
case kChineseConversionEnabled = "ChineseConversionEnabled"
case kShiftJISShinjitaiOutputEnabled = "ShiftJISShinjitaiOutputEnabled"
case kCurrencyNumeralsEnabled = "CurrencyNumeralsEnabled"
case kHalfWidthPunctuationEnabled = "HalfWidthPunctuationEnable"
case kMoveCursorAfterSelectingCandidate = "MoveCursorAfterSelectingCandidate"
case kEscToCleanInputBuffer = "EscToCleanInputBuffer"
case kSpecifyShiftTabKeyBehavior = "SpecifyShiftTabKeyBehavior"
case kSpecifyShiftSpaceKeyBehavior = "SpecifyShiftSpaceKeyBehavior"
case kAllowBoostingSingleKanjiAsUserPhrase = "AllowBoostingSingleKanjiAsUserPhrase"
case kUseSCPCTypingMode = "UseSCPCTypingMode"
case kMaxCandidateLength = "MaxCandidateLength"
case kShouldNotFartInLieuOfBeep = "ShouldNotFartInLieuOfBeep"
case kShowHanyuPinyinInCompositionBuffer = "ShowHanyuPinyinInCompositionBuffer"
case kInlineDumpPinyinInLieuOfZhuyin = "InlineDumpPinyinInLieuOfZhuyin"
case kFetchSuggestionsFromUserOverrideModel = "FetchSuggestionsFromUserOverrideModel"
case kUseFixecCandidateOrderOnSelection = "UseFixecCandidateOrderOnSelection"
case kAutoCorrectReadingCombination = "AutoCorrectReadingCombination"
case kAlsoConfirmAssociatedCandidatesByEnter = "AlsoConfirmAssociatedCandidatesByEnter"
case kKeepReadingUponCompositionError = "KeepReadingUponCompositionError"
static let kCandidateTextFontName = "CandidateTextFontName"
static let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
static let kCandidateKeys = "CandidateKeys"
case kCandidateTextFontName = "CandidateTextFontName"
case kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
case kCandidateKeys = "CandidateKeys"
static let kAssociatedPhrasesEnabled = "AssociatedPhrasesEnabled"
static let kPhraseReplacementEnabled = "PhraseReplacementEnabled"
case kAssociatedPhrasesEnabled = "AssociatedPhrasesEnabled"
case kPhraseReplacementEnabled = "PhraseReplacementEnabled"
static let kUsingHotKeySCPC = "UsingHotKeySCPC"
static let kUsingHotKeyAssociates = "UsingHotKeyAssociates"
static let kUsingHotKeyCNS = "UsingHotKeyCNS"
static let kUsingHotKeyKangXi = "UsingHotKeyKangXi"
static let kUsingHotKeyJIS = "UsingHotKeyJIS"
static let kUsingHotKeyHalfWidthASCII = "UsingHotKeyHalfWidthASCII"
static let kUsingHotKeyCurrencyNumerals = "UsingHotKeyCurrencyNumerals"
case kUsingHotKeySCPC = "UsingHotKeySCPC"
case kUsingHotKeyAssociates = "UsingHotKeyAssociates"
case kUsingHotKeyCNS = "UsingHotKeyCNS"
case kUsingHotKeyKangXi = "UsingHotKeyKangXi"
case kUsingHotKeyJIS = "UsingHotKeyJIS"
case kUsingHotKeyHalfWidthASCII = "UsingHotKeyHalfWidthASCII"
case kUsingHotKeyCurrencyNumerals = "UsingHotKeyCurrencyNumerals"
}
private let kDefaultCandidateListTextSize: CGFloat = 18
@ -237,92 +239,117 @@ enum MandarinParser: Int {
public enum mgrPrefs {
public static func setMissingDefaults() {
UserDefaults.standard.setDefault(mgrPrefs.isDebugModeEnabled, forKey: UserDef.kIsDebugModeEnabled)
UserDefaults.standard.setDefault(mgrPrefs.mostRecentInputMode, forKey: UserDef.kMostRecentInputMode)
UserDefaults.standard.setDefault(mgrPrefs.checkUpdateAutomatically, forKey: UserDef.kCheckUpdateAutomatically)
UserDefaults.standard.setDefault(mgrPrefs.isDebugModeEnabled, forKey: UserDef.kIsDebugModeEnabled.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.showPageButtonsInCandidateWindow, forKey: UserDef.kShowPageButtonsInCandidateWindow
mgrPrefs.failureFlagForUOMObservation, forKey: UserDef.kFailureFlagForUOMObservation.rawValue
)
UserDefaults.standard.setDefault(mgrPrefs.symbolInputEnabled, forKey: UserDef.kSymbolInputEnabled)
UserDefaults.standard.setDefault(mgrPrefs.candidateListTextSize, forKey: UserDef.kCandidateListTextSize)
UserDefaults.standard.setDefault(mgrPrefs.chooseCandidateUsingSpace, forKey: UserDef.kChooseCandidateUsingSpace)
UserDefaults.standard.setDefault(mgrPrefs.mostRecentInputMode, forKey: UserDef.kMostRecentInputMode.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.shouldAutoReloadUserDataFiles, forKey: UserDef.kShouldAutoReloadUserDataFiles
mgrPrefs.checkUpdateAutomatically, forKey: UserDef.kCheckUpdateAutomatically.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.specifyShiftTabKeyBehavior, forKey: UserDef.kSpecifyShiftTabKeyBehavior
mgrPrefs.showPageButtonsInCandidateWindow, forKey: UserDef.kShowPageButtonsInCandidateWindow.rawValue
)
UserDefaults.standard.setDefault(mgrPrefs.symbolInputEnabled, forKey: UserDef.kSymbolInputEnabled.rawValue)
UserDefaults.standard.setDefault(mgrPrefs.candidateListTextSize, forKey: UserDef.kCandidateListTextSize.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.chooseCandidateUsingSpace, forKey: UserDef.kChooseCandidateUsingSpace.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.specifyShiftSpaceKeyBehavior, forKey: UserDef.kSpecifyShiftSpaceKeyBehavior
)
UserDefaults.standard.setDefault(mgrPrefs.useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode)
UserDefaults.standard.setDefault(mgrPrefs.associatedPhrasesEnabled, forKey: UserDef.kAssociatedPhrasesEnabled)
UserDefaults.standard.setDefault(
mgrPrefs.useRearCursorMode, forKey: UserDef.kuseRearCursorMode
mgrPrefs.shouldAutoReloadUserDataFiles, forKey: UserDef.kShouldAutoReloadUserDataFiles.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.moveCursorAfterSelectingCandidate, forKey: UserDef.kMoveCursorAfterSelectingCandidate
mgrPrefs.specifyShiftTabKeyBehavior, forKey: UserDef.kSpecifyShiftTabKeyBehavior.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.useHorizontalCandidateList, forKey: UserDef.kUseHorizontalCandidateList
mgrPrefs.specifyShiftSpaceKeyBehavior, forKey: UserDef.kSpecifyShiftSpaceKeyBehavior.rawValue
)
UserDefaults.standard.setDefault(mgrPrefs.cns11643Enabled, forKey: UserDef.kCNS11643Enabled)
UserDefaults.standard.setDefault(mgrPrefs.chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled)
UserDefaults.standard.setDefault(mgrPrefs.useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled
)
UserDefaults.standard.setDefault(mgrPrefs.phraseReplacementEnabled, forKey: UserDef.kPhraseReplacementEnabled)
UserDefaults.standard.setDefault(mgrPrefs.shouldNotFartInLieuOfBeep, forKey: UserDef.kShouldNotFartInLieuOfBeep)
UserDefaults.standard.setDefault(
mgrPrefs.showHanyuPinyinInCompositionBuffer, forKey: UserDef.kShowHanyuPinyinInCompositionBuffer
mgrPrefs.associatedPhrasesEnabled, forKey: UserDef.kAssociatedPhrasesEnabled.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.inlineDumpPinyinInLieuOfZhuyin, forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin
mgrPrefs.useRearCursorMode, forKey: UserDef.kUseRearCursorMode.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase, forKey: UserDef.kAllowBoostingSingleKanjiAsUserPhrase
mgrPrefs.moveCursorAfterSelectingCandidate, forKey: UserDef.kMoveCursorAfterSelectingCandidate.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.fetchSuggestionsFromUserOverrideModel, forKey: UserDef.kFetchSuggestionsFromUserOverrideModel
mgrPrefs.useHorizontalCandidateList, forKey: UserDef.kUseHorizontalCandidateList.rawValue
)
UserDefaults.standard.setDefault(mgrPrefs.cns11643Enabled, forKey: UserDef.kCNS11643Enabled.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.useFixecCandidateOrderOnSelection, forKey: UserDef.kUseFixecCandidateOrderOnSelection
mgrPrefs.shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.autoCorrectReadingCombination, forKey: UserDef.kAutoCorrectReadingCombination
mgrPrefs.phraseReplacementEnabled, forKey: UserDef.kPhraseReplacementEnabled.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter, forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter
mgrPrefs.shouldNotFartInLieuOfBeep, forKey: UserDef.kShouldNotFartInLieuOfBeep.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.currencyNumeralsEnabled, forKey: UserDef.kCurrencyNumeralsEnabled
mgrPrefs.showHanyuPinyinInCompositionBuffer, forKey: UserDef.kShowHanyuPinyinInCompositionBuffer.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.inlineDumpPinyinInLieuOfZhuyin, forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase, forKey: UserDef.kAllowBoostingSingleKanjiAsUserPhrase.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.fetchSuggestionsFromUserOverrideModel, forKey: UserDef.kFetchSuggestionsFromUserOverrideModel.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.useFixecCandidateOrderOnSelection, forKey: UserDef.kUseFixecCandidateOrderOnSelection.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.autoCorrectReadingCombination, forKey: UserDef.kAutoCorrectReadingCombination.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter, forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.currencyNumeralsEnabled, forKey: UserDef.kCurrencyNumeralsEnabled.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.keepReadingUponCompositionError, forKey: UserDef.kKeepReadingUponCompositionError.rawValue
)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeySCPC, forKey: UserDef.kUsingHotKeySCPC)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyAssociates, forKey: UserDef.kUsingHotKeyAssociates)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyCNS, forKey: UserDef.kUsingHotKeyCNS)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyKangXi, forKey: UserDef.kUsingHotKeyKangXi)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyJIS, forKey: UserDef.kUsingHotKeyJIS)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyHalfWidthASCII, forKey: UserDef.kUsingHotKeyHalfWidthASCII)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyCurrencyNumerals, forKey: UserDef.kUsingHotKeyCurrencyNumerals)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeySCPC, forKey: UserDef.kUsingHotKeySCPC.rawValue)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyAssociates, forKey: UserDef.kUsingHotKeyAssociates.rawValue)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyCNS, forKey: UserDef.kUsingHotKeyCNS.rawValue)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyKangXi, forKey: UserDef.kUsingHotKeyKangXi.rawValue)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyJIS, forKey: UserDef.kUsingHotKeyJIS.rawValue)
UserDefaults.standard.setDefault(
mgrPrefs.usingHotKeyHalfWidthASCII, forKey: UserDef.kUsingHotKeyHalfWidthASCII.rawValue
)
UserDefaults.standard.setDefault(
mgrPrefs.usingHotKeyCurrencyNumerals, forKey: UserDef.kUsingHotKeyCurrencyNumerals.rawValue
)
UserDefaults.standard.synchronize()
}
@UserDefault(key: UserDef.kIsDebugModeEnabled, defaultValue: false)
@UserDefault(key: UserDef.kIsDebugModeEnabled.rawValue, defaultValue: false)
static var isDebugModeEnabled: Bool
@UserDefault(key: UserDef.kMostRecentInputMode, defaultValue: "")
@UserDefault(key: UserDef.kFailureFlagForUOMObservation.rawValue, defaultValue: false)
static var failureFlagForUOMObservation: Bool
@UserDefault(key: UserDef.kMostRecentInputMode.rawValue, defaultValue: "")
static var mostRecentInputMode: String
@UserDefault(key: UserDef.kCheckUpdateAutomatically, defaultValue: false)
@UserDefault(key: UserDef.kCheckUpdateAutomatically.rawValue, defaultValue: false)
static var checkUpdateAutomatically: Bool
@UserDefault(key: UserDef.kUserDataFolderSpecified, defaultValue: "")
@UserDefault(key: UserDef.kUserDataFolderSpecified.rawValue, defaultValue: "")
static var userDataFolderSpecified: String
static func ifSpecifiedUserDataPathExistsInPlist() -> Bool {
UserDefaults.standard.object(forKey: UserDef.kUserDataFolderSpecified) != nil
UserDefaults.standard.object(forKey: UserDef.kUserDataFolderSpecified.rawValue) != nil
}
static func resetSpecifiedUserDataFolder() {
@ -330,10 +357,10 @@ public enum mgrPrefs {
IME.initLangModels(userOnly: true)
}
@UserDefault(key: UserDef.kAppleLanguages, defaultValue: [])
@UserDefault(key: UserDef.kAppleLanguages.rawValue, defaultValue: [])
static var appleLanguages: [String]
@UserDefault(key: UserDef.kMandarinParser, defaultValue: 0)
@UserDefault(key: UserDef.kMandarinParser.rawValue, defaultValue: 0)
static var mandarinParser: Int
static var mandarinParserName: String {
@ -341,103 +368,106 @@ public enum mgrPrefs {
}
@UserDefault(
key: UserDef.kBasicKeyboardLayout, defaultValue: "com.apple.keylayout.ZhuyinBopomofo"
key: UserDef.kBasicKeyboardLayout.rawValue, defaultValue: "com.apple.keylayout.ZhuyinBopomofo"
)
static var basicKeyboardLayout: String
@UserDefault(key: UserDef.kShowPageButtonsInCandidateWindow, defaultValue: true)
@UserDefault(key: UserDef.kShowPageButtonsInCandidateWindow.rawValue, defaultValue: true)
static var showPageButtonsInCandidateWindow: Bool
@CandidateListTextSize(key: UserDef.kCandidateListTextSize)
@CandidateListTextSize(key: UserDef.kCandidateListTextSize.rawValue)
static var candidateListTextSize: CGFloat
static var minKeyLabelSize: CGFloat { kDefaultMinKeyLabelSize }
@UserDefault(key: UserDef.kShouldAutoReloadUserDataFiles, defaultValue: true)
@UserDefault(key: UserDef.kShouldAutoReloadUserDataFiles.rawValue, defaultValue: true)
static var shouldAutoReloadUserDataFiles: Bool
@UserDefault(key: UserDef.kuseRearCursorMode, defaultValue: false)
@UserDefault(key: UserDef.kUseRearCursorMode.rawValue, defaultValue: false)
static var useRearCursorMode: Bool
@UserDefault(key: UserDef.kMoveCursorAfterSelectingCandidate, defaultValue: true)
@UserDefault(key: UserDef.kMoveCursorAfterSelectingCandidate.rawValue, defaultValue: true)
static var moveCursorAfterSelectingCandidate: Bool
@UserDefault(key: UserDef.kUseHorizontalCandidateList, defaultValue: true)
@UserDefault(key: UserDef.kUseHorizontalCandidateList.rawValue, defaultValue: true)
static var useHorizontalCandidateList: Bool
@ComposingBufferSize(key: UserDef.kComposingBufferSize)
@ComposingBufferSize(key: UserDef.kComposingBufferSize.rawValue)
static var composingBufferSize: Int
@UserDefault(key: UserDef.kChooseCandidateUsingSpace, defaultValue: true)
@UserDefault(key: UserDef.kChooseCandidateUsingSpace.rawValue, defaultValue: true)
static var chooseCandidateUsingSpace: Bool
@UserDefault(key: UserDef.kAllowBoostingSingleKanjiAsUserPhrase, defaultValue: false)
@UserDefault(key: UserDef.kAllowBoostingSingleKanjiAsUserPhrase.rawValue, defaultValue: false)
static var allowBoostingSingleKanjiAsUserPhrase: Bool
@UserDefault(key: UserDef.kFetchSuggestionsFromUserOverrideModel, defaultValue: true)
@UserDefault(key: UserDef.kFetchSuggestionsFromUserOverrideModel.rawValue, defaultValue: true)
static var fetchSuggestionsFromUserOverrideModel: Bool
@UserDefault(key: UserDef.kUseFixecCandidateOrderOnSelection, defaultValue: false)
@UserDefault(key: UserDef.kUseFixecCandidateOrderOnSelection.rawValue, defaultValue: false)
static var useFixecCandidateOrderOnSelection: Bool
@UserDefault(key: UserDef.kAutoCorrectReadingCombination, defaultValue: true)
@UserDefault(key: UserDef.kAutoCorrectReadingCombination.rawValue, defaultValue: true)
static var autoCorrectReadingCombination: Bool
@UserDefault(key: UserDef.kAlsoConfirmAssociatedCandidatesByEnter, defaultValue: true)
@UserDefault(key: UserDef.kAlsoConfirmAssociatedCandidatesByEnter.rawValue, defaultValue: true)
static var alsoConfirmAssociatedCandidatesByEnter: Bool
@UserDefault(key: UserDef.kAlsoConfirmAssociatedCandidatesByEnter.rawValue, defaultValue: false)
static var keepReadingUponCompositionError: Bool
static var minCandidateLength: Int {
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2
}
@UserDefault(key: UserDef.kUseSCPCTypingMode, defaultValue: false)
@UserDefault(key: UserDef.kUseSCPCTypingMode.rawValue, defaultValue: false)
static var useSCPCTypingMode: Bool
static func toggleSCPCTypingModeEnabled() -> Bool {
useSCPCTypingMode = !useSCPCTypingMode
UserDefaults.standard.set(useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode)
UserDefaults.standard.set(useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode.rawValue)
return useSCPCTypingMode
}
@UserDefault(key: UserDef.kMaxCandidateLength, defaultValue: 10)
@UserDefault(key: UserDef.kMaxCandidateLength.rawValue, defaultValue: 10)
static var maxCandidateLength: Int
@UserDefault(key: UserDef.kShouldNotFartInLieuOfBeep, defaultValue: true)
@UserDefault(key: UserDef.kShouldNotFartInLieuOfBeep.rawValue, defaultValue: true)
static var shouldNotFartInLieuOfBeep: Bool
@UserDefault(key: UserDef.kShowHanyuPinyinInCompositionBuffer, defaultValue: false)
@UserDefault(key: UserDef.kShowHanyuPinyinInCompositionBuffer.rawValue, defaultValue: false)
static var showHanyuPinyinInCompositionBuffer: Bool
@UserDefault(key: UserDef.kInlineDumpPinyinInLieuOfZhuyin, defaultValue: false)
@UserDefault(key: UserDef.kInlineDumpPinyinInLieuOfZhuyin.rawValue, defaultValue: false)
static var inlineDumpPinyinInLieuOfZhuyin: Bool
static func toggleShouldNotFartInLieuOfBeep() -> Bool {
shouldNotFartInLieuOfBeep = !shouldNotFartInLieuOfBeep
UserDefaults.standard.set(shouldNotFartInLieuOfBeep, forKey: UserDef.kShouldNotFartInLieuOfBeep)
UserDefaults.standard.set(shouldNotFartInLieuOfBeep, forKey: UserDef.kShouldNotFartInLieuOfBeep.rawValue)
return shouldNotFartInLieuOfBeep
}
@UserDefault(key: UserDef.kCNS11643Enabled, defaultValue: false)
@UserDefault(key: UserDef.kCNS11643Enabled.rawValue, defaultValue: false)
static var cns11643Enabled: Bool
static func toggleCNS11643Enabled() -> Bool {
cns11643Enabled = !cns11643Enabled
mgrLangModel.setCNSEnabled(cns11643Enabled) //
UserDefaults.standard.set(cns11643Enabled, forKey: UserDef.kCNS11643Enabled)
UserDefaults.standard.set(cns11643Enabled, forKey: UserDef.kCNS11643Enabled.rawValue)
return cns11643Enabled
}
@UserDefault(key: UserDef.kSymbolInputEnabled, defaultValue: true)
@UserDefault(key: UserDef.kSymbolInputEnabled.rawValue, defaultValue: true)
static var symbolInputEnabled: Bool
static func toggleSymbolInputEnabled() -> Bool {
symbolInputEnabled = !symbolInputEnabled
mgrLangModel.setSymbolEnabled(symbolInputEnabled) //
UserDefaults.standard.set(symbolInputEnabled, forKey: UserDef.kSymbolInputEnabled)
UserDefaults.standard.set(symbolInputEnabled, forKey: UserDef.kSymbolInputEnabled.rawValue)
return symbolInputEnabled
}
@UserDefault(key: UserDef.kChineseConversionEnabled, defaultValue: false)
@UserDefault(key: UserDef.kChineseConversionEnabled.rawValue, defaultValue: false)
static var chineseConversionEnabled: Bool
@discardableResult static func toggleChineseConversionEnabled() -> Bool {
@ -446,14 +476,14 @@ public enum mgrPrefs {
if chineseConversionEnabled, shiftJISShinjitaiOutputEnabled {
toggleShiftJISShinjitaiOutputEnabled()
UserDefaults.standard.set(
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue
)
}
UserDefaults.standard.set(chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled)
UserDefaults.standard.set(chineseConversionEnabled, forKey: UserDef.kChineseConversionEnabled.rawValue)
return chineseConversionEnabled
}
@UserDefault(key: UserDef.kShiftJISShinjitaiOutputEnabled, defaultValue: false)
@UserDefault(key: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue, defaultValue: false)
static var shiftJISShinjitaiOutputEnabled: Bool
@discardableResult static func toggleShiftJISShinjitaiOutputEnabled() -> Bool {
@ -463,12 +493,12 @@ public enum mgrPrefs {
toggleChineseConversionEnabled()
}
UserDefaults.standard.set(
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled
shiftJISShinjitaiOutputEnabled, forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue
)
return shiftJISShinjitaiOutputEnabled
}
@UserDefault(key: UserDef.kCurrencyNumeralsEnabled, defaultValue: false)
@UserDefault(key: UserDef.kCurrencyNumeralsEnabled.rawValue, defaultValue: false)
static var currencyNumeralsEnabled: Bool
static func toggleCurrencyNumeralsEnabled() -> Bool {
@ -476,7 +506,7 @@ public enum mgrPrefs {
return currencyNumeralsEnabled
}
@UserDefault(key: UserDef.kHalfWidthPunctuationEnabled, defaultValue: false)
@UserDefault(key: UserDef.kHalfWidthPunctuationEnabled.rawValue, defaultValue: false)
static var halfWidthPunctuationEnabled: Bool
static func toggleHalfWidthPunctuationEnabled() -> Bool {
@ -484,24 +514,24 @@ public enum mgrPrefs {
return halfWidthPunctuationEnabled
}
@UserDefault(key: UserDef.kEscToCleanInputBuffer, defaultValue: true)
@UserDefault(key: UserDef.kEscToCleanInputBuffer.rawValue, defaultValue: true)
static var escToCleanInputBuffer: Bool
@UserDefault(key: UserDef.kSpecifyShiftTabKeyBehavior, defaultValue: false)
@UserDefault(key: UserDef.kSpecifyShiftTabKeyBehavior.rawValue, defaultValue: false)
static var specifyShiftTabKeyBehavior: Bool
@UserDefault(key: UserDef.kSpecifyShiftSpaceKeyBehavior, defaultValue: false)
@UserDefault(key: UserDef.kSpecifyShiftSpaceKeyBehavior.rawValue, defaultValue: false)
static var specifyShiftSpaceKeyBehavior: Bool
// MARK: - Optional settings
@UserDefault(key: UserDef.kCandidateTextFontName, defaultValue: nil)
@UserDefault(key: UserDef.kCandidateTextFontName.rawValue, defaultValue: nil)
static var candidateTextFontName: String?
@UserDefault(key: UserDef.kCandidateKeyLabelFontName, defaultValue: nil)
@UserDefault(key: UserDef.kCandidateKeyLabelFontName.rawValue, defaultValue: nil)
static var candidateKeyLabelFontName: String?
@UserDefault(key: UserDef.kCandidateKeys, defaultValue: kDefaultKeys)
@UserDefault(key: UserDef.kCandidateKeys.rawValue, defaultValue: kDefaultKeys)
static var candidateKeys: String
static var defaultCandidateKeys: String {
@ -566,46 +596,46 @@ public enum mgrPrefs {
}
}
@UserDefault(key: UserDef.kPhraseReplacementEnabled, defaultValue: false)
@UserDefault(key: UserDef.kPhraseReplacementEnabled.rawValue, defaultValue: false)
static var phraseReplacementEnabled: Bool
static func togglePhraseReplacementEnabled() -> Bool {
phraseReplacementEnabled = !phraseReplacementEnabled
mgrLangModel.setPhraseReplacementEnabled(phraseReplacementEnabled)
UserDefaults.standard.set(phraseReplacementEnabled, forKey: UserDef.kPhraseReplacementEnabled)
UserDefaults.standard.set(phraseReplacementEnabled, forKey: UserDef.kPhraseReplacementEnabled.rawValue)
return phraseReplacementEnabled
}
@UserDefault(key: UserDef.kAssociatedPhrasesEnabled, defaultValue: false)
@UserDefault(key: UserDef.kAssociatedPhrasesEnabled.rawValue, defaultValue: false)
static var associatedPhrasesEnabled: Bool
static func toggleAssociatedPhrasesEnabled() -> Bool {
associatedPhrasesEnabled = !associatedPhrasesEnabled
UserDefaults.standard.set(associatedPhrasesEnabled, forKey: UserDef.kAssociatedPhrasesEnabled)
UserDefaults.standard.set(associatedPhrasesEnabled, forKey: UserDef.kAssociatedPhrasesEnabled.rawValue)
return associatedPhrasesEnabled
}
// MARK: - Keyboard HotKey Enable / Disable
@UserDefault(key: UserDef.kUsingHotKeySCPC, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeySCPC.rawValue, defaultValue: true)
static var usingHotKeySCPC: Bool
@UserDefault(key: UserDef.kUsingHotKeyAssociates, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyAssociates.rawValue, defaultValue: true)
static var usingHotKeyAssociates: Bool
@UserDefault(key: UserDef.kUsingHotKeyCNS, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyCNS.rawValue, defaultValue: true)
static var usingHotKeyCNS: Bool
@UserDefault(key: UserDef.kUsingHotKeyKangXi, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyKangXi.rawValue, defaultValue: true)
static var usingHotKeyKangXi: Bool
@UserDefault(key: UserDef.kUsingHotKeyJIS, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyJIS.rawValue, defaultValue: true)
static var usingHotKeyJIS: Bool
@UserDefault(key: UserDef.kUsingHotKeyHalfWidthASCII, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyHalfWidthASCII.rawValue, defaultValue: true)
static var usingHotKeyHalfWidthASCII: Bool
@UserDefault(key: UserDef.kUsingHotKeyCurrencyNumerals, defaultValue: true)
@UserDefault(key: UserDef.kUsingHotKeyCurrencyNumerals.rawValue, defaultValue: true)
static var usingHotKeyCurrencyNumerals: Bool
}
@ -614,45 +644,23 @@ public enum mgrPrefs {
var snapshot: [String: Any]?
extension mgrPrefs {
static var allKeys: [String] {
[
UserDef.kIsDebugModeEnabled, UserDef.kMostRecentInputMode, UserDef.kUserDataFolderSpecified,
UserDef.kCheckUpdateAutomatically, UserDef.kMandarinParser, UserDef.kBasicKeyboardLayout,
UserDef.kShowPageButtonsInCandidateWindow, UserDef.kCandidateListTextSize, UserDef.kAppleLanguages,
UserDef.kShouldAutoReloadUserDataFiles, UserDef.kuseRearCursorMode, UserDef.kUseHorizontalCandidateList,
UserDef.kComposingBufferSize, UserDef.kChooseCandidateUsingSpace, UserDef.kCNS11643Enabled,
UserDef.kSymbolInputEnabled, UserDef.kChineseConversionEnabled, UserDef.kShiftJISShinjitaiOutputEnabled,
UserDef.kHalfWidthPunctuationEnabled, UserDef.kMoveCursorAfterSelectingCandidate, UserDef.kEscToCleanInputBuffer,
UserDef.kSpecifyShiftTabKeyBehavior, UserDef.kSpecifyShiftSpaceKeyBehavior,
UserDef.kAllowBoostingSingleKanjiAsUserPhrase, UserDef.kUseSCPCTypingMode, UserDef.kMaxCandidateLength,
UserDef.kShouldNotFartInLieuOfBeep, UserDef.kShowHanyuPinyinInCompositionBuffer,
UserDef.kInlineDumpPinyinInLieuOfZhuyin, UserDef.kFetchSuggestionsFromUserOverrideModel,
UserDef.kCandidateTextFontName, UserDef.kCandidateKeyLabelFontName, UserDef.kCandidateKeys,
UserDef.kAssociatedPhrasesEnabled, UserDef.kPhraseReplacementEnabled, UserDef.kUsingHotKeySCPC,
UserDef.kUsingHotKeyAssociates, UserDef.kUsingHotKeyCNS, UserDef.kUsingHotKeyKangXi, UserDef.kUsingHotKeyJIS,
UserDef.kUsingHotKeyHalfWidthASCII, UserDef.kUseFixecCandidateOrderOnSelection,
UserDef.kAutoCorrectReadingCombination, UserDef.kAlsoConfirmAssociatedCandidatesByEnter,
UserDef.kCurrencyNumeralsEnabled, UserDef.kUsingHotKeyCurrencyNumerals,
]
}
func reset() {
mgrPrefs.allKeys.forEach {
UserDefaults.standard.removeObject(forKey: $0)
UserDef.allCases.forEach {
UserDefaults.standard.removeObject(forKey: $0.rawValue)
}
}
func makeSnapshot() -> [String: Any] {
var dict = [String: Any]()
mgrPrefs.allKeys.forEach {
dict[$0] = UserDefaults.standard.object(forKey: $0)
UserDef.allCases.forEach {
dict[$0.rawValue] = UserDefaults.standard.object(forKey: $0.rawValue)
}
return dict
}
func restore(from snapshot: [String: Any]) {
mgrPrefs.allKeys.forEach {
UserDefaults.standard.set(snapshot[$0], forKey: $0)
UserDef.allCases.forEach {
UserDefaults.standard.set(snapshot[$0.rawValue], forKey: $0.rawValue)
}
}
}

View File

@ -62,7 +62,7 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
strData.ranges(splitBy: "\n").filter { !$0.isEmpty }.forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])

View File

@ -87,7 +87,7 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
strData.ranges(splitBy: "\n").filter { !$0.isEmpty }.forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2, String(neta[0]).first != "#" {
if !neta[0].isEmpty, !neta[1].isEmpty {

View File

@ -53,7 +53,7 @@ extension vChewing {
do {
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
strData = strData.replacingOccurrences(of: "\r", with: "\n")
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
strData.ranges(splitBy: "\n").filter { !$0.isEmpty }.forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])

View File

@ -326,9 +326,8 @@ extension vChewing.LMUserOverride {
public func saveData(toURL fileURL: URL) {
let encoder = JSONEncoder()
do {
if let jsonData = try? encoder.encode(mutLRUMap) {
guard let jsonData = try? encoder.encode(mutLRUMap) else { return }
try jsonData.write(to: fileURL, options: .atomic)
}
} catch {
IME.prtDebugIntel("UOM Error: Unable to save data, abort saving. Details: \(error)")
return

View File

@ -67,4 +67,6 @@ else {
exit(-1)
}
public let theServer = server
NSApp.run()

View File

@ -1,3 +1,5 @@
"vChewing" = "vChewing";
"vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability." = "vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability.";
"About vChewing…" = "About vChewing…";
"vChewing Preferences…" = "vChewing Preferences…";
"Uninstallation" = "Uninstallation";
@ -37,7 +39,7 @@
"Please specify at least 4 candidate keys." = "Please specify at least 4 candidate keys.";
"Maximum 15 candidate keys allowed." = "Maximum 15 candidate keys allowed.";
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ Phrase replacement mode enabled, interfering user phrase entry.";
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match.";
"⚠︎ Beware: Chars and Readings in buffer doesn't match." = "⚠︎ Beware: Chars and Readings in buffer doesn't match.";
"Per-Char Select Mode" = "Per-Char Select Mode";
"CNS11643 Mode" = "CNS11643 Mode";
"JIS Shinjitai Output" = "JIS Shinjitai Output";
@ -85,6 +87,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow backspace-editing miscomposed readings" = "Allow backspace-editing miscomposed readings";
"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";

View File

@ -1,3 +1,5 @@
"vChewing" = "vChewing";
"vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability." = "vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability.";
"About vChewing…" = "About vChewing…";
"vChewing Preferences…" = "vChewing Preferences…";
"Uninstallation" = "Uninstallation";
@ -37,7 +39,7 @@
"Please specify at least 4 candidate keys." = "Please specify at least 4 candidate keys.";
"Maximum 15 candidate keys allowed." = "Maximum 15 candidate keys allowed.";
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ Phrase replacement mode enabled, interfering user phrase entry.";
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match.";
"⚠︎ Beware: Chars and Readings in buffer doesn't match." = "⚠︎ Beware: Chars and Readings in buffer doesn't match.";
"Per-Char Select Mode" = "Per-Char Select Mode";
"CNS11643 Mode" = "CNS11643 Mode";
"JIS Shinjitai Output" = "JIS Shinjitai Output";
@ -85,6 +87,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow backspace-editing miscomposed readings" = "Allow backspace-editing miscomposed readings";
"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";

View File

@ -1,3 +1,5 @@
"vChewing" = "威注音入力アプリ";
"vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability." = "臨時記憶モジュールの観測行為による威注音入力アプリの意外中止は発生した。威注音入力アプリの無事利用のために、既存臨時記憶データは全てお消しした。";
"About vChewing…" = "威注音について…";
"vChewing Preferences…" = "入力機能設定…";
"Uninstallation" = "入力アプリの卸除(おろしのぞき)";
@ -37,7 +39,7 @@
"Please specify at least 4 candidate keys." = "言選り用キー陣列に少なくとも4つのキーをご登録ください。";
"Maximum 15 candidate keys allowed." = "言選り用キー陣列には最多15つキー登録できます。";
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 言葉置換機能稼働中、新添付言葉にも影響。";
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 緩衝列の字数は読みの数と不同等のため、対処不可。";
"⚠︎ Beware: Chars and Readings in buffer doesn't match." = "⚠︎ 注意:緩衝列の字数は読みの数と不同等。";
"Per-Char Select Mode" = "全候補入力モード";
"CNS11643 Mode" = "全字庫モード";
"JIS Shinjitai Output" = "JIS 新字体モード";
@ -85,6 +87,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow backspace-editing miscomposed readings" = "効かぬ音読みを BackSpace で再編集";
"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" = "候補文字を固定順番で陳列する";

View File

@ -1,3 +1,5 @@
"vChewing" = "威注音输入法";
"vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability." = "威注音输入法的使用者半衰记忆模组在观测时崩溃,相关半衰记忆资料档案内容已全部清空。";
"About vChewing…" = "关于威注音…";
"vChewing Preferences…" = "威注音偏好设定…";
"Uninstallation" = "卸除输入法";
@ -37,7 +39,7 @@
"Please specify at least 4 candidate keys." = "请至少指定四个选字键。";
"Maximum 15 candidate keys allowed." = "选字键最多只能指定十五个。";
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 语汇置换功能已启用,会波及语汇自订。";
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 无法处理组字区字数与读音数不对应的情形。";
"⚠︎ Beware: Chars and Readings in buffer doesn't match." = "⚠︎ 注意:组字区字数与读音数不对应。";
"Per-Char Select Mode" = "仿真逐字选字输入";
"CNS11643 Mode" = "全字库模式";
"JIS Shinjitai Output" = "JIS 新字体模式";
@ -85,6 +87,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)空格键:";
"Allow backspace-editing miscomposed readings" = "允许对无效的读音使用 BackSpace 编辑";
"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" = "以固定顺序来陈列选字窗内的候选字";

View File

@ -1,3 +1,5 @@
"vChewing" = "威注音輸入法";
"vChewing crashed while handling previously loaded UOM observation data. These data files are cleaned now to ensure the usability." = "威注音輸入法的使用者半衰記憶模組在觀測時崩潰,相關半衰記憶資料檔案內容已全部清空。";
"About vChewing…" = "關於威注音…";
"vChewing Preferences…" = "威注音偏好設定…";
"Uninstallation" = "卸除輸入法";
@ -37,7 +39,7 @@
"Please specify at least 4 candidate keys." = "請至少指定四個選字鍵。";
"Maximum 15 candidate keys allowed." = "選字鍵最多只能指定十五個。";
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 語彙置換功能已啟用,會波及語彙自訂。";
"⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 無法處理組字區字數與讀音數不對應的情形。";
"⚠︎ Beware: Chars and Readings in buffer doesn't match." = "⚠︎ 注意:組字區字數與讀音數不對應。";
"Per-Char Select Mode" = "模擬逐字選字輸入";
"CNS11643 Mode" = "全字庫模式";
"JIS Shinjitai Output" = "JIS 新字體模式";
@ -85,6 +87,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)空格鍵:";
"Allow backspace-editing miscomposed readings" = "允許對無效的讀音使用 BackSpace 編輯";
"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" = "以固定順序來陳列選字窗內的候選字";

View File

@ -26,6 +26,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import Cocoa
public enum CandidateLayout {
case horizontal
case vertical
}
public class CandidateKeyLabel: NSObject {
public private(set) var key: String
public private(set) var displayedText: String
@ -38,21 +43,39 @@ public class CandidateKeyLabel: NSObject {
}
public protocol ctlCandidateDelegate: AnyObject {
func candidateCountForController(_ controller: ctlCandidate) -> Int
func ctlCandidate(_ controller: ctlCandidate, candidateAtIndex index: Int)
func handleDelegateEvent(_ event: NSEvent!) -> Bool
func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int
func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)]
func ctlCandidate(_ controller: ctlCandidateProtocol, candidateAtIndex index: Int)
-> (String, String)
func ctlCandidate(
_ controller: ctlCandidate, didSelectCandidateAtIndex index: Int
_ controller: ctlCandidateProtocol, didSelectCandidateAtIndex index: Int
)
}
public class ctlCandidate: NSWindowController {
public enum Layout {
case horizontal
case vertical
}
public protocol ctlCandidateProtocol {
var currentLayout: CandidateLayout { get set }
var delegate: ctlCandidateDelegate? { get set }
var selectedCandidateIndex: Int { get set }
var visible: Bool { get set }
var windowTopLeftPoint: NSPoint { get set }
var keyLabels: [CandidateKeyLabel] { get set }
var keyLabelFont: NSFont { get set }
var candidateFont: NSFont { get set }
var tooltip: String { get set }
public var currentLayout: Layout = .horizontal
init(_ layout: CandidateLayout)
func reloadData()
func showNextPage() -> Bool
func showPreviousPage() -> Bool
func highlightNextCandidate() -> Bool
func highlightPreviousCandidate() -> Bool
func candidateIndexAtKeyLabelIndex(_: Int) -> Int
func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: CGFloat)
}
public class ctlCandidate: NSWindowController, ctlCandidateProtocol {
public var currentLayout: CandidateLayout = .horizontal
public weak var delegate: ctlCandidateDelegate? {
didSet {
reloadData()
@ -85,6 +108,16 @@ public class ctlCandidate: NSWindowController {
}
}
public required init(_: CandidateLayout = .horizontal) {
super.init(window: .init())
visible = false
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public var keyLabels: [CandidateKeyLabel] = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
.map {
CandidateKeyLabel(key: $0, displayedText: $0)

View File

@ -0,0 +1,141 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
2. No trademark license is granted to use the trade names, trademarks, service
marks, or product names of Contributor, except as required to fulfill notice
requirements above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import Foundation
import InputMethodKit
public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
public var currentLayout: CandidateLayout = .horizontal
public weak var delegate: ctlCandidateDelegate? {
didSet {
reloadData()
}
}
public var selectedCandidateIndex: Int = .max
public var visible: Bool = false {
didSet {
if visible {
show()
} else {
hide()
}
}
}
public var windowTopLeftPoint: NSPoint = .init(x: 0, y: 0) {
didSet {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
self.set(windowTopLeftPoint: self.windowTopLeftPoint, bottomOutOfScreenAdjustmentHeight: 0)
}
}
}
public var keyLabels: [CandidateKeyLabel] = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
.map {
CandidateKeyLabel(key: $0, displayedText: $0)
}
public var keyLabelFont: NSFont = NSFont.monospacedDigitSystemFont(
ofSize: 14, weight: .medium
)
public var candidateFont: NSFont = NSFont.systemFont(ofSize: 18)
public var tooltip: String = ""
var keyCount = 0
var displayedCandidates = [String]()
public func specifyLayout(_ layout: CandidateLayout = .horizontal) {
currentLayout = layout
switch currentLayout {
case .horizontal:
setPanelType(kIMKScrollingGridCandidatePanel)
case .vertical:
setPanelType(kIMKSingleColumnScrollingCandidatePanel)
}
setAttributes([IMKCandidatesSendServerKeyEventFirst: false])
}
public required init(_ layout: CandidateLayout = .horizontal) {
super.init(server: theServer, panelType: kIMKScrollingGridCandidatePanel)
specifyLayout(layout)
visible = false
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func reloadData() {
guard let delegate = delegate else { return }
let candidates = delegate.candidatesForController(self).map { theCandidate -> String in
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
}
setCandidateData(candidates)
keyCount = selectionKeys().count
selectedCandidateIndex = 0
update()
}
public func showNextPage() -> Bool {
if selectedCandidateIndex == candidates(self).count - 1 { return false }
selectedCandidateIndex = min(selectedCandidateIndex + keyCount, candidates(self).count - 1)
return selectCandidate(withIdentifier: selectedCandidateIndex)
}
public func showPreviousPage() -> Bool {
if selectedCandidateIndex == 0 { return true }
selectedCandidateIndex = max(selectedCandidateIndex - keyCount, 0)
return selectCandidate(withIdentifier: selectedCandidateIndex)
}
public func highlightNextCandidate() -> Bool {
if selectedCandidateIndex == candidates(self).count - 1 { return false }
selectedCandidateIndex = min(selectedCandidateIndex + 1, candidates(self).count - 1)
return selectCandidate(withIdentifier: selectedCandidateIndex)
}
public func highlightPreviousCandidate() -> Bool {
if selectedCandidateIndex == 0 { return true }
selectedCandidateIndex = max(selectedCandidateIndex - 1, 0)
return selectCandidate(withIdentifier: selectedCandidateIndex)
}
public func candidateIndexAtKeyLabelIndex(_: Int) -> Int {
selectedCandidateIndex
}
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight _: CGFloat = 0) {
setCandidateFrameTopLeft(windowTopLeftPoint)
}
override public func handle(_ event: NSEvent!, client _: Any!) -> Bool {
guard let delegate = delegate else { return false }
return delegate.handleDelegateEvent(event)
}
}

View File

@ -370,7 +370,7 @@ public class ctlCandidateUniversal: ctlCandidate {
private var nextPageButton: NSButton
private var pageCounterLabel: NSTextField
private var currentPageIndex: Int = 0
override public var currentLayout: Layout {
override public var currentLayout: CandidateLayout {
get { candidateView.isVerticalLayout ? .vertical : .horizontal }
set {
switch newValue {
@ -380,7 +380,7 @@ public class ctlCandidateUniversal: ctlCandidate {
}
}
public init(_ layout: Layout = .horizontal) {
public required init(_ layout: CandidateLayout = .horizontal) {
var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0)
let styleMask: NSWindow.StyleMask = [.nonactivatingPanel]
let panel = NSPanel(
@ -448,7 +448,8 @@ public class ctlCandidateUniversal: ctlCandidate {
// MARK: Post-Init()
super.init(window: panel)
super.init(layout)
window = panel
currentLayout = layout
candidateView.target = self

View File

@ -28,19 +28,19 @@ import SwiftUI
struct suiPrefPaneDictionary: View {
private var fdrDefault = mgrLangModel.dataFolderPath(isDefaultFolder: true)
@State private var tbxUserDataPathSpecified: String =
UserDefaults.standard.string(forKey: UserDef.kUserDataFolderSpecified)
UserDefaults.standard.string(forKey: UserDef.kUserDataFolderSpecified.rawValue)
?? mgrLangModel.dataFolderPath(isDefaultFolder: true)
@State private var selAutoReloadUserData: Bool = UserDefaults.standard.bool(
forKey: UserDef.kShouldAutoReloadUserDataFiles)
@State private var selEnableCNS11643: Bool = UserDefaults.standard.bool(forKey: UserDef.kCNS11643Enabled)
forKey: UserDef.kShouldAutoReloadUserDataFiles.rawValue)
@State private var selEnableCNS11643: Bool = UserDefaults.standard.bool(forKey: UserDef.kCNS11643Enabled.rawValue)
@State private var selEnableSymbolInputSupport: Bool = UserDefaults.standard.bool(
forKey: UserDef.kSymbolInputEnabled)
forKey: UserDef.kSymbolInputEnabled.rawValue)
@State private var selAllowBoostingSingleKanjiAsUserPhrase: Bool = UserDefaults.standard.bool(
forKey: UserDef.kAllowBoostingSingleKanjiAsUserPhrase)
forKey: UserDef.kAllowBoostingSingleKanjiAsUserPhrase.rawValue)
@State private var selFetchSuggestionsFromUserOverrideModel: Bool = UserDefaults.standard.bool(
forKey: UserDef.kFetchSuggestionsFromUserOverrideModel)
forKey: UserDef.kFetchSuggestionsFromUserOverrideModel.rawValue)
@State private var selUseFixecCandidateOrderOnSelection: Bool = UserDefaults.standard.bool(
forKey: UserDef.kUseFixecCandidateOrderOnSelection)
forKey: UserDef.kUseFixecCandidateOrderOnSelection.rawValue)
private let contentWidth: Double = {
switch mgrPrefs.appleLanguages[0] {
case "ja":

View File

@ -29,27 +29,30 @@ import SwiftUI
struct suiPrefPaneExperience: View {
@State private var selSelectionKeysList = mgrPrefs.suggestedCandidateKeys
@State private var selSelectionKeys =
(UserDefaults.standard.string(forKey: UserDef.kCandidateKeys) ?? mgrPrefs.defaultCandidateKeys) as String
(UserDefaults.standard.string(forKey: UserDef.kCandidateKeys.rawValue) ?? mgrPrefs.defaultCandidateKeys) as String
@State private var selCursorPosition =
UserDefaults.standard.bool(
forKey: UserDef.kuseRearCursorMode) ? 1 : 0
forKey: UserDef.kUseRearCursorMode.rawValue) ? 1 : 0
@State private var selPushCursorAfterSelection = UserDefaults.standard.bool(
forKey: UserDef.kMoveCursorAfterSelectingCandidate)
forKey: UserDef.kMoveCursorAfterSelectingCandidate.rawValue)
@State private var selKeyBehaviorShiftTab =
UserDefaults.standard.bool(forKey: UserDef.kSpecifyShiftTabKeyBehavior) ? 1 : 0
UserDefaults.standard.bool(forKey: UserDef.kSpecifyShiftTabKeyBehavior.rawValue) ? 1 : 0
@State private var selKeyBehaviorShiftSpace =
UserDefaults.standard.bool(
forKey: UserDef.kSpecifyShiftSpaceKeyBehavior) ? 1 : 0
forKey: UserDef.kSpecifyShiftSpaceKeyBehavior.rawValue) ? 1 : 0
@State private var selKeyBehaviorSpaceForCallingCandidate = UserDefaults.standard.bool(
forKey: UserDef.kChooseCandidateUsingSpace)
forKey: UserDef.kChooseCandidateUsingSpace.rawValue)
@State private var selKeyBehaviorESCForClearingTheBuffer = UserDefaults.standard.bool(
forKey: UserDef.kEscToCleanInputBuffer)
@State private var selEnableSCPCTypingMode = UserDefaults.standard.bool(forKey: UserDef.kUseSCPCTypingMode)
@State private var selComposingBufferSize = UserDefaults.standard.integer(forKey: UserDef.kComposingBufferSize)
forKey: UserDef.kEscToCleanInputBuffer.rawValue)
@State private var selEnableSCPCTypingMode = UserDefaults.standard.bool(forKey: UserDef.kUseSCPCTypingMode.rawValue)
@State private var selComposingBufferSize = UserDefaults.standard.integer(
forKey: UserDef.kComposingBufferSize.rawValue)
@State private var selAutoCorrectReadingCombination = UserDefaults.standard.bool(
forKey: UserDef.kAutoCorrectReadingCombination)
forKey: UserDef.kAutoCorrectReadingCombination.rawValue)
@State private var selAlsoConfirmAssociatedCandidatesByEnter = UserDefaults.standard.bool(
forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter)
forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter.rawValue)
@State private var selKeepReadingUponCompositionError = UserDefaults.standard.bool(
forKey: UserDef.kKeepReadingUponCompositionError.rawValue)
private let contentWidth: Double = {
switch mgrPrefs.appleLanguages[0] {
case "ja":
@ -188,6 +191,12 @@ struct suiPrefPaneExperience: View {
).onChange(of: selAlsoConfirmAssociatedCandidatesByEnter) { value in
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter = value
}
Toggle(
LocalizedStringKey("Allow backspace-editing miscomposed readings"),
isOn: $selKeepReadingUponCompositionError
).onChange(of: selKeepReadingUponCompositionError) { value in
mgrPrefs.keepReadingUponCompositionError = value
}
}
}
}

View File

@ -27,29 +27,32 @@ import SwiftUI
@available(macOS 11.0, *)
struct suiPrefPaneGeneral: View {
@State private var selCandidateUIFontSize = UserDefaults.standard.integer(forKey: UserDef.kCandidateListTextSize)
@State private var selCandidateUIFontSize = UserDefaults.standard.integer(
forKey: UserDef.kCandidateListTextSize.rawValue)
@State private var selUILanguage: [String] =
IME.arrSupportedLocales.contains(
((UserDefaults.standard.object(forKey: UserDef.kAppleLanguages) == nil)
? ["auto"] : UserDefaults.standard.array(forKey: UserDef.kAppleLanguages) as? [String] ?? ["auto"])[0])
? ((UserDefaults.standard.object(forKey: UserDef.kAppleLanguages) == nil)
? ["auto"] : UserDefaults.standard.array(forKey: UserDef.kAppleLanguages) as? [String] ?? ["auto"])
((UserDefaults.standard.object(forKey: UserDef.kAppleLanguages.rawValue) == nil)
? ["auto"] : UserDefaults.standard.array(forKey: UserDef.kAppleLanguages.rawValue) as? [String] ?? ["auto"])[0])
? ((UserDefaults.standard.object(forKey: UserDef.kAppleLanguages.rawValue) == nil)
? ["auto"] : UserDefaults.standard.array(forKey: UserDef.kAppleLanguages.rawValue) as? [String] ?? ["auto"])
: ["auto"]
@State private var selEnableHorizontalCandidateLayout = UserDefaults.standard.bool(
forKey: UserDef.kUseHorizontalCandidateList)
forKey: UserDef.kUseHorizontalCandidateList.rawValue)
@State private var selShowPageButtonsInCandidateUI = UserDefaults.standard.bool(
forKey: UserDef.kShowPageButtonsInCandidateWindow)
forKey: UserDef.kShowPageButtonsInCandidateWindow.rawValue)
@State private var selEnableKanjiConvToKangXi = UserDefaults.standard.bool(
forKey: UserDef.kChineseConversionEnabled)
forKey: UserDef.kChineseConversionEnabled.rawValue)
@State private var selEnableKanjiConvToJIS = UserDefaults.standard.bool(
forKey: UserDef.kShiftJISShinjitaiOutputEnabled)
forKey: UserDef.kShiftJISShinjitaiOutputEnabled.rawValue)
@State private var selShowHanyuPinyinInCompositionBuffer = UserDefaults.standard.bool(
forKey: UserDef.kShowHanyuPinyinInCompositionBuffer)
forKey: UserDef.kShowHanyuPinyinInCompositionBuffer.rawValue)
@State private var selInlineDumpPinyinInLieuOfZhuyin = UserDefaults.standard.bool(
forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin)
@State private var selEnableFartSuppressor = UserDefaults.standard.bool(forKey: UserDef.kShouldNotFartInLieuOfBeep)
@State private var selEnableAutoUpdateCheck = UserDefaults.standard.bool(forKey: UserDef.kCheckUpdateAutomatically)
@State private var selEnableDebugMode = UserDefaults.standard.bool(forKey: UserDef.kIsDebugModeEnabled)
forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin.rawValue)
@State private var selEnableFartSuppressor = UserDefaults.standard.bool(
forKey: UserDef.kShouldNotFartInLieuOfBeep.rawValue)
@State private var selEnableAutoUpdateCheck = UserDefaults.standard.bool(
forKey: UserDef.kCheckUpdateAutomatically.rawValue)
@State private var selEnableDebugMode = UserDefaults.standard.bool(forKey: UserDef.kIsDebugModeEnabled.rawValue)
private let contentWidth: Double = {
switch mgrPrefs.appleLanguages[0] {
case "ja":
@ -94,14 +97,14 @@ struct suiPrefPaneGeneral: View {
IME.prtDebugIntel(value[0])
if selUILanguage == mgrPrefs.appleLanguages
|| (selUILanguage[0] == "auto"
&& UserDefaults.standard.object(forKey: UserDef.kAppleLanguages) == nil)
&& UserDefaults.standard.object(forKey: UserDef.kAppleLanguages.rawValue) == nil)
{
return
}
if selUILanguage[0] != "auto" {
mgrPrefs.appleLanguages = value
} else {
UserDefaults.standard.removeObject(forKey: UserDef.kAppleLanguages)
UserDefaults.standard.removeObject(forKey: UserDef.kAppleLanguages.rawValue)
}
NSLog("vChewing App self-terminated due to UI language change.")
NSApplication.shared.terminate(nil)

View File

@ -26,19 +26,20 @@ import SwiftUI
@available(macOS 11.0, *)
struct suiPrefPaneKeyboard: View {
@State private var selMandarinParser = UserDefaults.standard.integer(forKey: UserDef.kMandarinParser)
@State private var selMandarinParser = UserDefaults.standard.integer(forKey: UserDef.kMandarinParser.rawValue)
@State private var selBasicKeyboardLayout: String =
UserDefaults.standard.string(forKey: UserDef.kBasicKeyboardLayout) ?? mgrPrefs.basicKeyboardLayout
UserDefaults.standard.string(forKey: UserDef.kBasicKeyboardLayout.rawValue) ?? mgrPrefs.basicKeyboardLayout
@State private var selUsingHotKeySCPC = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeySCPC)
@State private var selUsingHotKeyAssociates = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyAssociates)
@State private var selUsingHotKeyCNS = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyCNS)
@State private var selUsingHotKeyKangXi = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyKangXi)
@State private var selUsingHotKeyJIS = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyJIS)
@State private var selUsingHotKeySCPC = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeySCPC.rawValue)
@State private var selUsingHotKeyAssociates = UserDefaults.standard.bool(
forKey: UserDef.kUsingHotKeyAssociates.rawValue)
@State private var selUsingHotKeyCNS = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyCNS.rawValue)
@State private var selUsingHotKeyKangXi = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyKangXi.rawValue)
@State private var selUsingHotKeyJIS = UserDefaults.standard.bool(forKey: UserDef.kUsingHotKeyJIS.rawValue)
@State private var selUsingHotKeyHalfWidthASCII = UserDefaults.standard.bool(
forKey: UserDef.kUsingHotKeyHalfWidthASCII)
forKey: UserDef.kUsingHotKeyHalfWidthASCII.rawValue)
@State private var selUsingHotKeyCurrencyNumerals = UserDefaults.standard.bool(
forKey: UserDef.kUsingHotKeyCurrencyNumerals)
forKey: UserDef.kUsingHotKeyCurrencyNumerals.rawValue)
private let contentWidth: Double = {
switch mgrPrefs.appleLanguages[0] {

View File

@ -57,13 +57,13 @@ class ctlAboutWindow: NSWindowController {
)
}
@IBAction func btnBugReport(_ sender: NSButton) {
@IBAction func btnBugReport(_: NSButton) {
if let url = URL(string: "https://vchewing.github.io/BUGREPORT.html") {
NSWorkspace.shared.open(url)
}
}
@IBAction func btnWebsite(_ sender: NSButton) {
@IBAction func btnWebsite(_: NSButton) {
if let url = URL(string: "https://vchewing.github.io/") {
NSWorkspace.shared.open(url)
}

View File

@ -388,7 +388,8 @@ extension ctlPrefWindow: NSToolbarDelegate {
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences")
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences"
)
} else {
item.image = NSImage(named: NSImage.homeTemplateName)
}
@ -399,7 +400,8 @@ extension ctlPrefWindow: NSToolbarDelegate {
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences")
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences"
)
} else {
item.image = NSImage(named: NSImage.flowViewTemplateName)
}
@ -410,7 +412,8 @@ extension ctlPrefWindow: NSToolbarDelegate {
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences")
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences"
)
} else {
item.image = NSImage(named: NSImage.bookmarksTemplateName)
}

View File

@ -591,12 +591,23 @@
<binding destination="32" name="value" keyPath="values.AlsoConfirmAssociatedCandidatesByEnter" id="P1C-j9-N88"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="HaB-rc-AcW">
<rect key="frame" x="19" y="40.5" width="388" height="16"/>
<buttonCell key="cell" type="check" title="Allow backspace-editing miscomposed readings" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="chkKeepReadingUponCompositionError">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
<connections>
<binding destination="32" name="value" keyPath="values.KeepReadingUponCompositionError" id="ddF-qg-jes"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="n7q-ew-DYu" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="33" id="2gT-9Z-6F4"/>
<constraint firstItem="109" firstAttribute="top" secondItem="YkJ-lr-EP6" secondAttribute="bottom" constant="9" id="3tl-Zc-C5n"/>
<constraint firstItem="13" firstAttribute="top" secondItem="d5f-bq-dRQ" secondAttribute="bottom" constant="8" symbolic="YES" id="4pp-NX-pCc"/>
<constraint firstItem="YkJ-lr-EP6" firstAttribute="top" secondItem="J0f-Aw-dxC" secondAttribute="bottom" constant="7" id="5fd-qi-hJ6"/>
<constraint firstItem="HaB-rc-AcW" firstAttribute="leading" secondItem="6MM-WC-Mpd" secondAttribute="leading" id="7Fs-9l-g66"/>
<constraint firstItem="d5f-bq-dRQ" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="20" id="9wo-7x-RKb"/>
<constraint firstItem="TMn-LX-3Ub" firstAttribute="top" secondItem="7z2-DD-c58" secondAttribute="bottom" constant="9" id="AXY-LV-HMX"/>
<constraint firstItem="7z2-DD-c58" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="34" id="BUo-Us-u2B"/>
@ -618,6 +629,7 @@
<constraint firstItem="IpX-f7-rTL" firstAttribute="top" secondItem="XWo-36-xGi" secondAttribute="top" constant="20" id="YaG-ab-LJH"/>
<constraint firstItem="uHU-aL-du7" firstAttribute="top" secondItem="IpX-f7-rTL" secondAttribute="bottom" constant="8" symbolic="YES" id="aet-Zq-v6x"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="TMn-LX-3Ub" secondAttribute="trailing" constant="20" symbolic="YES" id="atz-4L-U9s"/>
<constraint firstItem="HaB-rc-AcW" firstAttribute="top" secondItem="6MM-WC-Mpd" secondAttribute="bottom" constant="6" symbolic="YES" id="cBa-57-gWH"/>
<constraint firstItem="ETa-09-qWI" firstAttribute="top" secondItem="IpX-f7-rTL" secondAttribute="bottom" constant="11" id="cx2-US-uOU"/>
<constraint firstItem="6MM-WC-Mpd" firstAttribute="top" secondItem="j8R-Hj-3dj" secondAttribute="bottom" constant="6" id="dmy-Au-peI"/>
<constraint firstItem="YkJ-lr-EP6" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="33" id="e3v-m2-co7"/>
@ -630,6 +642,7 @@
<constraint firstItem="6MM-WC-Mpd" firstAttribute="leading" secondItem="j8R-Hj-3dj" secondAttribute="leading" id="mbl-sV-kc8"/>
<constraint firstItem="mzw-F2-aAQ" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="20" id="pHT-DE-qdx"/>
<constraint firstItem="ETa-09-qWI" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="33" id="qFL-i6-eUT"/>
<constraint firstItem="HaB-rc-AcW" firstAttribute="trailing" secondItem="6MM-WC-Mpd" secondAttribute="trailing" id="rA7-0f-akd"/>
<constraint firstItem="JG6-RM-ZdJ" firstAttribute="top" secondItem="uHU-aL-du7" secondAttribute="bottom" constant="8" id="shS-7h-z7u"/>
<constraint firstItem="TMn-LX-3Ub" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="20" id="tFX-Eg-X70"/>
<constraint firstItem="J0f-Aw-dxC" firstAttribute="leading" secondItem="XWo-36-xGi" secondAttribute="leading" constant="20" id="v75-cS-TsO"/>

View File

@ -43,6 +43,7 @@
"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";
"chkKeepReadingUponCompositionError.title" = "Allow backspace-editing miscomposed readings";
"chkUseFixecCandidateOrderOnSelection.title" = "Always use fixed listing order in candidate window";
"DbW-eq-ZdB.title" = "Starlight";
"dIN-TZ-67g.title" = "Space to +cycle candidates, Shift+Space to +cycle pages";

View File

@ -43,6 +43,7 @@
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "Enter キーを連想語彙候補の確認のために使う";
"chkAutoCorrectReadingCombination.title" = "入力中で打ち間違った発音組み合わせを自動的に訂正する";
"chkFetchSuggestionsFromUserOverrideModel.title" = "入力中で臨時記憶モジュールからお薦めの候補を自動的に選ぶ";
"chkKeepReadingUponCompositionError.title" = "効かぬ音読みを BackSpace で再編集";
"chkUseFixecCandidateOrderOnSelection.title" = "候補文字を固定順番で陳列する";
"DbW-eq-ZdB.title" = "星光";
"dIN-TZ-67g.title" = "Shift+Space で次のページ、Space で次の候補文字を";

View File

@ -43,6 +43,7 @@
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允许使用 Enter 确认当前选中的联想词";
"chkAutoCorrectReadingCombination.title" = "敲字时自动纠正读音组合";
"chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字时自动套用来自半衰记忆模组的建议";
"chkKeepReadingUponCompositionError.title" = "允许对无效的读音使用 BackSpace 编辑";
"chkUseFixecCandidateOrderOnSelection.title" = "以固定顺序来陈列选字窗内的候选字";
"DbW-eq-ZdB.title" = "星光";
"dIN-TZ-67g.title" = "Shift+Space 换下一页Space 换选下一个候选字。";

View File

@ -43,6 +43,7 @@
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允許使用 Enter 確認當前選中的聯想詞";
"chkAutoCorrectReadingCombination.title" = "敲字時自動糾正讀音組合";
"chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字時自動套用來自半衰記憶模組的建議";
"chkKeepReadingUponCompositionError.title" = "允許對無效的讀音使用 BackSpace 編輯";
"chkUseFixecCandidateOrderOnSelection.title" = "以固定順序來陳列選字窗內的候選字";
"DbW-eq-ZdB.title" = "星光";
"dIN-TZ-67g.title" = "Shift+Space 換下一頁Space 換選下一個候選字";

View File

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

View File

@ -57,7 +57,7 @@ import Cocoa
)
}
@IBAction func btnWebsite(_ sender: NSButton) {
@IBAction func btnWebsite(_: NSButton) {
if let url = URL(string: "https://vchewing.github.io/") {
NSWorkspace.shared.open(url)
}

View File

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

View File

@ -116,6 +116,7 @@
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2528840E6200DBD48E /* template-replacements.txt */; };
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */; };
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */; };
5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */; };
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; };
6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; };
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; };
@ -320,6 +321,7 @@
5BF9DA2528840E6200DBD48E /* template-replacements.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-replacements.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-userphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-cht.txt"; path = "../Data/components/cht/template-associatedPhrases-cht.txt"; sourceTree = "<group>"; };
5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlCandidateIMK.swift; sourceTree = "<group>"; };
5BFDF48C27B51867009523B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; };
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewing.app; sourceTree = BUILT_PRODUCTS_DIR; };
6A0D4EF515FC0DA600ABF4B3 /* IME-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "IME-Info.plist"; sourceTree = "<group>"; };
@ -570,6 +572,7 @@
children = (
5B62A34027AE7CD900A19448 /* ctlCandidate.swift */,
5B242402284B0D6500520FE4 /* ctlCandidateUniversal.swift */,
5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */,
);
path = CandidateUI;
sourceTree = "<group>";
@ -1203,6 +1206,7 @@
5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */,
5B949BDB2816DDBC00D87B5D /* LMConsolidator.swift in Sources */,
5B38F59F281E2E49007D5F5D /* 3_NodeAnchor.swift in Sources */,
5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */,
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */,
5BA9FD3F27FEF3C8002DE248 /* Pane.swift in Sources */,
5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */,
@ -1393,7 +1397,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
@ -1403,7 +1407,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1432,13 +1436,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
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.6;
MARKETING_VERSION = 1.8.7;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1469,7 +1473,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@ -1490,7 +1494,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1519,7 +1523,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1536,7 +1540,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1650,7 +1654,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1678,7 +1682,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1705,7 +1709,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1727,7 +1731,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1749,7 +1753,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1769,7 +1773,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1791,7 +1795,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1986;
CURRENT_PROJECT_VERSION = 1987;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1805,7 +1809,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.6;
MARKETING_VERSION = 1.8.7;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -357,7 +357,7 @@ extension String {
extension vChewing.LMAssociates {
public mutating func forceOpenStringInstead(_ strData: String) {
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
strData.ranges(splitBy: "\n").filter { !$0.isEmpty }.forEach {
let neta = strData[$0].split(separator: " ")
if neta.count >= 2 {
let theKey = String(neta[0])