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

View File

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

View File

@ -44,35 +44,29 @@ extension String {
/// 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
/// in an NSString (or .utf16).
public func utf16CharIndex(from utf16Index: Int) -> (Int, String) {
let string = self
public func utf16CharIndex(from utf16Index: Int) -> Int {
var length = 0
for (i, character) in string.enumerated() {
for (i, character) in self.enumerated() {
length += character.utf16.count
if length > utf16Index {
return (i, string)
return (i)
}
}
return (string.count, string)
return count
}
public func utf16NextPosition(for index: Int) -> Int {
var (fixedIndex, string) = utf16CharIndex(from: index)
if fixedIndex < string.count {
fixedIndex += 1
}
return string[..<string.index(string.startIndex, offsetBy: fixedIndex)].utf16.count
let fixedIndex = min(utf16CharIndex(from: index) + 1, count)
return self[..<self.index(startIndex, offsetBy: fixedIndex)].utf16.count
}
public func utf16PreviousPosition(for index: Int) -> Int {
var (fixedIndex, string) = utf16CharIndex(from: index)
if fixedIndex > 0 {
fixedIndex -= 1
}
return string[..<string.index(string.startIndex, offsetBy: fixedIndex)].utf16.count
let fixedIndex = max(utf16CharIndex(from: index) - 1, 0)
return self[..<self.index(startIndex, offsetBy: fixedIndex)].utf16.count
}
public func utf16SubString(with range: NSRange) -> String {
(self as NSString).substring(with: range)
func utf16SubString(with r: Range<Int>) -> String {
let arr = Array(self.utf16)[r].map { $0 }
return String(utf16CodeUnits: arr, count: arr.count)
}
}