Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: third_party/WebKit/Source/core/editing/InputMethodController.cpp

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Address yosin@'s review Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/InputMethodController.cpp
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index 538a611263d2e62f88249952a03bd8489e6cfa7f..48bb936d4a137cb06d3e0f41ce44b32fb1f8e44c 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -200,6 +200,65 @@ AtomicString getInputModeAttribute(Element* element) {
return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
}
+bool hasInvalidSurrogatePair(const UChar* text,
+ const int start,
+ const int end) {
+ DCHECK_GE(start, 0);
+ DCHECK_LE(start, end);
+ for (int i = start; i < end; ++i) {
+ if (U_IS_SURROGATE(text[i])) {
+ const bool isValidSurrogatePair =
+ U16_IS_LEAD(text[i]) && i + 1 < end && U16_IS_TRAIL(text[i + 1]);
+ if (!isValidSurrogatePair)
+ return true;
+ ++i;
+ }
+ }
+ return false;
+}
+
+std::pair<int, int> invalidDeletionLength() {
+ return std::make_pair(-1, -1);
+}
+
+bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) {
+ return lengthPair.first == -1 && lengthPair.second == -1;
yosin_UTC9 2017/02/10 04:54:11 You could write: return lengthPair == invalidDele
+}
+
+std::pair<int, int> calculateDeletionLengthsInCodePoints(
+ const String& text,
+ const int beforeLengthInCodePoints,
+ const int afterLengthInCodePoints,
+ const int selectionStart,
+ const int selectionEnd) {
+ int deletionStart = selectionStart;
+ int deletionEnd = selectionEnd;
+ const int length = static_cast<int>(text.length());
+
+ if (text.is8Bit()) {
+ const LChar* character8s = text.characters8();
+ U8_BACK_N(character8s, 0, deletionStart, beforeLengthInCodePoints);
+ U8_FWD_N(character8s, deletionEnd, length, afterLengthInCodePoints);
+ } else {
+ const UChar* character16s = text.characters16();
+ U16_BACK_N(character16s, 0, deletionStart, beforeLengthInCodePoints);
yosin_UTC9 2017/02/10 04:54:11 Let's avoid U16_BACK_N() and U16_FWD_N() since the
yosin_UTC9 2017/02/10 05:20:19 Refined. Make BackwardCodePointMachine::feed() to
yabinh 2017/02/10 10:49:22 Thanks! Do we need to add a separate file and add
+ // Required by Android's InputConnection spec.
+ if (hasInvalidSurrogatePair(character16s, deletionStart, selectionStart))
+ return invalidDeletionLength();
+
+ U16_FWD_N(character16s, deletionEnd, length, afterLengthInCodePoints);
+ // Required by Android's InputConnection spec.
+ if (hasInvalidSurrogatePair(character16s, selectionEnd, deletionEnd))
+ return invalidDeletionLength();
+ }
+
+ const int beforeLength = selectionStart - deletionStart;
+ const int afterLength = deletionEnd - selectionEnd;
+ DCHECK_GE(beforeLength, 0);
+ DCHECK_GE(afterLength, 0);
+ return std::make_pair(beforeLength, afterLength);
+}
+
} // anonymous namespace
InputMethodController* InputMethodController::create(LocalFrame& frame) {
@@ -891,6 +950,37 @@ void InputMethodController::deleteSurroundingText(int before, int after) {
setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
}
+void InputMethodController::deleteSurroundingTextInCodePoints(int before,
+ int after) {
+ DCHECK_GE(before, 0);
+ DCHECK_GE(after, 0);
+ if (!editor().canEdit())
+ return;
+ const PlainTextRange selectionOffsets(getSelectionOffsets());
+ if (selectionOffsets.isNull())
+ return;
+ Element* const rootEditableElement =
+ frame().selection().rootEditableElement();
+ if (!rootEditableElement)
+ return;
+
+ const int selectionStart = static_cast<int>(selectionOffsets.start());
+ const int selectionEnd = static_cast<int>(selectionOffsets.end());
+ const TextIteratorBehavior& behavior =
+ TextIteratorBehavior::Builder()
+ .setEmitsObjectReplacementCharacter(true)
+ .build();
+ const String& text = plainText(
+ EphemeralRange::rangeOfContents(*rootEditableElement), behavior);
+ std::pair<int, int> deletionLengthPair = calculateDeletionLengthsInCodePoints(
+ text, before, after, selectionStart, selectionEnd);
+ if (isInvalidDeletionLength(deletionLengthPair))
+ return;
+
+ return deleteSurroundingText(deletionLengthPair.first,
+ deletionLengthPair.second);
+}
+
WebTextInputInfo InputMethodController::textInputInfo() const {
WebTextInputInfo info;
if (!isAvailable())

Powered by Google App Engine
This is Rietveld 408576698