2.6.1 // Security enhancement. Merge PR #136 from upd/2.6.1

This commit is contained in:
ShikiSuen 2022-09-13 22:01:07 +08:00 committed by GitHub
commit cd20b97a7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 226 additions and 100 deletions

View File

@ -60,7 +60,7 @@ public class NSAttributedTextView: NSView {
} }
} }
public var attributedStringValue: NSAttributedString { public func attributedStringValue(areaCalculation: Bool = false) -> NSAttributedString {
var newAttributes = attributes var newAttributes = attributes
let isVertical: Bool = !(direction == .horizontal) let isVertical: Bool = !(direction == .horizontal)
newAttributes[.verticalGlyphForm] = isVertical newAttributes[.verticalGlyphForm] = isVertical
@ -71,23 +71,14 @@ public class NSAttributedTextView: NSView {
newStyle.minimumLineHeight = fontSize * 1.1 newStyle.minimumLineHeight = fontSize * 1.1
} }
newAttributes[.paragraphStyle] = newStyle newAttributes[.paragraphStyle] = newStyle
var text: String = text ?? "" var text: String = text ?? text ?? ""
if !(direction == .horizontal) { if areaCalculation {
text = text.replacingOccurrences(of: "˙", with: "") text = text.replacingOccurrences(
text = text.replacingOccurrences(of: "\u{A0}", with: " ") of: "[^\n]",
text = text.replacingOccurrences(of: "+", with: "") with: "",
text = text.replacingOccurrences(of: "Shift", with: "") options: .regularExpression,
text = text.replacingOccurrences(of: "Control", with: "") range: text.range(of: text)
text = text.replacingOccurrences(of: "Enter", with: "") )
text = text.replacingOccurrences(of: "Command", with: "")
text = text.replacingOccurrences(of: "Delete", with: "")
text = text.replacingOccurrences(of: "BackSpace", with: "")
text = text.replacingOccurrences(of: "SHIFT", with: "")
text = text.replacingOccurrences(of: "CONTROL", with: "")
text = text.replacingOccurrences(of: "ENTER", with: "")
text = text.replacingOccurrences(of: "COMMAND", with: "")
text = text.replacingOccurrences(of: "DELETE", with: "")
text = text.replacingOccurrences(of: "BACKSPACE", with: "")
} }
let attributedText = NSMutableAttributedString(string: text, attributes: newAttributes) let attributedText = NSMutableAttributedString(string: text, attributes: newAttributes)
return attributedText return attributedText
@ -109,10 +100,33 @@ public class NSAttributedTextView: NSView {
private var ctFrame: CTFrame? private var ctFrame: CTFrame?
private(set) var currentRect: NSRect? private(set) var currentRect: NSRect?
@discardableResult public func shrinkFrame() -> NSRect {
let attrString: NSAttributedString = {
switch direction {
case .horizontal: return attributedStringValue()
default: return attributedStringValue(areaCalculation: true)
}
}()
var rect = attrString.boundingRect(
with: NSSize(width: 1600.0, height: 1600.0),
options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics]
)
rect.size.height *= 1.03
rect.size.height = max(rect.size.height, NSFont.systemFontSize * 1.1)
rect.size.height = ceil(rect.size.height)
rect.size.width *= 1.03
rect.size.width = max(rect.size.width, NSFont.systemFontSize * 1.05)
rect.size.width = ceil(rect.size.width)
if direction != .horizontal {
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
}
return rect
}
override public func draw(_ rect: CGRect) { override public func draw(_ rect: CGRect) {
let context = NSGraphicsContext.current?.cgContext let context = NSGraphicsContext.current?.cgContext
guard let context = context else { return } guard let context = context else { return }
let setter = CTFramesetterCreateWithAttributedString(attributedStringValue) let setter = CTFramesetterCreateWithAttributedString(attributedStringValue())
let path = CGPath(rect: rect, transform: nil) let path = CGPath(rect: rect, transform: nil)
let theCTFrameProgression: CTFrameProgression = { let theCTFrameProgression: CTFrameProgression = {
switch direction { switch direction {
@ -134,3 +148,46 @@ public class NSAttributedTextView: NSView {
CTFrameDraw(newFrame, context) CTFrameDraw(newFrame, context)
} }
} }
public class NSAttributedTooltipTextView: NSAttributedTextView {
override public func attributedStringValue(areaCalculation: Bool = false) -> NSAttributedString {
var newAttributes = attributes
let isVertical: Bool = !(direction == .horizontal)
newAttributes[.verticalGlyphForm] = isVertical
let newStyle: NSMutableParagraphStyle = newAttributes[.paragraphStyle] as! NSMutableParagraphStyle
if #available(macOS 10.13, *) {
newStyle.lineSpacing = isVertical ? (fontSize / -2) : fontSize * 0.1
newStyle.maximumLineHeight = fontSize * 1.1
newStyle.minimumLineHeight = fontSize * 1.1
}
newAttributes[.paragraphStyle] = newStyle
var text: String = text ?? text ?? ""
if !(direction == .horizontal) {
text = text.replacingOccurrences(of: "˙", with: "")
text = text.replacingOccurrences(of: "\u{A0}", with: " ")
text = text.replacingOccurrences(of: "+", with: "")
text = text.replacingOccurrences(of: "Shift", with: "")
text = text.replacingOccurrences(of: "Control", with: "")
text = text.replacingOccurrences(of: "Enter", with: "")
text = text.replacingOccurrences(of: "Command", with: "")
text = text.replacingOccurrences(of: "Delete", with: "")
text = text.replacingOccurrences(of: "BackSpace", with: "")
text = text.replacingOccurrences(of: "SHIFT", with: "")
text = text.replacingOccurrences(of: "CONTROL", with: "")
text = text.replacingOccurrences(of: "ENTER", with: "")
text = text.replacingOccurrences(of: "COMMAND", with: "")
text = text.replacingOccurrences(of: "DELETE", with: "")
text = text.replacingOccurrences(of: "BACKSPACE", with: "")
}
if areaCalculation {
text = text.replacingOccurrences(
of: "[^\n]",
with: "",
options: .regularExpression,
range: text.range(of: text)
)
}
let attributedText = NSMutableAttributedString(string: text, attributes: newAttributes)
return attributedText
}
}

@ -1 +1 @@
Subproject commit eeff2e3f7073873c07b4011717e32430db01227f Subproject commit c5b2fe7f08971cf2719f553de9de967097bd56b6

View File

@ -174,7 +174,10 @@ extension KeyHandler {
} else if currentLM.hasUnigramsFor(key: " ") { } else if currentLM.hasUnigramsFor(key: " ") {
compositor.insertKey(" ") compositor.insertKey(" ")
walk() walk()
let inputting = buildInputtingState // App
let textToCommit = commitOverflownComposition
var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting) stateCallback(inputting)
} }
return true return true
@ -293,7 +296,10 @@ extension KeyHandler {
if composer.isEmpty { if composer.isEmpty {
compositor.insertKey("_punctuation_list") compositor.insertKey("_punctuation_list")
walk() walk()
let inputting = buildInputtingState // App
let textToCommit = commitOverflownComposition
var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting) stateCallback(inputting)
stateCallback(buildCandidate(state: inputting)) stateCallback(buildCandidate(state: inputting))
} else { // } else { //

View File

@ -274,7 +274,10 @@ extension KeyHandler {
compositor.insertKey(customPunctuation) compositor.insertKey(customPunctuation)
walk() walk()
let inputting = buildInputtingState // App
let textToCommit = commitOverflownComposition
var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting) stateCallback(inputting)
// //

View File

@ -81,11 +81,12 @@ class ctlInputMethod: IMKInputController {
keyHandler.composer.clear() keyHandler.composer.clear()
handle(state: keyHandler.buildInputtingState) handle(state: keyHandler.buildInputtingState)
} }
if state.hasComposition { let isSecureMode = mgrPrefs.clientsIMKTextInputIncapable.contains(clientBundleIdentifier)
if state.hasComposition, !isSecureMode {
/// 調 /// 調
handle(state: IMEState.ofCommitting(textToCommit: state.displayedText)) handle(state: IMEState.ofCommitting(textToCommit: state.displayedText))
} }
handle(state: IMEState.ofEmpty()) handle(state: isSecureMode ? IMEState.ofAbortion() : IMEState.ofEmpty())
} }
// MARK: - IMKInputController // MARK: - IMKInputController

View File

@ -13,6 +13,15 @@ import Cocoa
// MARK: - Tooltip Display and Candidate Display Methods // MARK: - Tooltip Display and Candidate Display Methods
extension ctlInputMethod { extension ctlInputMethod {
// App 使
// App App
// 使 20
var attributedStringSecured: (NSAttributedString, NSRange) {
mgrPrefs.clientsIMKTextInputIncapable.contains(clientBundleIdentifier)
? (state.data.attributedStringPlaceholder, NSRange(location: 0, length: 0))
: (state.attributedString, NSRange(state.data.u16MarkedRange))
}
func lineHeightRect(zeroCursor: Bool = false) -> NSRect { func lineHeightRect(zeroCursor: Bool = false) -> NSRect {
var lineHeightRect = NSRect.seniorTheBeast var lineHeightRect = NSRect.seniorTheBeast
guard let client = client() else { guard let client = client() else {

View File

@ -83,6 +83,7 @@ extension ctlInputMethod {
} }
// //
if state.hasComposition, mgrPrefs.clientsIMKTextInputIncapable.contains(clientBundleIdentifier) { if state.hasComposition, mgrPrefs.clientsIMKTextInputIncapable.contains(clientBundleIdentifier) {
ctlInputMethod.popupCompositionBuffer.isTypingDirectionVertical = isVerticalTyping
ctlInputMethod.popupCompositionBuffer.show( ctlInputMethod.popupCompositionBuffer.show(
state: state, at: lineHeightRect(zeroCursor: true).origin state: state, at: lineHeightRect(zeroCursor: true).origin
) )
@ -96,7 +97,7 @@ extension ctlInputMethod {
guard let client = client() else { return } guard let client = client() else { return }
if state.type == .ofAssociates { if state.type == .ofAssociates {
client.setMarkedText( client.setMarkedText(
state.attributedString, selectionRange: NSRange(location: 0, length: 0), state.data.attributedStringPlaceholder, selectionRange: NSRange(location: 0, length: 0),
replacementRange: NSRange(location: NSNotFound, length: NSNotFound) replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
) )
return return
@ -107,7 +108,7 @@ extension ctlInputMethod {
/// 0 replacementRangeNSNotFound /// 0 replacementRangeNSNotFound
/// ///
client.setMarkedText( client.setMarkedText(
state.attributedString, selectionRange: NSRange(state.data.u16MarkedRange), attributedStringSecured.0, selectionRange: attributedStringSecured.1,
replacementRange: NSRange(location: NSNotFound, length: NSNotFound) replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
) )
return return

View File

@ -208,7 +208,9 @@ extension ctlInputMethod {
@objc func showCheatSheet(_: Any?) { @objc func showCheatSheet(_: Any?) {
guard let url = Bundle.main.url(forResource: "shortcuts", withExtension: "html") else { return } guard let url = Bundle.main.url(forResource: "shortcuts", withExtension: "html") else { return }
NSWorkspace.shared.openFile(url.path, withApplication: "Safari") DispatchQueue.main.async {
NSWorkspace.shared.openFile(url.path, withApplication: "Safari")
}
} }
@objc func showClientListMgr(_: Any?) { @objc func showClientListMgr(_: Any?) {

View File

@ -125,7 +125,9 @@ public enum IME {
// MARK: - Open a phrase data file. // MARK: - Open a phrase data file.
static func openPhraseFile(fromURL url: URL) { static func openPhraseFile(fromURL url: URL) {
openPhraseFile(userFileAt: url.path) DispatchQueue.main.async {
openPhraseFile(userFileAt: url.path)
}
} }
static func openPhraseFile(userFileAt path: String) { static func openPhraseFile(userFileAt path: String) {

View File

@ -9,6 +9,14 @@
import Cocoa import Cocoa
public class ctlPopupCompositionBuffer: NSWindowController { public class ctlPopupCompositionBuffer: NSWindowController {
public var isTypingDirectionVertical: Bool = false {
didSet {
if #unavailable(macOS 10.14) {
isTypingDirectionVertical = false
}
}
}
private var messageTextField: NSTextField private var messageTextField: NSTextField
private var textShown: NSAttributedString = .init(string: "") { private var textShown: NSAttributedString = .init(string: "") {
didSet { didSet {
@ -18,18 +26,15 @@ public class ctlPopupCompositionBuffer: NSWindowController {
} }
public init() { public init() {
let transparentVisualEffect = NSVisualEffectView()
transparentVisualEffect.blendingMode = .behindWindow
transparentVisualEffect.state = .active
let contentRect = NSRect(x: 128.0, y: 128.0, width: 300.0, height: 20.0) let contentRect = NSRect(x: 128.0, y: 128.0, width: 300.0, height: 20.0)
let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel] let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel( let panel = NSPanel(
contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false
) )
panel.contentView = transparentVisualEffect
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1) panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true panel.hasShadow = true
panel.backgroundColor = NSColor.clear panel.backgroundColor = NSColor.controlBackgroundColor
panel.styleMask = .fullSizeContentView
messageTextField = NSTextField() messageTextField = NSTextField()
messageTextField.isEditable = false messageTextField.isEditable = false
@ -40,6 +45,7 @@ public class ctlPopupCompositionBuffer: NSWindowController {
messageTextField.backgroundColor = NSColor.clear messageTextField.backgroundColor = NSColor.clear
messageTextField.font = .systemFont(ofSize: 18) messageTextField.font = .systemFont(ofSize: 18)
panel.contentView?.addSubview(messageTextField) panel.contentView?.addSubview(messageTextField)
panel.contentView?.wantsLayer = true
super.init(window: panel) super.init(window: panel)
} }
@ -53,31 +59,74 @@ public class ctlPopupCompositionBuffer: NSWindowController {
hide() hide()
return return
} }
//
let attrString: NSMutableAttributedString = .init(string: state.data.displayedTextConverted) let attrString: NSMutableAttributedString = .init(string: state.data.displayedTextConverted)
attrString.setAttributes( let verticalAttributes: [NSAttributedString.Key: Any] = [
[ .verticalGlyphForm: true,
.backgroundColor: NSColor.alternateSelectedControlColor, .paragraphStyle: {
.foregroundColor: NSColor.alternateSelectedControlTextColor, let newStyle = NSMutableParagraphStyle()
if #available(macOS 10.13, *) {
let fontSize = messageTextField.font?.pointSize ?? 18
newStyle.lineSpacing = fontSize / -3
newStyle.maximumLineHeight = fontSize
newStyle.minimumLineHeight = fontSize
}
return newStyle
}(),
]
if isTypingDirectionVertical {
attrString.setAttributes(
verticalAttributes, range: NSRange(location: 0, length: attrString.string.utf16.count)
)
}
let markerAttributes: [NSAttributedString.Key: Any] = {
var result: [NSAttributedString.Key: Any] = [
.backgroundColor: IME.isDarkMode ? NSColor.systemRed : NSColor.systemYellow,
.markedClauseSegment: 0, .markedClauseSegment: 0,
], ]
if isTypingDirectionVertical {
result[.paragraphStyle] = verticalAttributes[.paragraphStyle]
result[.verticalGlyphForm] = true
}
return result
}()
//
attrString.setAttributes(
markerAttributes,
range: NSRange( range: NSRange(
location: state.data.u16MarkedRange.lowerBound, location: state.data.u16MarkedRange.lowerBound,
length: state.data.u16MarkedRange.upperBound - state.data.u16MarkedRange.lowerBound length: state.data.u16MarkedRange.upperBound - state.data.u16MarkedRange.lowerBound
) )
) )
let attrCursor = NSMutableAttributedString(string: "_")
if #available(macOS 10.13, *) { let cursorAttributes: [NSAttributedString.Key: Any] = {
attrCursor.setAttributes( var result: [NSAttributedString.Key: Any] = [
[ .kern: -18,
.kern: -18, .foregroundColor: NSColor.textColor,
.baselineOffset: -2, ]
.markedClauseSegment: 1, if isTypingDirectionVertical {
], result[.paragraphStyle] = verticalAttributes[.paragraphStyle]
range: NSRange(location: 0, length: attrCursor.string.utf16.count) result[.verticalGlyphForm] = true
) result[.baselineOffset] = 3
} } else {
result[.baselineOffset] = -2
}
if #unavailable(macOS 10.13) {
result[.kern] = 0
result[.baselineOffset] = 0
}
return result
}()
let attrCursor: NSAttributedString =
isTypingDirectionVertical
? NSMutableAttributedString(string: "", attributes: cursorAttributes)
: NSMutableAttributedString(string: "_", attributes: cursorAttributes)
attrString.insert(attrCursor, at: state.data.u16Cursor) attrString.insert(attrCursor, at: state.data.u16Cursor)
textShown = attrString textShown = attrString
messageTextField.maximumNumberOfLines = 1 messageTextField.maximumNumberOfLines = 1
if let editor = messageTextField.currentEditor() { if let editor = messageTextField.currentEditor() {
@ -105,7 +154,11 @@ public class ctlPopupCompositionBuffer: NSWindowController {
adjustedPoint.y = min(max(adjustedPoint.y, screenFrame.minY + windowSize.height), screenFrame.maxY) adjustedPoint.y = min(max(adjustedPoint.y, screenFrame.minY + windowSize.height), screenFrame.maxY)
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width) adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width)
window.setFrameOrigin(adjustedPoint) if isTypingDirectionVertical {
window.setFrameTopLeftPoint(adjustedPoint)
} else {
window.setFrameOrigin(adjustedPoint)
}
} }
private func adjustSize() { private func adjustSize() {
@ -115,12 +168,21 @@ public class ctlPopupCompositionBuffer: NSWindowController {
options: [.usesLineFragmentOrigin, .usesFontLeading] options: [.usesLineFragmentOrigin, .usesFontLeading]
) )
rect.size.width = max(rect.size.width, 20 * CGFloat(attrString.string.count)) + 2 rect.size.width = max(rect.size.width, 20 * CGFloat(attrString.string.count)) + 2
rect.size.height = 22 rect.size.height *= 1.2
rect.size.height = max(22, rect.size.height)
if isTypingDirectionVertical {
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
}
var bigRect = rect var bigRect = rect
bigRect.size.width += NSFont.systemFontSize bigRect.size.width += NSFont.systemFontSize
bigRect.size.height += NSFont.systemFontSize bigRect.size.height += NSFont.systemFontSize
rect.origin.x += ceil(NSFont.systemFontSize / 2) rect.origin.x += ceil(NSFont.systemFontSize / 2)
rect.origin.y += ceil(NSFont.systemFontSize / 2) rect.origin.y += ceil(NSFont.systemFontSize / 2)
if isTypingDirectionVertical {
messageTextField.boundsRotation = 90
} else {
messageTextField.boundsRotation = 0
}
messageTextField.frame = rect messageTextField.frame = rect
window?.setFrame(bigRect, display: true) window?.setFrame(bigRect, display: true)
} }

View File

@ -18,7 +18,7 @@ public class ctlTooltip: NSWindowController {
case prompt case prompt
} }
private var messageText: NSAttributedTextView private var messageText: NSAttributedTooltipTextView
private var tooltip: String = "" { private var tooltip: String = "" {
didSet { didSet {
messageText.text = tooltip.isEmpty ? nil : tooltip messageText.text = tooltip.isEmpty ? nil : tooltip
@ -26,7 +26,7 @@ public class ctlTooltip: NSWindowController {
} }
} }
public var direction: NSAttributedTextView.writingDirection = .horizontal { public var direction: NSAttributedTooltipTextView.writingDirection = .horizontal {
didSet { didSet {
if #unavailable(macOS 10.13) { direction = .horizontal } if #unavailable(macOS 10.13) { direction = .horizontal }
if Bundle.main.preferredLocalizations[0] == "en" { direction = .horizontal } if Bundle.main.preferredLocalizations[0] == "en" { direction = .horizontal }
@ -43,7 +43,7 @@ public class ctlTooltip: NSWindowController {
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 2) panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 2)
panel.hasShadow = true panel.hasShadow = true
panel.backgroundColor = NSColor.controlBackgroundColor panel.backgroundColor = NSColor.controlBackgroundColor
messageText = NSAttributedTextView() messageText = NSAttributedTooltipTextView()
messageText.backgroundColor = NSColor.controlBackgroundColor messageText.backgroundColor = NSColor.controlBackgroundColor
messageText.textColor = NSColor.textColor messageText.textColor = NSColor.textColor
panel.contentView?.addSubview(messageText) panel.contentView?.addSubview(messageText)
@ -58,7 +58,7 @@ public class ctlTooltip: NSWindowController {
public func show( public func show(
tooltip: String = "", at point: NSPoint, tooltip: String = "", at point: NSPoint,
bottomOutOfScreenAdjustmentHeight heightDelta: CGFloat, bottomOutOfScreenAdjustmentHeight heightDelta: CGFloat,
direction: NSAttributedTextView.writingDirection = .horizontal direction: NSAttributedTooltipTextView.writingDirection = .horizontal
) { ) {
self.direction = direction self.direction = direction
self.tooltip = tooltip self.tooltip = tooltip
@ -147,24 +147,7 @@ public class ctlTooltip: NSWindowController {
} }
private func adjustSize() { private func adjustSize() {
let attrString = messageText.attributedStringValue var rect = messageText.shrinkFrame()
var rect = attrString.boundingRect(
with: NSSize(width: 1600.0, height: 1600.0),
options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics]
)
if direction != .horizontal {
rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width)
rect.size.height += NSFont.systemFontSize
rect.size.width *= 1.03
rect.size.width = max(rect.size.width, NSFont.systemFontSize * 1.05)
rect.size.width = ceil(rect.size.width)
} else {
rect = .init(x: rect.minX, y: rect.minY, width: rect.width, height: rect.height)
rect.size.width += NSFont.systemFontSize
rect.size.height *= 1.03
rect.size.height = max(rect.size.height, NSFont.systemFontSize * 1.05)
rect.size.height = ceil(rect.size.height)
}
var bigRect = rect var bigRect = rect
bigRect.size.width += NSFont.systemFontSize bigRect.size.width += NSFont.systemFontSize
bigRect.size.height += NSFont.systemFontSize bigRect.size.height += NSFont.systemFontSize

View File

@ -3,7 +3,7 @@
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed."; "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.";
"Just Select" = "Just Select"; "Just Select" = "Just Select";
"Client Manager" = "Client Manager"; "Client Manager" = "Client Manager";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable."; "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable.";
"Add Client" = "Add Client"; "Add Client" = "Add Client";
"Remove Selected" = "Remove Selected"; "Remove Selected" = "Remove Selected";
"Choose the target application bundle." = "Choose the target application bundle."; "Choose the target application bundle." = "Choose the target application bundle.";

View File

@ -3,7 +3,7 @@
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed."; "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.";
"Just Select" = "Just Select"; "Just Select" = "Just Select";
"Client Manager" = "Client Manager"; "Client Manager" = "Client Manager";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable."; "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable.";
"Add Client" = "Add Client"; "Add Client" = "Add Client";
"Remove Selected" = "Remove Selected"; "Remove Selected" = "Remove Selected";
"Choose the target application bundle." = "Choose the target application bundle."; "Choose the target application bundle." = "Choose the target application bundle.";

View File

@ -3,7 +3,7 @@
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "毎行はつ記録とみなす。Option+Enter キーで改行。\n空白の記録値は無視される。"; "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "毎行はつ記録とみなす。Option+Enter キーで改行。\n空白の記録値は無視される。";
"Just Select" = "直接に選ぶ"; "Just Select" = "直接に選ぶ";
"Client Manager" = "客体アプリの管理"; "Client Manager" = "客体アプリの管理";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "IMKTextInput 議定規約に従っていない客体アプリはここでご登録ください。登録済みのアプリは客体アプリ(文字入力を受くアプリ)とされた時に、威注音入力アプリは「吹き出し入力緩衝列ウィンドウ」と「緩衝列容量制限」を起用し、その容量制限は最大限音読み20箇とする。"; "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "下記の種類の客体アプリはここでご登録くださいIMKTextInput 議定規約に反するもの;2)文脈内入力緩衝列の内容の不正利用の疑いのあるもの。登録済みのアプリには、威注音入力アプリは「吹き出し入力緩衝列ウィンドウ」と「緩衝列容量制限」を起用し、容量制限は最大限音読み20箇とする。";
"Add Client" = "入れる"; "Add Client" = "入れる";
"Remove Selected" = "外す"; "Remove Selected" = "外す";
"Choose the target application bundle." = "登録したいアプリのバンドルのお選びを。"; "Choose the target application bundle." = "登録したいアプリのバンドルのお選びを。";

View File

@ -3,7 +3,7 @@
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一笔记录,用 Option+Enter 换行。\n空白值会被无视。"; "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一笔记录,用 Option+Enter 换行。\n空白值会被无视。";
"Just Select" = "直接选取"; "Just Select" = "直接选取";
"Client Manager" = "管理客体应用"; "Client Manager" = "管理客体应用";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "请在此管理那些不遵守 IMKTextInput 协定的客体应用。威注音输入法对于任何位列在此的客体应用均启用浮动组字窗、且对组字区内容设定容量上限(最多二十个读音)。"; "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "请在此管理这两类客体应用1) 不遵守 IMKTextInput 协定2有滥用内文组字区的嫌疑。威注音输入法对于任何位列在此的客体应用均启用浮动组字窗、且对组字区内容设定容量上限(最多二十个读音)。";
"Add Client" = "登记新客体"; "Add Client" = "登记新客体";
"Remove Selected" = "移除所选条目"; "Remove Selected" = "移除所选条目";
"Choose the target application bundle." = "请选择要登记的应用程式的封包。"; "Choose the target application bundle." = "请选择要登记的应用程式的封包。";

View File

@ -3,7 +3,7 @@
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一筆記錄,用 Option+Enter 換行。\n空白值會被無視。"; "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一筆記錄,用 Option+Enter 換行。\n空白值會被無視。";
"Just Select" = "直接選取"; "Just Select" = "直接選取";
"Client Manager" = "管理客體應用"; "Client Manager" = "管理客體應用";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "請在此管理那些不遵守 IMKTextInput 協定的客體應用。威注音輸入法對於任何位列在此的客體應用均啟用浮動組字窗、且對組字區內容設定容量上限(最多二十個讀音)。"; "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "請在此管理這兩類客體應用1) 不遵守 IMKTextInput 協定2有濫用內文組字區的嫌疑。威注音輸入法對於任何位列在此的客體應用均啟用浮動組字窗、且對組字區內容設定容量上限(最多二十個讀音)。";
"Add Client" = "登記新客體"; "Add Client" = "登記新客體";
"Remove Selected" = "移除所選條目"; "Remove Selected" = "移除所選條目";
"Choose the target application bundle." = "請選擇要登記的應用程式的封包。"; "Choose the target application bundle." = "請選擇要登記的應用程式的封包。";

View File

@ -165,7 +165,7 @@ extension ctlClientListMgr {
guard let window = window else { return } guard let window = window else { return }
window.title = NSLocalizedString("Client Manager", comment: "") window.title = NSLocalizedString("Client Manager", comment: "")
lblClientMgrWindow.stringValue = NSLocalizedString( lblClientMgrWindow.stringValue = NSLocalizedString(
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable.", "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable.",
comment: "" comment: ""
) )
btnAddClient.title = NSLocalizedString("Add Client", comment: "") btnAddClient.title = NSLocalizedString("Add Client", comment: "")

View File

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

View File

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

View File

@ -1483,7 +1483,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
@ -1493,7 +1493,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1522,13 +1522,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1560,7 +1560,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1582,7 +1582,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1612,7 +1612,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -1630,7 +1630,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1746,7 +1746,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1775,7 +1775,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1805,7 +1805,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1828,7 +1828,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -1852,7 +1852,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1873,7 +1873,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1896,7 +1896,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2602; CURRENT_PROJECT_VERSION = 2610;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1911,7 +1911,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.6.0; MARKETING_VERSION = 2.6.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";