PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/webview/native/Source/WebCore/dom/DocumentMarkerController.cpp

https://bitbucket.org/rbair/rbair-controls-8
C++ | 700 lines | 503 code | 112 blank | 85 comment | 153 complexity | 68580ede36f3538c103073d35db6459b MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  3. * (C) 1999 Antti Koivisto (koivisto@kde.org)
  4. * (C) 2001 Dirk Mueller (mueller@kde.org)
  5. * (C) 2006 Alexey Proskuryakov (ap@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. #include "config.h"
  27. #include "DocumentMarkerController.h"
  28. #include "Node.h"
  29. #include "Range.h"
  30. #include "RenderObject.h"
  31. #include "RenderedDocumentMarker.h"
  32. #include "TextIterator.h"
  33. #ifndef NDEBUG
  34. #include <stdio.h>
  35. #endif
  36. namespace WebCore {
  37. inline bool DocumentMarkerController::possiblyHasMarkers(DocumentMarker::MarkerTypes types)
  38. {
  39. return m_possiblyExistingMarkerTypes.intersects(types);
  40. }
  41. DocumentMarkerController::DocumentMarkerController()
  42. : m_possiblyExistingMarkerTypes(0)
  43. {
  44. }
  45. void DocumentMarkerController::detach()
  46. {
  47. m_possiblyExistingMarkerTypes = 0;
  48. if (m_markers.isEmpty())
  49. return;
  50. deleteAllValues(m_markers);
  51. m_markers.clear();
  52. }
  53. void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type, const String& description)
  54. {
  55. // Use a TextIterator to visit the potentially multiple nodes the range covers.
  56. for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
  57. RefPtr<Range> textPiece = markedText.range();
  58. int exception = 0;
  59. addMarker(textPiece->startContainer(exception),
  60. DocumentMarker(type, textPiece->startOffset(exception), textPiece->endOffset(exception), description));
  61. }
  62. }
  63. void DocumentMarkerController::addMarker(Range* range, DocumentMarker::MarkerType type)
  64. {
  65. // Use a TextIterator to visit the potentially multiple nodes the range covers.
  66. for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
  67. RefPtr<Range> textPiece = markedText.range();
  68. int exception = 0;
  69. addMarker(textPiece->startContainer(exception),
  70. DocumentMarker(type, textPiece->startOffset(exception), textPiece->endOffset(exception)));
  71. }
  72. }
  73. void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type)
  74. {
  75. addMarker(node, DocumentMarker(type, startOffset, startOffset + length));
  76. }
  77. void DocumentMarkerController::addMarkerToNode(Node* node, unsigned startOffset, unsigned length, DocumentMarker::MarkerType type, PassRefPtr<DocumentMarkerDetails> details)
  78. {
  79. addMarker(node, DocumentMarker(type, startOffset, startOffset + length, details));
  80. }
  81. void DocumentMarkerController::addTextMatchMarker(Range* range, bool activeMatch)
  82. {
  83. // Use a TextIterator to visit the potentially multiple nodes the range covers.
  84. for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
  85. RefPtr<Range> textPiece = markedText.range();
  86. int exception = 0;
  87. unsigned startOffset = textPiece->startOffset(exception);
  88. unsigned endOffset = textPiece->endOffset(exception);
  89. addMarker(textPiece->startContainer(exception), DocumentMarker(startOffset, endOffset, activeMatch));
  90. if (endOffset > startOffset) {
  91. // Rendered rects for markers in WebKit are not populated until each time
  92. // the markers are painted. However, we need it to happen sooner, because
  93. // the whole purpose of tickmarks on the scrollbar is to show where
  94. // matches off-screen are (that haven't been painted yet).
  95. Node* node = textPiece->startContainer(exception);
  96. Vector<DocumentMarker*> markers = markersFor(node);
  97. static_cast<RenderedDocumentMarker*>(markers[markers.size() - 1])->setRenderedRect(range->boundingBox());
  98. }
  99. }
  100. }
  101. void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
  102. {
  103. for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
  104. if (!possiblyHasMarkers(markerTypes))
  105. return;
  106. ASSERT(!m_markers.isEmpty());
  107. RefPtr<Range> textPiece = markedText.range();
  108. int startOffset = textPiece->startOffset();
  109. int endOffset = textPiece->endOffset();
  110. removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
  111. }
  112. }
  113. // Markers are stored in order sorted by their start offset.
  114. // Markers of the same type do not overlap each other.
  115. void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker)
  116. {
  117. ASSERT(newMarker.endOffset() >= newMarker.startOffset());
  118. if (newMarker.endOffset() == newMarker.startOffset())
  119. return;
  120. m_possiblyExistingMarkerTypes.add(newMarker.type());
  121. MarkerList* list = m_markers.get(node);
  122. if (!list) {
  123. list = new MarkerList;
  124. list->append(RenderedDocumentMarker(newMarker));
  125. m_markers.set(node, list);
  126. } else {
  127. RenderedDocumentMarker toInsert(newMarker);
  128. size_t numMarkers = list->size();
  129. size_t i;
  130. // Iterate over all markers whose start offset is less than or equal to the new marker's.
  131. // If one of them is of the same type as the new marker and touches it or intersects with it
  132. // (there is at most one), remove it and adjust the new marker's start offset to encompass it.
  133. for (i = 0; i < numMarkers; ++i) {
  134. DocumentMarker marker = list->at(i);
  135. if (marker.startOffset() > toInsert.startOffset())
  136. break;
  137. if (marker.type() == toInsert.type() && marker.endOffset() >= toInsert.startOffset()) {
  138. toInsert.setStartOffset(marker.startOffset());
  139. list->remove(i);
  140. numMarkers--;
  141. break;
  142. }
  143. }
  144. size_t j = i;
  145. // Iterate over all markers whose end offset is less than or equal to the new marker's,
  146. // removing markers of the same type as the new marker which touch it or intersect with it,
  147. // adjusting the new marker's end offset to cover them if necessary.
  148. while (j < numMarkers) {
  149. DocumentMarker marker = list->at(j);
  150. if (marker.startOffset() > toInsert.endOffset())
  151. break;
  152. if (marker.type() == toInsert.type()) {
  153. list->remove(j);
  154. if (toInsert.endOffset() <= marker.endOffset()) {
  155. toInsert.setEndOffset(marker.endOffset());
  156. break;
  157. }
  158. numMarkers--;
  159. } else
  160. j++;
  161. }
  162. // At this point i points to the node before which we want to insert.
  163. list->insert(i, RenderedDocumentMarker(toInsert));
  164. }
  165. // repaint the affected node
  166. if (node->renderer())
  167. node->renderer()->repaint();
  168. }
  169. // copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is
  170. // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode.
  171. void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta)
  172. {
  173. if (length <= 0)
  174. return;
  175. if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
  176. return;
  177. ASSERT(!m_markers.isEmpty());
  178. MarkerList* list = m_markers.get(srcNode);
  179. if (!list)
  180. return;
  181. bool docDirty = false;
  182. unsigned endOffset = startOffset + length - 1;
  183. for (size_t i = 0; i != list->size(); ++i) {
  184. DocumentMarker marker = list->at(i);
  185. // stop if we are now past the specified range
  186. if (marker.startOffset() > endOffset)
  187. break;
  188. // skip marker that is before the specified range or is the wrong type
  189. if (marker.endOffset() < startOffset)
  190. continue;
  191. // pin the marker to the specified range and apply the shift delta
  192. docDirty = true;
  193. if (marker.startOffset() < startOffset)
  194. marker.setStartOffset(startOffset);
  195. if (marker.endOffset() > endOffset)
  196. marker.setEndOffset(endOffset);
  197. marker.shiftOffsets(delta);
  198. addMarker(dstNode, marker);
  199. }
  200. // repaint the affected node
  201. if (docDirty && dstNode->renderer())
  202. dstNode->renderer()->repaint();
  203. }
  204. void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
  205. {
  206. if (length <= 0)
  207. return;
  208. if (!possiblyHasMarkers(markerTypes))
  209. return;
  210. ASSERT(!(m_markers.isEmpty()));
  211. MarkerList* list = m_markers.get(node);
  212. if (!list)
  213. return;
  214. bool docDirty = false;
  215. unsigned endOffset = startOffset + length;
  216. for (size_t i = 0; i < list->size();) {
  217. DocumentMarker marker = list->at(i);
  218. // markers are returned in order, so stop if we are now past the specified range
  219. if (marker.startOffset() >= endOffset)
  220. break;
  221. // skip marker that is wrong type or before target
  222. if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) {
  223. i++;
  224. continue;
  225. }
  226. // at this point we know that marker and target intersect in some way
  227. docDirty = true;
  228. // pitch the old marker
  229. list->remove(i);
  230. if (shouldRemovePartiallyOverlappingMarker)
  231. // Stop here. Don't add resulting slices back.
  232. continue;
  233. // add either of the resulting slices that are left after removing target
  234. if (startOffset > marker.startOffset()) {
  235. DocumentMarker newLeft = marker;
  236. newLeft.setEndOffset(startOffset);
  237. list->insert(i, RenderedDocumentMarker(newLeft));
  238. // i now points to the newly-inserted node, but we want to skip that one
  239. i++;
  240. }
  241. if (marker.endOffset() > endOffset) {
  242. DocumentMarker newRight = marker;
  243. newRight.setStartOffset(endOffset);
  244. list->insert(i, RenderedDocumentMarker(newRight));
  245. // i now points to the newly-inserted node, but we want to skip that one
  246. i++;
  247. }
  248. }
  249. if (list->isEmpty()) {
  250. m_markers.remove(node);
  251. delete list;
  252. }
  253. if (m_markers.isEmpty())
  254. m_possiblyExistingMarkerTypes = 0;
  255. // repaint the affected node
  256. if (docDirty && node->renderer())
  257. node->renderer()->repaint();
  258. }
  259. DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType)
  260. {
  261. if (!possiblyHasMarkers(markerType))
  262. return 0;
  263. ASSERT(!(m_markers.isEmpty()));
  264. // outer loop: process each node that contains any markers
  265. MarkerMap::iterator end = m_markers.end();
  266. for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
  267. // inner loop; process each marker in this node
  268. MarkerList* list = nodeIterator->second;
  269. unsigned markerCount = list->size();
  270. for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
  271. RenderedDocumentMarker& marker = list->at(markerIndex);
  272. // skip marker that is wrong type
  273. if (marker.type() != markerType)
  274. continue;
  275. if (marker.contains(point))
  276. return &marker;
  277. }
  278. }
  279. return 0;
  280. }
  281. Vector<DocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes)
  282. {
  283. Vector<DocumentMarker*> result;
  284. MarkerList* list = m_markers.get(node);
  285. if (!list)
  286. return result;
  287. for (size_t i = 0; i < list->size(); ++i) {
  288. if (markerTypes.contains(list->at(i).type()))
  289. result.append(&(list->at(i)));
  290. }
  291. return result;
  292. }
  293. // FIXME: Should be removed after all relevant patches are landed
  294. Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node)
  295. {
  296. Vector<DocumentMarker> result;
  297. MarkerList* list = m_markers.get(node);
  298. if (!list)
  299. return result;
  300. for (size_t i = 0; i < list->size(); ++i)
  301. result.append(list->at(i));
  302. return result;
  303. }
  304. Vector<DocumentMarker*> DocumentMarkerController::markersInRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
  305. {
  306. if (!possiblyHasMarkers(markerTypes))
  307. return Vector<DocumentMarker*>();
  308. Vector<DocumentMarker*> foundMarkers;
  309. Node* startContainer = range->startContainer();
  310. ASSERT(startContainer);
  311. Node* endContainer = range->endContainer();
  312. ASSERT(endContainer);
  313. Node* pastLastNode = range->pastLastNode();
  314. for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
  315. Vector<DocumentMarker*> markers = markersFor(node);
  316. Vector<DocumentMarker*>::const_iterator end = markers.end();
  317. for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
  318. DocumentMarker* marker = *it;
  319. if (!markerTypes.contains(marker->type()))
  320. continue;
  321. if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
  322. continue;
  323. if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
  324. continue;
  325. foundMarkers.append(marker);
  326. }
  327. }
  328. return foundMarkers;
  329. }
  330. Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType)
  331. {
  332. Vector<IntRect> result;
  333. if (!possiblyHasMarkers(markerType))
  334. return result;
  335. ASSERT(!(m_markers.isEmpty()));
  336. // outer loop: process each node
  337. MarkerMap::iterator end = m_markers.end();
  338. for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
  339. // inner loop; process each marker in this node
  340. MarkerList* list = nodeIterator->second;
  341. unsigned markerCount = list->size();
  342. for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) {
  343. const RenderedDocumentMarker& marker = list->at(markerIndex);
  344. // skip marker that is wrong type
  345. if (marker.type() != markerType)
  346. continue;
  347. if (!marker.isRendered())
  348. continue;
  349. result.append(marker.renderedRect());
  350. }
  351. }
  352. return result;
  353. }
  354. void DocumentMarkerController::removeMarkers(Node* node, DocumentMarker::MarkerTypes markerTypes)
  355. {
  356. if (!possiblyHasMarkers(markerTypes))
  357. return;
  358. ASSERT(!m_markers.isEmpty());
  359. MarkerMap::iterator iterator = m_markers.find(node);
  360. if (iterator != m_markers.end())
  361. removeMarkersFromList(node, iterator->second, markerTypes);
  362. }
  363. void DocumentMarkerController::removeMarkers(DocumentMarker::MarkerTypes markerTypes)
  364. {
  365. if (!possiblyHasMarkers(markerTypes))
  366. return;
  367. ASSERT(!m_markers.isEmpty());
  368. // outer loop: process each markered node in the document
  369. MarkerMap markerMapCopy = m_markers;
  370. MarkerMap::iterator end = markerMapCopy.end();
  371. for (MarkerMap::iterator i = markerMapCopy.begin(); i != end; ++i)
  372. removeMarkersFromList(i->first.get(), i->second, markerTypes);
  373. m_possiblyExistingMarkerTypes.remove(markerTypes);
  374. }
  375. // This function may release node and vectorPair.
  376. void DocumentMarkerController::removeMarkersFromList(Node* node, MarkerList* list, DocumentMarker::MarkerTypes markerTypes)
  377. {
  378. if (markerTypes == DocumentMarker::AllMarkers()) {
  379. delete list;
  380. m_markers.remove(node);
  381. if (RenderObject* renderer = node->renderer())
  382. renderer->repaint();
  383. } else {
  384. bool needsRepaint = false;
  385. for (size_t i = 0; i != list->size();) {
  386. DocumentMarker marker = list->at(i);
  387. // skip nodes that are not of the specified type
  388. if (!markerTypes.contains(marker.type())) {
  389. ++i;
  390. continue;
  391. }
  392. // pitch the old marker
  393. list->remove(i);
  394. needsRepaint = true;
  395. // i now is the index of the next marker
  396. }
  397. // Redraw the node if it changed. Do this before the node is removed from m_markers, since
  398. // m_markers might contain the last reference to the node.
  399. if (needsRepaint) {
  400. RenderObject* renderer = node->renderer();
  401. if (renderer)
  402. renderer->repaint();
  403. }
  404. // delete the node's list if it is now empty
  405. if (list->isEmpty()) {
  406. m_markers.remove(node);
  407. delete list;
  408. }
  409. }
  410. if (m_markers.isEmpty())
  411. m_possiblyExistingMarkerTypes = 0;
  412. }
  413. void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes)
  414. {
  415. if (!possiblyHasMarkers(markerTypes))
  416. return;
  417. ASSERT(!m_markers.isEmpty());
  418. // outer loop: process each markered node in the document
  419. MarkerMap::iterator end = m_markers.end();
  420. for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
  421. Node* node = i->first.get();
  422. // inner loop: process each marker in the current node
  423. MarkerList* list = i->second;
  424. bool nodeNeedsRepaint = false;
  425. for (size_t i = 0; i != list->size(); ++i) {
  426. DocumentMarker marker = list->at(i);
  427. // skip nodes that are not of the specified type
  428. if (markerTypes.contains(marker.type())) {
  429. nodeNeedsRepaint = true;
  430. break;
  431. }
  432. }
  433. if (!nodeNeedsRepaint)
  434. continue;
  435. // cause the node to be redrawn
  436. if (RenderObject* renderer = node->renderer())
  437. renderer->repaint();
  438. }
  439. }
  440. void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect& r)
  441. {
  442. // outer loop: process each markered node in the document
  443. MarkerMap::iterator end = m_markers.end();
  444. for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) {
  445. // inner loop: process each rect in the current node
  446. MarkerList* list = i->second;
  447. for (size_t listIndex = 0; listIndex < list->size(); ++listIndex)
  448. list->at(listIndex).invalidate(r);
  449. }
  450. }
  451. void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta)
  452. {
  453. if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
  454. return;
  455. ASSERT(!m_markers.isEmpty());
  456. MarkerList* list = m_markers.get(node);
  457. if (!list)
  458. return;
  459. bool docDirty = false;
  460. for (size_t i = 0; i != list->size(); ++i) {
  461. RenderedDocumentMarker& marker = list->at(i);
  462. if (marker.startOffset() >= startOffset) {
  463. ASSERT((int)marker.startOffset() + delta >= 0);
  464. marker.shiftOffsets(delta);
  465. docDirty = true;
  466. // Marker moved, so previously-computed rendered rectangle is now invalid
  467. marker.invalidate();
  468. }
  469. }
  470. // repaint the affected node
  471. if (docDirty && node->renderer())
  472. node->renderer()->repaint();
  473. }
  474. void DocumentMarkerController::setMarkersActive(Range* range, bool active)
  475. {
  476. if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
  477. return;
  478. ASSERT(!m_markers.isEmpty());
  479. ExceptionCode ec = 0;
  480. Node* startContainer = range->startContainer(ec);
  481. Node* endContainer = range->endContainer(ec);
  482. Node* pastLastNode = range->pastLastNode();
  483. for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
  484. int startOffset = node == startContainer ? range->startOffset(ec) : 0;
  485. int endOffset = node == endContainer ? range->endOffset(ec) : INT_MAX;
  486. setMarkersActive(node, startOffset, endOffset, active);
  487. }
  488. }
  489. void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
  490. {
  491. MarkerList* list = m_markers.get(node);
  492. if (!list)
  493. return;
  494. bool docDirty = false;
  495. for (size_t i = 0; i != list->size(); ++i) {
  496. DocumentMarker& marker = list->at(i);
  497. // Markers are returned in order, so stop if we are now past the specified range.
  498. if (marker.startOffset() >= endOffset)
  499. break;
  500. // Skip marker that is wrong type or before target.
  501. if (marker.endOffset() < startOffset || marker.type() != DocumentMarker::TextMatch)
  502. continue;
  503. marker.setActiveMatch(active);
  504. docDirty = true;
  505. }
  506. // repaint the affected node
  507. if (docDirty && node->renderer())
  508. node->renderer()->repaint();
  509. }
  510. bool DocumentMarkerController::hasMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes)
  511. {
  512. if (!possiblyHasMarkers(markerTypes))
  513. return false;
  514. ASSERT(!m_markers.isEmpty());
  515. Node* startContainer = range->startContainer();
  516. ASSERT(startContainer);
  517. Node* endContainer = range->endContainer();
  518. ASSERT(endContainer);
  519. Node* pastLastNode = range->pastLastNode();
  520. for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
  521. Vector<DocumentMarker*> markers = markersFor(node);
  522. Vector<DocumentMarker*>::const_iterator end = markers.end();
  523. for (Vector<DocumentMarker*>::const_iterator it = markers.begin(); it != end; ++it) {
  524. DocumentMarker* marker = *it;
  525. if (!markerTypes.contains(marker->type()))
  526. continue;
  527. if (node == startContainer && marker->endOffset() <= static_cast<unsigned>(range->startOffset()))
  528. continue;
  529. if (node == endContainer && marker->startOffset() >= static_cast<unsigned>(range->endOffset()))
  530. continue;
  531. return true;
  532. }
  533. }
  534. return false;
  535. }
  536. void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes)
  537. {
  538. if (!possiblyHasMarkers(markerTypes))
  539. return;
  540. ASSERT(!m_markers.isEmpty());
  541. Node* startContainer = range->startContainer();
  542. Node* endContainer = range->endContainer();
  543. Node* pastLastNode = range->pastLastNode();
  544. for (Node* node = range->firstNode(); node != pastLastNode; node = node->traverseNextNode()) {
  545. unsigned startOffset = node == startContainer ? range->startOffset() : 0;
  546. unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max();
  547. MarkerList* list = m_markers.get(node);
  548. if (!list)
  549. continue;
  550. for (size_t i = 0; i < list->size(); ++i) {
  551. DocumentMarker& marker = list->at(i);
  552. // markers are returned in order, so stop if we are now past the specified range
  553. if (marker.startOffset() >= endOffset)
  554. break;
  555. // skip marker that is wrong type or before target
  556. if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) {
  557. i++;
  558. continue;
  559. }
  560. marker.clearDetails();
  561. }
  562. }
  563. }
  564. #ifndef NDEBUG
  565. void DocumentMarkerController::showMarkers() const
  566. {
  567. fprintf(stderr, "%d nodes have markers:\n", m_markers.size());
  568. MarkerMap::const_iterator end = m_markers.end();
  569. for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) {
  570. Node* node = nodeIterator->first.get();
  571. fprintf(stderr, "%p", node);
  572. MarkerList* list = nodeIterator->second;
  573. for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) {
  574. const DocumentMarker& marker = list->at(markerIndex);
  575. fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset(), marker.endOffset(), marker.activeMatch());
  576. }
  577. fprintf(stderr, "\n");
  578. }
  579. }
  580. #endif
  581. } // namespace WebCore
  582. #ifndef NDEBUG
  583. void showDocumentMarkers(const WebCore::DocumentMarkerController* controller)
  584. {
  585. if (controller)
  586. controller->showMarkers();
  587. }
  588. #endif