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

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

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Don't convert utf8 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..25469887b98ce086ec24b4f45dc878a147927d5d 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -200,6 +200,63 @@ AtomicString getInputModeAttribute(Element* element) {
return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
}
+bool hasInvalidSurrogatePair(const UChar* text,
+ const int start,
+ const int end) {
yosin_UTC9 2017/02/09 07:19:27 Let's have following DCHECK's DCHECK_GE(start, 0)
yabinh 2017/02/09 10:37:03 Done.
+ for (int i = start; i < end; i++) {
yosin_UTC9 2017/02/09 07:19:27 nit: s/i++/++i/ [1] allows to use both pre and pos
yabinh 2017/02/09 10:37:03 Done.
+ if (U_IS_SURROGATE(text[i])) {
+ const bool isValidSurrogatePair =
+ U16_IS_LEAD(text[i]) && i + 1 < end && U16_IS_TRAIL(text[i + 1]);
yosin_UTC9 2017/02/09 07:19:27 Let's loop over |end - 1| to avoid checking |i| he
yabinh 2017/02/09 10:37:03 We shouldn't do that because it will fail when tex
+ if (!isValidSurrogatePair)
+ return true;
+ i++;
yosin_UTC9 2017/02/09 07:19:27 nit: s/i++/++i/ [1] allows to use both pre and pos
yabinh 2017/02/09 10:37:03 Done.
+ }
+ }
+ return false;
+}
+
+std::pair<int, int> invalidDeletionLength() {
yosin_UTC9 2017/02/09 07:19:27 Try to mark |constexpr|.
yabinh 2017/02/09 10:37:03 Do you mean simply adding a mark, like this: cons
yosin_UTC9 2017/02/10 04:54:11 I mean constexpr std::pair<int, int> invalidDelet
yabinh 2017/02/10 05:46:07 Sorry, I was referring to the above lines. It can
+ return std::make_pair(-1, -1);
+}
+
+bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) {
+ return lengthPair.first == -1 && lengthPair.second == -1;
+}
+
+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* LText = text.characters8();
yosin_UTC9 2017/02/09 07:19:27 s/LText/character8s/
yabinh 2017/02/09 10:37:03 Done.
+ U8_BACK_N(LText, 0, deletionStart, beforeLengthInCodePoints);
yosin_UTC9 2017/02/09 07:19:27 I think LChar, Latin-1 Character/ doesn't have sur
yabinh 2017/02/09 10:37:03 Yes. That's why we don't need to check whether it
yosin_UTC9 2017/02/10 04:54:11 U8_XXX_N() is for UTF-8, but LChar contains Latin-
yabinh 2017/02/10 07:27:26 You are right. Actually utf8 is converted in WebSt
+ U8_FWD_N(LText, deletionEnd, length, afterLengthInCodePoints);
+ } else {
+ const UChar* UText = text.characters16();
yosin_UTC9 2017/02/09 07:19:27 s/LText/character16s/
yabinh 2017/02/09 10:37:03 Done.
+ U16_BACK_N(UText, 0, deletionStart, beforeLengthInCodePoints);
yosin_UTC9 2017/02/09 07:19:27 nona@, do we have utility function to walk around
Seigo Nonaka 2017/02/09 07:29:21 We only have base/i18n/char_iterator.h, but it can
+ // Required by Android's InputConnection spec.
+ if (hasInvalidSurrogatePair(UText, deletionStart, selectionStart))
+ return invalidDeletionLength();
+
+ U16_FWD_N(UText, deletionEnd, length, afterLengthInCodePoints);
+ // Required by Android's InputConnection spec.
+ if (hasInvalidSurrogatePair(UText, 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 +948,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