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

Side by Side 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 } 193 }
194 194
195 if (!queryAttribute) 195 if (!queryAttribute)
196 return AtomicString(); 196 return AtomicString();
197 197
198 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed 198 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed
199 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016. 199 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016.
200 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower(); 200 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
201 } 201 }
202 202
203 bool hasInvalidSurrogatePair(const UChar* text,
204 const int start,
205 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.
206 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.
207 if (U_IS_SURROGATE(text[i])) {
208 const bool isValidSurrogatePair =
209 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
210 if (!isValidSurrogatePair)
211 return true;
212 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.
213 }
214 }
215 return false;
216 }
217
218 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
219 return std::make_pair(-1, -1);
220 }
221
222 bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) {
223 return lengthPair.first == -1 && lengthPair.second == -1;
224 }
225
226 std::pair<int, int> calculateDeletionLengthsInCodePoints(
227 const String& text,
228 const int beforeLengthInCodePoints,
229 const int afterLengthInCodePoints,
230 const int selectionStart,
231 const int selectionEnd) {
232 int deletionStart = selectionStart;
233 int deletionEnd = selectionEnd;
234 const int length = static_cast<int>(text.length());
235
236 if (text.is8Bit()) {
237 const LChar* LText = text.characters8();
yosin_UTC9 2017/02/09 07:19:27 s/LText/character8s/
yabinh 2017/02/09 10:37:03 Done.
238 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
239 U8_FWD_N(LText, deletionEnd, length, afterLengthInCodePoints);
240 } else {
241 const UChar* UText = text.characters16();
yosin_UTC9 2017/02/09 07:19:27 s/LText/character16s/
yabinh 2017/02/09 10:37:03 Done.
242 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
243 // Required by Android's InputConnection spec.
244 if (hasInvalidSurrogatePair(UText, deletionStart, selectionStart))
245 return invalidDeletionLength();
246
247 U16_FWD_N(UText, deletionEnd, length, afterLengthInCodePoints);
248 // Required by Android's InputConnection spec.
249 if (hasInvalidSurrogatePair(UText, selectionEnd, deletionEnd))
250 return invalidDeletionLength();
251 }
252
253 const int beforeLength = selectionStart - deletionStart;
254 const int afterLength = deletionEnd - selectionEnd;
255 DCHECK_GE(beforeLength, 0);
256 DCHECK_GE(afterLength, 0);
257 return std::make_pair(beforeLength, afterLength);
258 }
259
203 } // anonymous namespace 260 } // anonymous namespace
204 261
205 InputMethodController* InputMethodController::create(LocalFrame& frame) { 262 InputMethodController* InputMethodController::create(LocalFrame& frame) {
206 return new InputMethodController(frame); 263 return new InputMethodController(frame);
207 } 264 }
208 265
209 InputMethodController::InputMethodController(LocalFrame& frame) 266 InputMethodController::InputMethodController(LocalFrame& frame)
210 : m_frame(&frame), m_hasComposition(false) {} 267 : m_frame(&frame), m_hasComposition(false) {}
211 268
212 InputMethodController::~InputMethodController() = default; 269 InputMethodController::~InputMethodController() = default;
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 const size_t diff = computeDistanceToRightGraphemeBoundary(position); 941 const size_t diff = computeDistanceToRightGraphemeBoundary(position);
885 const int adjustedEnd = end + static_cast<int>(diff); 942 const int adjustedEnd = end + static_cast<int>(diff);
886 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) 943 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
887 return; 944 return;
888 TypingCommand::deleteSelection(document()); 945 TypingCommand::deleteSelection(document());
889 } 946 }
890 947
891 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); 948 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
892 } 949 }
893 950
951 void InputMethodController::deleteSurroundingTextInCodePoints(int before,
952 int after) {
953 DCHECK_GE(before, 0);
954 DCHECK_GE(after, 0);
955 if (!editor().canEdit())
956 return;
957 const PlainTextRange selectionOffsets(getSelectionOffsets());
958 if (selectionOffsets.isNull())
959 return;
960 Element* const rootEditableElement =
961 frame().selection().rootEditableElement();
962 if (!rootEditableElement)
963 return;
964
965 const int selectionStart = static_cast<int>(selectionOffsets.start());
966 const int selectionEnd = static_cast<int>(selectionOffsets.end());
967 const TextIteratorBehavior& behavior =
968 TextIteratorBehavior::Builder()
969 .setEmitsObjectReplacementCharacter(true)
970 .build();
971 const String& text = plainText(
972 EphemeralRange::rangeOfContents(*rootEditableElement), behavior);
973 std::pair<int, int> deletionLengthPair = calculateDeletionLengthsInCodePoints(
974 text, before, after, selectionStart, selectionEnd);
975 if (isInvalidDeletionLength(deletionLengthPair))
976 return;
977
978 return deleteSurroundingText(deletionLengthPair.first,
979 deletionLengthPair.second);
980 }
981
894 WebTextInputInfo InputMethodController::textInputInfo() const { 982 WebTextInputInfo InputMethodController::textInputInfo() const {
895 WebTextInputInfo info; 983 WebTextInputInfo info;
896 if (!isAvailable()) 984 if (!isAvailable())
897 return info; 985 return info;
898 986
899 if (!frame().selection().isAvailable()) { 987 if (!frame().selection().isAvailable()) {
900 // plugins/mouse-capture-inside-shadow.html reaches here. 988 // plugins/mouse-capture-inside-shadow.html reaches here.
901 return info; 989 return info;
902 } 990 }
903 Element* element = frame().selection().rootEditableElement(); 991 Element* element = frame().selection().rootEditableElement();
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 frame().chromeClient().resetInputMethod(); 1196 frame().chromeClient().resetInputMethod();
1109 } 1197 }
1110 1198
1111 DEFINE_TRACE(InputMethodController) { 1199 DEFINE_TRACE(InputMethodController) {
1112 visitor->trace(m_frame); 1200 visitor->trace(m_frame);
1113 visitor->trace(m_compositionRange); 1201 visitor->trace(m_compositionRange);
1114 SynchronousMutationObserver::trace(visitor); 1202 SynchronousMutationObserver::trace(visitor);
1115 } 1203 }
1116 1204
1117 } // namespace blink 1205 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698