OLD | NEW |
---|---|
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 Loading... | |
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) { | |
206 DCHECK_GE(start, 0); | |
207 DCHECK_LE(start, end); | |
208 for (int i = start; i < end; ++i) { | |
209 if (U_IS_SURROGATE(text[i])) { | |
210 const bool isValidSurrogatePair = | |
211 U16_IS_LEAD(text[i]) && i + 1 < end && U16_IS_TRAIL(text[i + 1]); | |
212 if (!isValidSurrogatePair) | |
213 return true; | |
214 ++i; | |
215 } | |
216 } | |
217 return false; | |
218 } | |
219 | |
220 std::pair<int, int> invalidDeletionLength() { | |
221 return std::make_pair(-1, -1); | |
222 } | |
223 | |
224 bool isInvalidDeletionLength(const std::pair<int, int>& lengthPair) { | |
225 return lengthPair.first == -1 && lengthPair.second == -1; | |
yosin_UTC9
2017/02/10 04:54:11
You could write:
return lengthPair == invalidDele
| |
226 } | |
227 | |
228 std::pair<int, int> calculateDeletionLengthsInCodePoints( | |
229 const String& text, | |
230 const int beforeLengthInCodePoints, | |
231 const int afterLengthInCodePoints, | |
232 const int selectionStart, | |
233 const int selectionEnd) { | |
234 int deletionStart = selectionStart; | |
235 int deletionEnd = selectionEnd; | |
236 const int length = static_cast<int>(text.length()); | |
237 | |
238 if (text.is8Bit()) { | |
239 const LChar* character8s = text.characters8(); | |
240 U8_BACK_N(character8s, 0, deletionStart, beforeLengthInCodePoints); | |
241 U8_FWD_N(character8s, deletionEnd, length, afterLengthInCodePoints); | |
242 } else { | |
243 const UChar* character16s = text.characters16(); | |
244 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
| |
245 // Required by Android's InputConnection spec. | |
246 if (hasInvalidSurrogatePair(character16s, deletionStart, selectionStart)) | |
247 return invalidDeletionLength(); | |
248 | |
249 U16_FWD_N(character16s, deletionEnd, length, afterLengthInCodePoints); | |
250 // Required by Android's InputConnection spec. | |
251 if (hasInvalidSurrogatePair(character16s, selectionEnd, deletionEnd)) | |
252 return invalidDeletionLength(); | |
253 } | |
254 | |
255 const int beforeLength = selectionStart - deletionStart; | |
256 const int afterLength = deletionEnd - selectionEnd; | |
257 DCHECK_GE(beforeLength, 0); | |
258 DCHECK_GE(afterLength, 0); | |
259 return std::make_pair(beforeLength, afterLength); | |
260 } | |
261 | |
203 } // anonymous namespace | 262 } // anonymous namespace |
204 | 263 |
205 InputMethodController* InputMethodController::create(LocalFrame& frame) { | 264 InputMethodController* InputMethodController::create(LocalFrame& frame) { |
206 return new InputMethodController(frame); | 265 return new InputMethodController(frame); |
207 } | 266 } |
208 | 267 |
209 InputMethodController::InputMethodController(LocalFrame& frame) | 268 InputMethodController::InputMethodController(LocalFrame& frame) |
210 : m_frame(&frame), m_hasComposition(false) {} | 269 : m_frame(&frame), m_hasComposition(false) {} |
211 | 270 |
212 InputMethodController::~InputMethodController() = default; | 271 InputMethodController::~InputMethodController() = default; |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
884 const size_t diff = computeDistanceToRightGraphemeBoundary(position); | 943 const size_t diff = computeDistanceToRightGraphemeBoundary(position); |
885 const int adjustedEnd = end + static_cast<int>(diff); | 944 const int adjustedEnd = end + static_cast<int>(diff); |
886 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) | 945 if (!setSelectionOffsets(PlainTextRange(selectionEnd, adjustedEnd))) |
887 return; | 946 return; |
888 TypingCommand::deleteSelection(document()); | 947 TypingCommand::deleteSelection(document()); |
889 } | 948 } |
890 | 949 |
891 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); | 950 setSelectionOffsets(PlainTextRange(selectionStart, selectionEnd)); |
892 } | 951 } |
893 | 952 |
953 void InputMethodController::deleteSurroundingTextInCodePoints(int before, | |
954 int after) { | |
955 DCHECK_GE(before, 0); | |
956 DCHECK_GE(after, 0); | |
957 if (!editor().canEdit()) | |
958 return; | |
959 const PlainTextRange selectionOffsets(getSelectionOffsets()); | |
960 if (selectionOffsets.isNull()) | |
961 return; | |
962 Element* const rootEditableElement = | |
963 frame().selection().rootEditableElement(); | |
964 if (!rootEditableElement) | |
965 return; | |
966 | |
967 const int selectionStart = static_cast<int>(selectionOffsets.start()); | |
968 const int selectionEnd = static_cast<int>(selectionOffsets.end()); | |
969 const TextIteratorBehavior& behavior = | |
970 TextIteratorBehavior::Builder() | |
971 .setEmitsObjectReplacementCharacter(true) | |
972 .build(); | |
973 const String& text = plainText( | |
974 EphemeralRange::rangeOfContents(*rootEditableElement), behavior); | |
975 std::pair<int, int> deletionLengthPair = calculateDeletionLengthsInCodePoints( | |
976 text, before, after, selectionStart, selectionEnd); | |
977 if (isInvalidDeletionLength(deletionLengthPair)) | |
978 return; | |
979 | |
980 return deleteSurroundingText(deletionLengthPair.first, | |
981 deletionLengthPair.second); | |
982 } | |
983 | |
894 WebTextInputInfo InputMethodController::textInputInfo() const { | 984 WebTextInputInfo InputMethodController::textInputInfo() const { |
895 WebTextInputInfo info; | 985 WebTextInputInfo info; |
896 if (!isAvailable()) | 986 if (!isAvailable()) |
897 return info; | 987 return info; |
898 | 988 |
899 if (!frame().selection().isAvailable()) { | 989 if (!frame().selection().isAvailable()) { |
900 // plugins/mouse-capture-inside-shadow.html reaches here. | 990 // plugins/mouse-capture-inside-shadow.html reaches here. |
901 return info; | 991 return info; |
902 } | 992 } |
903 Element* element = frame().selection().rootEditableElement(); | 993 Element* element = frame().selection().rootEditableElement(); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1108 frame().chromeClient().resetInputMethod(); | 1198 frame().chromeClient().resetInputMethod(); |
1109 } | 1199 } |
1110 | 1200 |
1111 DEFINE_TRACE(InputMethodController) { | 1201 DEFINE_TRACE(InputMethodController) { |
1112 visitor->trace(m_frame); | 1202 visitor->trace(m_frame); |
1113 visitor->trace(m_compositionRange); | 1203 visitor->trace(m_compositionRange); |
1114 SynchronousMutationObserver::trace(visitor); | 1204 SynchronousMutationObserver::trace(visitor); |
1115 } | 1205 } |
1116 | 1206 |
1117 } // namespace blink | 1207 } // namespace blink |
OLD | NEW |