Repo // Swap NSRange to Range when necessary.

- Also let utf16SubString() retrieve Swift range parameters.
This commit is contained in:
ShikiSuen 2022-06-02 22:12:00 +08:00
parent af08a31efa
commit aff3a2014e
3 changed files with 37 additions and 43 deletions

View File

@ -157,7 +157,7 @@ class InputState {
/// Represents that the user is marking a range in the composing buffer. /// Represents that the user is marking a range in the composing buffer.
class Marking: NotEmpty { class Marking: NotEmpty {
private(set) var markerIndex: Int = 0 { didSet { markerIndex = max(markerIndex, 0) } } private(set) var markerIndex: Int = 0 { didSet { markerIndex = max(markerIndex, 0) } }
private(set) var markedRange: NSRange private(set) var markedRange: Range<Int>
private var deleteTargetExists = false private var deleteTargetExists = false
var tooltip: String { var tooltip: String {
if composingBuffer.count != readings.count { if composingBuffer.count != readings.count {
@ -172,19 +172,19 @@ class InputState {
"⚠︎ Phrase replacement mode enabled, interfering user phrase entry.", comment: "" "⚠︎ Phrase replacement mode enabled, interfering user phrase entry.", comment: ""
) )
} }
if markedRange.length == 0 { if markedRange.isEmpty {
return "" return ""
} }
let text = composingBuffer.utf16SubString(with: markedRange) let text = composingBuffer.utf16SubString(with: markedRange)
if markedRange.length < kMinMarkRangeLength { if markedRange.count < kMinMarkRangeLength {
ctlInputMethod.tooltipController.setColor(state: .denialInsufficiency) ctlInputMethod.tooltipController.setColor(state: .denialInsufficiency)
return String( return String(
format: NSLocalizedString( format: NSLocalizedString(
"\"%@\" length must ≥ 2 for a user phrase.", comment: "" "\"%@\" length must ≥ 2 for a user phrase.", comment: ""
), text ), text
) )
} else if markedRange.length > kMaxMarkRangeLength { } else if markedRange.count > kMaxMarkRangeLength {
ctlInputMethod.tooltipController.setColor(state: .denialOverflow) ctlInputMethod.tooltipController.setColor(state: .denialOverflow)
return String( return String(
format: NSLocalizedString( format: NSLocalizedString(
@ -194,9 +194,8 @@ class InputState {
) )
} }
let (exactBegin, _) = composingBuffer.utf16CharIndex(from: markedRange.location) let exactBegin = composingBuffer.utf16CharIndex(from: markedRange.lowerBound)
let (exactEnd, _) = composingBuffer.utf16CharIndex( let exactEnd = composingBuffer.utf16CharIndex(from: markedRange.upperBound)
from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") let joined = selectedReadings.joined(separator: "-")
let exist = mgrLangModel.checkIfUserPhraseExist( let exist = mgrLangModel.checkIfUserPhraseExist(
@ -225,26 +224,30 @@ class InputState {
self.markerIndex = markerIndex self.markerIndex = markerIndex
let begin = min(cursorIndex, markerIndex) let begin = min(cursorIndex, markerIndex)
let end = max(cursorIndex, markerIndex) let end = max(cursorIndex, markerIndex)
markedRange = NSRange(location: begin, length: end - begin) markedRange = begin..<end
self.readings = readings self.readings = readings
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex) super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
} }
var attributedString: NSAttributedString { var attributedString: NSAttributedString {
let attributedString = NSMutableAttributedString(string: composingBuffer) let attributedString = NSMutableAttributedString(string: composingBuffer)
let end = markedRange.location + markedRange.length let end = markedRange.upperBound
attributedString.setAttributes( attributedString.setAttributes(
[ [
.underlineStyle: NSUnderlineStyle.single.rawValue, .underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0, .markedClauseSegment: 0,
], range: NSRange(location: 0, length: markedRange.location) ], range: NSRange(location: 0, length: markedRange.lowerBound)
) )
attributedString.setAttributes( attributedString.setAttributes(
[ [
.underlineStyle: NSUnderlineStyle.thick.rawValue, .underlineStyle: NSUnderlineStyle.thick.rawValue,
.markedClauseSegment: 1, .markedClauseSegment: 1,
], range: markedRange ],
range: NSRange(
location: markedRange.lowerBound,
length: markedRange.upperBound - markedRange.lowerBound
)
) )
attributedString.setAttributes( attributedString.setAttributes(
[ [
@ -277,24 +280,23 @@ class InputState {
if composingBuffer.count != readings.count { if composingBuffer.count != readings.count {
return false return false
} }
if markedRange.length < kMinMarkRangeLength { if markedRange.count < kMinMarkRangeLength {
return false return false
} }
if markedRange.length > kMaxMarkRangeLength { if markedRange.count > kMaxMarkRangeLength {
return false return false
} }
if ctlInputMethod.areWeDeleting, !deleteTargetExists { if ctlInputMethod.areWeDeleting, !deleteTargetExists {
return false return false
} }
return markedRange.length >= kMinMarkRangeLength return markedRange.count >= kMinMarkRangeLength
&& markedRange.length <= kMaxMarkRangeLength && markedRange.count <= kMaxMarkRangeLength
} }
var chkIfUserPhraseExists: Bool { var chkIfUserPhraseExists: Bool {
let text = composingBuffer.utf16SubString(with: markedRange) let text = composingBuffer.utf16SubString(with: markedRange)
let (exactBegin, _) = composingBuffer.utf16CharIndex(from: markedRange.location) let exactBegin = composingBuffer.utf16CharIndex(from: markedRange.lowerBound)
let (exactEnd, _) = composingBuffer.utf16CharIndex( let exactEnd = composingBuffer.utf16CharIndex(from: markedRange.upperBound)
from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") let joined = selectedReadings.joined(separator: "-")
return mgrLangModel.checkIfUserPhraseExist( return mgrLangModel.checkIfUserPhraseExist(
@ -304,9 +306,8 @@ class InputState {
var userPhrase: String { var userPhrase: String {
let text = composingBuffer.utf16SubString(with: markedRange) let text = composingBuffer.utf16SubString(with: markedRange)
let (exactBegin, _) = composingBuffer.utf16CharIndex(from: markedRange.location) let exactBegin = composingBuffer.utf16CharIndex(from: markedRange.lowerBound)
let (exactEnd, _) = composingBuffer.utf16CharIndex( let exactEnd = composingBuffer.utf16CharIndex(from: markedRange.upperBound)
from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") let joined = selectedReadings.joined(separator: "-")
return "\(text) \(joined)" return "\(text) \(joined)"
@ -315,9 +316,8 @@ class InputState {
var userPhraseConverted: String { var userPhraseConverted: String {
let text = let text =
OpenCCBridge.crossConvert(composingBuffer.utf16SubString(with: markedRange)) ?? "" OpenCCBridge.crossConvert(composingBuffer.utf16SubString(with: markedRange)) ?? ""
let (exactBegin, _) = composingBuffer.utf16CharIndex(from: markedRange.location) let exactBegin = composingBuffer.utf16CharIndex(from: markedRange.lowerBound)
let (exactEnd, _) = composingBuffer.utf16CharIndex( let exactEnd = composingBuffer.utf16CharIndex(from: markedRange.upperBound)
from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") let joined = selectedReadings.joined(separator: "-")
let convertedMark = "#𝙊𝙥𝙚𝙣𝘾𝘾" let convertedMark = "#𝙊𝙥𝙚𝙣𝘾𝘾"

View File

@ -214,7 +214,7 @@ extension KeyHandler {
readings: state.readings readings: state.readings
) )
marking.tooltipForInputting = state.tooltipForInputting marking.tooltipForInputting = state.tooltipForInputting
stateCallback(marking.markedRange.length == 0 ? marking.convertedToInputting : marking) stateCallback(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
} else { } else {
IME.prtDebugIntel("1149908D") IME.prtDebugIntel("1149908D")
errorCallback() errorCallback()
@ -235,7 +235,7 @@ extension KeyHandler {
readings: state.readings readings: state.readings
) )
marking.tooltipForInputting = state.tooltipForInputting marking.tooltipForInputting = state.tooltipForInputting
stateCallback(marking.markedRange.length == 0 ? marking.convertedToInputting : marking) stateCallback(marking.markedRange.isEmpty ? marking.convertedToInputting : marking)
} else { } else {
IME.prtDebugIntel("9B51408D") IME.prtDebugIntel("9B51408D")
errorCallback() errorCallback()

View File

@ -44,35 +44,29 @@ extension String {
/// string have different lengths once the string contains such Emoji. The /// string have different lengths once the string contains such Emoji. The
/// method helps to find the index in a Swift string by passing the index /// method helps to find the index in a Swift string by passing the index
/// in an NSString (or .utf16). /// in an NSString (or .utf16).
public func utf16CharIndex(from utf16Index: Int) -> (Int, String) { public func utf16CharIndex(from utf16Index: Int) -> Int {
let string = self
var length = 0 var length = 0
for (i, character) in string.enumerated() { for (i, character) in self.enumerated() {
length += character.utf16.count length += character.utf16.count
if length > utf16Index { if length > utf16Index {
return (i, string) return (i)
} }
} }
return (string.count, string) return count
} }
public func utf16NextPosition(for index: Int) -> Int { public func utf16NextPosition(for index: Int) -> Int {
var (fixedIndex, string) = utf16CharIndex(from: index) let fixedIndex = min(utf16CharIndex(from: index) + 1, count)
if fixedIndex < string.count { return self[..<self.index(startIndex, offsetBy: fixedIndex)].utf16.count
fixedIndex += 1
}
return string[..<string.index(string.startIndex, offsetBy: fixedIndex)].utf16.count
} }
public func utf16PreviousPosition(for index: Int) -> Int { public func utf16PreviousPosition(for index: Int) -> Int {
var (fixedIndex, string) = utf16CharIndex(from: index) let fixedIndex = max(utf16CharIndex(from: index) - 1, 0)
if fixedIndex > 0 { return self[..<self.index(startIndex, offsetBy: fixedIndex)].utf16.count
fixedIndex -= 1
}
return string[..<string.index(string.startIndex, offsetBy: fixedIndex)].utf16.count
} }
public func utf16SubString(with range: NSRange) -> String { func utf16SubString(with r: Range<Int>) -> String {
(self as NSString).substring(with: range) let arr = Array(self.utf16)[r].map { $0 }
return String(utf16CodeUnits: arr, count: arr.count)
} }
} }