Filters out prefixed LTR/RTL marks from context.

This commit is contained in:
jahorton 2019-05-03 12:43:45 +07:00
parent fcbd7db229
commit dbbeccebdb
5 changed files with 43 additions and 41 deletions

View file

@ -201,8 +201,7 @@ open class InputViewController: UIInputViewController, KeymanWebDelegate {
newRange = context.startIndex..<context.startIndex
}
setText(context)
setSelectionRange(NSRange(newRange, in: context), manually: false)
setContextState(text: context, range: NSRange(newRange, in: context))
}
func insertText(_ keymanWeb: KeymanWebViewController, numCharsToDelete: Int, newText: String) {
@ -411,24 +410,35 @@ open class InputViewController: UIInputViewController, KeymanWebDelegate {
func showHelpBubble(afterDelay delay: TimeInterval) {
keymanWeb.showHelpBubble(afterDelay: delay)
}
// func setCursorRange(_ range: NSRange) {
// keymanWeb.setCursorRange(range)
// }
func setText(_ text: String?) {
keymanWeb.setText(text)
}
func clearText() {
setText(nil)
setSelectionRange(NSRange(location: 0, length: 0), manually: true)
setContextState(text: nil, range: NSRange(location: 0, length: 0))
log.info("Cleared text.")
}
func setSelectionRange(_ range: NSRange, manually: Bool) {
func setContextState(text: String?, range: NSRange) {
// Check for any LTR or RTL marks at the context's start; if they exist, we should
// offset the selection range.
let characterOrderingChecks = [ "\u{200e}" /*LTR*/, "\u{202e}" /*RTL 1*/, "\u{200f}" /*RTL 2*/ ]
var offsetPrefix = false;
let context = text ?? ""
for codepoint in characterOrderingChecks {
if(context.hasPrefix(codepoint)) {
offsetPrefix = true;
break;
}
}
var selRange = range;
if(offsetPrefix) { // If we have a character ordering mark, offset range location to hide it.
selRange = NSRange(location: selRange.location - 1, length: selRange.length)
}
keymanWeb.setText(context)
if range.location != NSNotFound {
keymanWeb.setCursorRange(range)
keymanWeb.setCursorRange(selRange)
}
}

View file

@ -184,6 +184,12 @@ extension KeymanWebViewController {
func setText(_ text: String?) {
var text = text ?? ""
// Remove any system-added LTR/RTL marks.
text = text.replacingOccurrences(of: "\u{200e}", with: "") // Unicode's LTR codepoint
text = text.replacingOccurrences(of: "\u{200f}", with: "") // Unicode's RTL codepoint (v1)
text = text.replacingOccurrences(of: "\u{202e}", with: "") // Unicode's RTL codepoint (v2)
// JavaScript escape-sequence encodings.
text = text.replacingOccurrences(of: "\\", with: "\\\\")
text = text.replacingOccurrences(of: "'", with: "\\'")
text = text.replacingOccurrences(of: "\n", with: "\\n")

View file

@ -903,16 +903,12 @@ public class Manager: NSObject, HTTPDownloadDelegate, UIGestureRecognizerDelegat
Manager.shared.inputViewController.resetKeyboardState()
}
func setText(_ text: String?) {
inputViewController.setText(text)
}
func clearText() {
inputViewController.clearText()
}
func setSelectionRange(_ range: NSRange, manually: Bool) {
inputViewController.setSelectionRange(range, manually: manually)
func setContextState(text: String?, range: NSRange) {
inputViewController.setContextState(text: text, range: range)
}
var vibrationSupportLevel: VibrationSupport {

View file

@ -112,11 +112,11 @@ public class TextField: UITextField, KeymanResponder {
super.text = ""
}
Manager.shared.setText(self.text)
let textRange = selectedTextRange ?? UITextRange()
let newRange = NSRange(location: offset(from: beginningOfDocument, to: textRange.start),
length: offset(from: textRange.start, to: textRange.end))
Manager.shared.setSelectionRange(newRange, manually: false)
Manager.shared.setContextState(text: self.text, range: newRange)
}
}
@ -127,7 +127,8 @@ public class TextField: UITextField, KeymanResponder {
}
let newRange = NSRange(location: offset(from: beginningOfDocument, to: range.start),
length: offset(from: range.start, to: range.end))
Manager.shared.setSelectionRange(newRange, manually: false)
Manager.shared.setContextState(text: self.text, range: newRange)
}
}
@ -159,11 +160,11 @@ public class TextField: UITextField, KeymanResponder {
@objc func textFieldTextDidChange(_ notification: Notification) {
if shouldUpdateKMText {
// Catches copy/paste operations
Manager.shared.setText(text)
let textRange = selectedTextRange!
let newRange = NSRange(location: offset(from: beginningOfDocument, to: textRange.start),
length: offset(from: textRange.start, to: textRange.end))
Manager.shared.setSelectionRange(newRange, manually: false)
Manager.shared.setContextState(text: text, range: newRange)
shouldUpdateKMText = false
}
}
@ -262,12 +263,6 @@ extension TextField: UITextFieldDelegate {
log.debug("TextField: \(self.hashValue) setFont: \(font?.familyName ?? "nil")")
// copy this textField's text to the webview
Manager.shared.setText(text)
let textRange = selectedTextRange!
let newRange = NSRange(location: offset(from: beginningOfDocument, to: textRange.start),
length: offset(from: textRange.start, to: textRange.end))
Manager.shared.setSelectionRange(newRange, manually: false)
log.debug("TextField: \(self.hashValue) Became first responder. Value: \(String(describing: text))")
}

View file

@ -109,14 +109,13 @@ public class TextView: UITextView, KeymanResponder {
super.text = ""
}
Manager.shared.inputViewController.setText(self.text)
Manager.shared.inputViewController.setSelectionRange(selectedRange, manually: false)
Manager.shared.inputViewController.setContextState(text: self.text, range: selectedRange)
}
}
public override var selectedTextRange: UITextRange? {
didSet {
Manager.shared.setSelectionRange(selectedRange, manually: false)
Manager.shared.setContextState(text: self.text, range: selectedRange)
}
}
@ -259,9 +258,6 @@ extension TextView: UITextViewDelegate {
log.debug("TextView: \(self.hashValue) setFont: \(font?.familyName ?? "nil")")
// copy this textView's text to the webview
Manager.shared.setText(text)
Manager.shared.setSelectionRange(selectedRange, manually: false)
log.debug("TextView: \(self.hashValue) Became first responder. Value: \(String(describing: text))")
}
@ -275,8 +271,7 @@ extension TextView: UITextViewDelegate {
public func textViewDidChange(_ textView: UITextView) {
if shouldUpdateKMText {
// Catches copy/paste operations
Manager.shared.setText(textView.text)
Manager.shared.setSelectionRange(textView.selectedRange, manually: false)
Manager.shared.setContextState(text: textView.text, range: textView.selectedRange)
shouldUpdateKMText = false
}
}