Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  *           (C) 2006 Alexey Proskuryakov (ap (at) webkit.org)
      6  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      7  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      8  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      9  *
     10  * This library is free software; you can redistribute it and/or
     11  * modify it under the terms of the GNU Library General Public
     12  * License as published by the Free Software Foundation; either
     13  * version 2 of the License, or (at your option) any later version.
     14  *
     15  * This library is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * Library General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU Library General Public License
     21  * along with this library; see the file COPYING.LIB.  If not, write to
     22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     23  * Boston, MA 02110-1301, USA.
     24  *
     25  */
     26 
     27 #include "config.h"
     28 #include "DocumentMarkerController.h"
     29 
     30 #include "Node.h"
     31 #include "Range.h"
     32 #include "TextIterator.h"
     33 
     34 namespace WebCore {
     35 
     36 static IntRect placeholderRectForMarker()
     37 {
     38     return IntRect(-1, -1, -1, -1);
     39 }
     40 
     41 inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
     42 {
     43     return m_possiblyExistingMarkerTypes.intersects(types);
     44 }
     45 
     46 DocumentMarkerController::DocumentMarkerController()
     47     : m_possiblyExistingMarkerTypes(0)
     48 {
     49 }
     50 
     51 void DocumentMarkerController::detach()
     52 {
     53     m_possiblyExistingMarkerTypes = 0;
     54     if (m_markers.isEmpty())
     55         return;
     56     deleteAllValues(m_markers);
     57     m_markers.clear();
     58 }
     59 
     60 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, String description)
     61 {
     62     // Use a TextIterator to visit the potentially multiple nodes the range covers.
     63     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     64         RefPtr<Range> textPiece = markedText.range();
     65         int exception = 0;
     66         DocumentMarker marker = {type, textPiece->startOffset(exception), textPiece->endOffset(exception), description, false};
     67         addMarker(textPiece->startContainer(exception), marker);
     68     }
     69 }
     70 
     71 void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
     72 {
     73     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     74         if (!possiblyHasMarkers(markerTypes))
     75             return;
     76         ASSERT(!m_markers.isEmpty());
     77 
     78         RefPtr<Range> textPiece = markedText.range();
     79         int startOffset = textPiece->startOffset();
     80         int endOffset = textPiece->endOffset();
     81         removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
     82     }
     83 }
     84 
     85 // Markers are stored in order sorted by their start offset.
     86 // Markers of the same type do not overlap each other.
     87 
     88 void DocumentMarkerController::addMarker(Node* node, DocumentMarker newMarker)
     89 {
     90     ASSERT(newMarker.endOffset >= newMarker.startOffset);
     91     if (newMarker.endOffset == newMarker.startOffset)
     92         return;
     93 
     94     m_possiblyExistingMarkerTypes.add(newMarker.type);
     95 
     96     MarkerMapVectorPair* vectorPair = m_markers.get(node);
     97 
     98     if (!vectorPair) {
     99         vectorPair = new MarkerMapVectorPair;
    100         vectorPair->first.append(newMarker);
    101         vectorPair->second.append(placeholderRectForMarker());
    102         m_markers.set(node, vectorPair);
    103     } else {
    104         Vector<DocumentMarker>& markers = vectorPair->first;
    105         Vector<IntRect>& rects = vectorPair->second;
    106         size_t numMarkers = markers.size();
    107         ASSERT(numMarkers == rects.size());
    108         size_t i;
    109         // Iterate over all markers whose start offset is less than or equal to the new marker's.
    110         // If one of them is of the same type as the new marker and touches it or intersects with it
    111         // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
    112         for (i = 0; i < numMarkers; ++i) {
    113             DocumentMarker marker = markers[i];
    114             if (marker.startOffset > newMarker.startOffset)
    115                 break;
    116             if (marker.type == newMarker.type && marker.endOffset >= newMarker.startOffset) {
    117                 newMarker.startOffset = marker.startOffset;
    118                 markers.remove(i);
    119                 rects.remove(i);
    120                 numMarkers--;
    121                 break;
    122             }
    123         }
    124         size_t j = i;
    125         // Iterate over all markers whose end offset is less than or equal to the new marker's,
    126         // removing markers of the same type as the new marker which touch it or intersect with it,
    127         // adjusting the new marker's end offset to cover them if necessary.
    128         while (j < numMarkers) {
    129             DocumentMarker marker = markers[j];
    130             if (marker.startOffset > newMarker.endOffset)
    131                 break;
    132             if (marker.type == newMarker.type) {
    133                 markers.remove(j);
    134                 rects.remove(j);
    135                 if (newMarker.endOffset <= marker.endOffset) {
    136                     newMarker.endOffset = marker.endOffset;
    137                     break;
    138                 }
    139                 numMarkers--;
    140             } else
    141                 j++;
    142         }
    143         // At this point i points to the node before which we want to insert.
    144         markers.insert(i, newMarker);
    145         rects.insert(i, placeholderRectForMarker());
    146     }
    147 
    148     // repaint the affected node
    149     if (node->renderer())
    150         node->renderer()->repaint();
    151 }
    152 
    153 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies.  The shift is
    154 // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
    155 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
    156 {
    157     if (length <= 0)
    158         return;
    159 
    160     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    161         return;
    162     ASSERT(!m_markers.isEmpty());
    163 
    164     MarkerMapVectorPair* vectorPair = m_markers.get(srcNode);
    165     if (!vectorPair)
    166         return;
    167 
    168     ASSERT(vectorPair->first.size() == vectorPair->second.size());
    169 
    170     bool docDirty = false;
    171     unsigned endOffset = startOffset + length - 1;
    172     Vector<DocumentMarker>& markers = vectorPair->first;
    173     for (size_t i = 0; i != markers.size(); ++i) {
    174         DocumentMarker marker = markers[i];
    175 
    176         // stop if we are now past the specified range
    177         if (marker.startOffset > endOffset)
    178             break;
    179 
    180         // skip marker that is before the specified range or is the wrong type
    181         if (marker.endOffset < startOffset)
    182             continue;
    183 
    184         // pin the marker to the specified range and apply the shift delta
    185         docDirty = true;
    186         if (marker.startOffset < startOffset)
    187             marker.startOffset = startOffset;
    188         if (marker.endOffset > endOffset)
    189             marker.endOffset = endOffset;
    190         marker.startOffset += delta;
    191         marker.endOffset += delta;
    192 
    193         addMarker(dstNode, marker);
    194     }
    195 
    196     // repaint the affected node
    197     if (docDirty && dstNode->renderer())
    198         dstNode->renderer()->repaint();
    199 }
    200 
    201 void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
    202 {
    203     if (length <= 0)
    204         return;
    205 
    206     if (!possiblyHasMarkers(markerTypes))
    207         return;
    208     ASSERT(!(m_markers.isEmpty()));
    209 
    210     MarkerMapVectorPair* vectorPair = m_markers.get(node);
    211     if (!vectorPair)
    212         return;
    213 
    214     Vector<DocumentMarker>& markers = vectorPair->first;
    215     Vector<IntRect>& rects = vectorPair->second;
    216     ASSERT(markers.size() == rects.size());
    217     bool docDirty = false;
    218     unsigned endOffset = startOffset + length;
    219     for (size_t i = 0; i < markers.size();) {
    220         DocumentMarker marker = markers[i];
    221 
    222         // markers are returned in order, so stop if we are now past the specified range
    223         if (marker.startOffset >= endOffset)
    224             break;
    225 
    226         // skip marker that is wrong type or before target
    227         if (marker.endOffset <= startOffset || !markerTypes.contains(marker.type)) {
    228             i++;
    229             continue;
    230         }
    231 
    232         // at this point we know that marker and target intersect in some way
    233         docDirty = true;
    234 
    235         // pitch the old marker and any associated rect
    236         markers.remove(i);
    237         rects.remove(i);
    238 
    239         if (shouldRemovePartiallyOverlappingMarker)
    240             // Stop here. Don't add resulting slices back.
    241             continue;
    242 
    243         // add either of the resulting slices that are left after removing target
    244         if (startOffset > marker.startOffset) {
    245             DocumentMarker newLeft = marker;
    246             newLeft.endOffset = startOffset;
    247             markers.insert(i, newLeft);
    248             rects.insert(i, placeholderRectForMarker());
    249             // i now points to the newly-inserted node, but we want to skip that one
    250             i++;
    251         }
    252         if (marker.endOffset > endOffset) {
    253             DocumentMarker newRight = marker;
    254             newRight.startOffset = endOffset;
    255             markers.insert(i, newRight);
    256             rects.insert(i, placeholderRectForMarker());
    257             // i now points to the newly-inserted node, but we want to skip that one
    258             i++;
    259         }
    260     }
    261 
    262     if (markers.isEmpty()) {
    263         ASSERT(rects.isEmpty());
    264         m_markers.remove(node);
    265         delete vectorPair;
    266     }
    267 
    268     if (m_markers.isEmpty())
    269         m_possiblyExistingMarkerTypes = 0;
    270 
    271     // repaint the affected node
    272     if (docDirty && node->renderer())
    273         node->renderer()->repaint();
    274 }
    275 
    276 DocumentMarker* DocumentMarkerController::markerContainingPoint(const IntPoint& point, DocumentMarker::MarkerType markerType)
    277 {
    278     if (!possiblyHasMarkers(markerType))
    279         return 0;
    280     ASSERT(!(m_markers.isEmpty()));
    281 
    282     // outer loop: process each node that contains any markers
    283     MarkerMap::iterator end = m_markers.end();
    284     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    285         // inner loop; process each marker in this node
    286         MarkerMapVectorPair* vectorPair = nodeIterator->second;
    287         Vector<DocumentMarker>& markers = vectorPair->first;
    288         Vector<IntRect>& rects = vectorPair->second;
    289         ASSERT(markers.size() == rects.size());
    290         unsigned markerCount = markers.size();
    291         for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
    292             DocumentMarker& marker = markers[markerIndex];
    293 
    294             // skip marker that is wrong type
    295             if (marker.type != markerType)
    296                 continue;
    297 
    298             IntRect& r = rects[markerIndex];
    299 
    300             // skip placeholder rects
    301             if (r == placeholderRectForMarker())
    302                 continue;
    303 
    304             if (r.contains(point))
    305                 return &marker;
    306         }
    307     }
    308 
    309     return 0;
    310 }
    311 
    312 Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node)
    313 {
    314     MarkerMapVectorPair* vectorPair = m_markers.get(node);
    315     if (vectorPair)
    316         return vectorPair->first;
    317     return Vector<DocumentMarker>();
    318 }
    319 
    320 Vector<DocumentMarker> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerType markerType)
    321 {
    322     if (!possiblyHasMarkers(markerType))
    323         return Vector<DocumentMarker>();
    324 
    325     Vector<DocumentMarker> foundMarkers;
    326 
    327     Node* startContainer = range->startContainer();
    328     ASSERT(startContainer);
    329     Node* endContainer = range->endContainer();
    330     ASSERT(endContainer);
    331 
    332     Node* pastLastNode = range->pastLastNode();
    333     for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
    334         Vector<DocumentMarker> markers = markersForNode(node);
    335         Vector<DocumentMarker>::const_iterator end = markers.end();
    336         for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
    337             if (markerType != it->type)
    338                 continue;
    339             if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
    340                 continue;
    341             if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
    342                 continue;
    343             foundMarkers.append(*it);
    344         }
    345     }
    346     return foundMarkers;
    347 }
    348 
    349 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
    350 {
    351     Vector<IntRect> result;
    352 
    353     if (!possiblyHasMarkers(markerType))
    354         return result;
    355     ASSERT(!(m_markers.isEmpty()));
    356 
    357     // outer loop: process each node
    358     MarkerMap::iterator end = m_markers.end();
    359     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    360         // inner loop; process each marker in this node
    361         MarkerMapVectorPair* vectorPair = nodeIterator->second;
    362         Vector<DocumentMarker>& markers = vectorPair->first;
    363         Vector<IntRect>& rects = vectorPair->second;
    364         ASSERT(markers.size() == rects.size());
    365         unsigned markerCount = markers.size();
    366         for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
    367             DocumentMarker marker = markers[markerIndex];
    368 
    369             // skip marker that is wrong type
    370             if (marker.type != markerType)
    371                 continue;
    372 
    373             IntRect r = rects[markerIndex];
    374             // skip placeholder rects
    375             if (r == placeholderRectForMarker())
    376                 continue;
    377 
    378             result.append(r);
    379         }
    380     }
    381 
    382     return result;
    383 }
    384 
    385 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
    386 {
    387     if (!possiblyHasMarkers(markerTypes))
    388         return;
    389     ASSERT(!m_markers.isEmpty());
    390 
    391     MarkerMap::iterator iterator = m_markers.find(node);
    392     if (iterator != m_markers.end())
    393         removeMarkersFromMarkerMapVectorPair(node, iterator->second, markerTypes);
    394 }
    395 
    396 void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
    397 {
    398     if (!possiblyHasMarkers(markerTypes))
    399         return;
    400     ASSERT(!m_markers.isEmpty());
    401 
    402     // outer loop: process each markered node in the document
    403     MarkerMap markerMapCopy = m_markers;
    404     MarkerMap::iterator end = markerMapCopy.end();
    405     for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i) {
    406         Node* node = i->first.get();
    407         MarkerMapVectorPair* vectorPair = i->second;
    408         removeMarkersFromMarkerMapVectorPair(node, vectorPair, markerTypes);
    409     }
    410 
    411     m_possiblyExistingMarkerTypes.remove(markerTypes);
    412 }
    413 
    414 // This function may release node and vectorPair.
    415 void DocumentMarkerController::removeMarkersFromMarkerMapVectorPair(Node* node, MarkerMapVectorPair* vectorPair, DocumentMarker::MarkerTypes markerTypes)
    416 {
    417     if (markerTypes == DocumentMarker::AllMarkers()) {
    418         delete vectorPair;
    419         m_markers.remove(node);
    420         if (RenderObject* renderer = node->renderer())
    421             renderer->repaint();
    422     } else {
    423         bool needsRepaint = false;
    424         Vector<DocumentMarker>& markers = vectorPair->first;
    425         Vector<IntRect>& rects = vectorPair->second;
    426         ASSERT(markers.size() == rects.size());
    427         for (size_t i = 0; i != markers.size();) {
    428             DocumentMarker marker = markers[i];
    429 
    430             // skip nodes that are not of the specified type
    431             if (!markerTypes.contains(marker.type)) {
    432                 ++i;
    433                 continue;
    434             }
    435 
    436             // pitch the old marker
    437             markers.remove(i);
    438             rects.remove(i);
    439             needsRepaint = true;
    440             // i now is the index of the next marker
    441         }
    442 
    443         // Redraw the node if it changed. Do this before the node is removed from m_markers, since
    444         // m_markers might contain the last reference to the node.
    445         if (needsRepaint) {
    446             RenderObject* renderer = node->renderer();
    447             if (renderer)
    448                 renderer->repaint();
    449         }
    450 
    451         // delete the node's list if it is now empty
    452         if (markers.isEmpty()) {
    453             ASSERT(rects.isEmpty());
    454             m_markers.remove(node);
    455             delete vectorPair;
    456         }
    457     }
    458     if (m_markers.isEmpty())
    459         m_possiblyExistingMarkerTypes = 0;
    460 }
    461 
    462 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
    463 {
    464     if (!possiblyHasMarkers(markerTypes))
    465         return;
    466     ASSERT(!m_markers.isEmpty());
    467 
    468     // outer loop: process each markered node in the document
    469     MarkerMap::iterator end = m_markers.end();
    470     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    471         Node* node = i->first.get();
    472 
    473         // inner loop: process each marker in the current node
    474         MarkerMapVectorPair* vectorPair = i->second;
    475         Vector<DocumentMarker>& markers = vectorPair->first;
    476         bool nodeNeedsRepaint = false;
    477         for (size_t i = 0; i != markers.size(); ++i) {
    478             DocumentMarker marker = markers[i];
    479 
    480             // skip nodes that are not of the specified type
    481             if (markerTypes.contains(marker.type)) {
    482                 nodeNeedsRepaint = true;
    483                 break;
    484             }
    485         }
    486 
    487         if (!nodeNeedsRepaint)
    488             continue;
    489 
    490         // cause the node to be redrawn
    491         if (RenderObject* renderer = node->renderer())
    492             renderer->repaint();
    493     }
    494 }
    495 
    496 void DocumentMarkerController::setRenderedRectForMarker(Node* node, const DocumentMarker& marker, const IntRect& r)
    497 {
    498     MarkerMapVectorPair* vectorPair = m_markers.get(node);
    499     if (!vectorPair) {
    500         ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about
    501         return;
    502     }
    503 
    504     Vector<DocumentMarker>& markers = vectorPair->first;
    505     ASSERT(markers.size() == vectorPair->second.size());
    506     unsigned markerCount = markers.size();
    507     for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
    508         DocumentMarker m = markers[markerIndex];
    509         if (m == marker) {
    510             vectorPair->second[markerIndex] = r;
    511             return;
    512         }
    513     }
    514 
    515     ASSERT_NOT_REACHED(); // shouldn't be trying to set the rect for a marker we don't already know about
    516 }
    517 
    518 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const IntRect& r)
    519 {
    520     // outer loop: process each markered node in the document
    521     MarkerMap::iterator end = m_markers.end();
    522     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    523 
    524         // inner loop: process each rect in the current node
    525         MarkerMapVectorPair* vectorPair = i->second;
    526         Vector<IntRect>& rects = vectorPair->second;
    527 
    528         unsigned rectCount = rects.size();
    529         for (unsigned rectIndex = 0; rectIndex < rectCount; ++rectIndex)
    530             if (rects[rectIndex].intersects(r))
    531                 rects[rectIndex] = placeholderRectForMarker();
    532     }
    533 }
    534 
    535 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
    536 {
    537     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    538         return;
    539     ASSERT(!m_markers.isEmpty());
    540 
    541     MarkerMapVectorPair* vectorPair = m_markers.get(node);
    542     if (!vectorPair)
    543         return;
    544 
    545     Vector<DocumentMarker>& markers = vectorPair->first;
    546     Vector<IntRect>& rects = vectorPair->second;
    547     ASSERT(markers.size() == rects.size());
    548 
    549     bool docDirty = false;
    550     for (size_t i = 0; i != markers.size(); ++i) {
    551         DocumentMarker& marker = markers[i];
    552         if (marker.startOffset >= startOffset) {
    553             ASSERT((int)marker.startOffset + delta >= 0);
    554             marker.startOffset += delta;
    555             marker.endOffset += delta;
    556             docDirty = true;
    557 
    558             // Marker moved, so previously-computed rendered rectangle is now invalid
    559             rects[i] = placeholderRectForMarker();
    560         }
    561     }
    562 
    563     // repaint the affected node
    564     if (docDirty && node->renderer())
    565         node->renderer()->repaint();
    566 }
    567 
    568 void DocumentMarkerController::setMarkersActive(Range* range, bool active)
    569 {
    570     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    571         return;
    572     ASSERT(!m_markers.isEmpty());
    573 
    574     ExceptionCode ec = 0;
    575     Node* startContainer = range->startContainer(ec);
    576     Node* endContainer = range->endContainer(ec);
    577 
    578     Node* pastLastNode = range->pastLastNode();
    579     for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
    580         int startOffset = node == startContainer ? range->startOffset(ec) : 0;
    581         int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX;
    582         setMarkersActive(node, startOffset, endOffset, active);
    583     }
    584 }
    585 
    586 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
    587 {
    588     MarkerMapVectorPair* vectorPair = m_markers.get(node);
    589     if (!vectorPair)
    590         return;
    591 
    592     Vector<DocumentMarker>& markers = vectorPair->first;
    593     ASSERT(markers.size() == vectorPair->second.size());
    594 
    595     bool docDirty = false;
    596     for (size_t i = 0; i != markers.size(); ++i) {
    597         DocumentMarker& marker = markers[i];
    598 
    599         // Markers are returned in order, so stop if we are now past the specified range.
    600         if (marker.startOffset >= endOffset)
    601             break;
    602 
    603         // Skip marker that is wrong type or before target.
    604         if (marker.endOffset < startOffset || marker.type != DocumentMarker::TextMatch)
    605             continue;
    606 
    607         marker.activeMatch = active;
    608         docDirty = true;
    609     }
    610 
    611     // repaint the affected node
    612     if (docDirty && node->renderer())
    613         node->renderer()->repaint();
    614 }
    615 
    616 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
    617 {
    618     if (!possiblyHasMarkers(markerTypes))
    619         return false;
    620     ASSERT(!m_markers.isEmpty());
    621 
    622     Node* startContainer = range->startContainer();
    623     ASSERT(startContainer);
    624     Node* endContainer = range->endContainer();
    625     ASSERT(endContainer);
    626 
    627     Node* pastLastNode = range->pastLastNode();
    628     for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
    629         Vector<DocumentMarker> markers = markersForNode(node);
    630         Vector<DocumentMarker>::const_iterator end = markers.end();
    631         for (Vector<DocumentMarker>::const_iterator it = markers.begin(); it != end; ++it) {
    632             if (!markerTypes.contains(it->type))
    633                 continue;
    634             if (node == startContainer && it->endOffset <= static_cast<unsigned>(range->startOffset()))
    635                 continue;
    636             if (node == endContainer && it->startOffset >= static_cast<unsigned>(range->endOffset()))
    637                 continue;
    638             return true;
    639         }
    640     }
    641     return false;
    642 }
    643 
    644 void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
    645 {
    646     if (!possiblyHasMarkers(markerTypes))
    647         return;
    648     ASSERT(!m_markers.isEmpty());
    649 
    650     Node* startContainer = range->startContainer();
    651     Node* endContainer = range->endContainer();
    652 
    653     Node* pastLastNode = range->pastLastNode();
    654     for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
    655         unsigned startOffset = node == startContainer ? range->startOffset() : 0;
    656         unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max();
    657         MarkerMapVectorPair* vectorPair = m_markers.get(node);
    658         if (!vectorPair)
    659             continue;
    660 
    661         Vector<DocumentMarker>& markers = vectorPair->first;
    662         for (size_t i = 0; i < markers.size(); ++i) {
    663             DocumentMarker& marker = markers[i];
    664 
    665             // markers are returned in order, so stop if we are now past the specified range
    666             if (marker.startOffset >= endOffset)
    667                 break;
    668 
    669             // skip marker that is wrong type or before target
    670             if (marker.endOffset <= startOffset || !markerTypes.contains(marker.type)) {
    671                 i++;
    672                 continue;
    673             }
    674 
    675             marker.description = String();
    676         }
    677     }
    678 }
    679 
    680 #ifndef NDEBUG
    681 void DocumentMarkerController::showMarkers() const
    682 {
    683     fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
    684     MarkerMap::const_iterator end = m_markers.end();
    685     for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    686         Node* node = nodeIterator->first.get();
    687         fprintf(stderr, "%p", node);
    688         MarkerMapVectorPair* vectorPair = nodeIterator->second;
    689         Vector<DocumentMarker>& markers = vectorPair->first;
    690         unsigned markerCount = markers.size();
    691         for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex)
    692             fprintf(stderr, " %d:[%d:%d](%d)", markers[markerIndex].type, markers[markerIndex].startOffset, markers[markerIndex].endOffset, markers[markerIndex].activeMatch);
    693         fprintf(stderr, "\n");
    694     }
    695 }
    696 #endif
    697 
    698 } // namespace WebCore
    699 
    700 
    701 #ifndef NDEBUG
    702 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
    703 {
    704     if (controller)
    705         controller->showMarkers();
    706 }
    707 #endif
    708