Chromium Code Reviews| 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 |