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 24 matching lines...) Expand all Loading... | |
326 doc_dirty = true; | 271 doc_dirty = true; |
327 } | 272 } |
328 | 273 |
329 // repaint the affected node | 274 // repaint the affected node |
330 if (doc_dirty && dst_node->GetLayoutObject()) { | 275 if (doc_dirty && dst_node->GetLayoutObject()) { |
331 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 276 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
332 kPaintInvalidationDocumentMarkerChange); | 277 kPaintInvalidationDocumentMarkerChange); |
333 } | 278 } |
334 } | 279 } |
335 | 280 |
336 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
337 bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, | |
338 int length, | |
339 MarkerList* dst_list) { | |
340 DCHECK_GT(length, 0); | |
341 bool doc_dirty = false; | |
342 unsigned end_offset = length - 1; | |
343 MarkerList::iterator it; | |
344 for (it = src_list->begin(); it != src_list->end(); ++it) { | |
345 DocumentMarker* marker = it->Get(); | |
346 | |
347 // stop if we are now past the specified range | |
348 if (marker->StartOffset() > end_offset) | |
349 break; | |
350 | |
351 // pin the marker to the specified range | |
352 doc_dirty = true; | |
353 if (marker->EndOffset() > end_offset) | |
354 marker->SetEndOffset(end_offset); | |
355 | |
356 DocumentMarkerListEditor::AddMarker(dst_list, marker); | |
357 } | |
358 | |
359 // Remove the range of markers that were moved to dst_node | |
360 src_list->erase(0, it - src_list->begin()); | |
361 | |
362 return doc_dirty; | |
363 } | |
364 | |
365 void DocumentMarkerController::RemoveMarkers( | 281 void DocumentMarkerController::RemoveMarkers( |
366 Node* node, | 282 Node* node, |
367 unsigned start_offset, | 283 unsigned start_offset, |
368 int length, | 284 int length, |
369 DocumentMarker::MarkerTypes marker_types) { | 285 DocumentMarker::MarkerTypes marker_types) { |
370 if (length <= 0) | 286 if (length <= 0) |
371 return; | 287 return; |
372 | 288 |
373 if (!PossiblyHasMarkers(marker_types)) | 289 if (!PossiblyHasMarkers(marker_types)) |
374 return; | 290 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 possibly_existing_marker_types_ = 0; | 324 possibly_existing_marker_types_ = 0; |
409 } | 325 } |
410 | 326 |
411 // repaint the affected node | 327 // repaint the affected node |
412 if (doc_dirty && node->GetLayoutObject()) { | 328 if (doc_dirty && node->GetLayoutObject()) { |
413 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 329 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
414 kPaintInvalidationDocumentMarkerChange); | 330 kPaintInvalidationDocumentMarkerChange); |
415 } | 331 } |
416 } | 332 } |
417 | 333 |
418 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
419 // TODO(rlanday): this method was created by cutting and pasting code from | |
420 // DocumentMarkerController::RemoveMarkers(), it should be refactored in a | |
421 // future CL | |
422 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | |
423 unsigned start_offset, | |
424 int length) { | |
425 bool doc_dirty = false; | |
426 unsigned end_offset = start_offset + length; | |
427 MarkerList::iterator start_pos = | |
428 std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | |
429 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
430 DocumentMarker marker(*i->Get()); | |
431 | |
432 // markers are returned in order, so stop if we are now past the specified | |
433 // range | |
434 if (marker.StartOffset() >= end_offset) | |
435 break; | |
436 | |
437 list->erase(i - list->begin()); | |
438 doc_dirty = true; | |
439 } | |
440 | |
441 return doc_dirty; | |
442 } | |
443 | |
444 DocumentMarkerVector DocumentMarkerController::MarkersFor( | 334 DocumentMarkerVector DocumentMarkerController::MarkersFor( |
445 Node* node, | 335 Node* node, |
446 DocumentMarker::MarkerTypes marker_types) { | 336 DocumentMarker::MarkerTypes marker_types) { |
447 DocumentMarkerVector result; | 337 DocumentMarkerVector result; |
448 | 338 |
449 MarkerLists* markers = markers_.at(node); | 339 MarkerLists* markers = markers_.at(node); |
450 if (!markers) | 340 if (!markers) |
451 return result; | 341 return result; |
452 | 342 |
453 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... | |
762 | 652 |
763 bool marker_found = false; | 653 bool marker_found = false; |
764 for (Node& node : range.Nodes()) { | 654 for (Node& node : range.Nodes()) { |
765 int start_offset = node == start_container ? container_start_offset : 0; | 655 int start_offset = node == start_container ? container_start_offset : 0; |
766 int end_offset = node == end_container ? container_end_offset : INT_MAX; | 656 int end_offset = node == end_container ? container_end_offset : INT_MAX; |
767 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); | 657 marker_found |= SetMarkersActive(&node, start_offset, end_offset, active); |
768 } | 658 } |
769 return marker_found; | 659 return marker_found; |
770 } | 660 } |
771 | 661 |
662 static bool EndsBefore(size_t start_offset, | |
Xiaocheng
2017/04/19 03:33:23
It's weird to have a chunk of new code in an old f
rlanday
2017/04/20 02:19:05
This isn't new code, I moved it because I thought
| |
663 const Member<RenderedDocumentMarker>& rhv) { | |
yosin_UTC9
2017/04/20 01:43:01
Please use descriptive parameter name instead of |
rlanday
2017/04/20 02:19:05
I'm only moving this code; I think it stands for "
| |
664 return start_offset < rhv->EndOffset(); | |
665 } | |
666 | |
772 bool DocumentMarkerController::SetMarkersActive(Node* node, | 667 bool DocumentMarkerController::SetMarkersActive(Node* node, |
773 unsigned start_offset, | 668 unsigned start_offset, |
774 unsigned end_offset, | 669 unsigned end_offset, |
775 bool active) { | 670 bool active) { |
776 MarkerLists* markers = markers_.at(node); | 671 MarkerLists* markers = markers_.at(node); |
777 if (!markers) | 672 if (!markers) |
778 return false; | 673 return false; |
779 | 674 |
780 bool doc_dirty = false; | 675 bool doc_dirty = false; |
781 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... | |
861 | 756 |
862 if (!did_shift_marker) | 757 if (!did_shift_marker) |
863 return; | 758 return; |
864 if (!node->GetLayoutObject()) | 759 if (!node->GetLayoutObject()) |
865 return; | 760 return; |
866 InvalidateRectsForMarkersInNode(*node); | 761 InvalidateRectsForMarkersInNode(*node); |
867 // repaint the affected node | 762 // repaint the affected node |
868 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 763 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
869 } | 764 } |
870 | 765 |
871 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
872 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | |
873 unsigned offset, | |
874 unsigned old_length, | |
875 unsigned new_length) { | |
876 bool did_shift_marker = false; | |
877 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
878 RenderedDocumentMarker& marker = **it; | |
879 Optional<DocumentMarker::MarkerOffsets> result = | |
880 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
881 if (result == WTF::kNullopt) { | |
882 list->erase(it - list->begin()); | |
883 --it; | |
884 did_shift_marker = true; | |
885 continue; | |
886 } | |
887 | |
888 if (marker.StartOffset() != result.value().start_offset || | |
889 marker.EndOffset() != result.value().end_offset) { | |
890 did_shift_marker = true; | |
891 marker.SetStartOffset(result.value().start_offset); | |
892 marker.SetEndOffset(result.value().end_offset); | |
893 } | |
894 } | |
895 | |
896 return did_shift_marker; | |
897 } | |
898 | |
899 } // namespace blink | 766 } // namespace blink |
900 | 767 |
901 #ifndef NDEBUG | 768 #ifndef NDEBUG |
902 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 769 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
903 if (controller) | 770 if (controller) |
904 controller->ShowMarkers(); | 771 controller->ShowMarkers(); |
905 } | 772 } |
906 #endif | 773 #endif |
OLD | NEW |