| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
| 3 * Copyright (C) 2005 Alexey Proskuryakov. | 3 * Copyright (C) 2005 Alexey Proskuryakov. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1370 PassRefPtr<Range> CharacterIterator::range() const | 1370 PassRefPtr<Range> CharacterIterator::range() const |
| 1371 { | 1371 { |
| 1372 RefPtr<Range> r = m_textIterator.range(); | 1372 RefPtr<Range> r = m_textIterator.range(); |
| 1373 if (!m_textIterator.atEnd()) { | 1373 if (!m_textIterator.atEnd()) { |
| 1374 if (m_textIterator.length() <= 1) { | 1374 if (m_textIterator.length() <= 1) { |
| 1375 ASSERT(m_runOffset == 0); | 1375 ASSERT(m_runOffset == 0); |
| 1376 } else { | 1376 } else { |
| 1377 Node* n = r->startContainer(); | 1377 Node* n = r->startContainer(); |
| 1378 ASSERT(n == r->endContainer()); | 1378 ASSERT(n == r->endContainer()); |
| 1379 int offset = r->startOffset() + m_runOffset; | 1379 int offset = r->startOffset() + m_runOffset; |
| 1380 r->setStart(n, offset, ASSERT_NO_EXCEPTION_STATE); | 1380 r->setStart(n, offset, ASSERT_NO_EXCEPTION); |
| 1381 r->setEnd(n, offset + 1, ASSERT_NO_EXCEPTION_STATE); | 1381 r->setEnd(n, offset + 1, ASSERT_NO_EXCEPTION); |
| 1382 } | 1382 } |
| 1383 } | 1383 } |
| 1384 return r.release(); | 1384 return r.release(); |
| 1385 } | 1385 } |
| 1386 | 1386 |
| 1387 void CharacterIterator::advance(int count) | 1387 void CharacterIterator::advance(int count) |
| 1388 { | 1388 { |
| 1389 if (count <= 0) { | 1389 if (count <= 0) { |
| 1390 ASSERT(count == 0); | 1390 ASSERT(count == 0); |
| 1391 return; | 1391 return; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 PassRefPtr<Range> BackwardsCharacterIterator::range() const | 1469 PassRefPtr<Range> BackwardsCharacterIterator::range() const |
| 1470 { | 1470 { |
| 1471 RefPtr<Range> r = m_textIterator.range(); | 1471 RefPtr<Range> r = m_textIterator.range(); |
| 1472 if (!m_textIterator.atEnd()) { | 1472 if (!m_textIterator.atEnd()) { |
| 1473 if (m_textIterator.length() <= 1) | 1473 if (m_textIterator.length() <= 1) |
| 1474 ASSERT(m_runOffset == 0); | 1474 ASSERT(m_runOffset == 0); |
| 1475 else { | 1475 else { |
| 1476 Node* n = r->startContainer(); | 1476 Node* n = r->startContainer(); |
| 1477 ASSERT(n == r->endContainer()); | 1477 ASSERT(n == r->endContainer()); |
| 1478 int offset = r->endOffset() - m_runOffset; | 1478 int offset = r->endOffset() - m_runOffset; |
| 1479 r->setStart(n, offset - 1, ASSERT_NO_EXCEPTION_STATE); | 1479 r->setStart(n, offset - 1, ASSERT_NO_EXCEPTION); |
| 1480 r->setEnd(n, offset, ASSERT_NO_EXCEPTION_STATE); | 1480 r->setEnd(n, offset, ASSERT_NO_EXCEPTION); |
| 1481 } | 1481 } |
| 1482 } | 1482 } |
| 1483 return r.release(); | 1483 return r.release(); |
| 1484 } | 1484 } |
| 1485 | 1485 |
| 1486 void BackwardsCharacterIterator::advance(int count) | 1486 void BackwardsCharacterIterator::advance(int count) |
| 1487 { | 1487 { |
| 1488 if (count <= 0) { | 1488 if (count <= 0) { |
| 1489 ASSERT(!count); | 1489 ASSERT(!count); |
| 1490 return; | 1490 return; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 | 1568 |
| 1569 // Look ahead to next chunk. If it is whitespace or a break, we can use
the previous stuff | 1569 // Look ahead to next chunk. If it is whitespace or a break, we can use
the previous stuff |
| 1570 m_textIterator.advance(); | 1570 m_textIterator.advance(); |
| 1571 if (m_textIterator.atEnd() || !m_textIterator.length() || isSpaceOrNewli
ne(m_textIterator.characterAt(0))) { | 1571 if (m_textIterator.atEnd() || !m_textIterator.length() || isSpaceOrNewli
ne(m_textIterator.characterAt(0))) { |
| 1572 m_didLookAhead = true; | 1572 m_didLookAhead = true; |
| 1573 return; | 1573 return; |
| 1574 } | 1574 } |
| 1575 | 1575 |
| 1576 // Start gobbling chunks until we get to a suitable stopping point | 1576 // Start gobbling chunks until we get to a suitable stopping point |
| 1577 m_textIterator.appendTextTo(m_buffer); | 1577 m_textIterator.appendTextTo(m_buffer); |
| 1578 m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.r
ange()->endOffset(), IGNORE_EXCEPTION_STATE); | 1578 m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.r
ange()->endOffset(), IGNORE_EXCEPTION); |
| 1579 } | 1579 } |
| 1580 } | 1580 } |
| 1581 | 1581 |
| 1582 int WordAwareIterator::length() const | 1582 int WordAwareIterator::length() const |
| 1583 { | 1583 { |
| 1584 if (!m_buffer.isEmpty()) | 1584 if (!m_buffer.isEmpty()) |
| 1585 return m_buffer.size(); | 1585 return m_buffer.size(); |
| 1586 return m_textIterator.length(); | 1586 return m_textIterator.length(); |
| 1587 } | 1587 } |
| 1588 | 1588 |
| (...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 bool startRangeFound = false; | 2239 bool startRangeFound = false; |
| 2240 | 2240 |
| 2241 RefPtr<Range> textRunRange; | 2241 RefPtr<Range> textRunRange; |
| 2242 | 2242 |
| 2243 TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation ? Tex
tIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior
); | 2243 TextIterator it(rangeOfContents(scope).get(), forSelectionPreservation ? Tex
tIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior
); |
| 2244 | 2244 |
| 2245 // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://b
ugs.webkit.org/show_bug.cgi?id=6289>. | 2245 // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://b
ugs.webkit.org/show_bug.cgi?id=6289>. |
| 2246 if (rangeLocation == 0 && rangeLength == 0 && it.atEnd()) { | 2246 if (rangeLocation == 0 && rangeLength == 0 && it.atEnd()) { |
| 2247 textRunRange = it.range(); | 2247 textRunRange = it.range(); |
| 2248 | 2248 |
| 2249 resultRange->setStart(textRunRange->startContainer(), 0, ASSERT_NO_EXCEP
TION_STATE); | 2249 resultRange->setStart(textRunRange->startContainer(), 0, ASSERT_NO_EXCEP
TION); |
| 2250 resultRange->setEnd(textRunRange->startContainer(), 0, ASSERT_NO_EXCEPTI
ON_STATE); | 2250 resultRange->setEnd(textRunRange->startContainer(), 0, ASSERT_NO_EXCEPTI
ON); |
| 2251 | 2251 |
| 2252 return resultRange.release(); | 2252 return resultRange.release(); |
| 2253 } | 2253 } |
| 2254 | 2254 |
| 2255 for (; !it.atEnd(); it.advance()) { | 2255 for (; !it.atEnd(); it.advance()) { |
| 2256 int len = it.length(); | 2256 int len = it.length(); |
| 2257 textRunRange = it.range(); | 2257 textRunRange = it.range(); |
| 2258 | 2258 |
| 2259 bool foundStart = rangeLocation >= docTextPosition && rangeLocation <= d
ocTextPosition + len; | 2259 bool foundStart = rangeLocation >= docTextPosition && rangeLocation <= d
ocTextPosition + len; |
| 2260 bool foundEnd = rangeEnd >= docTextPosition && rangeEnd <= docTextPositi
on + len; | 2260 bool foundEnd = rangeEnd >= docTextPosition && rangeEnd <= docTextPositi
on + len; |
| 2261 | 2261 |
| 2262 // Fix textRunRange->endPosition(), but only if foundStart || foundEnd,
because it is only | 2262 // Fix textRunRange->endPosition(), but only if foundStart || foundEnd,
because it is only |
| 2263 // in those cases that textRunRange is used. | 2263 // in those cases that textRunRange is used. |
| 2264 if (foundEnd) { | 2264 if (foundEnd) { |
| 2265 // FIXME: This is a workaround for the fact that the end of a run is
often at the wrong | 2265 // FIXME: This is a workaround for the fact that the end of a run is
often at the wrong |
| 2266 // position for emitted '\n's. | 2266 // position for emitted '\n's. |
| 2267 if (len == 1 && it.characterAt(0) == '\n') { | 2267 if (len == 1 && it.characterAt(0) == '\n') { |
| 2268 scope->document()->updateLayoutIgnorePendingStylesheets(); | 2268 scope->document()->updateLayoutIgnorePendingStylesheets(); |
| 2269 it.advance(); | 2269 it.advance(); |
| 2270 if (!it.atEnd()) { | 2270 if (!it.atEnd()) { |
| 2271 RefPtr<Range> range = it.range(); | 2271 RefPtr<Range> range = it.range(); |
| 2272 textRunRange->setEnd(range->startContainer(), range->startOf
fset(), ASSERT_NO_EXCEPTION_STATE); | 2272 textRunRange->setEnd(range->startContainer(), range->startOf
fset(), ASSERT_NO_EXCEPTION); |
| 2273 } else { | 2273 } else { |
| 2274 Position runStart = textRunRange->startPosition(); | 2274 Position runStart = textRunRange->startPosition(); |
| 2275 Position runEnd = VisiblePosition(runStart).next().deepEquiv
alent(); | 2275 Position runEnd = VisiblePosition(runStart).next().deepEquiv
alent(); |
| 2276 if (runEnd.isNotNull()) | 2276 if (runEnd.isNotNull()) |
| 2277 textRunRange->setEnd(runEnd.containerNode(), runEnd.comp
uteOffsetInContainerNode(), ASSERT_NO_EXCEPTION_STATE); | 2277 textRunRange->setEnd(runEnd.containerNode(), runEnd.comp
uteOffsetInContainerNode(), ASSERT_NO_EXCEPTION); |
| 2278 } | 2278 } |
| 2279 } | 2279 } |
| 2280 } | 2280 } |
| 2281 | 2281 |
| 2282 if (foundStart) { | 2282 if (foundStart) { |
| 2283 startRangeFound = true; | 2283 startRangeFound = true; |
| 2284 if (textRunRange->startContainer()->isTextNode()) { | 2284 if (textRunRange->startContainer()->isTextNode()) { |
| 2285 int offset = rangeLocation - docTextPosition; | 2285 int offset = rangeLocation - docTextPosition; |
| 2286 resultRange->setStart(textRunRange->startContainer(), offset + t
extRunRange->startOffset(), IGNORE_EXCEPTION_STATE); | 2286 resultRange->setStart(textRunRange->startContainer(), offset + t
extRunRange->startOffset(), IGNORE_EXCEPTION); |
| 2287 } else { | 2287 } else { |
| 2288 if (rangeLocation == docTextPosition) | 2288 if (rangeLocation == docTextPosition) |
| 2289 resultRange->setStart(textRunRange->startContainer(), textRu
nRange->startOffset(), IGNORE_EXCEPTION_STATE); | 2289 resultRange->setStart(textRunRange->startContainer(), textRu
nRange->startOffset(), IGNORE_EXCEPTION); |
| 2290 else | 2290 else |
| 2291 resultRange->setStart(textRunRange->endContainer(), textRunR
ange->endOffset(), IGNORE_EXCEPTION_STATE); | 2291 resultRange->setStart(textRunRange->endContainer(), textRunR
ange->endOffset(), IGNORE_EXCEPTION); |
| 2292 } | 2292 } |
| 2293 } | 2293 } |
| 2294 | 2294 |
| 2295 if (foundEnd) { | 2295 if (foundEnd) { |
| 2296 if (textRunRange->startContainer()->isTextNode()) { | 2296 if (textRunRange->startContainer()->isTextNode()) { |
| 2297 int offset = rangeEnd - docTextPosition; | 2297 int offset = rangeEnd - docTextPosition; |
| 2298 resultRange->setEnd(textRunRange->startContainer(), offset + tex
tRunRange->startOffset(), IGNORE_EXCEPTION_STATE); | 2298 resultRange->setEnd(textRunRange->startContainer(), offset + tex
tRunRange->startOffset(), IGNORE_EXCEPTION); |
| 2299 } else { | 2299 } else { |
| 2300 if (rangeEnd == docTextPosition) | 2300 if (rangeEnd == docTextPosition) |
| 2301 resultRange->setEnd(textRunRange->startContainer(), textRunR
ange->startOffset(), IGNORE_EXCEPTION_STATE); | 2301 resultRange->setEnd(textRunRange->startContainer(), textRunR
ange->startOffset(), IGNORE_EXCEPTION); |
| 2302 else | 2302 else |
| 2303 resultRange->setEnd(textRunRange->endContainer(), textRunRan
ge->endOffset(), IGNORE_EXCEPTION_STATE); | 2303 resultRange->setEnd(textRunRange->endContainer(), textRunRan
ge->endOffset(), IGNORE_EXCEPTION); |
| 2304 } | 2304 } |
| 2305 docTextPosition += len; | 2305 docTextPosition += len; |
| 2306 break; | 2306 break; |
| 2307 } | 2307 } |
| 2308 docTextPosition += len; | 2308 docTextPosition += len; |
| 2309 } | 2309 } |
| 2310 | 2310 |
| 2311 if (!startRangeFound) | 2311 if (!startRangeFound) |
| 2312 return 0; | 2312 return 0; |
| 2313 | 2313 |
| 2314 if (rangeLength != 0 && rangeEnd > docTextPosition) { // rangeEnd is out of
bounds | 2314 if (rangeLength != 0 && rangeEnd > docTextPosition) { // rangeEnd is out of
bounds |
| 2315 resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffse
t(), IGNORE_EXCEPTION_STATE); | 2315 resultRange->setEnd(textRunRange->endContainer(), textRunRange->endOffse
t(), IGNORE_EXCEPTION); |
| 2316 } | 2316 } |
| 2317 | 2317 |
| 2318 return resultRange.release(); | 2318 return resultRange.release(); |
| 2319 } | 2319 } |
| 2320 | 2320 |
| 2321 bool TextIterator::getLocationAndLengthFromRange(Node* scope, const Range* range
, size_t& location, size_t& length) | 2321 bool TextIterator::getLocationAndLengthFromRange(Node* scope, const Range* range
, size_t& location, size_t& length) |
| 2322 { | 2322 { |
| 2323 location = notFound; | 2323 location = notFound; |
| 2324 length = 0; | 2324 length = 0; |
| 2325 | 2325 |
| 2326 if (!range->startContainer()) | 2326 if (!range->startContainer()) |
| 2327 return false; | 2327 return false; |
| 2328 | 2328 |
| 2329 // The critical assumption is that this only gets called with ranges that | 2329 // The critical assumption is that this only gets called with ranges that |
| 2330 // concentrate on a given area containing the selection root. This is done | 2330 // concentrate on a given area containing the selection root. This is done |
| 2331 // because of text fields and textareas. The DOM for those is not | 2331 // because of text fields and textareas. The DOM for those is not |
| 2332 // directly in the document DOM, so ensure that the range does not cross a | 2332 // directly in the document DOM, so ensure that the range does not cross a |
| 2333 // boundary of one of those. | 2333 // boundary of one of those. |
| 2334 if (range->startContainer() != scope && !range->startContainer()->isDescenda
ntOf(scope)) | 2334 if (range->startContainer() != scope && !range->startContainer()->isDescenda
ntOf(scope)) |
| 2335 return false; | 2335 return false; |
| 2336 if (range->endContainer() != scope && !range->endContainer()->isDescendantOf
(scope)) | 2336 if (range->endContainer() != scope && !range->endContainer()->isDescendantOf
(scope)) |
| 2337 return false; | 2337 return false; |
| 2338 | 2338 |
| 2339 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->
startContainer(), range->startOffset()); | 2339 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->
startContainer(), range->startOffset()); |
| 2340 ASSERT(testRange->startContainer() == scope); | 2340 ASSERT(testRange->startContainer() == scope); |
| 2341 location = TextIterator::rangeLength(testRange.get()); | 2341 location = TextIterator::rangeLength(testRange.get()); |
| 2342 | 2342 |
| 2343 testRange->setEnd(range->endContainer(), range->endOffset(), IGNORE_EXCEPTIO
N_STATE); | 2343 testRange->setEnd(range->endContainer(), range->endOffset(), IGNORE_EXCEPTIO
N); |
| 2344 ASSERT(testRange->startContainer() == scope); | 2344 ASSERT(testRange->startContainer() == scope); |
| 2345 length = TextIterator::rangeLength(testRange.get()) - location; | 2345 length = TextIterator::rangeLength(testRange.get()) - location; |
| 2346 return true; | 2346 return true; |
| 2347 } | 2347 } |
| 2348 | 2348 |
| 2349 // -------- | 2349 // -------- |
| 2350 | 2350 |
| 2351 String plainText(const Range* r, TextIteratorBehavior defaultBehavior, bool isDi
splayString) | 2351 String plainText(const Range* r, TextIteratorBehavior defaultBehavior, bool isDi
splayString) |
| 2352 { | 2352 { |
| 2353 // The initial buffer size can be critical for performance: https://bugs.web
kit.org/show_bug.cgi?id=81192 | 2353 // The initial buffer size can be critical for performance: https://bugs.web
kit.org/show_bug.cgi?id=81192 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2371 String result = builder.toString(); | 2371 String result = builder.toString(); |
| 2372 | 2372 |
| 2373 if (isDisplayString && r->ownerDocument()) | 2373 if (isDisplayString && r->ownerDocument()) |
| 2374 r->ownerDocument()->displayStringModifiedByEncoding(result); | 2374 r->ownerDocument()->displayStringModifiedByEncoding(result); |
| 2375 | 2375 |
| 2376 return result; | 2376 return result; |
| 2377 } | 2377 } |
| 2378 | 2378 |
| 2379 static PassRefPtr<Range> collapsedToBoundary(const Range* range, bool forward) | 2379 static PassRefPtr<Range> collapsedToBoundary(const Range* range, bool forward) |
| 2380 { | 2380 { |
| 2381 RefPtr<Range> result = range->cloneRange(ASSERT_NO_EXCEPTION_STATE); | 2381 RefPtr<Range> result = range->cloneRange(ASSERT_NO_EXCEPTION); |
| 2382 result->collapse(!forward, ASSERT_NO_EXCEPTION_STATE); | 2382 result->collapse(!forward, ASSERT_NO_EXCEPTION); |
| 2383 return result.release(); | 2383 return result.release(); |
| 2384 } | 2384 } |
| 2385 | 2385 |
| 2386 static size_t findPlainText(CharacterIterator& it, const String& target, FindOpt
ions options, size_t& matchStart) | 2386 static size_t findPlainText(CharacterIterator& it, const String& target, FindOpt
ions options, size_t& matchStart) |
| 2387 { | 2387 { |
| 2388 matchStart = 0; | 2388 matchStart = 0; |
| 2389 size_t matchLength = 0; | 2389 size_t matchLength = 0; |
| 2390 | 2390 |
| 2391 SearchBuffer buffer(target, options); | 2391 SearchBuffer buffer(target, options); |
| 2392 | 2392 |
| 2393 if (buffer.needsMoreContext()) { | 2393 if (buffer.needsMoreContext()) { |
| 2394 RefPtr<Range> startRange = it.range(); | 2394 RefPtr<Range> startRange = it.range(); |
| 2395 RefPtr<Range> beforeStartRange = startRange->ownerDocument()->createRang
e(); | 2395 RefPtr<Range> beforeStartRange = startRange->ownerDocument()->createRang
e(); |
| 2396 beforeStartRange->setEnd(startRange->startContainer(), startRange->start
Offset(), IGNORE_EXCEPTION_STATE); | 2396 beforeStartRange->setEnd(startRange->startContainer(), startRange->start
Offset(), IGNORE_EXCEPTION); |
| 2397 for (SimplifiedBackwardsTextIterator backwardsIterator(beforeStartRange.
get()); !backwardsIterator.atEnd(); backwardsIterator.advance()) { | 2397 for (SimplifiedBackwardsTextIterator backwardsIterator(beforeStartRange.
get()); !backwardsIterator.atEnd(); backwardsIterator.advance()) { |
| 2398 Vector<UChar, 1024> characters; | 2398 Vector<UChar, 1024> characters; |
| 2399 backwardsIterator.prependTextTo(characters); | 2399 backwardsIterator.prependTextTo(characters); |
| 2400 buffer.prependContext(characters.data(), characters.size()); | 2400 buffer.prependContext(characters.data(), characters.size()); |
| 2401 if (!buffer.needsMoreContext()) | 2401 if (!buffer.needsMoreContext()) |
| 2402 break; | 2402 break; |
| 2403 } | 2403 } |
| 2404 } | 2404 } |
| 2405 | 2405 |
| 2406 while (!it.atEnd()) { | 2406 while (!it.atEnd()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2443 if (!matchLength) | 2443 if (!matchLength) |
| 2444 return collapsedToBoundary(range, !(options & Backwards)); | 2444 return collapsedToBoundary(range, !(options & Backwards)); |
| 2445 } | 2445 } |
| 2446 | 2446 |
| 2447 // Then, find the document position of the start and the end of the text. | 2447 // Then, find the document position of the start and the end of the text. |
| 2448 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls
); | 2448 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls
); |
| 2449 return characterSubrange(computeRangeIterator, matchStart, matchLength); | 2449 return characterSubrange(computeRangeIterator, matchStart, matchLength); |
| 2450 } | 2450 } |
| 2451 | 2451 |
| 2452 } | 2452 } |
| OLD | NEW |