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

Side by Side Diff: third_party/WebKit/Source/core/editing/InputMethodController.cpp

Issue 2617443002: Implement ThreadedInputConnection.deleteSurroundingTextInCodePoints() (Closed)
Patch Set: Add more comments Created 3 years, 11 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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 177 }
178 178
179 if (!queryAttribute) 179 if (!queryAttribute)
180 return AtomicString(); 180 return AtomicString();
181 181
182 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed 182 // TODO(dtapuska): We may wish to restrict this to a yet to be proposed
183 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016. 183 // <contenteditable> or <richtext> element Mozilla discussed at TPAC 2016.
184 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower(); 184 return element->fastGetAttribute(HTMLNames::inputmodeAttr).lower();
185 } 185 }
186 186
187 bool hasInvalidSurrogatePair(const UChar* text,
188 const int start,
189 const int end) {
190 for (int i = start; i < end; i++) {
191 if (U_IS_SURROGATE(text[i])) {
192 const bool isValidSurrogatePair =
193 U16_IS_LEAD(text[i]) && i + 1 < end && U16_IS_TRAIL(text[i + 1]);
194 if (!isValidSurrogatePair)
195 return true;
196 i++;
197 }
198 }
199 return false;
200 }
201
202 bool hasInvalidSurrogatePair(const LChar* text,
Changwan Ryu 2017/01/11 06:44:33 This is somewhat weird. UTF-8 does not have surrog
yabinh 2017/01/24 11:39:56 Done. This function has been removed. We can simp
203 const int start,
204 const int end) {
205 for (int i = start; i < end; i++) {
206 if (!U8_IS_SINGLE(text[i])) {
207 const bool isValidSurrogatePair =
208 U8_IS_LEAD(text[i]) && i + 1 < end && U8_IS_TRAIL(text[i + 1]);
209 if (!isValidSurrogatePair)
210 return true;
211 i++;
212 }
213 }
214 return false;
215 }
216
217 std::pair<int, int> invalidDeletionLength() {
218 return std::make_pair(-1, -1);
219 }
220
221 bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) {
222 return lengthPair.first == -1 && lengthPair.second == -1;
223 }
224
225 std::pair<int, int> convertDeletionLengthForDeleteSurroundingTextInCodePoints(
226 const String& text,
227 const int beforeLengthInCodePoints,
228 const int afterLengthInCodePoints,
229 const int selectionStart,
230 const int selectionEnd) {
231 int deletionStart = selectionStart;
Changwan Ryu 2017/01/11 06:44:33 Are selectionStart / selectionEnd in code points?
yabinh 2017/01/24 11:39:56 No, it's in Java length. But we don't need convert
232 int deletionEnd = selectionEnd;
233 const int length = static_cast<int>(text.length());
234
235 if (text.is8Bit()) {
236 const LChar* LText = text.characters8();
237 U8_BACK_N(LText, 0, deletionStart, beforeLengthInCodePoints);
238
239 // Return an invalid value if there are one or more invalid surrogate pairs
240 // in the requested range
241 if (hasInvalidSurrogatePair(LText, deletionStart, selectionStart))
242 return invalidDeletionLength();
243
244 U8_FWD_N(LText, deletionEnd, length, afterLengthInCodePoints);
245 if (hasInvalidSurrogatePair(LText, selectionEnd, deletionEnd))
246 return invalidDeletionLength();
247 } else {
248 const UChar* UText = text.characters16();
249
250 U16_BACK_N(UText, 0, deletionStart, beforeLengthInCodePoints);
251 if (hasInvalidSurrogatePair(UText, deletionStart, selectionStart))
252 return invalidDeletionLength();
Changwan Ryu 2017/01/11 06:44:33 I think it should be ok to delete the range even w
yabinh 2017/01/24 11:39:56 This is to follow the specification: ''' This met
253
254 U16_FWD_N(UText, deletionEnd, length, afterLengthInCodePoints);
255 if (hasInvalidSurrogatePair(UText, selectionEnd, deletionEnd))
256 return invalidDeletionLength();
257 }
258
259 const int beforeLengthInJavaChars = selectionStart - deletionStart;
Changwan Ryu 2017/01/11 02:00:27 WebKit should not know about JavaChars. Also it do
yabinh 2017/01/24 11:39:56 Done.
260 const int afterLengthInJavaChars = deletionEnd - selectionEnd;
261 return std::make_pair(beforeLengthInJavaChars, afterLengthInJavaChars);
262 }
263
187 } // anonymous namespace 264 } // anonymous namespace
188 265
189 InputMethodController* InputMethodController::create(LocalFrame& frame) { 266 InputMethodController* InputMethodController::create(LocalFrame& frame) {
190 return new InputMethodController(frame); 267 return new InputMethodController(frame);
191 } 268 }
192 269
193 InputMethodController::InputMethodController(LocalFrame& frame) 270 InputMethodController::InputMethodController(LocalFrame& frame)
194 : m_frame(&frame), m_hasComposition(false) {} 271 : m_frame(&frame), m_hasComposition(false) {}
195 272
196 InputMethodController::~InputMethodController() = default; 273 InputMethodController::~InputMethodController() = default;
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 const int adjustedEnd = end + static_cast<int>(diff); 919 const int adjustedEnd = end + static_cast<int>(diff);
843 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) 920 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd)))
844 return; 921 return;
845 TypingCommand::deleteSelection(document(), 922 TypingCommand::deleteSelection(document(),
846 EditCommandSource::kMenuOrKeyBinding); 923 EditCommandSource::kMenuOrKeyBinding);
847 } 924 }
848 925
849 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); 926 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd));
850 } 927 }
851 928
929 void InputMethodController::deleteSurroundingTextInCodePoints(int before,
930 int after) {
931 DCHECK_GE(before, 0);
932 DCHECK_GE(after, 0);
933 if (!editor().canEdit())
934 return;
935 const PlainTextRange selectionOffsets(getSelectionOffsets());
936 if (selectionOffsets.isNull())
937 return;
938 Element* const rootEditableElement =
939 frame().selection().rootEditableElement();
940 if (!rootEditableElement)
941 return;
942
943 const int selectionStart = static_cast<int>(selectionOffsets.start());
944 const int selectionEnd = static_cast<int>(selectionOffsets.end());
945 const String& text =
946 plainText(EphemeralRange::rangeOfContents(*rootEditableElement),
947 TextIteratorEmitsObjectReplacementCharacter);
948 std::pair<int, int> deletionLengthPair =
949 convertDeletionLengthForDeleteSurroundingTextInCodePoints(
950 text, before, after, selectionStart, selectionEnd);
951 if (isInvalidDeletionLength(deletionLengthPair))
952 return;
953
954 return deleteSurroundingText(deletionLengthPair.first,
955 deletionLengthPair.second);
956 }
957
852 WebTextInputInfo InputMethodController::textInputInfo() const { 958 WebTextInputInfo InputMethodController::textInputInfo() const {
853 WebTextInputInfo info; 959 WebTextInputInfo info;
854 if (!isAvailable()) 960 if (!isAvailable())
855 return info; 961 return info;
856 962
857 if (!frame().selection().isAvailable()) { 963 if (!frame().selection().isAvailable()) {
858 // plugins/mouse-capture-inside-shadow.html reaches here. 964 // plugins/mouse-capture-inside-shadow.html reaches here.
859 return info; 965 return info;
860 } 966 }
861 Element* element = frame().selection().rootEditableElement(); 967 Element* element = frame().selection().rootEditableElement();
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 frame().chromeClient().resetInputMethod(); 1169 frame().chromeClient().resetInputMethod();
1064 } 1170 }
1065 1171
1066 DEFINE_TRACE(InputMethodController) { 1172 DEFINE_TRACE(InputMethodController) {
1067 visitor->trace(m_frame); 1173 visitor->trace(m_frame);
1068 visitor->trace(m_compositionRange); 1174 visitor->trace(m_compositionRange);
1069 SynchronousMutationObserver::trace(visitor); 1175 SynchronousMutationObserver::trace(visitor);
1070 } 1176 }
1071 1177
1072 } // namespace blink 1178 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698