| 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 Member<MarkerList>& list = ListForType(markers, new_marker_type); | 222 Member<MarkerList>& list = ListForType(markers, new_marker_type); |
| 222 DocumentMarkerListEditor::AddMarker(list, &new_marker); | 223 DocumentMarkerListEditor::AddMarker(list, &new_marker); |
| 223 | 224 |
| 224 // repaint the affected node | 225 // repaint the affected node |
| 225 if (node->GetLayoutObject()) { | 226 if (node->GetLayoutObject()) { |
| 226 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 227 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 227 kPaintInvalidationDocumentMarkerChange); | 228 kPaintInvalidationDocumentMarkerChange); |
| 228 } | 229 } |
| 229 } | 230 } |
| 230 | 231 |
| 231 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 232 // TODO(rlanday): this method was created by cutting and pasting code from | |
| 233 // DocumentMarkerController::AddMarker(), it should be refactored in a future CL | |
| 234 void DocumentMarkerListEditor::AddMarker(MarkerList* list, | |
| 235 const DocumentMarker* marker) { | |
| 236 RenderedDocumentMarker* rendered_marker = | |
| 237 RenderedDocumentMarker::Create(*marker); | |
| 238 if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { | |
| 239 list->push_back(rendered_marker); | |
| 240 } else { | |
| 241 if (marker->GetType() != DocumentMarker::kTextMatch && | |
| 242 marker->GetType() != DocumentMarker::kComposition) { | |
| 243 MergeOverlapping(list, rendered_marker); | |
| 244 } else { | |
| 245 MarkerList::iterator pos = std::lower_bound( | |
| 246 list->begin(), list->end(), marker, | |
| 247 [](const Member<RenderedDocumentMarker>& marker_in_list, | |
| 248 const DocumentMarker* marker_to_insert) { | |
| 249 return marker_in_list->StartOffset() < | |
| 250 marker_to_insert->StartOffset(); | |
| 251 }); | |
| 252 list->insert(pos - list->begin(), rendered_marker); | |
| 253 } | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 258 void DocumentMarkerListEditor::MergeOverlapping( | |
| 259 MarkerList* list, | |
| 260 RenderedDocumentMarker* to_insert) { | |
| 261 MarkerList::iterator first_overlapping = std::lower_bound( | |
| 262 list->begin(), list->end(), to_insert, | |
| 263 [](const Member<RenderedDocumentMarker>& marker_in_list, | |
| 264 const DocumentMarker* marker_to_insert) { | |
| 265 return marker_in_list->EndOffset() < marker_to_insert->StartOffset(); | |
| 266 }); | |
| 267 size_t index = first_overlapping - list->begin(); | |
| 268 list->insert(index, to_insert); | |
| 269 MarkerList::iterator inserted = list->begin() + index; | |
| 270 first_overlapping = inserted + 1; | |
| 271 for (MarkerList::iterator i = first_overlapping; | |
| 272 i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | |
| 273 (*inserted)->SetStartOffset( | |
| 274 std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | |
| 275 (*inserted)->SetEndOffset( | |
| 276 std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | |
| 277 list->erase(i - list->begin()); | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 // Moves markers from src_node to dst_node. Markers are moved if their start | 232 // Moves markers from src_node to dst_node. Markers are moved if their start |
| 282 // offset is less than length. Markers that run past that point are truncated. | 233 // offset is less than length. Markers that run past that point are truncated. |
| 283 void DocumentMarkerController::MoveMarkers(Node* src_node, | 234 void DocumentMarkerController::MoveMarkers(Node* src_node, |
| 284 int length, | 235 int length, |
| 285 Node* dst_node) { | 236 Node* dst_node) { |
| 286 if (length <= 0) | 237 if (length <= 0) |
| 287 return; | 238 return; |
| 288 | 239 |
| 289 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) | 240 if (!PossiblyHasMarkers(DocumentMarker::AllMarkers())) |
| 290 return; | 241 return; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 315 doc_dirty = true; | 266 doc_dirty = true; |
| 316 } | 267 } |
| 317 | 268 |
| 318 // repaint the affected node | 269 // repaint the affected node |
| 319 if (doc_dirty && dst_node->GetLayoutObject()) { | 270 if (doc_dirty && dst_node->GetLayoutObject()) { |
| 320 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 271 dst_node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 321 kPaintInvalidationDocumentMarkerChange); | 272 kPaintInvalidationDocumentMarkerChange); |
| 322 } | 273 } |
| 323 } | 274 } |
| 324 | 275 |
| 325 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 326 bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, | |
| 327 int length, | |
| 328 MarkerList* dst_list) { | |
| 329 DCHECK_GT(length, 0); | |
| 330 bool doc_dirty = false; | |
| 331 const unsigned end_offset = length - 1; | |
| 332 MarkerList::iterator it; | |
| 333 for (it = src_list->begin(); it != src_list->end(); ++it) { | |
| 334 DocumentMarker* marker = it->Get(); | |
| 335 | |
| 336 // stop if we are now past the specified range | |
| 337 if (marker->StartOffset() > end_offset) | |
| 338 break; | |
| 339 | |
| 340 // pin the marker to the specified range | |
| 341 doc_dirty = true; | |
| 342 if (marker->EndOffset() > end_offset) | |
| 343 marker->SetEndOffset(end_offset); | |
| 344 | |
| 345 DocumentMarkerListEditor::AddMarker(dst_list, marker); | |
| 346 } | |
| 347 | |
| 348 // Remove the range of markers that were moved to dst_node | |
| 349 src_list->erase(0, it - src_list->begin()); | |
| 350 | |
| 351 return doc_dirty; | |
| 352 } | |
| 353 | |
| 354 void DocumentMarkerController::RemoveMarkers( | 276 void DocumentMarkerController::RemoveMarkers( |
| 355 Node* node, | 277 Node* node, |
| 356 unsigned start_offset, | 278 unsigned start_offset, |
| 357 int length, | 279 int length, |
| 358 DocumentMarker::MarkerTypes marker_types) { | 280 DocumentMarker::MarkerTypes marker_types) { |
| 359 if (length <= 0) | 281 if (length <= 0) |
| 360 return; | 282 return; |
| 361 | 283 |
| 362 if (!PossiblyHasMarkers(marker_types)) | 284 if (!PossiblyHasMarkers(marker_types)) |
| 363 return; | 285 return; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 possibly_existing_marker_types_ = 0; | 319 possibly_existing_marker_types_ = 0; |
| 398 } | 320 } |
| 399 | 321 |
| 400 // repaint the affected node | 322 // repaint the affected node |
| 401 if (doc_dirty && node->GetLayoutObject()) { | 323 if (doc_dirty && node->GetLayoutObject()) { |
| 402 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( | 324 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation( |
| 403 kPaintInvalidationDocumentMarkerChange); | 325 kPaintInvalidationDocumentMarkerChange); |
| 404 } | 326 } |
| 405 } | 327 } |
| 406 | 328 |
| 407 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 408 // TODO(rlanday): this method was created by cutting and pasting code from | |
| 409 // DocumentMarkerController::RemoveMarkers(), it should be refactored in a | |
| 410 // future CL | |
| 411 bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | |
| 412 unsigned start_offset, | |
| 413 int length) { | |
| 414 bool doc_dirty = false; | |
| 415 unsigned end_offset = start_offset + length; | |
| 416 MarkerList::iterator start_pos = std::upper_bound( | |
| 417 list->begin(), list->end(), start_offset, | |
| 418 [](size_t start_offset, const Member<RenderedDocumentMarker>& marker) { | |
| 419 return start_offset < marker->EndOffset(); | |
| 420 }); | |
| 421 for (MarkerList::iterator i = start_pos; i != list->end();) { | |
| 422 DocumentMarker marker(*i->Get()); | |
| 423 | |
| 424 // markers are returned in order, so stop if we are now past the specified | |
| 425 // range | |
| 426 if (marker.StartOffset() >= end_offset) | |
| 427 break; | |
| 428 | |
| 429 list->erase(i - list->begin()); | |
| 430 doc_dirty = true; | |
| 431 } | |
| 432 | |
| 433 return doc_dirty; | |
| 434 } | |
| 435 | |
| 436 DocumentMarkerVector DocumentMarkerController::MarkersFor( | 329 DocumentMarkerVector DocumentMarkerController::MarkersFor( |
| 437 Node* node, | 330 Node* node, |
| 438 DocumentMarker::MarkerTypes marker_types) { | 331 DocumentMarker::MarkerTypes marker_types) { |
| 439 DocumentMarkerVector result; | 332 DocumentMarkerVector result; |
| 440 | 333 |
| 441 MarkerLists* markers = markers_.at(node); | 334 MarkerLists* markers = markers_.at(node); |
| 442 if (!markers) | 335 if (!markers) |
| 443 return result; | 336 return result; |
| 444 | 337 |
| 445 for (size_t marker_list_index = 0; | 338 for (size_t marker_list_index = 0; |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 | 757 |
| 865 if (!did_shift_marker) | 758 if (!did_shift_marker) |
| 866 return; | 759 return; |
| 867 if (!node->GetLayoutObject()) | 760 if (!node->GetLayoutObject()) |
| 868 return; | 761 return; |
| 869 InvalidateRectsForMarkersInNode(*node); | 762 InvalidateRectsForMarkersInNode(*node); |
| 870 // repaint the affected node | 763 // repaint the affected node |
| 871 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); | 764 node->GetLayoutObject()->SetShouldDoFullPaintInvalidation(); |
| 872 } | 765 } |
| 873 | 766 |
| 874 // TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | |
| 875 bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | |
| 876 unsigned offset, | |
| 877 unsigned old_length, | |
| 878 unsigned new_length) { | |
| 879 bool did_shift_marker = false; | |
| 880 for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | |
| 881 RenderedDocumentMarker& marker = **it; | |
| 882 Optional<DocumentMarker::MarkerOffsets> result = | |
| 883 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
| 884 if (result == WTF::kNullopt) { | |
| 885 list->erase(it - list->begin()); | |
| 886 --it; | |
| 887 did_shift_marker = true; | |
| 888 continue; | |
| 889 } | |
| 890 | |
| 891 if (marker.StartOffset() != result.value().start_offset || | |
| 892 marker.EndOffset() != result.value().end_offset) { | |
| 893 did_shift_marker = true; | |
| 894 marker.SetStartOffset(result.value().start_offset); | |
| 895 marker.SetEndOffset(result.value().end_offset); | |
| 896 } | |
| 897 } | |
| 898 | |
| 899 return did_shift_marker; | |
| 900 } | |
| 901 | |
| 902 } // namespace blink | 767 } // namespace blink |
| 903 | 768 |
| 904 #ifndef NDEBUG | 769 #ifndef NDEBUG |
| 905 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { | 770 void showDocumentMarkers(const blink::DocumentMarkerController* controller) { |
| 906 if (controller) | 771 if (controller) |
| 907 controller->ShowMarkers(); | 772 controller->ShowMarkers(); |
| 908 } | 773 } |
| 909 #endif | 774 #endif |
| OLD | NEW |