1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "core/editing/VisiblePosition.h" 29 30 #include "bindings/v8/ExceptionState.h" 31 #include "core/HTMLNames.h" 32 #include "core/dom/Document.h" 33 #include "core/dom/Range.h" 34 #include "core/dom/Text.h" 35 #include "core/editing/VisibleUnits.h" 36 #include "core/editing/htmlediting.h" 37 #include "core/html/HTMLElement.h" 38 #include "core/rendering/RenderBlock.h" 39 #include "core/rendering/RootInlineBox.h" 40 #include "platform/geometry/FloatQuad.h" 41 #include "wtf/text/CString.h" 42 43 #ifndef NDEBUG 44 #include <stdio.h> 45 #endif 46 47 namespace WebCore { 48 49 using namespace HTMLNames; 50 51 VisiblePosition::VisiblePosition(const Position &pos, EAffinity affinity) 52 { 53 init(pos, affinity); 54 } 55 56 VisiblePosition::VisiblePosition(const PositionWithAffinity& positionWithAffinity) 57 { 58 init(positionWithAffinity.position(), positionWithAffinity.affinity()); 59 } 60 61 void VisiblePosition::init(const Position& position, EAffinity affinity) 62 { 63 m_affinity = affinity; 64 65 m_deepPosition = canonicalPosition(position); 66 67 // When not at a line wrap, make sure to end up with DOWNSTREAM affinity. 68 if (m_affinity == UPSTREAM && (isNull() || inSameLine(VisiblePosition(position, DOWNSTREAM), *this))) 69 m_affinity = DOWNSTREAM; 70 } 71 72 VisiblePosition VisiblePosition::next(EditingBoundaryCrossingRule rule) const 73 { 74 VisiblePosition next(nextVisuallyDistinctCandidate(m_deepPosition), m_affinity); 75 76 switch (rule) { 77 case CanCrossEditingBoundary: 78 return next; 79 case CannotCrossEditingBoundary: 80 return honorEditingBoundaryAtOrAfter(next); 81 case CanSkipOverEditingBoundary: 82 return skipToEndOfEditingBoundary(next); 83 } 84 ASSERT_NOT_REACHED(); 85 return honorEditingBoundaryAtOrAfter(next); 86 } 87 88 VisiblePosition VisiblePosition::previous(EditingBoundaryCrossingRule rule) const 89 { 90 Position pos = previousVisuallyDistinctCandidate(m_deepPosition); 91 92 // return null visible position if there is no previous visible position 93 if (pos.atStartOfTree()) 94 return VisiblePosition(); 95 96 VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM); 97 ASSERT(prev != *this); 98 99 #ifndef NDEBUG 100 // we should always be able to make the affinity DOWNSTREAM, because going previous from an 101 // UPSTREAM position can never yield another UPSTREAM position (unless line wrap length is 0!). 102 if (prev.isNotNull() && m_affinity == UPSTREAM) { 103 VisiblePosition temp = prev; 104 temp.setAffinity(UPSTREAM); 105 ASSERT(inSameLine(temp, prev)); 106 } 107 #endif 108 109 switch (rule) { 110 case CanCrossEditingBoundary: 111 return prev; 112 case CannotCrossEditingBoundary: 113 return honorEditingBoundaryAtOrBefore(prev); 114 case CanSkipOverEditingBoundary: 115 return skipToStartOfEditingBoundary(prev); 116 } 117 118 ASSERT_NOT_REACHED(); 119 return honorEditingBoundaryAtOrBefore(prev); 120 } 121 122 Position VisiblePosition::leftVisuallyDistinctCandidate() const 123 { 124 Position p = m_deepPosition; 125 if (p.isNull()) 126 return Position(); 127 128 Position downstreamStart = p.downstream(); 129 TextDirection primaryDirection = p.primaryDirection(); 130 131 while (true) { 132 InlineBox* box; 133 int offset; 134 p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset); 135 if (!box) 136 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); 137 138 RenderObject* renderer = &box->renderer(); 139 140 while (true) { 141 if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset()) 142 return box->isLeftToRightDirection() ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); 143 144 if (!renderer->node()) { 145 box = box->prevLeafChild(); 146 if (!box) 147 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); 148 renderer = &box->renderer(); 149 offset = box->caretRightmostOffset(); 150 continue; 151 } 152 153 offset = box->isLeftToRightDirection() ? renderer->previousOffset(offset) : renderer->nextOffset(offset); 154 155 int caretMinOffset = box->caretMinOffset(); 156 int caretMaxOffset = box->caretMaxOffset(); 157 158 if (offset > caretMinOffset && offset < caretMaxOffset) 159 break; 160 161 if (box->isLeftToRightDirection() ? offset < caretMinOffset : offset > caretMaxOffset) { 162 // Overshot to the left. 163 InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak(); 164 if (!prevBox) { 165 Position positionOnLeft = primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition); 166 if (positionOnLeft.isNull()) 167 return Position(); 168 169 InlineBox* boxOnLeft; 170 int offsetOnLeft; 171 positionOnLeft.getInlineBoxAndOffset(m_affinity, primaryDirection, boxOnLeft, offsetOnLeft); 172 if (boxOnLeft && boxOnLeft->root() == box->root()) 173 return Position(); 174 return positionOnLeft; 175 } 176 177 // Reposition at the other logical position corresponding to our edge's visual position and go for another round. 178 box = prevBox; 179 renderer = &box->renderer(); 180 offset = prevBox->caretRightmostOffset(); 181 continue; 182 } 183 184 ASSERT(offset == box->caretLeftmostOffset()); 185 186 unsigned char level = box->bidiLevel(); 187 InlineBox* prevBox = box->prevLeafChild(); 188 189 if (box->direction() == primaryDirection) { 190 if (!prevBox) { 191 InlineBox* logicalStart = 0; 192 if (primaryDirection == LTR ? box->root().getLogicalStartBoxWithNode(logicalStart) : box->root().getLogicalEndBoxWithNode(logicalStart)) { 193 box = logicalStart; 194 renderer = &box->renderer(); 195 offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset(); 196 } 197 break; 198 } 199 if (prevBox->bidiLevel() >= level) 200 break; 201 202 level = prevBox->bidiLevel(); 203 204 InlineBox* nextBox = box; 205 do { 206 nextBox = nextBox->nextLeafChild(); 207 } while (nextBox && nextBox->bidiLevel() > level); 208 209 if (nextBox && nextBox->bidiLevel() == level) 210 break; 211 212 box = prevBox; 213 renderer = &box->renderer(); 214 offset = box->caretRightmostOffset(); 215 if (box->direction() == primaryDirection) 216 break; 217 continue; 218 } 219 220 while (prevBox && !prevBox->renderer().node()) 221 prevBox = prevBox->prevLeafChild(); 222 223 if (prevBox) { 224 box = prevBox; 225 renderer = &box->renderer(); 226 offset = box->caretRightmostOffset(); 227 if (box->bidiLevel() > level) { 228 do { 229 prevBox = prevBox->prevLeafChild(); 230 } while (prevBox && prevBox->bidiLevel() > level); 231 232 if (!prevBox || prevBox->bidiLevel() < level) 233 continue; 234 } 235 } else { 236 // Trailing edge of a secondary run. Set to the leading edge of the entire run. 237 while (true) { 238 while (InlineBox* nextBox = box->nextLeafChild()) { 239 if (nextBox->bidiLevel() < level) 240 break; 241 box = nextBox; 242 } 243 if (box->bidiLevel() == level) 244 break; 245 level = box->bidiLevel(); 246 while (InlineBox* prevBox = box->prevLeafChild()) { 247 if (prevBox->bidiLevel() < level) 248 break; 249 box = prevBox; 250 } 251 if (box->bidiLevel() == level) 252 break; 253 level = box->bidiLevel(); 254 } 255 renderer = &box->renderer(); 256 offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset(); 257 } 258 break; 259 } 260 261 p = createLegacyEditingPosition(renderer->node(), offset); 262 263 if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) 264 return p; 265 266 ASSERT(p != m_deepPosition); 267 } 268 } 269 270 VisiblePosition VisiblePosition::left(bool stayInEditableContent) const 271 { 272 Position pos = leftVisuallyDistinctCandidate(); 273 // FIXME: Why can't we move left from the last position in a tree? 274 if (pos.atStartOfTree() || pos.atEndOfTree()) 275 return VisiblePosition(); 276 277 VisiblePosition left = VisiblePosition(pos, DOWNSTREAM); 278 ASSERT(left != *this); 279 280 if (!stayInEditableContent) 281 return left; 282 283 // FIXME: This may need to do something different from "before". 284 return honorEditingBoundaryAtOrBefore(left); 285 } 286 287 Position VisiblePosition::rightVisuallyDistinctCandidate() const 288 { 289 Position p = m_deepPosition; 290 if (p.isNull()) 291 return Position(); 292 293 Position downstreamStart = p.downstream(); 294 TextDirection primaryDirection = p.primaryDirection(); 295 296 while (true) { 297 InlineBox* box; 298 int offset; 299 p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset); 300 if (!box) 301 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); 302 303 RenderObject* renderer = &box->renderer(); 304 305 while (true) { 306 if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset()) 307 return box->isLeftToRightDirection() ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); 308 309 if (!renderer->node()) { 310 box = box->nextLeafChild(); 311 if (!box) 312 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); 313 renderer = &box->renderer(); 314 offset = box->caretLeftmostOffset(); 315 continue; 316 } 317 318 offset = box->isLeftToRightDirection() ? renderer->nextOffset(offset) : renderer->previousOffset(offset); 319 320 int caretMinOffset = box->caretMinOffset(); 321 int caretMaxOffset = box->caretMaxOffset(); 322 323 if (offset > caretMinOffset && offset < caretMaxOffset) 324 break; 325 326 if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset < caretMinOffset) { 327 // Overshot to the right. 328 InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); 329 if (!nextBox) { 330 Position positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); 331 if (positionOnRight.isNull()) 332 return Position(); 333 334 InlineBox* boxOnRight; 335 int offsetOnRight; 336 positionOnRight.getInlineBoxAndOffset(m_affinity, primaryDirection, boxOnRight, offsetOnRight); 337 if (boxOnRight && boxOnRight->root() == box->root()) 338 return Position(); 339 return positionOnRight; 340 } 341 342 // Reposition at the other logical position corresponding to our edge's visual position and go for another round. 343 box = nextBox; 344 renderer = &box->renderer(); 345 offset = nextBox->caretLeftmostOffset(); 346 continue; 347 } 348 349 ASSERT(offset == box->caretRightmostOffset()); 350 351 unsigned char level = box->bidiLevel(); 352 InlineBox* nextBox = box->nextLeafChild(); 353 354 if (box->direction() == primaryDirection) { 355 if (!nextBox) { 356 InlineBox* logicalEnd = 0; 357 if (primaryDirection == LTR ? box->root().getLogicalEndBoxWithNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) { 358 box = logicalEnd; 359 renderer = &box->renderer(); 360 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); 361 } 362 break; 363 } 364 365 if (nextBox->bidiLevel() >= level) 366 break; 367 368 level = nextBox->bidiLevel(); 369 370 InlineBox* prevBox = box; 371 do { 372 prevBox = prevBox->prevLeafChild(); 373 } while (prevBox && prevBox->bidiLevel() > level); 374 375 if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA 376 break; 377 378 // For example, abc 123 ^ CBA or 123 ^ CBA abc 379 box = nextBox; 380 renderer = &box->renderer(); 381 offset = box->caretLeftmostOffset(); 382 if (box->direction() == primaryDirection) 383 break; 384 continue; 385 } 386 387 while (nextBox && !nextBox->renderer().node()) 388 nextBox = nextBox->nextLeafChild(); 389 390 if (nextBox) { 391 box = nextBox; 392 renderer = &box->renderer(); 393 offset = box->caretLeftmostOffset(); 394 395 if (box->bidiLevel() > level) { 396 do { 397 nextBox = nextBox->nextLeafChild(); 398 } while (nextBox && nextBox->bidiLevel() > level); 399 400 if (!nextBox || nextBox->bidiLevel() < level) 401 continue; 402 } 403 } else { 404 // Trailing edge of a secondary run. Set to the leading edge of the entire run. 405 while (true) { 406 while (InlineBox* prevBox = box->prevLeafChild()) { 407 if (prevBox->bidiLevel() < level) 408 break; 409 box = prevBox; 410 } 411 if (box->bidiLevel() == level) 412 break; 413 level = box->bidiLevel(); 414 while (InlineBox* nextBox = box->nextLeafChild()) { 415 if (nextBox->bidiLevel() < level) 416 break; 417 box = nextBox; 418 } 419 if (box->bidiLevel() == level) 420 break; 421 level = box->bidiLevel(); 422 } 423 renderer = &box->renderer(); 424 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); 425 } 426 break; 427 } 428 429 p = createLegacyEditingPosition(renderer->node(), offset); 430 431 if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) 432 return p; 433 434 ASSERT(p != m_deepPosition); 435 } 436 } 437 438 VisiblePosition VisiblePosition::right(bool stayInEditableContent) const 439 { 440 Position pos = rightVisuallyDistinctCandidate(); 441 // FIXME: Why can't we move left from the last position in a tree? 442 if (pos.atStartOfTree() || pos.atEndOfTree()) 443 return VisiblePosition(); 444 445 VisiblePosition right = VisiblePosition(pos, DOWNSTREAM); 446 ASSERT(right != *this); 447 448 if (!stayInEditableContent) 449 return right; 450 451 // FIXME: This may need to do something different from "after". 452 return honorEditingBoundaryAtOrAfter(right); 453 } 454 455 VisiblePosition VisiblePosition::honorEditingBoundaryAtOrBefore(const VisiblePosition &pos) const 456 { 457 if (pos.isNull()) 458 return pos; 459 460 Node* highestRoot = highestEditableRoot(deepEquivalent()); 461 462 // Return empty position if pos is not somewhere inside the editable region containing this position 463 if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot)) 464 return VisiblePosition(); 465 466 // Return pos itself if the two are from the very same editable region, or both are non-editable 467 // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement 468 // to it is allowed. VisibleSelection::adjustForEditableContent has this problem too. 469 if (highestEditableRoot(pos.deepEquivalent()) == highestRoot) 470 return pos; 471 472 // Return empty position if this position is non-editable, but pos is editable 473 // FIXME: Move to the previous non-editable region. 474 if (!highestRoot) 475 return VisiblePosition(); 476 477 // Return the last position before pos that is in the same editable region as this position 478 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot); 479 } 480 481 VisiblePosition VisiblePosition::honorEditingBoundaryAtOrAfter(const VisiblePosition &pos) const 482 { 483 if (pos.isNull()) 484 return pos; 485 486 Node* highestRoot = highestEditableRoot(deepEquivalent()); 487 488 // Return empty position if pos is not somewhere inside the editable region containing this position 489 if (highestRoot && !pos.deepEquivalent().deprecatedNode()->isDescendantOf(highestRoot)) 490 return VisiblePosition(); 491 492 // Return pos itself if the two are from the very same editable region, or both are non-editable 493 // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement 494 // to it is allowed. VisibleSelection::adjustForEditableContent has this problem too. 495 if (highestEditableRoot(pos.deepEquivalent()) == highestRoot) 496 return pos; 497 498 // Return empty position if this position is non-editable, but pos is editable 499 // FIXME: Move to the next non-editable region. 500 if (!highestRoot) 501 return VisiblePosition(); 502 503 // Return the next position after pos that is in the same editable region as this position 504 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); 505 } 506 507 VisiblePosition VisiblePosition::skipToStartOfEditingBoundary(const VisiblePosition &pos) const 508 { 509 if (pos.isNull()) 510 return pos; 511 512 Node* highestRoot = highestEditableRoot(deepEquivalent()); 513 Node* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); 514 515 // Return pos itself if the two are from the very same editable region, or both are non-editable. 516 if (highestRootOfPos == highestRoot) 517 return pos; 518 519 // If |pos| has an editable root, skip to the start 520 if (highestRootOfPos) 521 return VisiblePosition(previousVisuallyDistinctCandidate(Position(highestRootOfPos, Position::PositionIsBeforeAnchor).parentAnchoredEquivalent())); 522 523 // That must mean that |pos| is not editable. Return the last position before pos that is in the same editable region as this position 524 return lastEditableVisiblePositionBeforePositionInRoot(pos.deepEquivalent(), highestRoot); 525 } 526 527 VisiblePosition VisiblePosition::skipToEndOfEditingBoundary(const VisiblePosition &pos) const 528 { 529 if (pos.isNull()) 530 return pos; 531 532 Node* highestRoot = highestEditableRoot(deepEquivalent()); 533 Node* highestRootOfPos = highestEditableRoot(pos.deepEquivalent()); 534 535 // Return pos itself if the two are from the very same editable region, or both are non-editable. 536 if (highestRootOfPos == highestRoot) 537 return pos; 538 539 // If |pos| has an editable root, skip to the end 540 if (highestRootOfPos) 541 return VisiblePosition(Position(highestRootOfPos, Position::PositionIsAfterAnchor).parentAnchoredEquivalent()); 542 543 // That must mean that |pos| is not editable. Return the next position after pos that is in the same editable region as this position 544 return firstEditableVisiblePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot); 545 } 546 547 static Position canonicalizeCandidate(const Position& candidate) 548 { 549 if (candidate.isNull()) 550 return Position(); 551 ASSERT(candidate.isCandidate()); 552 Position upstream = candidate.upstream(); 553 if (upstream.isCandidate()) 554 return upstream; 555 return candidate; 556 } 557 558 Position VisiblePosition::canonicalPosition(const Position& passedPosition) 559 { 560 // The updateLayout call below can do so much that even the position passed 561 // in to us might get changed as a side effect. Specifically, there are code 562 // paths that pass selection endpoints, and updateLayout can change the selection. 563 Position position = passedPosition; 564 565 // FIXME (9535): Canonicalizing to the leftmost candidate means that if we're at a line wrap, we will 566 // ask renderers to paint downstream carets for other renderers. 567 // To fix this, we need to either a) add code to all paintCarets to pass the responsibility off to 568 // the appropriate renderer for VisiblePosition's like these, or b) canonicalize to the rightmost candidate 569 // unless the affinity is upstream. 570 if (position.isNull()) 571 return Position(); 572 573 ASSERT(position.document()); 574 position.document()->updateLayoutIgnorePendingStylesheets(); 575 576 Node* node = position.containerNode(); 577 578 Position candidate = position.upstream(); 579 if (candidate.isCandidate()) 580 return candidate; 581 candidate = position.downstream(); 582 if (candidate.isCandidate()) 583 return candidate; 584 585 // When neither upstream or downstream gets us to a candidate (upstream/downstream won't leave 586 // blocks or enter new ones), we search forward and backward until we find one. 587 Position next = canonicalizeCandidate(nextCandidate(position)); 588 Position prev = canonicalizeCandidate(previousCandidate(position)); 589 Node* nextNode = next.deprecatedNode(); 590 Node* prevNode = prev.deprecatedNode(); 591 592 // The new position must be in the same editable element. Enforce that first. 593 // Unless the descent is from a non-editable html element to an editable body. 594 if (isHTMLHtmlElement(node) && !node->rendererIsEditable() && node->document().body() && node->document().body()->rendererIsEditable()) 595 return next.isNotNull() ? next : prev; 596 597 Node* editingRoot = editableRootForPosition(position); 598 599 // If the html element is editable, descending into its body will look like a descent 600 // from non-editable to editable content since rootEditableElement() always stops at the body. 601 if (isHTMLHtmlElement(editingRoot) || position.deprecatedNode()->isDocumentNode()) 602 return next.isNotNull() ? next : prev; 603 604 bool prevIsInSameEditableElement = prevNode && editableRootForPosition(prev) == editingRoot; 605 bool nextIsInSameEditableElement = nextNode && editableRootForPosition(next) == editingRoot; 606 if (prevIsInSameEditableElement && !nextIsInSameEditableElement) 607 return prev; 608 609 if (nextIsInSameEditableElement && !prevIsInSameEditableElement) 610 return next; 611 612 if (!nextIsInSameEditableElement && !prevIsInSameEditableElement) 613 return Position(); 614 615 // The new position should be in the same block flow element. Favor that. 616 Node* originalBlock = node ? node->enclosingBlockFlowElement() : 0; 617 bool nextIsOutsideOriginalBlock = !nextNode->isDescendantOf(originalBlock) && nextNode != originalBlock; 618 bool prevIsOutsideOriginalBlock = !prevNode->isDescendantOf(originalBlock) && prevNode != originalBlock; 619 if (nextIsOutsideOriginalBlock && !prevIsOutsideOriginalBlock) 620 return prev; 621 622 return next; 623 } 624 625 UChar32 VisiblePosition::characterAfter() const 626 { 627 // We canonicalize to the first of two equivalent candidates, but the second of the two candidates 628 // is the one that will be inside the text node containing the character after this visible position. 629 Position pos = m_deepPosition.downstream(); 630 if (!pos.containerNode() || !pos.containerNode()->isTextNode()) 631 return 0; 632 switch (pos.anchorType()) { 633 case Position::PositionIsAfterChildren: 634 case Position::PositionIsAfterAnchor: 635 case Position::PositionIsBeforeAnchor: 636 case Position::PositionIsBeforeChildren: 637 return 0; 638 case Position::PositionIsOffsetInAnchor: 639 break; 640 } 641 unsigned offset = static_cast<unsigned>(pos.offsetInContainerNode()); 642 Text* textNode = pos.containerText(); 643 unsigned length = textNode->length(); 644 if (offset >= length) 645 return 0; 646 647 return textNode->data().characterStartingAt(offset); 648 } 649 650 LayoutRect VisiblePosition::localCaretRect(RenderObject*& renderer) const 651 { 652 if (m_deepPosition.isNull()) { 653 renderer = 0; 654 return IntRect(); 655 } 656 Node* node = m_deepPosition.anchorNode(); 657 658 renderer = node->renderer(); 659 if (!renderer) 660 return LayoutRect(); 661 662 InlineBox* inlineBox; 663 int caretOffset; 664 getInlineBoxAndOffset(inlineBox, caretOffset); 665 666 if (inlineBox) 667 renderer = &inlineBox->renderer(); 668 669 return renderer->localCaretRect(inlineBox, caretOffset); 670 } 671 672 IntRect VisiblePosition::absoluteCaretBounds() const 673 { 674 RenderObject* renderer; 675 LayoutRect localRect = localCaretRect(renderer); 676 if (localRect.isEmpty() || !renderer) 677 return IntRect(); 678 679 return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); 680 } 681 682 int VisiblePosition::lineDirectionPointForBlockDirectionNavigation() const 683 { 684 RenderObject* renderer; 685 LayoutRect localRect = localCaretRect(renderer); 686 if (localRect.isEmpty() || !renderer) 687 return 0; 688 689 // This ignores transforms on purpose, for now. Vertical navigation is done 690 // without consulting transforms, so that 'up' in transformed text is 'up' 691 // relative to the text, not absolute 'up'. 692 FloatPoint caretPoint = renderer->localToAbsolute(localRect.location()); 693 RenderObject* containingBlock = renderer->containingBlock(); 694 if (!containingBlock) 695 containingBlock = renderer; // Just use ourselves to determine the writing mode if we have no containing block. 696 return containingBlock->isHorizontalWritingMode() ? caretPoint.x() : caretPoint.y(); 697 } 698 699 #ifndef NDEBUG 700 701 void VisiblePosition::debugPosition(const char* msg) const 702 { 703 if (isNull()) 704 fprintf(stderr, "Position [%s]: null\n", msg); 705 else { 706 fprintf(stderr, "Position [%s]: %s, ", msg, m_deepPosition.deprecatedNode()->nodeName().utf8().data()); 707 m_deepPosition.showAnchorTypeAndOffset(); 708 } 709 } 710 711 void VisiblePosition::formatForDebugger(char* buffer, unsigned length) const 712 { 713 m_deepPosition.formatForDebugger(buffer, length); 714 } 715 716 void VisiblePosition::showTreeForThis() const 717 { 718 m_deepPosition.showTreeForThis(); 719 } 720 721 #endif 722 723 PassRefPtrWillBeRawPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition &end) 724 { 725 if (start.isNull() || end.isNull()) 726 return nullptr; 727 728 Position s = start.deepEquivalent().parentAnchoredEquivalent(); 729 Position e = end.deepEquivalent().parentAnchoredEquivalent(); 730 if (s.isNull() || e.isNull()) 731 return nullptr; 732 733 return Range::create(s.containerNode()->document(), s.containerNode(), s.offsetInContainerNode(), e.containerNode(), e.offsetInContainerNode()); 734 } 735 736 VisiblePosition startVisiblePosition(const Range *r, EAffinity affinity) 737 { 738 return VisiblePosition(r->startPosition(), affinity); 739 } 740 741 bool setStart(Range *r, const VisiblePosition &visiblePosition) 742 { 743 if (!r) 744 return false; 745 Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); 746 TrackExceptionState exceptionState; 747 r->setStart(p.containerNode(), p.offsetInContainerNode(), exceptionState); 748 return !exceptionState.hadException(); 749 } 750 751 bool setEnd(Range *r, const VisiblePosition &visiblePosition) 752 { 753 if (!r) 754 return false; 755 Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); 756 TrackExceptionState exceptionState; 757 r->setEnd(p.containerNode(), p.offsetInContainerNode(), exceptionState); 758 return !exceptionState.hadException(); 759 } 760 761 Element* enclosingBlockFlowElement(const VisiblePosition &visiblePosition) 762 { 763 if (visiblePosition.isNull()) 764 return NULL; 765 766 return visiblePosition.deepEquivalent().deprecatedNode()->enclosingBlockFlowElement(); 767 } 768 769 bool isFirstVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node) 770 { 771 if (visiblePosition.isNull()) 772 return false; 773 774 if (!visiblePosition.deepEquivalent().containerNode()->isDescendantOf(node)) 775 return false; 776 777 VisiblePosition previous = visiblePosition.previous(); 778 return previous.isNull() || !previous.deepEquivalent().deprecatedNode()->isDescendantOf(node); 779 } 780 781 bool isLastVisiblePositionInNode(const VisiblePosition &visiblePosition, const Node *node) 782 { 783 if (visiblePosition.isNull()) 784 return false; 785 786 if (!visiblePosition.deepEquivalent().containerNode()->isDescendantOf(node)) 787 return false; 788 789 VisiblePosition next = visiblePosition.next(); 790 return next.isNull() || !next.deepEquivalent().deprecatedNode()->isDescendantOf(node); 791 } 792 793 void VisiblePosition::trace(Visitor* visitor) 794 { 795 visitor->trace(m_deepPosition); 796 } 797 798 } // namespace WebCore 799 800 #ifndef NDEBUG 801 802 void showTree(const WebCore::VisiblePosition* vpos) 803 { 804 if (vpos) 805 vpos->showTreeForThis(); 806 } 807 808 void showTree(const WebCore::VisiblePosition& vpos) 809 { 810 vpos.showTreeForThis(); 811 } 812 813 #endif 814