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) { | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |