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