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
let isVertical: Bool = !(direction == .horizontal)
newAttributes[.verticalGlyphForm] = isVertical
@ -71,23 +71,14 @@ public class NSAttributedTextView: NSView {
newStyle.minimumLineHeight = fontSize * 1.1
}
newAttributes[.paragraphStyle] = newStyle
var text: String = 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: "")
var text: String = text ?? text ?? ""
if areaCalculation {
text = text.replacingOccurrences(
of: "[^\n]",
with: "",
options: .regularExpression,
range: text.range(of: text)
)
}
let attributedText = NSMutableAttributedString(string: text, attributes: newAttributes)
return attributedText
@ -109,10 +100,33 @@ public class NSAttributedTextView: NSView {
private var ctFrame: CTFrame?
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) {
let context = NSGraphicsContext.current?.cgContext
guard let context = context else { return }
let setter = CTFramesetterCreateWithAttributedString(attributedStringValue)
let setter = CTFramesetterCreateWithAttributedString(attributedStringValue())
let path = CGPath(rect: rect, transform: nil)
let theCTFrameProgression: CTFrameProgression = {
switch direction {
@ -134,3 +148,46 @@ public class NSAttributedTextView: NSView {
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: " ") {
compositor.insertKey(" ")
walk()
let inputting = buildInputtingState
// App
let textToCommit = commitOverflownComposition
var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting)
}
return true
@ -293,7 +296,10 @@ extension KeyHandler {
if composer.isEmpty {
compositor.insertKey("_punctuation_list")
walk()
let inputting = buildInputtingState
// App
let textToCommit = commitOverflownComposition
var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting)
stateCallback(buildCandidate(state: inputting))
} else { //

View File

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

View File

@ -81,11 +81,12 @@ class ctlInputMethod: IMKInputController {
keyHandler.composer.clear()
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.ofEmpty())
handle(state: isSecureMode ? IMEState.ofAbortion() : IMEState.ofEmpty())
}
// MARK: - IMKInputController

View File

@ -13,6 +13,15 @@ import Cocoa
// MARK: - Tooltip Display and Candidate Display Methods
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 {
var lineHeightRect = NSRect.seniorTheBeast
guard let client = client() else {

View File

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

View File

@ -208,7 +208,9 @@ extension ctlInputMethod {
@objc func showCheatSheet(_: Any?) {
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?) {

View File

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

View File

@ -9,6 +9,14 @@
import Cocoa
public class ctlPopupCompositionBuffer: NSWindowController {
public var isTypingDirectionVertical: Bool = false {
didSet {
if #unavailable(macOS 10.14) {
isTypingDirectionVertical = false
}
}
}
private var messageTextField: NSTextField
private var textShown: NSAttributedString = .init(string: "") {
didSet {
@ -18,18 +26,15 @@ public class ctlPopupCompositionBuffer: NSWindowController {
}
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 styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel(
contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false
)
panel.contentView = transparentVisualEffect
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true
panel.backgroundColor = NSColor.clear
panel.backgroundColor = NSColor.controlBackgroundColor
panel.styleMask = .fullSizeContentView
messageTextField = NSTextField()
messageTextField.isEditable = false
@ -40,6 +45,7 @@ public class ctlPopupCompositionBuffer: NSWindowController {
messageTextField.backgroundColor = NSColor.clear
messageTextField.font = .systemFont(ofSize: 18)
panel.contentView?.addSubview(messageTextField)
panel.contentView?.wantsLayer = true
super.init(window: panel)
}
@ -53,31 +59,74 @@ public class ctlPopupCompositionBuffer: NSWindowController {
hide()
return
}
//
let attrString: NSMutableAttributedString = .init(string: state.data.displayedTextConverted)
attrString.setAttributes(
[
.backgroundColor: NSColor.alternateSelectedControlColor,
.foregroundColor: NSColor.alternateSelectedControlTextColor,
let verticalAttributes: [NSAttributedString.Key: Any] = [
.verticalGlyphForm: true,
.paragraphStyle: {
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,
],
]
if isTypingDirectionVertical {
result[.paragraphStyle] = verticalAttributes[.paragraphStyle]
result[.verticalGlyphForm] = true
}
return result
}()
//
attrString.setAttributes(
markerAttributes,
range: NSRange(
location: state.data.u16MarkedRange.lowerBound,
length: state.data.u16MarkedRange.upperBound - state.data.u16MarkedRange.lowerBound
)
)
let attrCursor = NSMutableAttributedString(string: "_")
if #available(macOS 10.13, *) {
attrCursor.setAttributes(
[
.kern: -18,
.baselineOffset: -2,
.markedClauseSegment: 1,
],
range: NSRange(location: 0, length: attrCursor.string.utf16.count)
)
}
let cursorAttributes: [NSAttributedString.Key: Any] = {
var result: [NSAttributedString.Key: Any] = [
.kern: -18,
.foregroundColor: NSColor.textColor,
]
if isTypingDirectionVertical {
result[.paragraphStyle] = verticalAttributes[.paragraphStyle]
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)
textShown = attrString
messageTextField.maximumNumberOfLines = 1
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.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() {
@ -115,12 +168,21 @@ public class ctlPopupCompositionBuffer: NSWindowController {
options: [.usesLineFragmentOrigin, .usesFontLeading]
)
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
bigRect.size.width += NSFont.systemFontSize
bigRect.size.height += NSFont.systemFontSize
rect.origin.x += ceil(NSFont.systemFontSize / 2)
rect.origin.y += ceil(NSFont.systemFontSize / 2)
if isTypingDirectionVertical {
messageTextField.boundsRotation = 90
} else {
messageTextField.boundsRotation = 0
}
messageTextField.frame = rect
window?.setFrame(bigRect, display: true)
}

View File

@ -18,7 +18,7 @@ public class ctlTooltip: NSWindowController {
case prompt
}
private var messageText: NSAttributedTextView
private var messageText: NSAttributedTooltipTextView
private var tooltip: String = "" {
didSet {
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 {
if #unavailable(macOS 10.13) { 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.hasShadow = true
panel.backgroundColor = NSColor.controlBackgroundColor
messageText = NSAttributedTextView()
messageText = NSAttributedTooltipTextView()
messageText.backgroundColor = NSColor.controlBackgroundColor
messageText.textColor = NSColor.textColor
panel.contentView?.addSubview(messageText)
@ -58,7 +58,7 @@ public class ctlTooltip: NSWindowController {
public func show(
tooltip: String = "", at point: NSPoint,
bottomOutOfScreenAdjustmentHeight heightDelta: CGFloat,
direction: NSAttributedTextView.writingDirection = .horizontal
direction: NSAttributedTooltipTextView.writingDirection = .horizontal
) {
self.direction = direction
self.tooltip = tooltip
@ -147,24 +147,7 @@ public class ctlTooltip: NSWindowController {
}
private func adjustSize() {
let attrString = messageText.attributedStringValue
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 rect = messageText.shrinkFrame()
var bigRect = rect
bigRect.size.width += 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.";
"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." = "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";
"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." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.";
"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." = "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";
"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空白の記録値は無視される。";
"Just Select" = "直接に選ぶ";
"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" = "入れる";
"Remove Selected" = "外す";
"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空白值会被无视。";
"Just Select" = "直接选取";
"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" = "登记新客体";
"Remove Selected" = "移除所选条目";
"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空白值會被無視。";
"Just Select" = "直接選取";
"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" = "登記新客體";
"Remove Selected" = "移除所選條目";
"Choose the target application bundle." = "請選擇要登記的應用程式的封包。";

View File

@ -165,7 +165,7 @@ extension ctlClientListMgr {
guard let window = window else { return }
window.title = NSLocalizedString("Client Manager", comment: "")
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: ""
)
btnAddClient.title = NSLocalizedString("Add Client", comment: "")

View File

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

View File

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

View File

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