void SpellCheckRequester::didCheckSucceed(int sequence, const Vector<TextCheckingResult>& results) { TextCheckingRequestData requestData = m_processingRequest->data(); if (requestData.sequence() == sequence) { DocumentMarker::MarkerTypes markers = DocumentMarker::SpellCheckClientMarkers(); if (!requestData.maskContains(TextCheckingTypeSpelling)) markers.remove(DocumentMarker::Spelling); if (!requestData.maskContains(TextCheckingTypeGrammar)) markers.remove(DocumentMarker::Grammar); frame().document()->markers().removeMarkers(m_processingRequest->checkingRange().get(), markers); } didCheck(sequence, results); }
void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); Node* startContainer = range->startContainer(); Node* endContainer = range->endContainer(); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { unsigned startOffset = node == startContainer ? range->startOffset() : 0; unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max(); MarkerList* list = m_markers.get(node); if (!list) continue; for (size_t i = 0; i < list->size(); ++i) { 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; } marker.clearDescription(); } } }
void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { Node* node = i->key.get(); // inner loop: process each marker in the current node MarkerList* list = i->value.get(); bool nodeNeedsRepaint = false; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (markerTypes.contains(marker.type())) { nodeNeedsRepaint = true; break; } } if (!nodeNeedsRepaint) continue; // cause the node to be redrawn if (auto renderer = node->renderer()) renderer->repaint(); } }
Vector<RenderedDocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return Vector<RenderedDocumentMarker*>(); Vector<RenderedDocumentMarker*> foundMarkers; Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) { for (auto* marker : markersFor(node)) { if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset())) continue; foundMarkers.append(marker); } } return foundMarkers; }
Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return Vector<DocumentMarker*>(); Vector<DocumentMarker*> foundMarkers; Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) { Vector<DocumentMarker*> markers = markersFor(node); Vector<DocumentMarker*>::const_iterator end = markers.end(); for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { DocumentMarker* marker = *it; if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset())) continue; foundMarkers.append(marker); } } return foundMarkers; }
bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return false; ASSERT(!m_markers.isEmpty()); Node* startContainer = range->startContainer(); ASSERT(startContainer); Node* endContainer = range->endContainer(); ASSERT(endContainer); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) { Vector<DocumentMarker*> markers = markersFor(node); Vector<DocumentMarker*>::const_iterator end = markers.end(); for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) { DocumentMarker* marker = *it; if (!markerTypes.contains(marker->type())) continue; if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset())) continue; if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset())) continue; return true; } } return false; }
void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document for (auto& marker : m_markers) { Node* node = marker.key.get(); // inner loop: process each marker in the current node bool nodeNeedsRepaint = false; for (auto& documentMarker : *marker.value) { if (markerTypes.contains(documentMarker.type())) { nodeNeedsRepaint = true; break; } } if (!nodeNeedsRepaint) continue; // cause the node to be redrawn if (auto renderer = node->renderer()) renderer->repaint(); } }
void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { const Node* node = i->key; // inner loop: process each marker in the current node MarkerLists* markers = i->value.get(); for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { OwnPtr<MarkerList>& list = (*markers)[markerListIndex]; if (!list || list->isEmpty() || !markerTypes.contains((*list->begin())->type())) continue; // cause the node to be redrawn if (RenderObject* renderer = node->renderer()) { renderer->doNotUseInvalidatePaintForWholeRendererSynchronously(); break; } } } }
Vector<RenderedDocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes) { Vector<RenderedDocumentMarker*> result; MarkerList* list = m_markers.get(node); if (!list) return result; for (size_t i = 0; i < list->size(); ++i) { if (markerTypes.contains(list->at(i).type())) result.append(&(list->at(i))); } return result; }
Vector<RenderedDocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes) { Vector<RenderedDocumentMarker*> result; MarkerList* list = m_markers.get(node); if (!list) return result; for (auto& marker : *list) { if (markerTypes.contains(marker.type())) result.append(&marker); } return result; }
void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes) { bool needsRepainting = false; bool nodeCanBeRemoved; size_t emptyListsCount = 0; if (markerTypes == DocumentMarker::AllMarkers()) { needsRepainting = true; nodeCanBeRemoved = true; } else { MarkerLists* markers = iterator->value.get(); 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())) { list->clear(); list.clear(); ++emptyListsCount; needsRepainting = true; } } nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesCount; } if (needsRepainting) { if (RenderObject* renderer = iterator->key->renderer()) renderer->doNotUseInvalidatePaintForWholeRendererSynchronously(); } if (nodeCanBeRemoved) { m_markers.remove(iterator); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } }
DocumentMarkerVector DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes) { DocumentMarkerVector result; MarkerLists* markers = m_markers.get(node); if (!markers) return result; for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) { OwnPtr<MarkerList>& list = (*markers)[markerListIndex]; if (!list || list->isEmpty() || !markerTypes.contains((*list->begin())->type())) continue; for (size_t i = 0; i < list->size(); ++i) result.append(list->at(i).get()); } std::sort(result.begin(), result.end(), compareByStart); return result; }
// This function may release node and vectorPair. void DocumentMarkerController::removeMarkersFromList(Node* node, MarkerList* list, DocumentMarker::MarkerTypes markerTypes) { if (markerTypes == DocumentMarker::AllMarkers()) { delete list; m_markers.remove(node); if (RenderObject* renderer = node->renderer()) renderer->repaint(); } else { bool needsRepaint = false; for (size_t i = 0; i != list->size();) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (!markerTypes.contains(marker.type())) { ++i; continue; } // pitch the old marker list->remove(i); needsRepaint = true; // i now is the index of the next marker } // Redraw the node if it changed. Do this before the node is removed from m_markers, since // m_markers might contain the last reference to the node. if (needsRepaint) { RenderObject* renderer = node->renderer(); if (renderer) renderer->repaint(); } // delete the node's list if it is now empty if (list->isEmpty()) { m_markers.remove(node); delete list; } } if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; }
void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes) { bool needsRepainting = false; bool listCanBeRemoved; if (markerTypes == DocumentMarker::AllMarkers()) { needsRepainting = true; listCanBeRemoved = true; } else { MarkerList* list = iterator->value.get(); for (size_t i = 0; i != list->size(); ) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (!markerTypes.contains(marker.type())) { ++i; continue; } // pitch the old marker list->remove(i); needsRepainting = true; // i now is the index of the next marker } listCanBeRemoved = list->isEmpty(); } if (needsRepainting) { if (auto renderer = iterator->key->renderer()) renderer->repaint(); } if (listCanBeRemoved) { m_markers.remove(iterator); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } }
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(); }