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 10 matching lines...) Expand all Loading... | |
21 * | 21 * |
22 * You should have received a copy of the GNU Library General Public License | 22 * You should have received a copy of the GNU Library General Public License |
23 * along with this library; see the file COPYING.LIB. If not, write to | 23 * along with this library; see the file COPYING.LIB. If not, write to |
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
25 * Boston, MA 02110-1301, USA. | 25 * Boston, MA 02110-1301, USA. |
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 "core/dom/Node.h" | 32 #include "core/dom/Node.h" |
32 #include "core/dom/NodeTraversal.h" | 33 #include "core/dom/NodeTraversal.h" |
33 #include "core/dom/Range.h" | 34 #include "core/dom/Range.h" |
34 #include "core/dom/Text.h" | 35 #include "core/dom/Text.h" |
35 #include "core/editing/iterators/TextIterator.h" | 36 #include "core/editing/iterators/TextIterator.h" |
37 #include "core/editing/markers/DocumentMarkerListEditor.h" | |
36 #include "core/editing/markers/RenderedDocumentMarker.h" | 38 #include "core/editing/markers/RenderedDocumentMarker.h" |
37 #include "core/frame/FrameView.h" | 39 #include "core/frame/FrameView.h" |
38 #include "core/layout/LayoutObject.h" | 40 #include "core/layout/LayoutObject.h" |
39 #include <algorithm> | |
40 | 41 |
41 #ifndef NDEBUG | 42 #ifndef NDEBUG |
42 #include <stdio.h> | 43 #include <stdio.h> |
43 #endif | 44 #endif |
44 | 45 |
45 namespace blink { | 46 namespace blink { |
46 | 47 |
47 MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words) | 48 MarkerRemoverPredicate::MarkerRemoverPredicate(const Vector<String>& words) |
48 : words_(words) {} | 49 : words_(words) {} |
49 | 50 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 | 169 |
169 void DocumentMarkerController::RemoveMarkers( | 170 void DocumentMarkerController::RemoveMarkers( |
170 const EphemeralRange& range, | 171 const EphemeralRange& range, |
171 DocumentMarker::MarkerTypes marker_types) { | 172 DocumentMarker::MarkerTypes marker_types) { |
172 DCHECK(!document_->NeedsLayoutTreeUpdate()); | 173 DCHECK(!document_->NeedsLayoutTreeUpdate()); |
173 | 174 |
174 TextIterator marked_text(range.StartPosition(), range.EndPosition()); | 175 TextIterator marked_text(range.StartPosition(), range.EndPosition()); |
175 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); | 176 DocumentMarkerController::RemoveMarkers(marked_text, marker_types); |
176 } | 177 } |
177 | 178 |
178 static bool StartsFurther(const Member<RenderedDocumentMarker>& lhv, | |
179 const DocumentMarker* rhv) { | |
180 return lhv->StartOffset() < rhv->StartOffset(); | |
181 } | |
182 | |
183 static bool EndsBefore(size_t start_offset, | |
184 const Member<RenderedDocumentMarker>& rhv) { | |
185 return start_offset < rhv->EndOffset(); | |
186 } | |
187 | |
188 static bool CompareByStart(const Member<DocumentMarker>& lhv, | 179 static bool CompareByStart(const Member<DocumentMarker>& lhv, |
189 const Member<DocumentMarker>& rhv) { | 180 const Member<DocumentMarker>& rhv) { |
190 return lhv->StartOffset() < rhv->StartOffset(); | 181 return lhv->StartOffset() < rhv->StartOffset(); |
191 } | 182 } |
192 | 183 |
193 static bool DoesNotOverlap(const Member<RenderedDocumentMarker>& lhv, | |
194 const DocumentMarker* rhv) { | |
195 return lhv->EndOffset() < rhv->StartOffset(); | |
196 } | |
197 | |
198 static void UpdateMarkerRenderedRect(const Node& node, | 184 static void UpdateMarkerRenderedRect(const Node& node, |
199 RenderedDocumentMarker& marker) { | 185 RenderedDocumentMarker& marker) { |
200 Range* range = Range::Create(node.GetDocument()); | 186 Range* range = Range::Create(node.GetDocument()); |
201 // The offsets of the marker may be out-dated, so check for exceptions. | 187 // The offsets of the marker may be out-dated, so check for exceptions. |
202 DummyExceptionStateForTesting exception_state; | 188 DummyExceptionStateForTesting exception_state; |
203 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), | 189 range->setStart(&const_cast<Node&>(node), marker.StartOffset(), |
204 exception_state); | 190 exception_state); |
205 if (!exception_state.HadException()) { | 191 if (!exception_state.HadException()) { |
206 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), | 192 range->setEnd(&const_cast<Node&>(node), marker.EndOffset(), |
207 IGNORE_EXCEPTION_FOR_TESTING); | 193 IGNORE_EXCEPTION_FOR_TESTING); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 Member<MarkerList>& list = ListForType(markers, new_marker_type); | 227 Member<MarkerList>& list = ListForType(markers, new_marker_type); |
242 DocumentMarkerListEditor::AddMarker(list, &new_marker); | 228 DocumentMarkerListEditor::AddMarker(list, &new_marker); |
243 | 229 |
244 // repaint the affected node | 230 // repaint the affected node |
245 if (node->GetLayoutObject()) { | 231 if (node->GetLayoutObject()) { |
246 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 232 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
247 kPaintInvalidationDocumentMarkerChange); | 233 kPaintInvalidationDocumentMarkerChange); |
248 } | 234 } |
249 } | 235 } |
250 | 236 |
251 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
252 // TODO(rlanday): this method was created by cutting and pasting code from | |
253 // DocumentMarkerController::AddMarker(), it should be refactored in a future CL | |
254 void DocumentMarkerListEditor::AddMarker(MarkerList* list, | |
255 const DocumentMarker* marker) { | |
256 RenderedDocumentMarker* rendered_marker = | |
257 RenderedDocumentMarker::Create(*marker); | |
258 if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { | |
259 list->push_back(rendered_marker); | |
260 } else { | |
261 if (marker->GetType() != DocumentMarker::kTextMatch && | |
262 marker->GetType() != DocumentMarker::kComposition) { | |
263 MergeOverlapping(list, rendered_marker); | |
264 } else { | |
265 MarkerList::iterator pos = | |
266 std::lower_bound(list->begin(), list->end(), marker, StartsFurther); | |
267 list->insert(pos - list->begin(), rendered_marker); | |
268 } | |
269 } | |
270 } | |
271 | |
272 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
273 void DocumentMarkerListEditor::MergeOverlapping( | |
274 MarkerList* list, | |
275 RenderedDocumentMarker* to_insert) { | |
276 MarkerList::iterator first_overlapping = | |
277 std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | |
278 size_t index = first_overlapping - list->begin(); | |
279 list->insert(index, to_insert); | |
280 MarkerList::iterator inserted = list->begin() + index; | |
281 first_overlapping = inserted + 1; | |
282 for (MarkerList::iterator i = first_overlapping; | |
283 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | |
284 (*inserted)->SetStartOffset( | |
285 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | |
286 (*inserted)->SetEndOffset( | |
287 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | |
288 list->erase(i - list->begin()); | |
289 } | |
290 } | |
291 | |
292 // Moves markers from src_node to dst_node. Markers are moved if their start | 237 // Moves markers from src_node to dst_node. Markers are moved if their start |
293 // offset is less than length. Markers that run past that point are truncated. | 238 // offset is less than length. Markers that run past that point are truncated. |
294 void DocumentMarkerController::MoveMarkers(Node* src_node, | 239 void DocumentMarkerController::MoveMarkers(Node* src_node, |
295 int length, | 240 int length, |
296 Node* dst_node) { | 241 Node* dst_node) { |
297 if (length <= 0) | 242 if (length <= 0) |
298 return; | 243 return; |
299 | 244 |
300 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 245 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
301 return; | 246 return; |
(...skipping 13 matching lines...) Expand all Loading... | |
315 for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); | 260 for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); |
316 ++marker_list_index) { | 261 ++marker_list_index) { |
317 MarkerList* src_list = src_markers->at(marker_list_index); | 262 MarkerList* src_list = src_markers->at(marker_list_index); |
318 if (!src_list) | 263 if (!src_list) |
319 continue; | 264 continue; |
320 | 265 |
321 if (!dst_markers->at(marker_list_index)) | 266 if (!dst_markers->at(marker_list_index)) |
322 dst_markers->at(marker_list_index) = new MarkerList; | 267 dst_markers->at(marker_list_index) = new MarkerList; |
323 MarkerList* dst_list = dst_markers->at(marker_list_index); | 268 MarkerList* dst_list = dst_markers->at(marker_list_index); |
324 | 269 |
325 unsigned end_offset = length - 1; | 270 if (DocumentMarkerListEditor::MoveMarkers(src_list, length, dst_list)) |
Xiaocheng
2017/04/18 04:29:56
Doesn't seem properly rebased... There should be o
| |
326 MarkerList::iterator it; | |
327 for (it = src_list->begin(); it != src_list->end(); ++it) { | |
328 DocumentMarker* marker = it->Get(); | |
329 | |
330 // stop if we are now past the specified range | |
331 if (marker->StartOffset() > end_offset) | |
332 break; | |
333 | |
334 // pin the marker to the specified range | |
335 doc_dirty = true; | 271 doc_dirty = true; |
336 if (marker->EndOffset() > end_offset) | |
337 marker->SetEndOffset(end_offset); | |
338 | |
339 DocumentMarkerListEditor::AddMarker(dst_list, marker); | |
340 } | |
341 | |
342 // Remove the range of markers that were moved to dst_node | |
343 src_list->erase(0, it - src_list->begin()); | |
344 } | 272 } |
345 | 273 |
346 // repaint the affected node | 274 // repaint the affected node |
347 if (doc_dirty && dst_node->GetLayoutObject()) { | 275 if (doc_dirty && dst_node->GetLayoutObject()) { |
348 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 276 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
349 kPaintInvalidationDocumentMarkerChange); | 277 kPaintInvalidationDocumentMarkerChange); |
350 } | 278 } |
351 } | 279 } |
352 | 280 |
353 void DocumentMarkerController::RemoveMarkers( | 281 void DocumentMarkerController::RemoveMarkers( |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
396 possibly_existing_marker_types_ = 0; | 324 possibly_existing_marker_types_ = 0; |
397 } | 325 } |
398 | 326 |
399 // repaint the affected node | 327 // repaint the affected node |
400 if (doc_dirty && node->GetLayoutObject()) { | 328 if (doc_dirty && node->GetLayoutObject()) { |
401 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 329 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
402 kPaintInvalidationDocumentMarkerChange); | 330 kPaintInvalidationDocumentMarkerChange); |
403 } | 331 } |
404 } | 332 } |
405 | 333 |
406 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
407 // TODO(rlanday): this method was created by cutting and pasting code from | |
408 // DocumentMarkerController::RemoveMarkers(), it should be refactored in a | |
409 // future CL | |
410 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | |
411 unsigned start_offset, | |
412 int length) { | |
413 bool doc_dirty = false; | |
414 unsigned end_offset = start_offset + length; | |
415 MarkerList::iterator start_pos = | |
416 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
417 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
418 DocumentMarker marker(*i->Get()); | |
419 | |
420 // markers are returned in order, so stop if we are now past the specified | |
421 // range | |
422 if (marker.StartOffset() >= end_offset) | |
423 break; | |
424 | |
425 list->erase(i - list->begin()); | |
426 doc_dirty = true; | |
427 } | |
428 | |
429 return doc_dirty; | |
430 } | |
431 | |
432 DocumentMarkerVector DocumentMarkerController::MarkersFor( | 334 DocumentMarkerVector DocumentMarkerController::MarkersFor( |
433 Node* node, | 335 Node* node, |
434 DocumentMarker::MarkerTypes marker_types) { | 336 DocumentMarker::MarkerTypes marker_types) { |
435 DocumentMarkerVector result; | 337 DocumentMarkerVector result; |
436 | 338 |
437 MarkerLists* markers = markers_.at(node); | 339 MarkerLists* markers = markers_.at(node); |
438 if (!markers) | 340 if (!markers) |
439 return result; | 341 return result; |
440 | 342 |
441 for (size_t marker_list_index = 0; | 343 for (size_t marker_list_index = 0; |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 | 652 |
751 bool marker_found = false; | 653 bool marker_found = false; |
752 for (Node& node : range.Nodes()) { | 654 for (Node& node : range.Nodes()) { |
753 int start_offset = node == start_container ? container_start_offset : 0; | 655 int start_offset = node == start_container ? container_start_offset : 0; |
754 int end_offset = node == end_container ? container_end_offset : INT_MAX; | 656 int end_offset = node == end_container ? container_end_offset : INT_MAX; |
755 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); | 657 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); |
756 } | 658 } |
757 return marker_found; | 659 return marker_found; |
758 } | 660 } |
759 | 661 |
662 static bool EndsBefore(size_t start_offset, | |
663 const Member<RenderedDocumentMarker>& rhv) { | |
664 return start_offset < rhv->EndOffset(); | |
665 } | |
666 | |
760 bool DocumentMarkerController::SetMarkersActive(Node* node, | 667 bool DocumentMarkerController::SetMarkersActive(Node* node, |
761 unsigned start_offset, | 668 unsigned start_offset, |
762 unsigned end_offset, | 669 unsigned end_offset, |
763 bool active) { | 670 bool active) { |
764 MarkerLists* markers = markers_.at(node); | 671 MarkerLists* markers = markers_.at(node); |
765 if (!markers) | 672 if (!markers) |
766 return false; | 673 return false; |
767 | 674 |
768 bool doc_dirty = false; | 675 bool doc_dirty = false; |
769 Member<MarkerList>& list = ListForType(markers, DocumentMarker::kTextMatch); | 676 Member<MarkerList>& list = ListForType(markers, DocumentMarker::kTextMatch); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 | 756 |
850 if (!did_shift_marker) | 757 if (!did_shift_marker) |
851 return; | 758 return; |
852 if (!node->GetLayoutObject()) | 759 if (!node->GetLayoutObject()) |
853 return; | 760 return; |
854 InvalidateRectsForMarkersInNode(*node); | 761 InvalidateRectsForMarkersInNode(*node); |
855 // repaint the affected node | 762 // repaint the affected node |
856 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 763 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
857 } | 764 } |
858 | 765 |
859 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
860 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | |
861 unsigned offset, | |
862 unsigned old_length, | |
863 unsigned new_length) { | |
864 bool did_shift_marker = false; | |
865 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
866 RenderedDocumentMarker& marker = **it; | |
867 Optional<DocumentMarker::MarkerOffsets> result = | |
868 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
869 if (result == WTF::kNullopt) { | |
870 list->erase(it - list->begin()); | |
871 --it; | |
872 did_shift_marker = true; | |
873 continue; | |
874 } | |
875 | |
876 if (marker.StartOffset() != result.value().start_offset || | |
877 marker.EndOffset() != result.value().end_offset) { | |
878 did_shift_marker = true; | |
879 marker.SetStartOffset(result.value().start_offset); | |
880 marker.SetEndOffset(result.value().end_offset); | |
881 } | |
882 } | |
883 | |
884 return did_shift_marker; | |
885 } | |
886 | |
887 } // namespace blink | 766 } // namespace blink |
888 | 767 |
889 #ifndef NDEBUG | 768 #ifndef NDEBUG |
890 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 769 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
891 if (controller) | 770 if (controller) |
892 controller->ShowMarkers(); | 771 controller->ShowMarkers(); |
893 } | 772 } |
894 #endif | 773 #endif |
OLD | NEW |