/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "DocumentMarkerController.h"

#include "Chrome.h"
#include "ChromeClient.h"
#include "Frame.h"
#include "NodeTraversal.h"
#include "Page.h"
#include "Range.h"
#include "RenderBlockFlow.h"
#include "RenderLayer.h"
#include "RenderText.h"
#include "RenderedDocumentMarker.h"
#include "TextIterator.h"
#include <stdio.h>

namespace WebCore {

inline bool DocumentMarkerController::possiblyHasMarkers(OptionSet<DocumentMarker::MarkerType> types)
{
    return m_possiblyExistingMarkerTypes.containsAny(types);
}

DocumentMarkerController::DocumentMarkerController(Document& document)
    : m_document(document)
{
}

DocumentMarkerController::~DocumentMarkerController() = default;

void DocumentMarkerController::detach()
{
    m_markers.clear();
    m_possiblyExistingMarkerTypes = { };
}

Vector<RefPtr<Range>> DocumentMarkerController::collectTextRanges(const SimpleRange& range)
{
    Vector<RefPtr<Range>> textRange;
    for (TextIterator textIterator(range); !textIterator.atEnd(); textIterator.advance())
        textRange.append(createLiveRange(textIterator.range()));
    return textRange;
}

void DocumentMarkerController::addMarker(const SimpleRange& range, DocumentMarker::MarkerType type, const String& description)
{
    for (auto textPiece : collectTextRanges(range))
        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description));
}

void DocumentMarkerController::addMarker(const SimpleRange& range, DocumentMarker::MarkerType type)
{
    for (auto textPiece : collectTextRanges(range))
        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset()));
}

void DocumentMarkerController::addMarkerToNode(Node& node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type)
{
    addMarker(node, DocumentMarker(type, startOffset, startOffset + length));
}

void DocumentMarkerController::addMarkerToNode(Node& node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type, DocumentMarker::Data&& data)
{
    addMarker(node, DocumentMarker(type, startOffset, startOffset + length, WTFMove(data)));
}

void DocumentMarkerController::addTextMatchMarker(const Range& range, bool activeMatch)
{
    for (auto textPiece : collectTextRanges(range)) {
        unsigned startOffset = textPiece->startOffset();
        unsigned endOffset = textPiece->endOffset();
        addMarker(textPiece->startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
    }
}

#if PLATFORM(IOS_FAMILY)

void DocumentMarkerController::addMarker(Range& range, DocumentMarker::MarkerType type, const String& description, const Vector<String>& interpretations, const RetainPtr<id>& metadata)
{
    for (auto textPiece : collectTextRanges(range))
        addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description, interpretations, metadata));
}

void DocumentMarkerController::addDictationPhraseWithAlternativesMarker(Range& range, const Vector<String>& interpretations)
{
    ASSERT(interpretations.size() > 1);
    if (interpretations.size() <= 1)
        return;

    size_t numberOfAlternatives = interpretations.size() - 1;
    for (auto textPiece : collectTextRanges(range)) {
        DocumentMarker marker(DocumentMarker::DictationPhraseWithAlternatives, textPiece->startOffset(), textPiece->endOffset(), emptyString(), Vector<String>(numberOfAlternatives), RetainPtr<id>());
        for (size_t i = 0; i < numberOfAlternatives; ++i)
            marker.setAlternative(interpretations[i + 1], i);
        addMarker(textPiece->startContainer(), marker);
    }
}

void DocumentMarkerController::addDictationResultMarker(const SimpleRange& range, const RetainPtr<id>& metadata)
{
    for (auto textPiece : collectTextRanges(range))
        addMarker(textPiece->startContainer(), DocumentMarker(DocumentMarker::DictationResult, textPiece->startOffset(), textPiece->endOffset(), String(), Vector<String>(), metadata));
}

#endif

void DocumentMarkerController::addDraggedContentMarker(Range& range)
{
    for (auto textPiece : collectTextRanges(range)) {
        DocumentMarker::DraggedContentData draggedContentData { textPiece->firstNode() };
        addMarker(textPiece->startContainer(), { DocumentMarker::DraggedContent, textPiece->startOffset(), textPiece->endOffset(), WTFMove(draggedContentData) });
    }
}

#if ENABLE(PLATFORM_DRIVEN_TEXT_CHECKING)
void DocumentMarkerController::addPlatformTextCheckingMarker(const SimpleRange& range, const String& key, const String& value)
{
    for (auto textPiece : collectTextRanges(range)) {
        DocumentMarker::PlatformTextCheckingData textCheckingData { key, value };
        addMarker(textPiece->startContainer(), { DocumentMarker::PlatformTextChecking, textPiece->startOffset(), textPiece->endOffset(), WTFMove(textCheckingData) });
    }
}
#endif

void DocumentMarkerController::removeMarkers(Range& range, OptionSet<DocumentMarker::MarkerType> markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
{
    for (auto textPiece : collectTextRanges(range)) {
        if (!possiblyHasMarkers(markerTypes))
            return;
        ASSERT(!m_markers.isEmpty());
        unsigned startOffset = textPiece->startOffset();
        unsigned endOffset = textPiece->endOffset();
        removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, nullptr, shouldRemovePartiallyOverlappingMarker);
    }
}

void DocumentMarkerController::filterMarkers(Range& range, std::function<bool(DocumentMarker*)> filterFunction, OptionSet<DocumentMarker::MarkerType> markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
{
    for (auto textPiece : collectTextRanges(range)) {
        if (!possiblyHasMarkers(markerTypes))
            return;
        ASSERT(!m_markers.isEmpty());

        unsigned startOffset = textPiece->startOffset();
        unsigned endOffset = textPiece->endOffset();
        removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, filterFunction, shouldRemovePartiallyOverlappingMarker);
    }
}

static void updateRenderedRectsForMarker(RenderedDocumentMarker& marker, Node& node)
{
    ASSERT(!node.document().view() || !node.document().view()->needsLayout());

    // FIXME: We should refactor this so that we don't use Range (because we only have one Node), but still share code with absoluteTextQuads().
    auto markerRange = Range::create(node.document(), &node, marker.startOffset(), &node, marker.endOffset());
    Vector<FloatQuad> absoluteMarkerQuads;
    markerRange->absoluteTextQuads(absoluteMarkerQuads, true);

    Vector<FloatRect> absoluteMarkerRects;
    absoluteMarkerRects.reserveInitialCapacity(absoluteMarkerQuads.size());
    for (const auto& quad : absoluteMarkerQuads)
        absoluteMarkerRects.uncheckedAppend(quad.boundingBox());

    marker.setUnclippedAbsoluteRects(absoluteMarkerRects);
}

void DocumentMarkerController::invalidateRectsForAllMarkers()
{
    if (!hasMarkers())
        return;

    for (auto& markers : m_markers.values()) {
        for (auto& marker : *markers)
            marker.invalidate();
    }

    if (Page* page = m_document.page())
        page->chrome().client().didInvalidateDocumentMarkerRects();
}

void DocumentMarkerController::invalidateRectsForMarkersInNode(Node& node)
{
    if (!hasMarkers())
        return;

    MarkerList* markers = m_markers.get(&node);
    ASSERT(markers);

    for (auto& marker : *markers)
        marker.invalidate();

    if (Page* page = m_document.page())
        page->chrome().client().didInvalidateDocumentMarkerRects();
}

static void updateMainFrameLayoutIfNeeded(Document& document)
{
    Frame* frame = document.frame();
    if (!frame)
        return;

    FrameView* mainFrameView = frame->mainFrame().view();
    if (!mainFrameView)
        return;

    mainFrameView->updateLayoutAndStyleIfNeededRecursive();
}

void DocumentMarkerController::updateRectsForInvalidatedMarkersOfType(DocumentMarker::MarkerType markerType)
{
    if (!possiblyHasMarkers(markerType))
        return;
    ASSERT(!(m_markers.isEmpty()));

    bool needsLayoutIfAnyRectsAreDirty = true;

    for (auto& nodeAndMarkers : m_markers) {
        Node& node = *nodeAndMarkers.key;
        for (auto& marker : *nodeAndMarkers.value) {
            if (marker.type() != markerType)
                continue;

            if (marker.isValid())
                continue;

            // We'll do up to one layout per call if we have any dirty markers.
            if (needsLayoutIfAnyRectsAreDirty) {
                updateMainFrameLayoutIfNeeded(m_document);
                needsLayoutIfAnyRectsAreDirty = false;
            }

            updateRenderedRectsForMarker(marker, node);
        }
    }
}

Vector<FloatRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
{
    Vector<FloatRect> result;

    if (!possiblyHasMarkers(markerType))
        return result;
    ASSERT(!(m_markers.isEmpty()));

    RefPtr<Frame> frame = m_document.frame();
    if (!frame)
        return result;
    FrameView* frameView = frame->view();
    if (!frameView)
        return result;

    updateRectsForInvalidatedMarkersOfType(markerType);

    bool isSubframe = !frame->isMainFrame();
    IntRect subframeClipRect;
    if (isSubframe)
        subframeClipRect = frameView->windowToContents(frameView->windowClipRect());

    for (auto& nodeAndMarkers : m_markers) {
        Node& node = *nodeAndMarkers.key;
        FloatRect overflowClipRect;
        if (RenderObject* renderer = node.renderer())
            overflowClipRect = renderer->absoluteClippedOverflowRect();
        for (auto& marker : *nodeAndMarkers.value) {
            if (marker.type() != markerType)
                continue;

            auto renderedRects = marker.unclippedAbsoluteRects();

            // Clip document markers by their overflow clip.
            if (node.renderer()) {
                for (auto& rect : renderedRects)
                    rect.intersect(overflowClipRect);
            }

            // Clip subframe document markers by their frame.
            if (isSubframe) {
                for (auto& rect : renderedRects)
                    rect.intersect(subframeClipRect);
            }

            for (const auto& rect : renderedRects) {
                if (!rect.isEmpty())
                    result.append(rect);
            }
        }
    }
    
    return result;
}

static bool shouldInsertAsSeparateMarker(const DocumentMarker& newMarker)
{
#if ENABLE(PLATFORM_DRIVEN_TEXT_CHECKING)
    if (newMarker.type() == DocumentMarker::PlatformTextChecking)
        return true;
#endif

#if PLATFORM(IOS_FAMILY)
    if (newMarker.type() == DocumentMarker::DictationPhraseWithAlternatives || newMarker.type() == DocumentMarker::DictationResult)
        return true;
#endif
    if (newMarker.type() == DocumentMarker::DraggedContent) {
        if (auto targetNode = WTF::get<DocumentMarker::DraggedContentData>(newMarker.data()).targetNode)
            return targetNode->renderer() && targetNode->renderer()->isRenderReplaced();
    }

    return false;
}

// Markers are stored in order sorted by their start offset.
// Markers of the same type do not overlap each other.

void DocumentMarkerController::addMarker(Node& node, const DocumentMarker& newMarker)
{
    ASSERT(newMarker.endOffset() >= newMarker.startOffset());
    if (newMarker.endOffset() == newMarker.startOffset())
        return;

    if (auto* renderer = node.renderer()) {
        // FIXME: Factor the marker painting code out of InlineTextBox and teach simple line layout to use it.
        if (is<RenderText>(*renderer))
            downcast<RenderText>(*renderer).ensureLineBoxes();
        else if (is<RenderBlockFlow>(*renderer))
            downcast<RenderBlockFlow>(*renderer).ensureLineBoxes();
    }

    m_possiblyExistingMarkerTypes.add(newMarker.type());

    std::unique_ptr<MarkerList>& list = m_markers.add(&node, nullptr).iterator->value;

    if (!list) {
        list = makeUnique<MarkerList>();
        list->append(RenderedDocumentMarker(newMarker));
    } else if (shouldInsertAsSeparateMarker(newMarker)) {
        // We don't merge dictation markers.
        size_t i;
        size_t numberOfMarkers = list->size();
        for (i = 0; i < numberOfMarkers; ++i) {
            DocumentMarker marker = list->at(i);
            if (marker.startOffset() > newMarker.startOffset())
                break;
        }
        list->insert(i, RenderedDocumentMarker(newMarker));
    } else {
        RenderedDocumentMarker toInsert(newMarker);
        size_t numMarkers = list->size();
        size_t i;
        // Iterate over all markers whose start offset is less than or equal to the new marker's.
        // If one of them is of the same type as the new marker and touches it or intersects with it
        // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
        for (i = 0; i < numMarkers; ++i) {
            DocumentMarker marker = list->at(i);
            if (marker.startOffset() > toInsert.startOffset())
                break;
            if (marker.type() == toInsert.type() && marker.endOffset() >= toInsert.startOffset()) {
                toInsert.setStartOffset(marker.startOffset());
                list->remove(i);
                numMarkers--;
                break;
            }
        }
        size_t j = i;
        // Iterate over all markers whose end offset is less than or equal to the new marker's,
        // removing markers of the same type as the new marker which touch it or intersect with it,
        // adjusting the new marker's end offset to cover them if necessary.
        while (j < numMarkers) {
            DocumentMarker marker = list->at(j);
            if (marker.startOffset() > toInsert.endOffset())
                break;
            if (marker.type() == toInsert.type()) {
                list->remove(j);
                if (toInsert.endOffset() <= marker.endOffset()) {
                    toInsert.setEndOffset(marker.endOffset());
                    break;
                }
                numMarkers--;
            } else
                j++;
        }
        // At this point i points to the node before which we want to insert.
        list->insert(i, RenderedDocumentMarker(toInsert));
    }

    if (node.renderer())
        node.renderer()->repaint();

    invalidateRectsForMarkersInNode(node);
}

// 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 (auto& marker : *list) {
        // 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);
    }

    if (docDirty && dstNode.renderer())
        dstNode.renderer()->repaint();
}

void DocumentMarkerController::removeMarkers(Node& node, unsigned startOffset, int length, OptionSet<DocumentMarker::MarkerType> markerTypes, std::function<bool(DocumentMarker*)> filterFunction, 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;
        }

        if (filterFunction && !filterFunction(&marker)) {
            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 = { };
    }

    if (docDirty && node.renderer())
        node.renderer()->repaint();
}

DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType)
{
    if (!possiblyHasMarkers(markerType))
        return nullptr;
    ASSERT(!(m_markers.isEmpty()));

    updateRectsForInvalidatedMarkersOfType(markerType);

    for (auto& nodeAndMarkers : m_markers) {
        for (auto& marker : *nodeAndMarkers.value) {
            if (marker.type() != markerType)
                continue;

            if (marker.contains(point))
                return &marker;
        }
    }

    return nullptr;
}

Vector<RenderedDocumentMarker*> DocumentMarkerController::markersFor(Node& node, OptionSet<DocumentMarker::MarkerType> markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return { };

    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;
}

Vector<RenderedDocumentMarker*> DocumentMarkerController::markersInRange(Range& range, OptionSet<DocumentMarker::MarkerType> markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return Vector<RenderedDocumentMarker*>();

    Vector<RenderedDocumentMarker*> foundMarkers;

    Node& startContainer = range.startContainer();
    Node& endContainer = range.endContainer();

    Node* pastLastNode = range.pastLastNode();
    for (Node* node = range.firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
        ASSERT(node);
        for (auto* marker : markersFor(*node)) {
            if (!markerTypes.contains(marker->type()))
                continue;
            if (node == &startContainer && marker->endOffset() <= range.startOffset())
                continue;
            if (node == &endContainer && marker->startOffset() >= range.endOffset())
                continue;
            foundMarkers.append(marker);
        }
    }
    return foundMarkers;
}

void DocumentMarkerController::removeMarkers(Node& node, OptionSet<DocumentMarker::MarkerType> markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return;
    ASSERT(!m_markers.isEmpty());
    
    auto iterator = m_markers.find(&node);
    if (iterator != m_markers.end())
        removeMarkersFromList(iterator, markerTypes);
}

void DocumentMarkerController::removeMarkers(OptionSet<DocumentMarker::MarkerType> markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return;
    ASSERT(!m_markers.isEmpty());

    for (auto& node : copyToVector(m_markers.keys())) {
        auto iterator = m_markers.find(node);
        if (iterator != m_markers.end())
            removeMarkersFromList(iterator, markerTypes);
    }

    m_possiblyExistingMarkerTypes.remove(markerTypes);
}

void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, OptionSet<DocumentMarker::MarkerType> 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 = { };
    }
}

void DocumentMarkerController::repaintMarkers(OptionSet<DocumentMarker::MarkerType> 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::shiftMarkers(Node& node, unsigned startOffset, int delta)
{
    if (!possiblyHasMarkers(DocumentMarker::allMarkers()))
        return;
    ASSERT(!m_markers.isEmpty());

    MarkerList* list = m_markers.get(&node);
    if (!list)
        return;

    bool didShiftMarker = false;
    for (size_t i = 0; i != list->size(); ) {
        RenderedDocumentMarker& marker = list->at(i);
        // FIXME: How can this possibly be iOS-specific code?
#if PLATFORM(IOS_FAMILY)
        int targetStartOffset = marker.startOffset() + delta;
        int targetEndOffset = marker.endOffset() + delta;
        if (targetStartOffset >= node.maxCharacterOffset() || targetEndOffset <= 0) {
            list->remove(i);
            continue;
        }
#endif
        if (marker.startOffset() >= startOffset) {
            ASSERT((int)marker.startOffset() + delta >= 0);
            marker.shiftOffsets(delta);
            didShiftMarker = true;
#if !PLATFORM(IOS_FAMILY)
        }
#else
        // FIXME: Inserting text inside a DocumentMarker does not grow the marker.
        // See <https://bugs.webkit.org/show_bug.cgi?id=62504>.
        } else if (marker.endOffset() > startOffset) {
            if (marker.endOffset() + delta <= marker.startOffset()) {
                list->remove(i);
                continue;
            }
            marker.setEndOffset(targetEndOffset < node.maxCharacterOffset() ? targetEndOffset : node.maxCharacterOffset());
            didShiftMarker = true;
        }
#endif
        ++i;
    }

    if (didShiftMarker) {
        invalidateRectsForMarkersInNode(node);

        if (node.renderer())
            node.renderer()->repaint();
    }
}

void DocumentMarkerController::setMarkersActive(Range& range, bool active)
{
    if (!possiblyHasMarkers(DocumentMarker::allMarkers()))
        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 = NodeTraversal::next(*node)) {
        unsigned startOffset = node == &startContainer ? range.startOffset() : 0;
        unsigned endOffset = node == &endContainer ? range.endOffset() : std::numeric_limits<unsigned>::max();
        setMarkersActive(*node, startOffset, endOffset, active);
    }
}

void DocumentMarkerController::setMarkersActive(Node& node, unsigned startOffset, unsigned endOffset, bool active)
{
    MarkerList* list = m_markers.get(&node);
    if (!list)
        return;

    bool didActivateMarker = false;
    for (auto& marker : *list) {
        // 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 || marker.type() != DocumentMarker::TextMatch)
            continue;

        marker.setActiveMatch(active);
        didActivateMarker = true;
    }

    if (didActivateMarker && node.renderer())
        node.renderer()->repaint();
}

bool DocumentMarkerController::hasMarkers(Range& range, OptionSet<DocumentMarker::MarkerType> markerTypes)
{
    if (!possiblyHasMarkers(markerTypes))
        return false;
    ASSERT(!m_markers.isEmpty());

    Node& startContainer = range.startContainer();
    Node& endContainer = range.endContainer();

    Node* pastLastNode = range.pastLastNode();
    for (Node* node = range.firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
        ASSERT(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;
            return true;
        }
    }
    return false;
}

void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range& range, OptionSet<DocumentMarker::MarkerType> 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 = NodeTraversal::next(*node)) {
        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.clearData();
        }
    }
}

#if ENABLE(TREE_DEBUGGING)
void DocumentMarkerController::showMarkers() const
{
    fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
    for (auto& marker : m_markers) {
        Node* node = marker.key.get();
        fprintf(stderr, "%p", node);
        for (auto& documentMarker : *marker.value)
            fprintf(stderr, " %d:[%d:%d](%d)", documentMarker.type(), documentMarker.startOffset(), documentMarker.endOffset(), documentMarker.isActiveMatch());

        fprintf(stderr, "\n");
    }
}
#endif

} // namespace WebCore

#if ENABLE(TREE_DEBUGGING)
void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
{
    if (controller)
        controller->showMarkers();
}
#endif
