1 /* 2 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "core/editing/VisibleSelection.h" 28 29 #include "bindings/v8/ExceptionState.h" 30 #include "core/dom/Document.h" 31 #include "core/dom/Element.h" 32 #include "core/dom/Range.h" 33 #include "core/editing/TextIterator.h" 34 #include "core/editing/VisiblePosition.h" 35 #include "core/editing/VisibleUnits.h" 36 #include "core/editing/htmlediting.h" 37 #include "core/platform/graphics/LayoutPoint.h" 38 #include "core/rendering/RenderObject.h" 39 #include "wtf/Assertions.h" 40 #include "wtf/text/CString.h" 41 #include "wtf/text/StringBuilder.h" 42 #include "wtf/unicode/CharacterNames.h" 43 #include <stdio.h> 44 45 namespace WebCore { 46 47 VisibleSelection::VisibleSelection() 48 : m_affinity(DOWNSTREAM) 49 , m_selectionType(NoSelection) 50 , m_baseIsFirst(true) 51 , m_isDirectional(false) 52 { 53 } 54 55 VisibleSelection::VisibleSelection(const Position& pos, EAffinity affinity, bool isDirectional) 56 : m_base(pos) 57 , m_extent(pos) 58 , m_affinity(affinity) 59 , m_isDirectional(isDirectional) 60 { 61 validate(); 62 } 63 64 VisibleSelection::VisibleSelection(const Position& base, const Position& extent, EAffinity affinity, bool isDirectional) 65 : m_base(base) 66 , m_extent(extent) 67 , m_affinity(affinity) 68 , m_isDirectional(isDirectional) 69 { 70 validate(); 71 } 72 73 VisibleSelection::VisibleSelection(const VisiblePosition& pos, bool isDirectional) 74 : m_base(pos.deepEquivalent()) 75 , m_extent(pos.deepEquivalent()) 76 , m_affinity(pos.affinity()) 77 , m_isDirectional(isDirectional) 78 { 79 validate(); 80 } 81 82 VisibleSelection::VisibleSelection(const VisiblePosition& base, const VisiblePosition& extent, bool isDirectional) 83 : m_base(base.deepEquivalent()) 84 , m_extent(extent.deepEquivalent()) 85 , m_affinity(base.affinity()) 86 , m_isDirectional(isDirectional) 87 { 88 validate(); 89 } 90 91 VisibleSelection::VisibleSelection(const Range* range, EAffinity affinity, bool isDirectional) 92 : m_base(range->startPosition()) 93 , m_extent(range->endPosition()) 94 , m_affinity(affinity) 95 , m_isDirectional(isDirectional) 96 { 97 validate(); 98 } 99 100 VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node) 101 { 102 ASSERT(!editingIgnoresContent(node)); 103 return VisibleSelection(firstPositionInNode(node), lastPositionInNode(node), DOWNSTREAM); 104 } 105 106 void VisibleSelection::setBase(const Position& position) 107 { 108 m_base = position; 109 validate(); 110 } 111 112 void VisibleSelection::setBase(const VisiblePosition& visiblePosition) 113 { 114 m_base = visiblePosition.deepEquivalent(); 115 validate(); 116 } 117 118 void VisibleSelection::setExtent(const Position& position) 119 { 120 m_extent = position; 121 validate(); 122 } 123 124 void VisibleSelection::setExtent(const VisiblePosition& visiblePosition) 125 { 126 m_extent = visiblePosition.deepEquivalent(); 127 validate(); 128 } 129 130 PassRefPtr<Range> VisibleSelection::firstRange() const 131 { 132 if (isNone()) 133 return 0; 134 Position start = m_start.parentAnchoredEquivalent(); 135 Position end = m_end.parentAnchoredEquivalent(); 136 return Range::create(start.anchorNode()->document(), start, end); 137 } 138 139 PassRefPtr<Range> VisibleSelection::toNormalizedRange() const 140 { 141 if (isNone()) 142 return 0; 143 144 // Make sure we have an updated layout since this function is called 145 // in the course of running edit commands which modify the DOM. 146 // Failing to call this can result in equivalentXXXPosition calls returning 147 // incorrect results. 148 m_start.anchorNode()->document()->updateLayout(); 149 150 // Check again, because updating layout can clear the selection. 151 if (isNone()) 152 return 0; 153 154 Position s, e; 155 if (isCaret()) { 156 // If the selection is a caret, move the range start upstream. This helps us match 157 // the conventions of text editors tested, which make style determinations based 158 // on the character before the caret, if any. 159 s = m_start.upstream().parentAnchoredEquivalent(); 160 e = s; 161 } else { 162 // If the selection is a range, select the minimum range that encompasses the selection. 163 // Again, this is to match the conventions of text editors tested, which make style 164 // determinations based on the first character of the selection. 165 // For instance, this operation helps to make sure that the "X" selected below is the 166 // only thing selected. The range should not be allowed to "leak" out to the end of the 167 // previous text node, or to the beginning of the next text node, each of which has a 168 // different style. 169 // 170 // On a treasure map, <b>X</b> marks the spot. 171 // ^ selected 172 // 173 ASSERT(isRange()); 174 s = m_start.downstream(); 175 e = m_end.upstream(); 176 if (comparePositions(s, e) > 0) { 177 // Make sure the start is before the end. 178 // The end can wind up before the start if collapsed whitespace is the only thing selected. 179 Position tmp = s; 180 s = e; 181 e = tmp; 182 } 183 s = s.parentAnchoredEquivalent(); 184 e = e.parentAnchoredEquivalent(); 185 } 186 187 if (!s.containerNode() || !e.containerNode()) 188 return 0; 189 190 // VisibleSelections are supposed to always be valid. This constructor will ASSERT 191 // if a valid range could not be created, which is fine for this callsite. 192 return Range::create(s.anchorNode()->document(), s, e); 193 } 194 195 bool VisibleSelection::expandUsingGranularity(TextGranularity granularity) 196 { 197 if (isNone()) 198 return false; 199 200 validate(granularity); 201 return true; 202 } 203 204 static PassRefPtr<Range> makeSearchRange(const Position& pos) 205 { 206 Node* n = pos.deprecatedNode(); 207 if (!n) 208 return 0; 209 Document* d = n->document(); 210 Node* de = d->documentElement(); 211 if (!de) 212 return 0; 213 Node* boundary = n->enclosingBlockFlowElement(); 214 if (!boundary) 215 return 0; 216 217 RefPtr<Range> searchRange(Range::create(d)); 218 TrackExceptionState es; 219 220 Position start(pos.parentAnchoredEquivalent()); 221 searchRange->selectNodeContents(boundary, es); 222 searchRange->setStart(start.containerNode(), start.offsetInContainerNode(), es); 223 224 ASSERT(!es.hadException()); 225 if (es.hadException()) 226 return 0; 227 228 return searchRange.release(); 229 } 230 231 bool VisibleSelection::isAll(EditingBoundaryCrossingRule rule) const 232 { 233 return !nonBoundaryShadowTreeRootNode() && visibleStart().previous(rule).isNull() && visibleEnd().next(rule).isNull(); 234 } 235 236 void VisibleSelection::appendTrailingWhitespace() 237 { 238 RefPtr<Range> searchRange = makeSearchRange(m_end); 239 if (!searchRange) 240 return; 241 242 CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); 243 244 for (; charIt.length(); charIt.advance(1)) { 245 UChar c = charIt.characterAt(0); 246 if ((!isSpaceOrNewline(c) && c != noBreakSpace) || c == '\n') 247 break; 248 m_end = charIt.range()->endPosition(); 249 } 250 } 251 252 void VisibleSelection::setBaseAndExtentToDeepEquivalents() 253 { 254 // Move the selection to rendered positions, if possible. 255 bool baseAndExtentEqual = m_base == m_extent; 256 if (m_base.isNotNull()) { 257 m_base = VisiblePosition(m_base, m_affinity).deepEquivalent(); 258 if (baseAndExtentEqual) 259 m_extent = m_base; 260 } 261 if (m_extent.isNotNull() && !baseAndExtentEqual) 262 m_extent = VisiblePosition(m_extent, m_affinity).deepEquivalent(); 263 264 // Make sure we do not have a dangling base or extent. 265 if (m_base.isNull() && m_extent.isNull()) 266 m_baseIsFirst = true; 267 else if (m_base.isNull()) { 268 m_base = m_extent; 269 m_baseIsFirst = true; 270 } else if (m_extent.isNull()) { 271 m_extent = m_base; 272 m_baseIsFirst = true; 273 } else 274 m_baseIsFirst = comparePositions(m_base, m_extent) <= 0; 275 } 276 277 void VisibleSelection::setStartAndEndFromBaseAndExtentRespectingGranularity(TextGranularity granularity) 278 { 279 if (m_baseIsFirst) { 280 m_start = m_base; 281 m_end = m_extent; 282 } else { 283 m_start = m_extent; 284 m_end = m_base; 285 } 286 287 switch (granularity) { 288 case CharacterGranularity: 289 // Don't do any expansion. 290 break; 291 case WordGranularity: { 292 // General case: Select the word the caret is positioned inside of, or at the start of (RightWordIfOnBoundary). 293 // Edge case: If the caret is after the last word in a soft-wrapped line or the last word in 294 // the document, select that last word (LeftWordIfOnBoundary). 295 // Edge case: If the caret is after the last word in a paragraph, select from the the end of the 296 // last word to the line break (also RightWordIfOnBoundary); 297 VisiblePosition start = VisiblePosition(m_start, m_affinity); 298 VisiblePosition originalEnd(m_end, m_affinity); 299 EWordSide side = RightWordIfOnBoundary; 300 if (isEndOfEditableOrNonEditableContent(start) || (isEndOfLine(start) && !isStartOfLine(start) && !isEndOfParagraph(start))) 301 side = LeftWordIfOnBoundary; 302 m_start = startOfWord(start, side).deepEquivalent(); 303 side = RightWordIfOnBoundary; 304 if (isEndOfEditableOrNonEditableContent(originalEnd) || (isEndOfLine(originalEnd) && !isStartOfLine(originalEnd) && !isEndOfParagraph(originalEnd))) 305 side = LeftWordIfOnBoundary; 306 307 VisiblePosition wordEnd(endOfWord(originalEnd, side)); 308 VisiblePosition end(wordEnd); 309 310 if (isEndOfParagraph(originalEnd) && !isEmptyTableCell(m_start.deprecatedNode())) { 311 // Select the paragraph break (the space from the end of a paragraph to the start of 312 // the next one) to match TextEdit. 313 end = wordEnd.next(); 314 315 if (Node* table = isFirstPositionAfterTable(end)) { 316 // The paragraph break after the last paragraph in the last cell of a block table ends 317 // at the start of the paragraph after the table. 318 if (isBlock(table)) 319 end = end.next(CannotCrossEditingBoundary); 320 else 321 end = wordEnd; 322 } 323 324 if (end.isNull()) 325 end = wordEnd; 326 327 } 328 329 m_end = end.deepEquivalent(); 330 break; 331 } 332 case SentenceGranularity: { 333 m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 334 m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent(); 335 break; 336 } 337 case LineGranularity: { 338 m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 339 VisiblePosition end = endOfLine(VisiblePosition(m_end, m_affinity)); 340 // If the end of this line is at the end of a paragraph, include the space 341 // after the end of the line in the selection. 342 if (isEndOfParagraph(end)) { 343 VisiblePosition next = end.next(); 344 if (next.isNotNull()) 345 end = next; 346 } 347 m_end = end.deepEquivalent(); 348 break; 349 } 350 case LineBoundary: 351 m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 352 m_end = endOfLine(VisiblePosition(m_end, m_affinity)).deepEquivalent(); 353 break; 354 case ParagraphGranularity: { 355 VisiblePosition pos(m_start, m_affinity); 356 if (isStartOfLine(pos) && isEndOfEditableOrNonEditableContent(pos)) 357 pos = pos.previous(); 358 m_start = startOfParagraph(pos).deepEquivalent(); 359 VisiblePosition visibleParagraphEnd = endOfParagraph(VisiblePosition(m_end, m_affinity)); 360 361 // Include the "paragraph break" (the space from the end of this paragraph to the start 362 // of the next one) in the selection. 363 VisiblePosition end(visibleParagraphEnd.next()); 364 365 if (Node* table = isFirstPositionAfterTable(end)) { 366 // The paragraph break after the last paragraph in the last cell of a block table ends 367 // at the start of the paragraph after the table, not at the position just after the table. 368 if (isBlock(table)) 369 end = end.next(CannotCrossEditingBoundary); 370 // There is no parargraph break after the last paragraph in the last cell of an inline table. 371 else 372 end = visibleParagraphEnd; 373 } 374 375 if (end.isNull()) 376 end = visibleParagraphEnd; 377 378 m_end = end.deepEquivalent(); 379 break; 380 } 381 case DocumentBoundary: 382 m_start = startOfDocument(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 383 m_end = endOfDocument(VisiblePosition(m_end, m_affinity)).deepEquivalent(); 384 break; 385 case ParagraphBoundary: 386 m_start = startOfParagraph(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 387 m_end = endOfParagraph(VisiblePosition(m_end, m_affinity)).deepEquivalent(); 388 break; 389 case SentenceBoundary: 390 m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent(); 391 m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent(); 392 break; 393 } 394 395 // Make sure we do not have a dangling start or end. 396 if (m_start.isNull()) 397 m_start = m_end; 398 if (m_end.isNull()) 399 m_end = m_start; 400 } 401 402 void VisibleSelection::updateSelectionType() 403 { 404 if (m_start.isNull()) { 405 ASSERT(m_end.isNull()); 406 m_selectionType = NoSelection; 407 } else if (m_start == m_end || m_start.upstream() == m_end.upstream()) { 408 m_selectionType = CaretSelection; 409 } else 410 m_selectionType = RangeSelection; 411 412 // Affinity only makes sense for a caret 413 if (m_selectionType != CaretSelection) 414 m_affinity = DOWNSTREAM; 415 } 416 417 void VisibleSelection::validate(TextGranularity granularity) 418 { 419 setBaseAndExtentToDeepEquivalents(); 420 setStartAndEndFromBaseAndExtentRespectingGranularity(granularity); 421 adjustSelectionToAvoidCrossingShadowBoundaries(); 422 adjustSelectionToAvoidCrossingEditingBoundaries(); 423 updateSelectionType(); 424 425 if (selectionType() == RangeSelection) { 426 // "Constrain" the selection to be the smallest equivalent range of nodes. 427 // This is a somewhat arbitrary choice, but experience shows that it is 428 // useful to make to make the selection "canonical" (if only for 429 // purposes of comparing selections). This is an ideal point of the code 430 // to do this operation, since all selection changes that result in a RANGE 431 // come through here before anyone uses it. 432 // FIXME: Canonicalizing is good, but haven't we already done it (when we 433 // set these two positions to VisiblePosition deepEquivalent()s above)? 434 m_start = m_start.downstream(); 435 m_end = m_end.upstream(); 436 437 // FIXME: Position::downstream() or Position::upStream() might violate editing boundaries 438 // if an anchor node has a Shadow DOM. So we adjust selection to avoid crossing editing 439 // boundaries again. See https://bugs.webkit.org/show_bug.cgi?id=87463 440 adjustSelectionToAvoidCrossingEditingBoundaries(); 441 } 442 } 443 444 // FIXME: This function breaks the invariant of this class. 445 // But because we use VisibleSelection to store values in editing commands for use when 446 // undoing the command, we need to be able to create a selection that while currently 447 // invalid, will be valid once the changes are undone. This is a design problem. 448 // To fix it we either need to change the invariants of VisibleSelection or create a new 449 // class for editing to use that can manipulate selections that are not currently valid. 450 void VisibleSelection::setWithoutValidation(const Position& base, const Position& extent) 451 { 452 ASSERT(!base.isNull()); 453 ASSERT(!extent.isNull()); 454 ASSERT(m_affinity == DOWNSTREAM); 455 m_base = base; 456 m_extent = extent; 457 m_baseIsFirst = comparePositions(base, extent) <= 0; 458 if (m_baseIsFirst) { 459 m_start = base; 460 m_end = extent; 461 } else { 462 m_start = extent; 463 m_end = base; 464 } 465 m_selectionType = base == extent ? CaretSelection : RangeSelection; 466 } 467 468 static Position adjustPositionForEnd(const Position& currentPosition, Node* startContainerNode) 469 { 470 TreeScope* treeScope = startContainerNode->treeScope(); 471 472 ASSERT(currentPosition.containerNode()->treeScope() != treeScope); 473 474 if (Node* ancestor = treeScope->ancestorInThisScope(currentPosition.containerNode())) { 475 if (ancestor->contains(startContainerNode)) 476 return positionAfterNode(ancestor); 477 return positionBeforeNode(ancestor); 478 } 479 480 if (Node* lastChild = treeScope->rootNode()->lastChild()) 481 return positionAfterNode(lastChild); 482 483 return Position(); 484 } 485 486 static Position adjustPositionForStart(const Position& currentPosition, Node* endContainerNode) 487 { 488 TreeScope* treeScope = endContainerNode->treeScope(); 489 490 ASSERT(currentPosition.containerNode()->treeScope() != treeScope); 491 492 if (Node* ancestor = treeScope->ancestorInThisScope(currentPosition.containerNode())) { 493 if (ancestor->contains(endContainerNode)) 494 return positionBeforeNode(ancestor); 495 return positionAfterNode(ancestor); 496 } 497 498 if (Node* firstChild = treeScope->rootNode()->firstChild()) 499 return positionBeforeNode(firstChild); 500 501 return Position(); 502 } 503 504 void VisibleSelection::adjustSelectionToAvoidCrossingShadowBoundaries() 505 { 506 if (m_base.isNull() || m_start.isNull() || m_end.isNull()) 507 return; 508 509 if (m_start.anchorNode()->treeScope() == m_end.anchorNode()->treeScope()) 510 return; 511 512 if (m_baseIsFirst) { 513 m_extent = adjustPositionForEnd(m_end, m_start.containerNode()); 514 m_end = m_extent; 515 } else { 516 m_extent = adjustPositionForStart(m_start, m_end.containerNode()); 517 m_start = m_extent; 518 } 519 520 ASSERT(m_start.anchorNode()->treeScope() == m_end.anchorNode()->treeScope()); 521 } 522 523 void VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries() 524 { 525 if (m_base.isNull() || m_start.isNull() || m_end.isNull()) 526 return; 527 528 Node* baseRoot = highestEditableRoot(m_base); 529 Node* startRoot = highestEditableRoot(m_start); 530 Node* endRoot = highestEditableRoot(m_end); 531 532 Node* baseEditableAncestor = lowestEditableAncestor(m_base.containerNode()); 533 534 // The base, start and end are all in the same region. No adjustment necessary. 535 if (baseRoot == startRoot && baseRoot == endRoot) 536 return; 537 538 // The selection is based in editable content. 539 if (baseRoot) { 540 // If the start is outside the base's editable root, cap it at the start of that root. 541 // If the start is in non-editable content that is inside the base's editable root, put it 542 // at the first editable position after start inside the base's editable root. 543 if (startRoot != baseRoot) { 544 VisiblePosition first = firstEditablePositionAfterPositionInRoot(m_start, baseRoot); 545 m_start = first.deepEquivalent(); 546 if (m_start.isNull()) { 547 ASSERT_NOT_REACHED(); 548 m_start = m_end; 549 } 550 } 551 // If the end is outside the base's editable root, cap it at the end of that root. 552 // If the end is in non-editable content that is inside the base's root, put it 553 // at the last editable position before the end inside the base's root. 554 if (endRoot != baseRoot) { 555 VisiblePosition last = lastEditablePositionBeforePositionInRoot(m_end, baseRoot); 556 m_end = last.deepEquivalent(); 557 if (m_end.isNull()) 558 m_end = m_start; 559 } 560 // The selection is based in non-editable content. 561 } else { 562 // FIXME: Non-editable pieces inside editable content should be atomic, in the same way that editable 563 // pieces in non-editable content are atomic. 564 565 // The selection ends in editable content or non-editable content inside a different editable ancestor, 566 // move backward until non-editable content inside the same lowest editable ancestor is reached. 567 Node* endEditableAncestor = lowestEditableAncestor(m_end.containerNode()); 568 if (endRoot || endEditableAncestor != baseEditableAncestor) { 569 570 Position p = previousVisuallyDistinctCandidate(m_end); 571 Node* shadowAncestor = endRoot ? endRoot->shadowHost() : 0; 572 if (p.isNull() && shadowAncestor) 573 p = positionAfterNode(shadowAncestor); 574 while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) { 575 Node* root = editableRootForPosition(p); 576 shadowAncestor = root ? root->shadowHost() : 0; 577 p = isAtomicNode(p.containerNode()) ? positionInParentBeforeNode(p.containerNode()) : previousVisuallyDistinctCandidate(p); 578 if (p.isNull() && shadowAncestor) 579 p = positionAfterNode(shadowAncestor); 580 } 581 VisiblePosition previous(p); 582 583 if (previous.isNull()) { 584 // The selection crosses an Editing boundary. This is a 585 // programmer error in the editing code. Happy debugging! 586 ASSERT_NOT_REACHED(); 587 m_base = Position(); 588 m_extent = Position(); 589 validate(); 590 return; 591 } 592 m_end = previous.deepEquivalent(); 593 } 594 595 // The selection starts in editable content or non-editable content inside a different editable ancestor, 596 // move forward until non-editable content inside the same lowest editable ancestor is reached. 597 Node* startEditableAncestor = lowestEditableAncestor(m_start.containerNode()); 598 if (startRoot || startEditableAncestor != baseEditableAncestor) { 599 Position p = nextVisuallyDistinctCandidate(m_start); 600 Node* shadowAncestor = startRoot ? startRoot->shadowHost() : 0; 601 if (p.isNull() && shadowAncestor) 602 p = positionBeforeNode(shadowAncestor); 603 while (p.isNotNull() && !(lowestEditableAncestor(p.containerNode()) == baseEditableAncestor && !isEditablePosition(p))) { 604 Node* root = editableRootForPosition(p); 605 shadowAncestor = root ? root->shadowHost() : 0; 606 p = isAtomicNode(p.containerNode()) ? positionInParentAfterNode(p.containerNode()) : nextVisuallyDistinctCandidate(p); 607 if (p.isNull() && shadowAncestor) 608 p = positionBeforeNode(shadowAncestor); 609 } 610 VisiblePosition next(p); 611 612 if (next.isNull()) { 613 // The selection crosses an Editing boundary. This is a 614 // programmer error in the editing code. Happy debugging! 615 ASSERT_NOT_REACHED(); 616 m_base = Position(); 617 m_extent = Position(); 618 validate(); 619 return; 620 } 621 m_start = next.deepEquivalent(); 622 } 623 } 624 625 // Correct the extent if necessary. 626 if (baseEditableAncestor != lowestEditableAncestor(m_extent.containerNode())) 627 m_extent = m_baseIsFirst ? m_end : m_start; 628 } 629 630 VisiblePosition VisibleSelection::visiblePositionRespectingEditingBoundary(const LayoutPoint& localPoint, Node* targetNode) const 631 { 632 if (!targetNode->renderer()) 633 return VisiblePosition(); 634 635 LayoutPoint selectionEndPoint = localPoint; 636 Element* editableElement = rootEditableElement(); 637 638 if (editableElement && !editableElement->contains(targetNode)) { 639 if (!editableElement->renderer()) 640 return VisiblePosition(); 641 642 FloatPoint absolutePoint = targetNode->renderer()->localToAbsolute(FloatPoint(selectionEndPoint)); 643 selectionEndPoint = roundedLayoutPoint(editableElement->renderer()->absoluteToLocal(absolutePoint)); 644 targetNode = editableElement; 645 } 646 647 return VisiblePosition(targetNode->renderer()->positionForPoint(selectionEndPoint)); 648 } 649 650 651 bool VisibleSelection::isContentEditable() const 652 { 653 return isEditablePosition(start()); 654 } 655 656 bool VisibleSelection::rendererIsEditable() const 657 { 658 return isEditablePosition(start(), ContentIsEditable, DoNotUpdateStyle); 659 } 660 661 bool VisibleSelection::isContentRichlyEditable() const 662 { 663 return isRichlyEditablePosition(start()); 664 } 665 666 Element* VisibleSelection::rootEditableElement() const 667 { 668 return editableRootForPosition(start()); 669 } 670 671 Node* VisibleSelection::nonBoundaryShadowTreeRootNode() const 672 { 673 return start().deprecatedNode() ? start().deprecatedNode()->nonBoundaryShadowTreeRootNode() : 0; 674 } 675 676 #ifndef NDEBUG 677 678 void VisibleSelection::debugPosition() const 679 { 680 fprintf(stderr, "VisibleSelection ===============\n"); 681 682 if (!m_start.anchorNode()) 683 fputs("pos: null", stderr); 684 else if (m_start == m_end) { 685 fprintf(stderr, "pos: %s ", m_start.anchorNode()->nodeName().utf8().data()); 686 m_start.showAnchorTypeAndOffset(); 687 } else { 688 fprintf(stderr, "start: %s ", m_start.anchorNode()->nodeName().utf8().data()); 689 m_start.showAnchorTypeAndOffset(); 690 fprintf(stderr, "end: %s ", m_end.anchorNode()->nodeName().utf8().data()); 691 m_end.showAnchorTypeAndOffset(); 692 } 693 694 fprintf(stderr, "================================\n"); 695 } 696 697 void VisibleSelection::formatForDebugger(char* buffer, unsigned length) const 698 { 699 StringBuilder result; 700 String s; 701 702 if (isNone()) { 703 result.appendLiteral("<none>"); 704 } else { 705 const int FormatBufferSize = 1024; 706 char s[FormatBufferSize]; 707 result.appendLiteral("from "); 708 start().formatForDebugger(s, FormatBufferSize); 709 result.append(s); 710 result.appendLiteral(" to "); 711 end().formatForDebugger(s, FormatBufferSize); 712 result.append(s); 713 } 714 715 strncpy(buffer, result.toString().utf8().data(), length - 1); 716 } 717 718 void VisibleSelection::showTreeForThis() const 719 { 720 if (start().anchorNode()) { 721 start().anchorNode()->showTreeAndMark(start().anchorNode(), "S", end().anchorNode(), "E"); 722 fputs("start: ", stderr); 723 start().showAnchorTypeAndOffset(); 724 fputs("end: ", stderr); 725 end().showAnchorTypeAndOffset(); 726 } 727 } 728 729 #endif 730 731 } // namespace WebCore 732 733 #ifndef NDEBUG 734 735 void showTree(const WebCore::VisibleSelection& sel) 736 { 737 sel.showTreeForThis(); 738 } 739 740 void showTree(const WebCore::VisibleSelection* sel) 741 { 742 if (sel) 743 sel->showTreeForThis(); 744 } 745 746 #endif 747