OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights |
7 * reserved. | 7 * reserved. |
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
10 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 10 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
(...skipping 15 matching lines...) Expand all Loading... |
26 * | 26 * |
27 */ | 27 */ |
28 | 28 |
29 #include "core/editing/markers/DocumentMarkerController.h" | 29 #include "core/editing/markers/DocumentMarkerController.h" |
30 | 30 |
31 #include <algorithm> | 31 #include <algorithm> |
32 #include "core/dom/Node.h" | 32 #include "core/dom/Node.h" |
33 #include "core/dom/NodeTraversal.h" | 33 #include "core/dom/NodeTraversal.h" |
34 #include "core/dom/Range.h" | 34 #include "core/dom/Range.h" |
35 #include "core/dom/Text.h" | 35 #include "core/dom/Text.h" |
| 36 #include "core/editing/FrameSelection.h" |
36 #include "core/editing/iterators/TextIterator.h" | 37 #include "core/editing/iterators/TextIterator.h" |
37 #include "core/editing/markers/CompositionMarker.h" | 38 #include "core/editing/markers/CompositionMarker.h" |
38 #include "core/editing/markers/CompositionMarkerList.h" | 39 #include "core/editing/markers/CompositionMarkerList.h" |
39 #include "core/editing/markers/DocumentMarkerList.h" | 40 #include "core/editing/markers/DocumentMarkerList.h" |
40 #include "core/editing/markers/EditingMarkerList.h" | 41 #include "core/editing/markers/EditingMarkerList.h" |
41 #include "core/editing/markers/SpellCheckMarker.h" | 42 #include "core/editing/markers/SpellCheckMarker.h" |
42 #include "core/editing/markers/SpellCheckMarkerList.h" | 43 #include "core/editing/markers/SpellCheckMarkerList.h" |
| 44 #include "core/editing/markers/SuggestionHighlightMarker.h" |
| 45 #include "core/editing/markers/SuggestionHighlightMarkerList.h" |
| 46 #include "core/editing/markers/SuggestionMarkerList.h" |
43 #include "core/editing/markers/TextMatchMarkerList.h" | 47 #include "core/editing/markers/TextMatchMarkerList.h" |
44 #include "core/frame/FrameView.h" | 48 #include "core/frame/FrameView.h" |
| 49 #include "core/frame/LocalFrame.h" |
45 #include "core/layout/LayoutObject.h" | 50 #include "core/layout/LayoutObject.h" |
46 | 51 |
47 #ifndef NDEBUG | 52 #ifndef NDEBUG |
48 #include <stdio.h> | 53 #include <stdio.h> |
49 #endif | 54 #endif |
50 | 55 |
51 namespace blink { | 56 namespace blink { |
52 | 57 |
53 DocumentMarkerController::DocumentMarkerController(Document& document) | 58 DocumentMarkerController::DocumentMarkerController(Document& document) |
54 : m_document(&document) { | 59 : m_document(&document) { |
55 setContext(&document); | 60 setContext(&document); |
56 } | 61 } |
57 | 62 |
58 void DocumentMarkerController::clear() { | 63 void DocumentMarkerController::clear() { |
59 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { | 64 for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { |
60 MarkerMap& markerMap = markerMapForType(type); | 65 MarkerMap& markerMap = markerMapForType(type); |
61 markerMap.clear(); | 66 markerMap.clear(); |
62 } | 67 } |
| 68 |
| 69 // Don't reset m_nextSuggestionMarkerID so if anything is still holding |
| 70 // onto an old ID, it won't get confused by new markers |
63 } | 71 } |
64 | 72 |
65 void DocumentMarkerController::addGrammarOrSpellingMarker( | 73 void DocumentMarkerController::addGrammarOrSpellingMarker( |
66 const EphemeralRange& range, | 74 const EphemeralRange& range, |
67 DocumentMarker::MarkerType type, | 75 DocumentMarker::MarkerType type, |
68 const String& description) { | 76 const String& description) { |
69 DCHECK(!m_document->needsLayoutTreeUpdate()); | 77 DCHECK(!m_document->needsLayoutTreeUpdate()); |
70 DCHECK(type == DocumentMarker::Grammar || type == DocumentMarker::Spelling) | 78 DCHECK(type == DocumentMarker::Grammar || type == DocumentMarker::Spelling) |
71 << type; | 79 << type; |
72 // Use a TextIterator to visit the potentially multiple nodes the range | 80 // Use a TextIterator to visit the potentially multiple nodes the range |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 | 124 |
117 for (TextIterator markedText(range.startPosition(), range.endPosition()); | 125 for (TextIterator markedText(range.startPosition(), range.endPosition()); |
118 !markedText.atEnd(); markedText.advance()) { | 126 !markedText.atEnd(); markedText.advance()) { |
119 addMarker(markedText.currentContainer(), | 127 addMarker(markedText.currentContainer(), |
120 new CompositionMarker(markedText.startOffsetInCurrentContainer(), | 128 new CompositionMarker(markedText.startOffsetInCurrentContainer(), |
121 markedText.endOffsetInCurrentContainer(), | 129 markedText.endOffsetInCurrentContainer(), |
122 underlineColor, thick, backgroundColor)); | 130 underlineColor, thick, backgroundColor)); |
123 } | 131 } |
124 } | 132 } |
125 | 133 |
| 134 void DocumentMarkerController::addSuggestionMarker(const EphemeralRange& range, |
| 135 Color underlineColor, |
| 136 bool thick, |
| 137 Color backgroundColor, |
| 138 const Vector<String>& suggest
ions) { |
| 139 DCHECK(!m_document->needsLayoutTreeUpdate()); |
| 140 |
| 141 for (TextIterator markedText(range.startPosition(), range.endPosition()); |
| 142 !markedText.atEnd(); markedText.advance()) { |
| 143 addMarker(markedText.currentContainer(), |
| 144 new SuggestionMarker( |
| 145 markedText.startOffsetInCurrentContainer(), |
| 146 markedText.endOffsetInCurrentContainer(), underlineColor, |
| 147 thick, backgroundColor, suggestions, m_nextSuggestionMarkerID+
+)); |
| 148 } |
| 149 } |
| 150 |
| 151 void DocumentMarkerController::addSuggestionHighlightMarker( |
| 152 const EphemeralRange& range, |
| 153 Color underlineColor, |
| 154 bool thick, |
| 155 Color backgroundColor) { |
| 156 DCHECK(!m_document->needsLayoutTreeUpdate()); |
| 157 |
| 158 for (TextIterator markedText(range.startPosition(), range.endPosition()); |
| 159 !markedText.atEnd(); markedText.advance()) { |
| 160 addMarker(markedText.currentContainer(), |
| 161 new SuggestionHighlightMarker( |
| 162 markedText.startOffsetInCurrentContainer(), |
| 163 markedText.endOffsetInCurrentContainer(), |
| 164 underlineColor, |
| 165 thick, backgroundColor)); |
| 166 } |
| 167 } |
| 168 |
126 void DocumentMarkerController::prepareForDestruction() { | 169 void DocumentMarkerController::prepareForDestruction() { |
127 clear(); | 170 clear(); |
128 } | 171 } |
129 | 172 |
130 void DocumentMarkerController::removeMarkers( | 173 void DocumentMarkerController::removeMarkers( |
131 const EphemeralRange& range, | 174 const EphemeralRange& range, |
132 DocumentMarker::MarkerTypes markerTypes, | 175 DocumentMarker::MarkerTypes markerTypes, |
133 RemovePartiallyOverlappingMarkerOrNot | 176 RemovePartiallyOverlappingMarkerOrNot |
134 shouldRemovePartiallyOverlappingMarker) { | 177 shouldRemovePartiallyOverlappingMarker) { |
135 DCHECK(!m_document->needsLayoutTreeUpdate()); | 178 DCHECK(!m_document->needsLayoutTreeUpdate()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 PaintInvalidationDocumentMarkerChange); | 248 PaintInvalidationDocumentMarkerChange); |
206 } | 249 } |
207 } | 250 } |
208 | 251 |
209 void DocumentMarkerController::removeMarkers( | 252 void DocumentMarkerController::removeMarkers( |
210 Node* node, | 253 Node* node, |
211 unsigned startOffset, | 254 unsigned startOffset, |
212 int length, | 255 int length, |
213 DocumentMarker::MarkerTypes markerTypes, | 256 DocumentMarker::MarkerTypes markerTypes, |
214 RemovePartiallyOverlappingMarkerOrNot | 257 RemovePartiallyOverlappingMarkerOrNot |
215 shouldRemovePartiallyOverlappingMarker) { | 258 shouldRemovePartiallyOverlappingMarker) { |
216 if (length <= 0) | 259 if (length <= 0) |
217 return; | 260 return; |
218 | 261 |
219 bool docDirty = false; | 262 bool docDirty = false; |
220 for (DocumentMarker::MarkerType type : markerTypes) { | 263 for (DocumentMarker::MarkerType type : markerTypes) { |
221 MarkerMap& markerMap = markerMapForType(type); | 264 MarkerMap& markerMap = markerMapForType(type); |
222 auto it = markerMap.find(node); | 265 auto it = markerMap.find(node); |
223 if (it != markerMap.end()) { | 266 if (it != markerMap.end()) { |
224 docDirty = | 267 docDirty = |
225 (it->value->removeMarkers(startOffset, length, | 268 (it->value->removeMarkers(startOffset, length, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 it->value->appendMarkersToInputList(&result); | 303 it->value->appendMarkersToInputList(&result); |
261 } | 304 } |
262 | 305 |
263 std::sort(result.begin(), result.end(), compareByStart); | 306 std::sort(result.begin(), result.end(), compareByStart); |
264 return result; | 307 return result; |
265 } | 308 } |
266 | 309 |
267 DocumentMarkerVector DocumentMarkerController::markersInRange( | 310 DocumentMarkerVector DocumentMarkerController::markersInRange( |
268 const EphemeralRange& range, | 311 const EphemeralRange& range, |
269 DocumentMarker::MarkerTypes markerTypes) { | 312 DocumentMarker::MarkerTypes markerTypes) { |
| 313 return markersInRangeInternal(range, markerTypes, false); |
| 314 } |
270 | 315 |
| 316 DocumentMarkerVector DocumentMarkerController::markersInRangeInclusive( |
| 317 const EphemeralRange& range, |
| 318 DocumentMarker::MarkerTypes markerTypes) { |
| 319 return markersInRangeInternal(range, markerTypes, true); |
| 320 } |
| 321 |
| 322 DocumentMarkerVector DocumentMarkerController::markersInRangeInternal( |
| 323 const EphemeralRange& range, |
| 324 DocumentMarker::MarkerTypes markerTypes, |
| 325 bool includeSpansTouchingEndpoints) { |
271 DocumentMarkerVector foundMarkers; | 326 DocumentMarkerVector foundMarkers; |
272 | 327 |
273 Node* startContainer = range.startPosition().computeContainerNode(); | 328 Node* startContainer = range.startPosition().computeContainerNode(); |
274 DCHECK(startContainer); | 329 if (!startContainer) |
| 330 return DocumentMarkerVector(); |
| 331 |
275 unsigned startOffset = static_cast<unsigned>( | 332 unsigned startOffset = static_cast<unsigned>( |
276 range.startPosition().computeOffsetInContainerNode()); | 333 range.startPosition().computeOffsetInContainerNode()); |
| 334 |
277 Node* endContainer = range.endPosition().computeContainerNode(); | 335 Node* endContainer = range.endPosition().computeContainerNode(); |
278 DCHECK(endContainer); | 336 if (!endContainer) |
| 337 return DocumentMarkerVector(); |
| 338 |
279 unsigned endOffset = | 339 unsigned endOffset = |
280 static_cast<unsigned>(range.endPosition().computeOffsetInContainerNode()); | 340 static_cast<unsigned>(range.endPosition().computeOffsetInContainerNode()); |
281 | 341 |
282 for (Node& node : range.nodes()) { | 342 for (Node& node : range.nodes()) { |
283 for (DocumentMarker* marker : markersFor(&node)) { | 343 for (DocumentMarker* marker : markersFor(&node)) { |
284 if (!markerTypes.contains(marker->type())) | 344 if (!markerTypes.contains(marker->type())) |
285 continue; | 345 continue; |
286 if (node == startContainer && marker->endOffset() <= startOffset) | 346 if (node == startContainer) { |
287 continue; | 347 if (marker->endOffset() < startOffset || |
288 if (node == endContainer && marker->startOffset() >= endOffset) | 348 (marker->endOffset() == startOffset && |
289 continue; | 349 !includeSpansTouchingEndpoints)) |
| 350 continue; |
| 351 } |
| 352 if (node == endContainer) { |
| 353 if (marker->startOffset() > endOffset || |
| 354 (marker->startOffset() == endOffset && |
| 355 !includeSpansTouchingEndpoints)) |
| 356 continue; |
| 357 } |
290 foundMarkers.push_back(marker); | 358 foundMarkers.push_back(marker); |
291 } | 359 } |
292 } | 360 } |
293 return foundMarkers; | 361 return foundMarkers; |
294 } | 362 } |
295 | 363 |
296 Vector<IntRect> DocumentMarkerController::renderedRectsForTextMatchMarkers() { | 364 Vector<IntRect> DocumentMarkerController::renderedRectsForTextMatchMarkers() { |
297 Vector<IntRect> result; | 365 Vector<IntRect> result; |
298 for (auto nodeIterator = m_textMatches.begin(); | 366 for (auto nodeIterator = m_textMatches.begin(); |
299 nodeIterator != m_textMatches.end(); ++nodeIterator) { | 367 nodeIterator != m_textMatches.end(); ++nodeIterator) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 for (auto& nodeMarkers : m_textMatches) | 399 for (auto& nodeMarkers : m_textMatches) |
332 invalidateRectsForTextMatchMarkersInNode(*nodeMarkers.key); | 400 invalidateRectsForTextMatchMarkersInNode(*nodeMarkers.key); |
333 } | 401 } |
334 | 402 |
335 DEFINE_TRACE(DocumentMarkerController) { | 403 DEFINE_TRACE(DocumentMarkerController) { |
336 visitor->trace(m_spelling); | 404 visitor->trace(m_spelling); |
337 visitor->trace(m_grammar); | 405 visitor->trace(m_grammar); |
338 visitor->trace(m_textMatches); | 406 visitor->trace(m_textMatches); |
339 visitor->trace(m_compositions); | 407 visitor->trace(m_compositions); |
340 visitor->trace(m_document); | 408 visitor->trace(m_document); |
| 409 visitor->trace(m_suggestions); |
| 410 visitor->trace(m_suggestionHighlights); |
341 SynchronousMutationObserver::trace(visitor); | 411 SynchronousMutationObserver::trace(visitor); |
342 } | 412 } |
343 | 413 |
344 void DocumentMarkerController::removeMarkers( | 414 void DocumentMarkerController::removeMarkers( |
345 Node* node, | 415 Node* node, |
346 DocumentMarker::MarkerTypes markerTypes) { | 416 DocumentMarker::MarkerTypes markerTypes) { |
347 for (DocumentMarker::MarkerType type : markerTypes) { | 417 for (DocumentMarker::MarkerType type : markerTypes) { |
348 MarkerMap& markerMap = markerMapForType(type); | 418 MarkerMap& markerMap = markerMapForType(type); |
349 markerMap.erase(node); | 419 markerMap.erase(node); |
350 } | 420 } |
(...skipping 11 matching lines...) Expand all Loading... |
362 const Vector<String>& words) { | 432 const Vector<String>& words) { |
363 for (auto& nodeMarkers : m_spelling) { | 433 for (auto& nodeMarkers : m_spelling) { |
364 const Node& node = *nodeMarkers.key; | 434 const Node& node = *nodeMarkers.key; |
365 if (!node.isTextNode()) | 435 if (!node.isTextNode()) |
366 continue; | 436 continue; |
367 toSpellCheckMarkerList(nodeMarkers.value.get()) | 437 toSpellCheckMarkerList(nodeMarkers.value.get()) |
368 ->removeMarkersForWords(static_cast<const Text&>(node).data(), words); | 438 ->removeMarkersForWords(static_cast<const Text&>(node).data(), words); |
369 } | 439 } |
370 } | 440 } |
371 | 441 |
| 442 void DocumentMarkerController::removeMarkersForWordsAffectedByEditing( |
| 443 DocumentMarker::MarkerTypes markerTypes, |
| 444 bool doNotRemoveIfSelectionAtWordBoundary) { |
| 445 LOG(INFO) << "removeMarkersForWordsAffectedByEditing: " << doNotRemoveIfSelect
ionAtWordBoundary; |
| 446 LOG(INFO) << "clearing suggestion markers: " << markerTypes.contains(DocumentM
arker::Suggestion); |
| 447 DCHECK(m_document->frame()->selection().isAvailable()); |
| 448 TRACE_EVENT0( |
| 449 "blink", |
| 450 "DocumentMarkerController::removeMarkersForWordsAffectedByEditing"); |
| 451 |
| 452 Document* document = m_document->frame()->document(); |
| 453 DCHECK(document); |
| 454 |
| 455 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 456 // needs to be audited. See http://crbug.com/590369 for more details. |
| 457 document->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 458 |
| 459 // We want to remove the markers from a word if an editing command will change |
| 460 // the word. This can happen in one of several scenarios: |
| 461 // 1. Insert in the middle of a word. |
| 462 // 2. Appending non whitespace at the beginning of word. |
| 463 // 3. Appending non whitespace at the end of word. |
| 464 // Note that, appending only whitespaces at the beginning or end of word won't |
| 465 // change the word, so we don't need to remove the markers on that word. Of |
| 466 // course, if current selection is a range, we potentially will edit two words |
| 467 // that fall on the boundaries of selection, and remove words between the |
| 468 // selection boundaries. |
| 469 VisiblePosition startOfSelection = m_document->frame() |
| 470 ->selection() |
| 471 .computeVisibleSelectionInDOMTree() |
| 472 .visibleStart(); |
| 473 VisiblePosition endOfSelection = m_document->frame() |
| 474 ->selection() |
| 475 .computeVisibleSelectionInDOMTree() |
| 476 .visibleEnd(); |
| 477 if (startOfSelection.isNull()) |
| 478 return; |
| 479 // First word is the word that ends after or on the start of selection. |
| 480 VisiblePosition startOfFirstWord = |
| 481 startOfWord(startOfSelection, LeftWordIfOnBoundary); |
| 482 VisiblePosition endOfFirstWord = |
| 483 endOfWord(startOfSelection, LeftWordIfOnBoundary); |
| 484 // Last word is the word that begins before or on the end of selection |
| 485 VisiblePosition startOfLastWord = |
| 486 startOfWord(endOfSelection, RightWordIfOnBoundary); |
| 487 VisiblePosition endOfLastWord = |
| 488 endOfWord(endOfSelection, RightWordIfOnBoundary); |
| 489 |
| 490 if (startOfFirstWord.isNull()) { |
| 491 startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary); |
| 492 endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary); |
| 493 } |
| 494 |
| 495 if (endOfLastWord.isNull()) { |
| 496 startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary); |
| 497 endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary); |
| 498 } |
| 499 |
| 500 // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the |
| 501 // start of selection, we choose next word as the first word. |
| 502 if (doNotRemoveIfSelectionAtWordBoundary && |
| 503 endOfFirstWord.deepEquivalent() == startOfSelection.deepEquivalent()) { |
| 504 startOfFirstWord = nextWordPosition(startOfFirstWord); |
| 505 endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary); |
| 506 if (startOfFirstWord.deepEquivalent() == endOfSelection.deepEquivalent()) |
| 507 return; |
| 508 } |
| 509 |
| 510 // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at |
| 511 // the end of selection, we choose previous word as the last word. |
| 512 if (doNotRemoveIfSelectionAtWordBoundary && |
| 513 startOfLastWord.deepEquivalent() == endOfSelection.deepEquivalent()) { |
| 514 startOfLastWord = previousWordPosition(startOfLastWord); |
| 515 endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary); |
| 516 if (endOfLastWord.deepEquivalent() == startOfSelection.deepEquivalent()) |
| 517 return; |
| 518 } |
| 519 |
| 520 if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || |
| 521 startOfLastWord.isNull() || endOfLastWord.isNull()) |
| 522 return; |
| 523 |
| 524 const Position& removeMarkerStart = startOfFirstWord.deepEquivalent(); |
| 525 const Position& removeMarkerEnd = endOfLastWord.deepEquivalent(); |
| 526 if (removeMarkerStart > removeMarkerEnd) { |
| 527 // editing/inserting/insert-br-008.html and more reach here. |
| 528 // TODO(yosin): To avoid |DCHECK(removeMarkerStart <= removeMarkerEnd)| |
| 529 // in |EphemeralRange| constructor, we have this if-statement. Once we |
| 530 // fix |startOfWord()| and |endOfWord()|, we should remove this |
| 531 // if-statement. |
| 532 return; |
| 533 } |
| 534 |
| 535 // Now we remove markers on everything between startOfFirstWord and |
| 536 // endOfLastWord. However, if an autocorrection change a single word to |
| 537 // multiple words, we want to remove correction mark from all the resulted |
| 538 // words even we only edit one of them. For example, assuming autocorrection |
| 539 // changes "avantgarde" to "avant garde", we will have CorrectionIndicator |
| 540 // marker on both words and on the whitespace between them. If we then edit |
| 541 // garde, we would like to remove the marker from word "avant" and whitespace |
| 542 // as well. So we need to get the continous range of of marker that contains |
| 543 // the word in question, and remove marker on that whole range. |
| 544 const EphemeralRange wordRange(removeMarkerStart, removeMarkerEnd); |
| 545 document->markers().removeMarkers( |
| 546 wordRange, markerTypes, |
| 547 DocumentMarkerController::RemovePartiallyOverlappingMarker); |
| 548 } |
| 549 |
372 void DocumentMarkerController::repaintMarkers( | 550 void DocumentMarkerController::repaintMarkers( |
373 DocumentMarker::MarkerTypes markerTypes) { | 551 DocumentMarker::MarkerTypes markerTypes) { |
374 HeapHashSet<Member<Node>> nodesToRepaint; | 552 HeapHashSet<Member<Node>> nodesToRepaint; |
375 for (DocumentMarker::MarkerType type : markerTypes) { | 553 for (DocumentMarker::MarkerType type : markerTypes) { |
376 MarkerMap& markerMap = markerMapForType(type); | 554 MarkerMap& markerMap = markerMapForType(type); |
377 for (auto& nodeMarkers : markerMap) { | 555 for (auto& nodeMarkers : markerMap) { |
378 if (!nodeMarkers.value->empty()) | 556 if (!nodeMarkers.value->empty()) |
379 nodesToRepaint.insert(nodeMarkers.key.get()); | 557 nodesToRepaint.insert(nodeMarkers.key.get()); |
380 } | 558 } |
381 } | 559 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 DocumentMarker::MarkerType type) { | 680 DocumentMarker::MarkerType type) { |
503 switch (type) { | 681 switch (type) { |
504 case DocumentMarker::Spelling: | 682 case DocumentMarker::Spelling: |
505 return new SpellCheckMarkerList(DocumentMarker::Spelling); | 683 return new SpellCheckMarkerList(DocumentMarker::Spelling); |
506 case DocumentMarker::Grammar: | 684 case DocumentMarker::Grammar: |
507 return new SpellCheckMarkerList(DocumentMarker::Grammar); | 685 return new SpellCheckMarkerList(DocumentMarker::Grammar); |
508 case DocumentMarker::TextMatch: | 686 case DocumentMarker::TextMatch: |
509 return new TextMatchMarkerList(); | 687 return new TextMatchMarkerList(); |
510 case DocumentMarker::Composition: | 688 case DocumentMarker::Composition: |
511 return new CompositionMarkerList(); | 689 return new CompositionMarkerList(); |
| 690 case DocumentMarker::Suggestion: |
| 691 return new SuggestionMarkerList(); |
| 692 case DocumentMarker::SuggestionHighlight: |
| 693 return new SuggestionHighlightMarkerList(); |
512 default: | 694 default: |
513 // MSVC thinks this method doesn't handle all enum values even though it | 695 // MSVC thinks this method doesn't handle all enum values even though it |
514 // does. So we have to return something for the default case to avoid a | 696 // does. So we have to return something for the default case to avoid a |
515 // C4715 warning. | 697 // C4715 warning. |
516 UNREACHABLE(); | 698 UNREACHABLE(); |
517 return nullptr; | 699 return nullptr; |
518 } | 700 } |
519 } | 701 } |
520 | 702 |
521 HeapVector<Member<DocumentMarkerList>> | 703 HeapVector<Member<DocumentMarkerList>> |
(...skipping 24 matching lines...) Expand all Loading... |
546 DocumentMarker::MarkerType type) const { | 728 DocumentMarker::MarkerType type) const { |
547 switch (type) { | 729 switch (type) { |
548 case DocumentMarker::Spelling: | 730 case DocumentMarker::Spelling: |
549 return m_spelling; | 731 return m_spelling; |
550 case DocumentMarker::Grammar: | 732 case DocumentMarker::Grammar: |
551 return m_grammar; | 733 return m_grammar; |
552 case DocumentMarker::TextMatch: | 734 case DocumentMarker::TextMatch: |
553 return m_textMatches; | 735 return m_textMatches; |
554 case DocumentMarker::Composition: | 736 case DocumentMarker::Composition: |
555 return m_compositions; | 737 return m_compositions; |
| 738 case DocumentMarker::Suggestion: |
| 739 return m_suggestions; |
| 740 case DocumentMarker::SuggestionHighlight: |
| 741 return m_suggestionHighlights; |
556 default: | 742 default: |
557 // MSVC thinks this method doesn't handle all enum values even though it | 743 // MSVC thinks this method doesn't handle all enum values even though it |
558 // does. So we have to return something for the default case to avoid a | 744 // does. So we have to return something for the default case to avoid a |
559 // C4715 warning. | 745 // C4715 warning. |
560 UNREACHABLE(); | 746 UNREACHABLE(); |
561 return m_spelling; | 747 return m_spelling; |
562 } | 748 } |
563 } | 749 } |
564 | 750 |
565 void DocumentMarkerController::removeMarkers( | 751 void DocumentMarkerController::removeMarkers( |
566 TextIterator& markedText, | 752 TextIterator& markedText, |
567 DocumentMarker::MarkerTypes markerTypes, | 753 DocumentMarker::MarkerTypes markerTypes, |
568 RemovePartiallyOverlappingMarkerOrNot | 754 RemovePartiallyOverlappingMarkerOrNot |
569 shouldRemovePartiallyOverlappingMarker) { | 755 shouldRemovePartiallyOverlappingMarker) { |
570 for (; !markedText.atEnd(); markedText.advance()) { | 756 for (; !markedText.atEnd(); markedText.advance()) { |
| 757 LOG(INFO) << "removing markers from " << markedText.currentContainer() << "
from offsets " << markedText.startOffsetInCurrentContainer() << " to " << marked
Text.endOffsetInCurrentContainer(); |
571 int startOffset = markedText.startOffsetInCurrentContainer(); | 758 int startOffset = markedText.startOffsetInCurrentContainer(); |
572 int endOffset = markedText.endOffsetInCurrentContainer(); | 759 int endOffset = markedText.endOffsetInCurrentContainer(); |
573 removeMarkers(markedText.currentContainer(), startOffset, | 760 removeMarkers(markedText.currentContainer(), startOffset, |
574 endOffset - startOffset, markerTypes, | 761 endOffset - startOffset, markerTypes, |
575 shouldRemovePartiallyOverlappingMarker); | 762 shouldRemovePartiallyOverlappingMarker); |
576 } | 763 } |
577 } | 764 } |
578 | 765 |
579 // SynchronousMutationObserver | 766 // SynchronousMutationObserver |
580 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, | 767 void DocumentMarkerController::didUpdateCharacterData(CharacterData* node, |
(...skipping 24 matching lines...) Expand all Loading... |
605 } | 792 } |
606 | 793 |
607 } // namespace blink | 794 } // namespace blink |
608 | 795 |
609 #ifndef NDEBUG | 796 #ifndef NDEBUG |
610 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 797 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
611 if (controller) | 798 if (controller) |
612 controller->showMarkers(); | 799 controller->showMarkers(); |
613 } | 800 } |
614 #endif | 801 #endif |
OLD | NEW |