OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/editing/markers/DocumentMarkerList.h" |
| 6 |
| 7 namespace blink { |
| 8 |
| 9 namespace { |
| 10 |
| 11 bool endsBefore(size_t startOffset, const Member<DocumentMarker>& rhv) { |
| 12 return startOffset < rhv->endOffset(); |
| 13 } |
| 14 |
| 15 } // namespace |
| 16 |
| 17 DocumentMarkerList::DocumentMarkerList() {} |
| 18 |
| 19 bool DocumentMarkerList::isEditingMarkerList() const { |
| 20 return false; |
| 21 } |
| 22 |
| 23 bool DocumentMarkerList::isSpellCheckMarkerList() const { |
| 24 return false; |
| 25 } |
| 26 |
| 27 void DocumentMarkerList::clear() { |
| 28 m_markers.clear(); |
| 29 } |
| 30 |
| 31 void DocumentMarkerList::appendMarkersToInputList( |
| 32 DocumentMarkerVector* list) const { |
| 33 for (Member<DocumentMarker> marker : m_markers) { |
| 34 list->push_back(marker); |
| 35 } |
| 36 } |
| 37 |
| 38 bool DocumentMarkerList::copyMarkers(unsigned startOffset, |
| 39 int length, |
| 40 DocumentMarkerList* dstList, |
| 41 int delta) const { |
| 42 bool docDirty = false; |
| 43 unsigned endOffset = startOffset + length - 1; |
| 44 |
| 45 for (Member<DocumentMarker> marker : m_markers) { |
| 46 // pin the marker to the specified range and apply the shift delta |
| 47 if (marker->endOffset() >= startOffset && |
| 48 marker->startOffset() <= endOffset) { |
| 49 docDirty = true; |
| 50 if (marker->startOffset() < startOffset) |
| 51 marker->setStartOffset(startOffset); |
| 52 if (marker->endOffset() > endOffset) |
| 53 marker->setEndOffset(endOffset); |
| 54 marker->shiftOffsets(delta); |
| 55 |
| 56 dstList->push_back(marker); |
| 57 } |
| 58 } |
| 59 |
| 60 return docDirty; |
| 61 } |
| 62 |
| 63 void DocumentMarkerList::removeMarkers( |
| 64 unsigned startOffset, |
| 65 int length, |
| 66 bool shouldRemovePartiallyOverlappingMarkers, |
| 67 bool* didRemoveMarker) { |
| 68 unsigned endOffset = startOffset + length; |
| 69 size_t markerIndex = 0; |
| 70 if (markerListIsSorted()) { |
| 71 markerIndex = |
| 72 getPosOfFirstMarkerNotEndingBefore(startOffset) - m_markers.begin(); |
| 73 } |
| 74 |
| 75 while (markerIndex < m_markers.size()) { |
| 76 DocumentMarker& marker = *m_markers.at(markerIndex); |
| 77 if (!markerListIsSorted()) { |
| 78 if (marker.endOffset() <= startOffset) { |
| 79 ++markerIndex; |
| 80 continue; |
| 81 } |
| 82 } |
| 83 |
| 84 if (marker.startOffset() >= endOffset) { |
| 85 if (markerListIsSorted()) |
| 86 break; |
| 87 ++markerIndex; |
| 88 continue; |
| 89 } |
| 90 |
| 91 // pitch the old marker |
| 92 m_markers.remove(markerIndex); |
| 93 *didRemoveMarker = true; |
| 94 |
| 95 if (shouldRemovePartiallyOverlappingMarkers) { |
| 96 // Stop here. Don't add resulting slices back. |
| 97 continue; |
| 98 } |
| 99 |
| 100 // add either of the resulting slices that are left after removing target |
| 101 if (startOffset > marker.startOffset()) { |
| 102 DocumentMarker* newLeft = new DocumentMarker(marker); |
| 103 newLeft->setEndOffset(startOffset); |
| 104 if (markerListIsSorted()) { |
| 105 m_markers.insert(markerIndex, *newLeft); |
| 106 // Move to the marker after the inserted one. |
| 107 ++markerIndex; |
| 108 } else { |
| 109 // For the unsorted case, we just stick the new marker at the end of the |
| 110 // list. The loop will eventually run on it but that's not a problem |
| 111 // since it's known to be outside the range being removed. |
| 112 m_markers.push_back(*newLeft); |
| 113 } |
| 114 } |
| 115 if (marker.endOffset() > endOffset) { |
| 116 DocumentMarker* newRight = new DocumentMarker(marker); |
| 117 newRight->setStartOffset(endOffset); |
| 118 if (markerListIsSorted()) { |
| 119 m_markers.insert(markerIndex, *newRight); |
| 120 // Move to the marker after the inserted one. |
| 121 ++markerIndex; |
| 122 } else { |
| 123 m_markers.push_back(*newRight); |
| 124 } |
| 125 } |
| 126 } |
| 127 } |
| 128 |
| 129 bool DocumentMarkerList::shiftMarkers(unsigned offset, |
| 130 unsigned oldLength, |
| 131 unsigned newLength) { |
| 132 bool didShift = false; |
| 133 for (auto it = m_markers.begin(); it != m_markers.end(); ++it) { |
| 134 DocumentMarker& marker = **it; |
| 135 |
| 136 DocumentMarker::ShiftMarkerResult result = |
| 137 marker.getShiftedMarkerPosition(offset, oldLength, newLength); |
| 138 if (result.shouldRemoveMarker) { |
| 139 m_markers.remove(it - m_markers.begin()); |
| 140 --it; |
| 141 |
| 142 didShift = true; |
| 143 } else if (result.newStartOffset != marker.startOffset() || |
| 144 result.newEndOffset != marker.endOffset()) { |
| 145 marker.setStartOffset(result.newStartOffset); |
| 146 marker.setEndOffset(result.newEndOffset); |
| 147 |
| 148 didShift = true; |
| 149 } |
| 150 } |
| 151 return didShift; |
| 152 } |
| 153 |
| 154 HeapVector<Member<DocumentMarker>>::iterator |
| 155 DocumentMarkerList::getPosOfFirstMarkerNotEndingBefore(size_t startOffset) { |
| 156 DCHECK(markerListIsSorted()); |
| 157 return std::upper_bound(m_markers.begin(), m_markers.end(), startOffset, |
| 158 endsBefore); |
| 159 } |
| 160 |
| 161 DEFINE_TRACE(DocumentMarkerList) { |
| 162 visitor->trace(m_markers); |
| 163 } |
| 164 |
| 165 } // namespace blink |
OLD | NEW |