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 "core/dom/DocumentMarkerController.h"
     29 
     30 #include "core/dom/Node.h"
     31 #include "core/dom/NodeTraversal.h"
     32 #include "core/dom/Range.h"
     33 #include "core/dom/RenderedDocumentMarker.h"
     34 #include "core/editing/TextIterator.h"
     35 #include "core/rendering/RenderObject.h"
     36 
     37 #ifndef NDEBUG
     38 #include <stdio.h>
     39 #endif
     40 
     41 namespace WebCore {
     42 
     43 namespace {
     44 
     45 DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(DocumentMarker::MarkerType type)
     46 {
     47     switch (type) {
     48     case DocumentMarker::Spelling:
     49         return DocumentMarker::SpellingMarkerIndex;
     50     case DocumentMarker::Grammar:
     51         return DocumentMarker::GramarMarkerIndex;
     52     case DocumentMarker::TextMatch:
     53         return DocumentMarker::TextMatchMarkerIndex;
     54     case DocumentMarker::InvisibleSpellcheck:
     55         return DocumentMarker::InvisibleSpellcheckMarkerIndex;
     56     }
     57 
     58     ASSERT_NOT_REACHED();
     59     return DocumentMarker::SpellingMarkerIndex;
     60 }
     61 
     62 } // namespace
     63 
     64 inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
     65 {
     66     return m_possiblyExistingMarkerTypes.intersects(types);
     67 }
     68 
     69 DocumentMarkerController::DocumentMarkerController()
     70     : m_possiblyExistingMarkerTypes(0)
     71 {
     72 }
     73 
     74 DocumentMarkerController::~DocumentMarkerController()
     75 {
     76 }
     77 
     78 void DocumentMarkerController::clear()
     79 {
     80     m_markers.clear();
     81     m_possiblyExistingMarkerTypes = 0;
     82 }
     83 
     84 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description, uint32_t hash)
     85 {
     86     // Use a TextIterator to visit the potentially multiple nodes the range covers.
     87     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     88         RefPtr<Range> textPiece = markedText.range();
     89         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description, hash));
     90     }
     91 }
     92 
     93 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description)
     94 {
     95     // Use a TextIterator to visit the potentially multiple nodes the range covers.
     96     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
     97         RefPtr<Range> textPiece = markedText.range();
     98         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset(), description));
     99     }
    100 }
    101 
    102 void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type)
    103 {
    104     // Use a TextIterator to visit the potentially multiple nodes the range covers.
    105     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    106         RefPtr<Range> textPiece = markedText.range();
    107         addMarker(textPiece->startContainer(), DocumentMarker(type, textPiece->startOffset(), textPiece->endOffset()));
    108     }
    109 
    110 }
    111 
    112 void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type)
    113 {
    114     addMarker(node, DocumentMarker(type, startOffset, startOffset + length));
    115 }
    116 
    117 void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type, PassRefPtr<DocumentMarkerDetails> details)
    118 {
    119     addMarker(node, DocumentMarker(type, startOffset, startOffset + length, details));
    120 }
    121 
    122 
    123 void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch)
    124 {
    125     // Use a TextIterator to visit the potentially multiple nodes the range covers.
    126     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    127         RefPtr<Range> textPiece = markedText.range();
    128         unsigned startOffset = textPiece->startOffset();
    129         unsigned endOffset = textPiece->endOffset();
    130         addMarker(textPiece->startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
    131         if (endOffset > startOffset) {
    132             // Rendered rects for markers in WebKit are not populated until each time
    133             // the markers are painted. However, we need it to happen sooner, because
    134             // the whole purpose of tickmarks on the scrollbar is to show where
    135             // matches off-screen are (that haven't been painted yet).
    136             Node* node = textPiece->startContainer();
    137             Vector<DocumentMarker*> markers = markersFor(node);
    138             toRenderedDocumentMarker(markers[markers.size() - 1])->setRenderedRect(range->boundingBox());
    139         }
    140     }
    141 }
    142 
    143 void DocumentMarkerController::prepareForDestruction()
    144 {
    145     clear();
    146 }
    147 
    148 void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
    149 {
    150     for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
    151         if (!possiblyHasMarkers(markerTypes))
    152             return;
    153         ASSERT(!m_markers.isEmpty());
    154 
    155         RefPtr<Range> textPiece = markedText.range();
    156         int startOffset = textPiece->startOffset();
    157         int endOffset = textPiece->endOffset();
    158         removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
    159     }
    160 }
    161 
    162 static bool startsFurther(const DocumentMarker& lhv, const DocumentMarker& rhv)
    163 {
    164     return lhv.startOffset() < rhv.startOffset();
    165 }
    166 
    167 static bool startsAfter(const DocumentMarker& marker, size_t startOffset)
    168 {
    169     return marker.startOffset() < startOffset;
    170 }
    171 
    172 static bool endsBefore(size_t startOffset, const DocumentMarker& rhv)
    173 {
    174     return startOffset < rhv.endOffset();
    175 }
    176 
    177 static bool compareByStart(const DocumentMarker* lhv, const DocumentMarker* rhv)
    178 {
    179     return startsFurther(*lhv, *rhv);
    180 }
    181 
    182 static bool doesNotOverlap(const DocumentMarker& lhv, const DocumentMarker& rhv)
    183 {
    184     return lhv.endOffset() < rhv.startOffset();
    185 }
    186 
    187 static bool doesNotInclude(const DocumentMarker& marker, size_t startOffset)
    188 {
    189     return marker.endOffset() < startOffset;
    190 }
    191 
    192 // Markers are stored in order sorted by their start offset.
    193 // Markers of the same type do not overlap each other.
    194 
    195 void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker)
    196 {
    197     ASSERT(newMarker.endOffset() >= newMarker.startOffset());
    198     if (newMarker.endOffset() == newMarker.startOffset())
    199         return;
    200 
    201     m_possiblyExistingMarkerTypes.add(newMarker.type());
    202 
    203     OwnPtr<MarkerLists>& markers = m_markers.add(node, nullptr).iterator->value;
    204     if (!markers) {
    205         markers = adoptPtr(new MarkerLists);
    206         markers->grow(DocumentMarker::MarkerTypeIndexesCount);
    207     }
    208 
    209     DocumentMarker::MarkerTypeIndex markerListIndex = MarkerTypeToMarkerIndex(newMarker.type());
    210     if (!markers->at(markerListIndex)) {
    211         markers->insert(markerListIndex, adoptPtr(new MarkerList));
    212     }
    213 
    214     OwnPtr<MarkerList>& list = markers->at(markerListIndex);
    215     if (list->isEmpty() || list->last().endOffset() < newMarker.startOffset()) {
    216         list->append(RenderedDocumentMarker(newMarker));
    217     } else {
    218         RenderedDocumentMarker toInsert(newMarker);
    219         if (toInsert.type() != DocumentMarker::TextMatch) {
    220             mergeOverlapping(list.get(), toInsert);
    221         } else {
    222             MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), toInsert, startsFurther);
    223             list->insert(pos - list->begin(), RenderedDocumentMarker(toInsert));
    224         }
    225     }
    226 
    227     // repaint the affected node
    228     if (node->renderer())
    229         node->renderer()->repaint();
    230 }
    231 
    232 void DocumentMarkerController::mergeOverlapping(MarkerList* list, DocumentMarker& toInsert)
    233 {
    234     MarkerList::iterator firstOverlapping = std::lower_bound(list->begin(), list->end(), toInsert, doesNotOverlap);
    235     size_t index = firstOverlapping - list->begin();
    236     list->insert(index, RenderedDocumentMarker(toInsert));
    237     MarkerList::iterator inserted = list->begin() + index;
    238     firstOverlapping = inserted + 1;
    239     for (MarkerList::iterator i = firstOverlapping; i != list->end() && i->startOffset() <= inserted->endOffset(); ) {
    240         inserted->setStartOffset(std::min(inserted->startOffset(), i->startOffset()));
    241         inserted->setEndOffset(std::max(inserted->endOffset(), i->endOffset()));
    242         list->remove(i - list->begin());
    243     }
    244 }
    245 
    246 // copies markers from srcNode to dstNode, applying the specified shift delta to the copies.  The shift is
    247 // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
    248 void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
    249 {
    250     if (length <= 0)
    251         return;
    252 
    253     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    254         return;
    255     ASSERT(!m_markers.isEmpty());
    256 
    257     MarkerLists* markers = m_markers.get(srcNode);
    258     if (!markers)
    259         return;
    260 
    261     bool docDirty = false;
    262     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    263         OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    264         if (!list)
    265             continue;
    266 
    267         unsigned endOffset = startOffset + length - 1;
    268         MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, doesNotInclude);
    269         for (MarkerList::iterator i = startPos; i != list->end(); ++i) {
    270             DocumentMarker marker = *i;
    271 
    272             // stop if we are now past the specified range
    273             if (marker.startOffset() > endOffset)
    274                 break;
    275 
    276             // pin the marker to the specified range and apply the shift delta
    277             docDirty = true;
    278             if (marker.startOffset() < startOffset)
    279                 marker.setStartOffset(startOffset);
    280             if (marker.endOffset() > endOffset)
    281                 marker.setEndOffset(endOffset);
    282             marker.shiftOffsets(delta);
    283 
    284             addMarker(dstNode, marker);
    285         }
    286     }
    287 
    288     // repaint the affected node
    289     if (docDirty && dstNode->renderer())
    290         dstNode->renderer()->repaint();
    291 }
    292 
    293 void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
    294 {
    295     if (length <= 0)
    296         return;
    297 
    298     if (!possiblyHasMarkers(markerTypes))
    299         return;
    300     ASSERT(!(m_markers.isEmpty()));
    301 
    302     MarkerLists* markers = m_markers.get(node);
    303     if (!markers)
    304         return;
    305 
    306     bool docDirty = false;
    307     size_t emptyListsCount = 0;
    308     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    309         OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    310         if (!list || list->isEmpty()) {
    311             if (list.get() && list->isEmpty())
    312                 list.clear();
    313             ++emptyListsCount;
    314             continue;
    315         }
    316         if (!markerTypes.contains(list->begin()->type()))
    317             continue;
    318         unsigned endOffset = startOffset + length;
    319         MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
    320         for (MarkerList::iterator i = startPos; i != list->end(); ) {
    321             DocumentMarker marker = *i;
    322 
    323             // markers are returned in order, so stop if we are now past the specified range
    324             if (marker.startOffset() >= endOffset)
    325                 break;
    326 
    327             // at this point we know that marker and target intersect in some way
    328             docDirty = true;
    329 
    330             // pitch the old marker
    331             list->remove(i - list->begin());
    332 
    333             if (shouldRemovePartiallyOverlappingMarker) {
    334                 // Stop here. Don't add resulting slices back.
    335                 continue;
    336             }
    337 
    338             // add either of the resulting slices that are left after removing target
    339             if (startOffset > marker.startOffset()) {
    340                 DocumentMarker newLeft = marker;
    341                 newLeft.setEndOffset(startOffset);
    342                 size_t insertIndex = i - list->begin();
    343                 list->insert(insertIndex , RenderedDocumentMarker(newLeft));
    344                 // Move to the marker after the inserted one.
    345                 i = list->begin() + insertIndex + 1;
    346             }
    347             if (marker.endOffset() > endOffset) {
    348                 DocumentMarker newRight = marker;
    349                 newRight.setStartOffset(endOffset);
    350                 size_t insertIndex = i - list->begin();
    351                 list->insert(insertIndex, RenderedDocumentMarker(newRight));
    352                 // Move to the marker after the inserted one.
    353                 i = list->begin() + insertIndex + 1;
    354             }
    355         }
    356 
    357         if (list->isEmpty()) {
    358             list.clear();
    359             ++emptyListsCount;
    360         }
    361     }
    362 
    363     if (emptyListsCount == DocumentMarker::MarkerTypeIndexesCount) {
    364         m_markers.remove(node);
    365         if (m_markers.isEmpty())
    366             m_possiblyExistingMarkerTypes = 0;
    367     }
    368 
    369     // repaint the affected node
    370     if (docDirty && node->renderer())
    371         node->renderer()->repaint();
    372 }
    373 
    374 DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType)
    375 {
    376     if (!possiblyHasMarkers(markerType))
    377         return 0;
    378     ASSERT(!(m_markers.isEmpty()));
    379 
    380     // outer loop: process each node that contains any markers
    381     MarkerMap::iterator end = m_markers.end();
    382     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    383         // inner loop; process each marker in this node
    384         MarkerLists* markers = nodeIterator->value.get();
    385         OwnPtr<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(markerType)];
    386         unsigned markerCount = list.get() ? list->size() : 0;
    387         for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
    388             RenderedDocumentMarker& marker = list->at(markerIndex);
    389 
    390             if (marker.contains(point))
    391                 return &marker;
    392         }
    393     }
    394 
    395     return 0;
    396 }
    397 
    398 Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes)
    399 {
    400     Vector<DocumentMarker*> result;
    401 
    402     MarkerLists* markers = m_markers.get(node);
    403     if (!markers)
    404         return result;
    405 
    406     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    407         OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    408         if (!list || list->isEmpty() || !markerTypes.contains(list->begin()->type()))
    409             continue;
    410 
    411         for (size_t i = 0; i < list->size(); ++i)
    412             result.append(&(list->at(i)));
    413     }
    414 
    415     std::sort(result.begin(), result.end(), compareByStart);
    416     return result;
    417 }
    418 
    419 Vector<DocumentMarker*> DocumentMarkerController::markers()
    420 {
    421     Vector<DocumentMarker*> result;
    422     for (MarkerMap::iterator i = m_markers.begin(); i != m_markers.end(); ++i) {
    423         MarkerLists* markers = i->value.get();
    424         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    425             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    426             for (size_t j = 0; list.get() && j < list->size(); ++j)
    427                 result.append(&(list->at(j)));
    428         }
    429     }
    430     std::sort(result.begin(), result.end(), compareByStart);
    431     return result;
    432 }
    433 
    434 Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
    435 {
    436     if (!possiblyHasMarkers(markerTypes))
    437         return Vector<DocumentMarker*>();
    438 
    439     Vector<DocumentMarker*> foundMarkers;
    440 
    441     Node* startContainer = range->startContainer();
    442     ASSERT(startContainer);
    443     Node* endContainer = range->endContainer();
    444     ASSERT(endContainer);
    445 
    446     Node* pastLastNode = range->pastLastNode();
    447     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    448         Vector<DocumentMarker*> markers = markersFor(node);
    449         Vector<DocumentMarker*>::const_iterator end = markers.end();
    450         for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
    451             DocumentMarker* marker = *it;
    452             if (!markerTypes.contains(marker->type()))
    453                 continue;
    454             if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
    455                 continue;
    456             if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
    457                 continue;
    458             foundMarkers.append(marker);
    459         }
    460     }
    461     return foundMarkers;
    462 }
    463 
    464 Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
    465 {
    466     Vector<IntRect> result;
    467 
    468     if (!possiblyHasMarkers(markerType))
    469         return result;
    470     ASSERT(!(m_markers.isEmpty()));
    471 
    472     // outer loop: process each node
    473     MarkerMap::iterator end = m_markers.end();
    474     for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    475         // inner loop; process each marker in this node
    476         MarkerLists* markers = nodeIterator->value.get();
    477         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    478             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    479             if (!list || list->isEmpty() || list->begin()->type() != markerType)
    480                 continue;
    481             for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) {
    482                 const RenderedDocumentMarker& marker = list->at(markerIndex);
    483 
    484                 if (!marker.isRendered())
    485                     continue;
    486 
    487                 result.append(marker.renderedRect());
    488             }
    489         }
    490     }
    491 
    492     return result;
    493 }
    494 
    495 void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
    496 {
    497     if (!possiblyHasMarkers(markerTypes))
    498         return;
    499     ASSERT(!m_markers.isEmpty());
    500 
    501     MarkerMap::iterator iterator = m_markers.find(node);
    502     if (iterator != m_markers.end())
    503         removeMarkersFromList(iterator, markerTypes);
    504 }
    505 
    506 void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
    507 {
    508     if (!possiblyHasMarkers(markerTypes))
    509         return;
    510     ASSERT(!m_markers.isEmpty());
    511 
    512     Vector<const Node*> nodesWithMarkers;
    513     copyKeysToVector(m_markers, nodesWithMarkers);
    514     unsigned size = nodesWithMarkers.size();
    515     for (unsigned i = 0; i < size; ++i) {
    516         MarkerMap::iterator iterator = m_markers.find(nodesWithMarkers[i]);
    517         if (iterator != m_markers.end())
    518             removeMarkersFromList(iterator, markerTypes);
    519     }
    520 
    521     m_possiblyExistingMarkerTypes.remove(markerTypes);
    522 }
    523 
    524 void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes)
    525 {
    526     bool needsRepainting = false;
    527     bool nodeCanBeRemoved;
    528 
    529     size_t emptyListsCount = 0;
    530     if (markerTypes == DocumentMarker::AllMarkers()) {
    531         needsRepainting = true;
    532         nodeCanBeRemoved = true;
    533     } else {
    534         MarkerLists* markers = iterator->value.get();
    535 
    536         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    537             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    538             if (!list || list->isEmpty()) {
    539                 if (list.get() && list->isEmpty())
    540                     list.clear();
    541                 ++emptyListsCount;
    542                 continue;
    543             }
    544             if (markerTypes.contains(list->begin()->type())) {
    545                 list->clear();
    546                 list.clear();
    547                 ++emptyListsCount;
    548                 needsRepainting = true;
    549             }
    550         }
    551 
    552         nodeCanBeRemoved = emptyListsCount == DocumentMarker::MarkerTypeIndexesCount;
    553     }
    554 
    555     if (needsRepainting) {
    556         if (RenderObject* renderer = iterator->key->renderer())
    557             renderer->repaint();
    558     }
    559 
    560     if (nodeCanBeRemoved) {
    561         m_markers.remove(iterator);
    562         if (m_markers.isEmpty())
    563             m_possiblyExistingMarkerTypes = 0;
    564     }
    565 }
    566 
    567 void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
    568 {
    569     if (!possiblyHasMarkers(markerTypes))
    570         return;
    571     ASSERT(!m_markers.isEmpty());
    572 
    573     // outer loop: process each markered node in the document
    574     MarkerMap::iterator end = m_markers.end();
    575     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    576         const Node* node = i->key;
    577 
    578         // inner loop: process each marker in the current node
    579         MarkerLists* markers = i->value.get();
    580         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    581             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    582             if (!list || list->isEmpty() || !markerTypes.contains(list->begin()->type()))
    583                 continue;
    584 
    585             // cause the node to be redrawn
    586             if (RenderObject* renderer = node->renderer()) {
    587                 renderer->repaint();
    588                 break;
    589             }
    590         }
    591     }
    592 }
    593 
    594 void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect& r)
    595 {
    596     // outer loop: process each markered node in the document
    597     MarkerMap::iterator end = m_markers.end();
    598     for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
    599 
    600         // inner loop: process each rect in the current node
    601         MarkerLists* markers = i->value.get();
    602         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    603             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    604             for (size_t markerIndex = 0; list.get() && markerIndex < list->size(); ++markerIndex)
    605                 list->at(markerIndex).invalidate(r);
    606         }
    607     }
    608 }
    609 
    610 void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
    611 {
    612     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    613         return;
    614     ASSERT(!m_markers.isEmpty());
    615 
    616     MarkerLists* markers = m_markers.get(node);
    617     if (!markers)
    618         return;
    619 
    620     bool docDirty = false;
    621     for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    622         OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    623         if (!list)
    624             continue;
    625         MarkerList::iterator startPos = std::lower_bound(list->begin(), list->end(), startOffset, startsAfter);
    626         for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker) {
    627             ASSERT((int)marker->startOffset() + delta >= 0);
    628             marker->shiftOffsets(delta);
    629             docDirty = true;
    630 
    631             // Marker moved, so previously-computed rendered rectangle is now invalid
    632             marker->invalidate();
    633         }
    634     }
    635 
    636     // repaint the affected node
    637     if (docDirty && node->renderer())
    638         node->renderer()->repaint();
    639 }
    640 
    641 void DocumentMarkerController::setMarkersActive(Range* range, bool active)
    642 {
    643     if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
    644         return;
    645     ASSERT(!m_markers.isEmpty());
    646 
    647     Node* startContainer = range->startContainer();
    648     Node* endContainer = range->endContainer();
    649 
    650     Node* pastLastNode = range->pastLastNode();
    651 
    652     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    653         int startOffset = node == startContainer ? range->startOffset() : 0;
    654         int endOffset = node == endContainer ? range->endOffset() : INT_MAX;
    655         setMarkersActive(node, startOffset, endOffset, active);
    656     }
    657 }
    658 
    659 void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
    660 {
    661     MarkerLists* markers = m_markers.get(node);
    662     if (!markers)
    663         return;
    664 
    665     bool docDirty = false;
    666     OwnPtr<MarkerList>& list = (*markers)[MarkerTypeToMarkerIndex(DocumentMarker::TextMatch)];
    667     if (!list)
    668         return;
    669     MarkerList::iterator startPos = std::upper_bound(list->begin(), list->end(), startOffset, endsBefore);
    670     for (MarkerList::iterator marker = startPos; marker != list->end(); ++marker) {
    671 
    672         // Markers are returned in order, so stop if we are now past the specified range.
    673         if (marker->startOffset() >= endOffset)
    674             break;
    675 
    676         marker->setActiveMatch(active);
    677         docDirty = true;
    678     }
    679 
    680     // repaint the affected node
    681     if (docDirty && node->renderer())
    682         node->renderer()->repaint();
    683 }
    684 
    685 bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
    686 {
    687     if (!possiblyHasMarkers(markerTypes))
    688         return false;
    689     ASSERT(!m_markers.isEmpty());
    690 
    691     Node* startContainer = range->startContainer();
    692     ASSERT(startContainer);
    693     Node* endContainer = range->endContainer();
    694     ASSERT(endContainer);
    695 
    696     Node* pastLastNode = range->pastLastNode();
    697     for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(*node)) {
    698         Vector<DocumentMarker*> markers = markersFor(node);
    699         Vector<DocumentMarker*>::const_iterator end = markers.end();
    700         for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
    701             DocumentMarker* marker = *it;
    702             if (!markerTypes.contains(marker->type()))
    703                 continue;
    704             if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
    705                 continue;
    706             if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
    707                 continue;
    708             return true;
    709         }
    710     }
    711     return false;
    712 }
    713 
    714 #ifndef NDEBUG
    715 void DocumentMarkerController::showMarkers() const
    716 {
    717     fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
    718     MarkerMap::const_iterator end = m_markers.end();
    719     for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
    720         const Node* node = nodeIterator->key;
    721         fprintf(stderr, "%p", node);
    722         MarkerLists* markers = m_markers.get(node);
    723         for (size_t markerListIndex = 0; markerListIndex < DocumentMarker::MarkerTypeIndexesCount; ++markerListIndex) {
    724             OwnPtr<MarkerList>& list = (*markers)[markerListIndex];
    725             for (unsigned markerIndex = 0; list.get() && markerIndex < list->size(); ++markerIndex) {
    726                 const DocumentMarker& marker = list->at(markerIndex);
    727                 fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset(), marker.endOffset(), marker.activeMatch());
    728             }
    729         }
    730 
    731         fprintf(stderr, "\n");
    732     }
    733 }
    734 #endif
    735 
    736 } // namespace WebCore
    737 
    738 #ifndef NDEBUG
    739 void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
    740 {
    741     if (controller)
    742         controller->showMarkers();
    743 }
    744 #endif
    745