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/DocumentMarkerListEditor.h" |
| 6 |
| 7 #include "core/editing/markers/RenderedDocumentMarker.h" |
| 8 |
| 9 namespace blink { |
| 10 |
| 11 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv, |
| 12 const DocumentMarker* rhv) { |
| 13 return lhv->StartOffset() < rhv->StartOffset(); |
| 14 } |
| 15 |
| 16 static bool EndsBefore(size_t start_offset, |
| 17 const Member<RenderedDocumentMarker>& rhv) { |
| 18 return start_offset < rhv->EndOffset(); |
| 19 } |
| 20 |
| 21 static bool DoesNotOverlap(const Member<RenderedDocumentMarker>& lhv, |
| 22 const DocumentMarker* rhv) { |
| 23 return lhv->EndOffset() < rhv->StartOffset(); |
| 24 } |
| 25 |
| 26 // TODO(rlanday): this method was created by cutting and pasting code from |
| 27 // DocumentMarkerController::AddMarker(), it should be refactored in a future CL |
| 28 void DocumentMarkerListEditor::AddMarker(MarkerList* list, |
| 29 const DocumentMarker* marker) { |
| 30 RenderedDocumentMarker* rendered_marker = |
| 31 RenderedDocumentMarker::Create(*marker); |
| 32 if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { |
| 33 list->push_back(rendered_marker); |
| 34 } else { |
| 35 if (marker->GetType() != DocumentMarker::kTextMatch && |
| 36 marker->GetType() != DocumentMarker::kComposition) { |
| 37 MergeOverlapping(list, rendered_marker); |
| 38 } else { |
| 39 MarkerList::iterator pos = |
| 40 std::lower_bound(list->begin(), list->end(), marker, StartsFurther); |
| 41 list->insert(pos - list->begin(), rendered_marker); |
| 42 } |
| 43 } |
| 44 } |
| 45 |
| 46 bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, |
| 47 int length, |
| 48 MarkerList* dst_list) { |
| 49 DCHECK_GT(length, 0); |
| 50 bool didMoveMarker = false; |
| 51 unsigned end_offset = length - 1; |
| 52 |
| 53 MarkerList::iterator it; |
| 54 for (it = src_list->begin(); it != src_list->end(); ++it) { |
| 55 DocumentMarker& marker = **it; |
| 56 if (marker.StartOffset() > end_offset) |
| 57 break; |
| 58 |
| 59 // pin the marker to the specified range and apply the shift delta |
| 60 if (marker.EndOffset() > end_offset) |
| 61 marker.SetEndOffset(end_offset); |
| 62 |
| 63 DocumentMarkerListEditor::AddMarker(dst_list, &marker); |
| 64 didMoveMarker = true; |
| 65 } |
| 66 |
| 67 // Remove the range of markers that were moved to dstNode |
| 68 src_list->erase(0, it - src_list->begin()); |
| 69 |
| 70 return didMoveMarker; |
| 71 } |
| 72 |
| 73 // TODO(rlanday): this method was created by cutting and pasting code from |
| 74 // DocumentMarkerController::RemoveMarkers(), it should be refactored in a |
| 75 // future CL |
| 76 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, |
| 77 unsigned start_offset, |
| 78 int length) { |
| 79 bool doc_dirty = false; |
| 80 unsigned end_offset = start_offset + length; |
| 81 MarkerList::iterator start_pos = |
| 82 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); |
| 83 for (MarkerList::iterator i = start_pos; i != list->end();) { |
| 84 DocumentMarker marker(*i->Get()); |
| 85 |
| 86 // markers are returned in order, so stop if we are now past the specified |
| 87 // range |
| 88 if (marker.StartOffset() >= end_offset) |
| 89 break; |
| 90 |
| 91 list->erase(i - list->begin()); |
| 92 doc_dirty = true; |
| 93 } |
| 94 |
| 95 return doc_dirty; |
| 96 } |
| 97 |
| 98 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, |
| 99 unsigned offset, |
| 100 unsigned old_length, |
| 101 unsigned new_length) { |
| 102 bool did_shift_marker = false; |
| 103 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { |
| 104 RenderedDocumentMarker& marker = **it; |
| 105 Optional<DocumentMarker::MarkerOffsets> result = |
| 106 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); |
| 107 if (result == WTF::kNullopt) { |
| 108 list->erase(it - list->begin()); |
| 109 --it; |
| 110 did_shift_marker = true; |
| 111 continue; |
| 112 } |
| 113 |
| 114 if (marker.StartOffset() != result.value().start_offset || |
| 115 marker.EndOffset() != result.value().end_offset) { |
| 116 did_shift_marker = true; |
| 117 marker.SetStartOffset(result.value().start_offset); |
| 118 marker.SetEndOffset(result.value().end_offset); |
| 119 } |
| 120 } |
| 121 |
| 122 return did_shift_marker; |
| 123 } |
| 124 |
| 125 void DocumentMarkerListEditor::MergeOverlapping( |
| 126 DocumentMarkerListEditor::MarkerList* list, |
| 127 RenderedDocumentMarker* to_insert) { |
| 128 auto first_overlapping = |
| 129 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); |
| 130 size_t index = first_overlapping - list->begin(); |
| 131 list->insert(index, to_insert); |
| 132 const auto inserted = list->begin() + index; |
| 133 first_overlapping = inserted + 1; |
| 134 for (const auto i = first_overlapping; |
| 135 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { |
| 136 (*inserted)->SetStartOffset( |
| 137 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); |
| 138 (*inserted)->SetEndOffset( |
| 139 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); |
| 140 list->erase(i - list->begin()); |
| 141 } |
| 142 } |
| 143 |
| 144 } // namespace blink |
OLD | NEW |