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/core/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 blink { 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 #if ENABLE(ASSERT) 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 ContainerNode* 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 ContainerNode* 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 ContainerNode* highestRoot = highestEditableRoot(deepEquivalent()); 513 ContainerNode* 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 ContainerNode* highestRoot = highestEditableRoot(deepEquivalent()); 533 ContainerNode* 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->hasEditableStyle() && node->document().body() && node->document().body()->hasEditableStyle()) 595 return next.isNotNull() ? next : prev; 596 597 Element* 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 Element* originalBlock = node ? enclosingBlockFlowElement(*node) : 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 PositionWithAffinity positionWithAffinity(m_deepPosition, m_affinity); 653 return localCaretRectOfPosition(positionWithAffinity, renderer); 654 } 655 656 IntRect VisiblePosition::absoluteCaretBounds() const 657 { 658 RenderObject* renderer; 659 LayoutRect localRect = localCaretRect(renderer); 660 if (localRect.isEmpty() || !renderer) 661 return IntRect(); 662 663 return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); 664 } 665 666 int VisiblePosition::lineDirectionPointForBlockDirectionNavigation() const 667 { 668 RenderObject* renderer; 669 LayoutRect localRect = localCaretRect(renderer); 670 if (localRect.isEmpty() || !renderer) 671 return 0; 672 673 // This ignores transforms on purpose, for now. Vertical navigation is done 674 // without consulting transforms, so that 'up' in transformed text is 'up' 675 // relative to the text, not absolute 'up'. 676 FloatPoint caretPoint = renderer->localToAbsolute(localRect.location()); 677 RenderObject* containingBlock = renderer->containingBlock(); 678 if (!containingBlock) 679 containingBlock = renderer; // Just use ourselves to determine the writing mode if we have no containing block. 680 return containingBlock->isHorizontalWritingMode() ? caretPoint.x() : caretPoint.y(); 681 } 682 683 #ifndef NDEBUG 684 685 void VisiblePosition::debugPosition(const char* msg) const 686 { 687 if (isNull()) 688 fprintf(stderr, "Position [%s]: null\n", msg); 689 else { 690 fprintf(stderr, "Position [%s]: %s, ", msg, m_deepPosition.deprecatedNode()->nodeName().utf8().data()); 691 m_deepPosition.showAnchorTypeAndOffset(); 692 } 693 } 694 695 void VisiblePosition::formatForDebugger(char* buffer, unsigned length) const 696 { 697 m_deepPosition.formatForDebugger(buffer, length); 698 } 699 700 void VisiblePosition::showTreeForThis() const 701 { 702 m_deepPosition.showTreeForThis(); 703 } 704 705 #endif 706 707 PassRefPtrWillBeRawPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition &end) 708 { 709 if (start.isNull() || end.isNull()) 710 return nullptr; 711 712 Position s = start.deepEquivalent().parentAnchoredEquivalent(); 713 Position e = end.deepEquivalent().parentAnchoredEquivalent(); 714 if (s.isNull() || e.isNull()) 715 return nullptr; 716 717 return Range::create(s.containerNode()->document(), s.containerNode(), s.offsetInContainerNode(), e.containerNode(), e.offsetInContainerNode()); 718 } 719 720 VisiblePosition startVisiblePosition(const Range *r, EAffinity affinity) 721 { 722 return VisiblePosition(r->startPosition(), affinity); 723 } 724 725 bool setStart(Range *r, const VisiblePosition &visiblePosition) 726 { 727 if (!r) 728 return false; 729 Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); 730 TrackExceptionState exceptionState; 731 r->setStart(p.containerNode(), p.offsetInContainerNode(), exceptionState); 732 return !exceptionState.hadException(); 733 } 734 735 bool setEnd(Range *r, const VisiblePosition &visiblePosition) 736 { 737 if (!r) 738 return false; 739 Position p = visiblePosition.deepEquivalent().parentAnchoredEquivalent(); 740 TrackExceptionState exceptionState; 741 r->setEnd(p.containerNode(), p.offsetInContainerNode(), exceptionState); 742 return !exceptionState.hadException(); 743 } 744 745 Element* enclosingBlockFlowElement(const VisiblePosition& visiblePosition) 746 { 747 if (visiblePosition.isNull()) 748 return 0; 749 750 return enclosingBlockFlowElement(*visiblePosition.deepEquivalent().deprecatedNode()); 751 } 752 753 bool isFirstVisiblePositionInNode(const VisiblePosition& visiblePosition, const ContainerNode* node) 754 { 755 if (visiblePosition.isNull()) 756 return false; 757 758 if (!visiblePosition.deepEquivalent().containerNode()->isDescendantOf(node)) 759 return false; 760 761 VisiblePosition previous = visiblePosition.previous(); 762 return previous.isNull() || !previous.deepEquivalent().deprecatedNode()->isDescendantOf(node); 763 } 764 765 bool isLastVisiblePositionInNode(const VisiblePosition& visiblePosition, const ContainerNode* node) 766 { 767 if (visiblePosition.isNull()) 768 return false; 769 770 if (!visiblePosition.deepEquivalent().containerNode()->isDescendantOf(node)) 771 return false; 772 773 VisiblePosition next = visiblePosition.next(); 774 return next.isNull() || !next.deepEquivalent().deprecatedNode()->isDescendantOf(node); 775 } 776 777 void VisiblePosition::trace(Visitor* visitor) 778 { 779 visitor->trace(m_deepPosition); 780 } 781 782 } // namespace blink 783 784 #ifndef NDEBUG 785 786 void showTree(const blink::VisiblePosition* vpos) 787 { 788 if (vpos) 789 vpos->showTreeForThis(); 790 } 791 792 void showTree(const blink::VisiblePosition& vpos) 793 { 794 vpos.showTreeForThis(); 795 } 796 797 #endif 798