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