// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta) { if (length <= 0) return; if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerLists* markers = m_markers.get(srcNode); if (!markers) return; bool docDirty = false; for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { OwnPtr<MarkerList>& list = (*markers)[markerListIndex]; if (!list) continue; unsigned endOffset = startOffset + length - 1; MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, doesNotInclude); for (MarkerList::iterator i = startPos; i != list->end(); ++i) { DocumentMarker* marker = i->get(); // stop if we are now past the specified range if (marker->startOffset() > endOffset) break; // pin the marker to the specified range and apply the shift delta docDirty = true; if (marker->startOffset() < startOffset) marker->setStartOffset(startOffset); if (marker->endOffset() > endOffset) marker->setEndOffset(endOffset); marker->shiftOffsets(delta); addMarker(dstNode, *marker); } } // repaint the affected node if (docDirty && dstNode->renderer()) dstNode->renderer()->doNotUseInvalidatePaintForWholeRendererSynchronously(); }
// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta) { if (length <= 0) return; if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerList* list = m_markers.get(srcNode); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length - 1; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // stop if we are now past the specified range if (marker.startOffset() > endOffset) break; // skip marker that is before the specified range or is the wrong type if (marker.endOffset() < startOffset) continue; // pin the marker to the specified range and apply the shift delta docDirty = true; if (marker.startOffset() < startOffset) marker.setStartOffset(startOffset); if (marker.endOffset() > endOffset) marker.setEndOffset(endOffset); marker.shiftOffsets(delta); addMarker(dstNode, marker); } // repaint the affected node if (docDirty && dstNode->renderer()) dstNode->renderer()->repaint(); }
void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) { if (length <= 0) return; if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!(m_markers.isEmpty())); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length; for (size_t i = 0; i < list->size();) { DocumentMarker marker = list->at(i); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // skip marker that is wrong type or before target if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) { i++; continue; } // at this point we know that marker and target intersect in some way docDirty = true; // pitch the old marker list->remove(i); if (shouldRemovePartiallyOverlappingMarker) // Stop here. Don't add resulting slices back. continue; // add either of the resulting slices that are left after removing target if (startOffset > marker.startOffset()) { DocumentMarker newLeft = marker; newLeft.setEndOffset(startOffset); list->insert(i, RenderedDocumentMarker(newLeft)); // i now points to the newly-inserted node, but we want to skip that one i++; } if (marker.endOffset() > endOffset) { DocumentMarker newRight = marker; newRight.setStartOffset(endOffset); list->insert(i, RenderedDocumentMarker(newRight)); // i now points to the newly-inserted node, but we want to skip that one i++; } } if (list->isEmpty()) { m_markers.remove(node); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }
void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) { if (length <= 0) return; if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!(m_markers.isEmpty())); MarkerLists* markers = m_markers.get(node); if (!markers) return; bool docDirty = false; size_t emptyListsCount = 0; for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { OwnPtr<MarkerList>& list = (*markers)[markerListIndex]; if (!list || list->isEmpty()) { if (list.get() && list->isEmpty()) list.clear(); ++emptyListsCount; continue; } if (!markerTypes.contains((*list->begin())->type())) continue; unsigned endOffset = startOffset + length; MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore); for (MarkerList::iterator i = startPos; i != list->end(); ) { DocumentMarker marker(*i->get()); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // at this point we know that marker and target intersect in some way docDirty = true; // pitch the old marker list->remove(i - list->begin()); if (shouldRemovePartiallyOverlappingMarker) { // Stop here. Don't add resulting slices back. continue; } // add either of the resulting slices that are left after removing target if (startOffset > marker.startOffset()) { DocumentMarker newLeft = marker; newLeft.setEndOffset(startOffset); size_t insertIndex = i - list->begin(); list->insert(insertIndex, RenderedDocumentMarker::create(newLeft)); // Move to the marker after the inserted one. i = list->begin() + insertIndex + 1; } if (marker.endOffset() > endOffset) { DocumentMarker newRight = marker; newRight.setStartOffset(endOffset); size_t insertIndex = i - list->begin(); list->insert(insertIndex, RenderedDocumentMarker::create(newRight)); // Move to the marker after the inserted one. i = list->begin() + insertIndex + 1; } } if (list->isEmpty()) { list.clear(); ++emptyListsCount; } } if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) { m_markers.remove(node); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->doNotUseInvalidatePaintForWholeRendererSynchronously(); }