Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007 Apple 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 "htmlediting.h"
     28 
     29 #include "Document.h"
     30 #include "EditingText.h"
     31 #include "HTMLBRElement.h"
     32 #include "HTMLDivElement.h"
     33 #include "HTMLElementFactory.h"
     34 #include "HTMLInterchange.h"
     35 #include "HTMLLIElement.h"
     36 #include "HTMLNames.h"
     37 #include "HTMLObjectElement.h"
     38 #include "HTMLOListElement.h"
     39 #include "HTMLUListElement.h"
     40 #include "PositionIterator.h"
     41 #include "RenderObject.h"
     42 #include "Range.h"
     43 #include "VisibleSelection.h"
     44 #include "Text.h"
     45 #include "TextIterator.h"
     46 #include "VisiblePosition.h"
     47 #include "visible_units.h"
     48 #include <wtf/StdLibExtras.h>
     49 #include <wtf/unicode/CharacterNames.h>
     50 
     51 #if ENABLE(WML)
     52 #include "WMLNames.h"
     53 #endif
     54 
     55 using namespace std;
     56 
     57 namespace WebCore {
     58 
     59 using namespace HTMLNames;
     60 
     61 // Atomic means that the node has no children, or has children which are ignored for the
     62 // purposes of editing.
     63 bool isAtomicNode(const Node *node)
     64 {
     65     return node && (!node->hasChildNodes() || editingIgnoresContent(node));
     66 }
     67 
     68 // Returns true for nodes that either have no content, or have content that is ignored (skipped
     69 // over) while editing.  There are no VisiblePositions inside these nodes.
     70 bool editingIgnoresContent(const Node* node)
     71 {
     72     return !canHaveChildrenForEditing(node) && !node->isTextNode();
     73 }
     74 
     75 bool canHaveChildrenForEditing(const Node* node)
     76 {
     77     return !node->isTextNode()
     78         && !node->hasTagName(brTag)
     79         && !node->hasTagName(imgTag)
     80         && !node->hasTagName(inputTag)
     81         && !node->hasTagName(textareaTag)
     82         && (!node->hasTagName(objectTag) || static_cast<const HTMLObjectElement*>(node)->useFallbackContent())
     83         && !node->hasTagName(iframeTag)
     84         && !node->hasTagName(embedTag)
     85         && !node->hasTagName(appletTag)
     86         && !node->hasTagName(selectTag)
     87 #if ENABLE(WML)
     88         && !node->hasTagName(WMLNames::doTag)
     89 #endif
     90         && ((!node->hasTagName(hrTag) && !node->hasTagName(datagridTag)) || node->hasChildNodes());
     91 }
     92 
     93 // Compare two positions, taking into account the possibility that one or both
     94 // could be inside a shadow tree. Only works for non-null values.
     95 int comparePositions(const Position& a, const Position& b)
     96 {
     97     Node* nodeA = a.deprecatedNode();
     98     ASSERT(nodeA);
     99     Node* nodeB = b.deprecatedNode();
    100     ASSERT(nodeB);
    101     int offsetA = a.deprecatedEditingOffset();
    102     int offsetB = b.deprecatedEditingOffset();
    103 
    104     Node* shadowAncestorA = nodeA->shadowAncestorNode();
    105     if (shadowAncestorA == nodeA)
    106         shadowAncestorA = 0;
    107     Node* shadowAncestorB = nodeB->shadowAncestorNode();
    108     if (shadowAncestorB == nodeB)
    109         shadowAncestorB = 0;
    110 
    111     int bias = 0;
    112     if (shadowAncestorA != shadowAncestorB) {
    113         if (shadowAncestorA) {
    114             nodeA = shadowAncestorA;
    115             offsetA = 0;
    116             bias = 1;
    117         }
    118         if (shadowAncestorB) {
    119             nodeB = shadowAncestorB;
    120             offsetB = 0;
    121             bias = -1;
    122         }
    123     }
    124 
    125     ExceptionCode ec;
    126     int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB, ec);
    127     return result ? result : bias;
    128 }
    129 
    130 int comparePositions(const VisiblePosition& a, const VisiblePosition& b)
    131 {
    132     return comparePositions(a.deepEquivalent(), b.deepEquivalent());
    133 }
    134 
    135 Node* highestEditableRoot(const Position& position)
    136 {
    137     Node* node = position.deprecatedNode();
    138     if (!node)
    139         return 0;
    140 
    141     Node* highestRoot = editableRootForPosition(position);
    142     if (!highestRoot)
    143         return 0;
    144 
    145     node = highestRoot;
    146     while (node) {
    147         if (node->rendererIsEditable())
    148             highestRoot = node;
    149         if (node->hasTagName(bodyTag))
    150             break;
    151         node = node->parentNode();
    152     }
    153 
    154     return highestRoot;
    155 }
    156 
    157 Node* lowestEditableAncestor(Node* node)
    158 {
    159     if (!node)
    160         return 0;
    161 
    162     Node *lowestRoot = 0;
    163     while (node) {
    164         if (node->rendererIsEditable())
    165             return node->rootEditableElement();
    166         if (node->hasTagName(bodyTag))
    167             break;
    168         node = node->parentNode();
    169     }
    170 
    171     return lowestRoot;
    172 }
    173 
    174 bool isEditablePosition(const Position& p)
    175 {
    176     Node* node = p.deprecatedNode();
    177     if (!node)
    178         return false;
    179 
    180     if (node->renderer() && node->renderer()->isTable())
    181         node = node->parentNode();
    182 
    183     return node->rendererIsEditable();
    184 }
    185 
    186 bool isAtUnsplittableElement(const Position& pos)
    187 {
    188     Node* node = pos.deprecatedNode();
    189     return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(pos, &isTableCell));
    190 }
    191 
    192 
    193 bool isRichlyEditablePosition(const Position& p)
    194 {
    195     Node* node = p.deprecatedNode();
    196     if (!node)
    197         return false;
    198 
    199     if (node->renderer() && node->renderer()->isTable())
    200         node = node->parentNode();
    201 
    202     return node->rendererIsRichlyEditable();
    203 }
    204 
    205 Element* editableRootForPosition(const Position& p)
    206 {
    207     Node* node = p.deprecatedNode();
    208     if (!node)
    209         return 0;
    210 
    211     if (node->renderer() && node->renderer()->isTable())
    212         node = node->parentNode();
    213 
    214     return node->rootEditableElement();
    215 }
    216 
    217 // Finds the enclosing element until which the tree can be split.
    218 // When a user hits ENTER, he/she won't expect this element to be split into two.
    219 // You may pass it as the second argument of splitTreeToNode.
    220 Element* unsplittableElementForPosition(const Position& p)
    221 {
    222     // Since enclosingNodeOfType won't search beyond the highest root editable node,
    223     // this code works even if the closest table cell was outside of the root editable node.
    224     Element* enclosingCell = static_cast<Element*>(enclosingNodeOfType(p, &isTableCell));
    225     if (enclosingCell)
    226         return enclosingCell;
    227 
    228     return editableRootForPosition(p);
    229 }
    230 
    231 Position nextCandidate(const Position& position)
    232 {
    233     PositionIterator p = position;
    234     while (!p.atEnd()) {
    235         p.increment();
    236         if (p.isCandidate())
    237             return p;
    238     }
    239     return Position();
    240 }
    241 
    242 Position nextVisuallyDistinctCandidate(const Position& position)
    243 {
    244     Position p = position;
    245     Position downstreamStart = p.downstream();
    246     while (!p.atEndOfTree()) {
    247         p = p.next(Character);
    248         if (p.isCandidate() && p.downstream() != downstreamStart)
    249             return p;
    250     }
    251     return Position();
    252 }
    253 
    254 Position previousCandidate(const Position& position)
    255 {
    256     PositionIterator p = position;
    257     while (!p.atStart()) {
    258         p.decrement();
    259         if (p.isCandidate())
    260             return p;
    261     }
    262     return Position();
    263 }
    264 
    265 Position previousVisuallyDistinctCandidate(const Position& position)
    266 {
    267     Position p = position;
    268     Position downstreamStart = p.downstream();
    269     while (!p.atStartOfTree()) {
    270         p = p.previous(Character);
    271         if (p.isCandidate() && p.downstream() != downstreamStart)
    272             return p;
    273     }
    274     return Position();
    275 }
    276 
    277 VisiblePosition firstEditablePositionAfterPositionInRoot(const Position& position, Node* highestRoot)
    278 {
    279     // position falls before highestRoot.
    280     if (comparePositions(position, firstPositionInNode(highestRoot)) == -1 && highestRoot->rendererIsEditable())
    281         return firstPositionInNode(highestRoot);
    282 
    283     Position p = position;
    284 
    285     if (Node* shadowAncestor = p.deprecatedNode()->shadowAncestorNode())
    286         if (shadowAncestor != p.deprecatedNode())
    287             p = positionAfterNode(shadowAncestor);
    288 
    289     while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
    290         p = isAtomicNode(p.deprecatedNode()) ? positionInParentAfterNode(p.deprecatedNode()) : nextVisuallyDistinctCandidate(p);
    291 
    292     if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
    293         return VisiblePosition();
    294 
    295     return VisiblePosition(p);
    296 }
    297 
    298 VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& position, Node* highestRoot)
    299 {
    300     // When position falls after highestRoot, the result is easy to compute.
    301     if (comparePositions(position, lastPositionInNode(highestRoot)) == 1)
    302         return lastPositionInNode(highestRoot);
    303 
    304     Position p = position;
    305 
    306     if (Node* shadowAncestor = p.deprecatedNode()->shadowAncestorNode()) {
    307         if (shadowAncestor != p.deprecatedNode())
    308             p = firstPositionInOrBeforeNode(shadowAncestor);
    309     }
    310 
    311     while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
    312         p = isAtomicNode(p.deprecatedNode()) ? positionInParentBeforeNode(p.deprecatedNode()) : previousVisuallyDistinctCandidate(p);
    313 
    314     if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
    315         return VisiblePosition();
    316 
    317     return VisiblePosition(p);
    318 }
    319 
    320 // FIXME: The method name, comment, and code say three different things here!
    321 // Whether or not content before and after this node will collapse onto the same line as it.
    322 bool isBlock(const Node* node)
    323 {
    324     return node && node->renderer() && !node->renderer()->isInline();
    325 }
    326 
    327 // FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
    328 // FIXME: Pass a position to this function.  The enclosing block of [table, x] for example, should be the
    329 // block that contains the table and not the table, and this function should be the only one responsible for
    330 // knowing about these kinds of special cases.
    331 Node* enclosingBlock(Node* node, EditingBoundaryCrossingRule rule)
    332 {
    333     return static_cast<Element*>(enclosingNodeOfType(firstPositionInOrBeforeNode(node), isBlock, rule));
    334 }
    335 
    336 TextDirection directionOfEnclosingBlock(const Position& position)
    337 {
    338     Node* enclosingBlockNode = enclosingBlock(position.containerNode());
    339     if (!enclosingBlockNode)
    340         return LTR;
    341     RenderObject* renderer = enclosingBlockNode->renderer();
    342     return renderer ? renderer->style()->direction() : LTR;
    343 }
    344 
    345 // This method is used to create positions in the DOM. It returns the maximum valid offset
    346 // in a node.  It returns 1 for some elements even though they do not have children, which
    347 // creates technically invalid DOM Positions.  Be sure to call parentAnchoredEquivalent
    348 // on a Position before using it to create a DOM Range, or an exception will be thrown.
    349 int lastOffsetForEditing(const Node* node)
    350 {
    351     ASSERT(node);
    352     if (!node)
    353         return 0;
    354     if (node->offsetInCharacters())
    355         return node->maxCharacterOffset();
    356 
    357     if (node->hasChildNodes())
    358         return node->childNodeCount();
    359 
    360     // NOTE: This should preempt the childNodeCount for, e.g., select nodes
    361     if (editingIgnoresContent(node))
    362         return 1;
    363 
    364     return 0;
    365 }
    366 
    367 String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph)
    368 {
    369     Vector<UChar> rebalancedString;
    370     append(rebalancedString, string);
    371 
    372     bool previousCharacterWasSpace = false;
    373     for (size_t i = 0; i < rebalancedString.size(); i++) {
    374         if (!isWhitespace(rebalancedString[i])) {
    375             previousCharacterWasSpace = false;
    376             continue;
    377         }
    378 
    379         if (previousCharacterWasSpace || (!i && startIsStartOfParagraph) || (i + 1 == rebalancedString.size() && endIsEndOfParagraph)) {
    380             rebalancedString[i] = noBreakSpace;
    381             previousCharacterWasSpace = false;
    382         } else {
    383             rebalancedString[i] = ' ';
    384             previousCharacterWasSpace = true;
    385         }
    386 
    387     }
    388 
    389     return String::adopt(rebalancedString);
    390 }
    391 
    392 bool isTableStructureNode(const Node *node)
    393 {
    394     RenderObject *r = node->renderer();
    395     return (r && (r->isTableCell() || r->isTableRow() || r->isTableSection() || r->isTableCol()));
    396 }
    397 
    398 const String& nonBreakingSpaceString()
    399 {
    400     DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1));
    401     return nonBreakingSpaceString;
    402 }
    403 
    404 // FIXME: need to dump this
    405 bool isSpecialElement(const Node *n)
    406 {
    407     if (!n)
    408         return false;
    409 
    410     if (!n->isHTMLElement())
    411         return false;
    412 
    413     if (n->isLink())
    414         return true;
    415 
    416     RenderObject *renderer = n->renderer();
    417     if (!renderer)
    418         return false;
    419 
    420     if (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE)
    421         return true;
    422 
    423     if (renderer->style()->isFloating())
    424         return true;
    425 
    426     if (renderer->style()->position() != StaticPosition)
    427         return true;
    428 
    429     return false;
    430 }
    431 
    432 static Node* firstInSpecialElement(const Position& pos)
    433 {
    434     // FIXME: This begins at pos.deprecatedNode(), which doesn't necessarily contain pos (suppose pos was [img, 0]).  See <rdar://problem/5027702>.
    435     Node* rootEditableElement = pos.deprecatedNode()->rootEditableElement();
    436     for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
    437         if (isSpecialElement(n)) {
    438             VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
    439             VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBeforeNode(n), DOWNSTREAM);
    440             if (isTableElement(n) && vPos == firstInElement.next())
    441                 return n;
    442             if (vPos == firstInElement)
    443                 return n;
    444         }
    445     return 0;
    446 }
    447 
    448 static Node* lastInSpecialElement(const Position& pos)
    449 {
    450     // FIXME: This begins at pos.deprecatedNode(), which doesn't necessarily contain pos (suppose pos was [img, 0]).  See <rdar://problem/5027702>.
    451     Node* rootEditableElement = pos.deprecatedNode()->rootEditableElement();
    452     for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
    453         if (isSpecialElement(n)) {
    454             VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
    455             VisiblePosition lastInElement = VisiblePosition(Position(n, n->childNodeCount(), Position::PositionIsOffsetInAnchor), DOWNSTREAM);
    456             if (isTableElement(n) && vPos == lastInElement.previous())
    457                 return n;
    458             if (vPos == lastInElement)
    459                 return n;
    460         }
    461     return 0;
    462 }
    463 
    464 bool isFirstVisiblePositionInSpecialElement(const Position& pos)
    465 {
    466     return firstInSpecialElement(pos);
    467 }
    468 
    469 Position positionBeforeContainingSpecialElement(const Position& pos, Node** containingSpecialElement)
    470 {
    471     Node* n = firstInSpecialElement(pos);
    472     if (!n)
    473         return pos;
    474     Position result = positionInParentBeforeNode(n);
    475     if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos.deprecatedNode()->rootEditableElement())
    476         return pos;
    477     if (containingSpecialElement)
    478         *containingSpecialElement = n;
    479     return result;
    480 }
    481 
    482 bool isLastVisiblePositionInSpecialElement(const Position& pos)
    483 {
    484     return lastInSpecialElement(pos);
    485 }
    486 
    487 Position positionAfterContainingSpecialElement(const Position& pos, Node **containingSpecialElement)
    488 {
    489     Node* n = lastInSpecialElement(pos);
    490     if (!n)
    491         return pos;
    492     Position result = positionInParentAfterNode(n);
    493     if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos.deprecatedNode()->rootEditableElement())
    494         return pos;
    495     if (containingSpecialElement)
    496         *containingSpecialElement = n;
    497     return result;
    498 }
    499 
    500 Position positionOutsideContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
    501 {
    502     if (isFirstVisiblePositionInSpecialElement(pos))
    503         return positionBeforeContainingSpecialElement(pos, containingSpecialElement);
    504     if (isLastVisiblePositionInSpecialElement(pos))
    505         return positionAfterContainingSpecialElement(pos, containingSpecialElement);
    506     return pos;
    507 }
    508 
    509 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
    510 {
    511     Position upstream(visiblePosition.deepEquivalent().upstream());
    512     if (upstream.deprecatedNode() && upstream.deprecatedNode()->renderer() && upstream.deprecatedNode()->renderer()->isTable() && upstream.atLastEditingPositionForNode())
    513         return upstream.deprecatedNode();
    514 
    515     return 0;
    516 }
    517 
    518 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
    519 {
    520     Position downstream(visiblePosition.deepEquivalent().downstream());
    521     if (downstream.deprecatedNode() && downstream.deprecatedNode()->renderer() && downstream.deprecatedNode()->renderer()->isTable() && downstream.atFirstEditingPositionForNode())
    522         return downstream.deprecatedNode();
    523 
    524     return 0;
    525 }
    526 
    527 // Returns the visible position at the beginning of a node
    528 VisiblePosition visiblePositionBeforeNode(Node* node)
    529 {
    530     ASSERT(node);
    531     if (node->childNodeCount())
    532         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
    533     ASSERT(node->parentNode());
    534     return positionInParentBeforeNode(node);
    535 }
    536 
    537 // Returns the visible position at the ending of a node
    538 VisiblePosition visiblePositionAfterNode(Node* node)
    539 {
    540     ASSERT(node);
    541     if (node->childNodeCount())
    542         return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM);
    543     ASSERT(node->parentNode());
    544     return positionInParentAfterNode(node);
    545 }
    546 
    547 // Create a range object with two visible positions, start and end.
    548 // create(PassRefPtr<Document>, const Position&, const Position&); will use deprecatedEditingOffset
    549 // Use this function instead of create a regular range object (avoiding editing offset).
    550 PassRefPtr<Range> createRange(PassRefPtr<Document> document, const VisiblePosition& start, const VisiblePosition& end, ExceptionCode& ec)
    551 {
    552     ec = 0;
    553     RefPtr<Range> selectedRange = Range::create(document);
    554     selectedRange->setStart(start.deepEquivalent().containerNode(), start.deepEquivalent().computeOffsetInContainerNode(), ec);
    555     if (!ec)
    556         selectedRange->setEnd(end.deepEquivalent().containerNode(), end.deepEquivalent().computeOffsetInContainerNode(), ec);
    557     return selectedRange.release();
    558 }
    559 
    560 // Extend rangeToExtend to include nodes that wraps range and visibly starts and ends inside or at the boudnaries of maximumRange
    561 // e.g. if the original range spaned "hello" in <div>hello</div>, then this function extends the range to contain div's around it.
    562 // Call this function before copying / moving paragraphs to contain all wrapping nodes.
    563 // This function stops extending the range immediately below rootNode; i.e. the extended range can contain a child node of rootNode
    564 // but it can never contain rootNode itself.
    565 PassRefPtr<Range> extendRangeToWrappingNodes(PassRefPtr<Range> range, const Range* maximumRange, const Node* rootNode)
    566 {
    567     ASSERT(range);
    568     ASSERT(maximumRange);
    569 
    570     ExceptionCode ec = 0;
    571     Node* ancestor = range->commonAncestorContainer(ec);// find the cloeset common ancestor
    572     Node* highestNode = 0;
    573     // traverse through ancestors as long as they are contained within the range, content-editable, and below rootNode (could be =0).
    574     while (ancestor && ancestor->rendererIsEditable() && isNodeVisiblyContainedWithin(ancestor, maximumRange) && ancestor != rootNode) {
    575         highestNode = ancestor;
    576         ancestor = ancestor->parentNode();
    577     }
    578 
    579     if (!highestNode)
    580         return range;
    581 
    582     // Create new range with the highest editable node contained within the range
    583     RefPtr<Range> extendedRange = Range::create(range->ownerDocument());
    584     extendedRange->selectNode(highestNode, ec);
    585     return extendedRange.release();
    586 }
    587 
    588 bool isListElement(Node *n)
    589 {
    590     return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(dlTag)));
    591 }
    592 
    593 bool isListItem(Node *n)
    594 {
    595     return n && n->renderer() && n->renderer()->isListItem();
    596 }
    597 
    598 Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName)
    599 {
    600     if (p.isNull())
    601         return 0;
    602 
    603     Node* root = highestEditableRoot(p);
    604     for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) {
    605         if (root && !n->rendererIsEditable())
    606             continue;
    607         if (n->hasTagName(tagName))
    608             return n;
    609         if (n == root)
    610             return 0;
    611     }
    612 
    613     return 0;
    614 }
    615 
    616 Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
    617 {
    618     // FIXME: support CanSkipCrossEditingBoundary
    619     ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
    620     if (p.isNull())
    621         return 0;
    622 
    623     Node* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : 0;
    624     for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) {
    625         // Don't return a non-editable node if the input position was editable, since
    626         // the callers from editing will no doubt want to perform editing inside the returned node.
    627         if (root && !n->rendererIsEditable())
    628             continue;
    629         if (nodeIsOfType(n))
    630             return n;
    631         if (n == root)
    632             return 0;
    633     }
    634 
    635     return 0;
    636 }
    637 
    638 Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
    639 {
    640     Node* highest = 0;
    641     Node* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : 0;
    642     for (Node* n = p.containerNode(); n; n = n->parentNode()) {
    643         if (root && !n->rendererIsEditable())
    644             continue;
    645         if (nodeIsOfType(n))
    646             highest = n;
    647         if (n == root)
    648             break;
    649     }
    650 
    651     return highest;
    652 }
    653 
    654 Node* enclosingTableCell(const Position& p)
    655 {
    656     return static_cast<Element*>(enclosingNodeOfType(p, isTableCell));
    657 }
    658 
    659 Node* enclosingAnchorElement(const Position& p)
    660 {
    661     if (p.isNull())
    662         return 0;
    663 
    664     Node* node = p.deprecatedNode();
    665     while (node && !(node->isElementNode() && node->isLink()))
    666         node = node->parentNode();
    667     return node;
    668 }
    669 
    670 HTMLElement* enclosingList(Node* node)
    671 {
    672     if (!node)
    673         return 0;
    674 
    675     Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
    676 
    677     for (ContainerNode* n = node->parentNode(); n; n = n->parentNode()) {
    678         if (n->hasTagName(ulTag) || n->hasTagName(olTag))
    679             return toHTMLElement(n);
    680         if (n == root)
    681             return 0;
    682     }
    683 
    684     return 0;
    685 }
    686 
    687 Node* enclosingListChild(Node *node)
    688 {
    689     if (!node)
    690         return 0;
    691     // Check for a list item element, or for a node whose parent is a list element.  Such a node
    692     // will appear visually as a list item (but without a list marker)
    693     Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
    694 
    695     // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
    696     for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
    697         if (n->hasTagName(liTag) || isListElement(n->parentNode()))
    698             return n;
    699         if (n == root || isTableCell(n))
    700             return 0;
    701     }
    702 
    703     return 0;
    704 }
    705 
    706 static HTMLElement* embeddedSublist(Node* listItem)
    707 {
    708     // Check the DOM so that we'll find collapsed sublists without renderers.
    709     for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
    710         if (isListElement(n))
    711             return toHTMLElement(n);
    712     }
    713 
    714     return 0;
    715 }
    716 
    717 static Node* appendedSublist(Node* listItem)
    718 {
    719     // Check the DOM so that we'll find collapsed sublists without renderers.
    720     for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
    721         if (isListElement(n))
    722             return toHTMLElement(n);
    723         if (isListItem(listItem))
    724             return 0;
    725     }
    726 
    727     return 0;
    728 }
    729 
    730 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagraph
    731 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos)
    732 {
    733     // Check that position is on a line by itself inside a list item
    734     Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().deprecatedNode());
    735     if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(visiblePos))
    736         return 0;
    737 
    738     VisiblePosition firstInListChild(firstPositionInOrBeforeNode(listChildNode));
    739     VisiblePosition lastInListChild(lastPositionInOrAfterNode(listChildNode));
    740 
    741     if (firstInListChild != visiblePos || lastInListChild != visiblePos)
    742         return 0;
    743 
    744     if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
    745         return 0;
    746 
    747     return listChildNode;
    748 }
    749 
    750 HTMLElement* outermostEnclosingList(Node* node, Node* rootList)
    751 {
    752     HTMLElement* list = enclosingList(node);
    753     if (!list)
    754         return 0;
    755 
    756     while (HTMLElement* nextList = enclosingList(list)) {
    757         if (nextList == rootList)
    758             break;
    759         list = nextList;
    760     }
    761 
    762     return list;
    763 }
    764 
    765 bool canMergeLists(Element* firstList, Element* secondList)
    766 {
    767     if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList->isHTMLElement())
    768         return false;
    769 
    770     return firstList->hasTagName(secondList->tagQName())// make sure the list types match (ol vs. ul)
    771     && firstList->rendererIsEditable() && secondList->rendererIsEditable() // both lists are editable
    772     && firstList->rootEditableElement() == secondList->rootEditableElement()// don't cross editing boundaries
    773     && isVisiblyAdjacent(positionInParentAfterNode(firstList), positionInParentBeforeNode(secondList));
    774     // Make sure there is no visible content between this li and the previous list
    775 }
    776 
    777 Node* highestAncestor(Node* node)
    778 {
    779     ASSERT(node);
    780     Node* parent = node;
    781     while ((node = node->parentNode()))
    782         parent = node;
    783     return parent;
    784 }
    785 
    786 // FIXME: do not require renderer, so that this can be used within fragments, or rename to isRenderedTable()
    787 bool isTableElement(Node* n)
    788 {
    789     if (!n || !n->isElementNode())
    790         return false;
    791 
    792     RenderObject* renderer = n->renderer();
    793     return (renderer && (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE));
    794 }
    795 
    796 bool isTableCell(const Node* node)
    797 {
    798     RenderObject* r = node->renderer();
    799     if (!r)
    800         return node->hasTagName(tdTag) || node->hasTagName(thTag);
    801 
    802     return r->isTableCell();
    803 }
    804 
    805 bool isEmptyTableCell(const Node* node)
    806 {
    807     // Returns true IFF the passed in node is one of:
    808     //   .) a table cell with no children,
    809     //   .) a table cell with a single BR child, and which has no other child renderers, including :before and :after renderers
    810     //   .) the BR child of such a table cell
    811 
    812     // Find rendered node
    813     while (node && !node->renderer())
    814         node = node->parentNode();
    815     if (!node)
    816         return false;
    817 
    818     // Make sure the rendered node is a table cell or <br>.
    819     // If it's a <br>, then the parent node has to be a table cell.
    820     RenderObject* renderer = node->renderer();
    821     if (renderer->isBR()) {
    822         renderer = renderer->parent();
    823         if (!renderer)
    824             return false;
    825     }
    826     if (!renderer->isTableCell())
    827         return false;
    828 
    829     // Check that the table cell contains no child renderers except for perhaps a single <br>.
    830     RenderObject* childRenderer = renderer->firstChild();
    831     if (!childRenderer)
    832         return true;
    833     if (!childRenderer->isBR())
    834         return false;
    835     return !childRenderer->nextSibling();
    836 }
    837 
    838 PassRefPtr<HTMLElement> createDefaultParagraphElement(Document* document)
    839 {
    840     return HTMLDivElement::create(document);
    841 }
    842 
    843 PassRefPtr<HTMLElement> createBreakElement(Document* document)
    844 {
    845     return HTMLBRElement::create(document);
    846 }
    847 
    848 PassRefPtr<HTMLElement> createOrderedListElement(Document* document)
    849 {
    850     return HTMLOListElement::create(document);
    851 }
    852 
    853 PassRefPtr<HTMLElement> createUnorderedListElement(Document* document)
    854 {
    855     return HTMLUListElement::create(document);
    856 }
    857 
    858 PassRefPtr<HTMLElement> createListItemElement(Document* document)
    859 {
    860     return HTMLLIElement::create(document);
    861 }
    862 
    863 PassRefPtr<HTMLElement> createHTMLElement(Document* document, const QualifiedName& name)
    864 {
    865     return HTMLElementFactory::createHTMLElement(name, document, 0, false);
    866 }
    867 
    868 PassRefPtr<HTMLElement> createHTMLElement(Document* document, const AtomicString& tagName)
    869 {
    870     return createHTMLElement(document, QualifiedName(nullAtom, tagName, xhtmlNamespaceURI));
    871 }
    872 
    873 bool isTabSpanNode(const Node *node)
    874 {
    875     return node && node->hasTagName(spanTag) && node->isElementNode() && static_cast<const Element *>(node)->getAttribute(classAttr) == AppleTabSpanClass;
    876 }
    877 
    878 bool isTabSpanTextNode(const Node *node)
    879 {
    880     return node && node->isTextNode() && node->parentNode() && isTabSpanNode(node->parentNode());
    881 }
    882 
    883 Node *tabSpanNode(const Node *node)
    884 {
    885     return isTabSpanTextNode(node) ? node->parentNode() : 0;
    886 }
    887 
    888 bool isNodeInTextFormControl(Node* node)
    889 {
    890     if (!node)
    891         return false;
    892     Node* ancestor = node->shadowAncestorNode();
    893     if (ancestor == node)
    894         return false;
    895     return ancestor->isElementNode() && static_cast<Element*>(ancestor)->isTextFormControl();
    896 }
    897 
    898 Position positionOutsideTabSpan(const Position& pos)
    899 {
    900     Node* node = pos.containerNode();
    901     if (isTabSpanTextNode(node))
    902         node = tabSpanNode(node);
    903     else if (!isTabSpanNode(node))
    904         return pos;
    905 
    906     if (node && VisiblePosition(pos) == lastPositionInNode(node))
    907         return positionInParentAfterNode(node);
    908 
    909     return positionInParentBeforeNode(node);
    910 }
    911 
    912 PassRefPtr<Element> createTabSpanElement(Document* document, PassRefPtr<Node> tabTextNode)
    913 {
    914     // Make the span to hold the tab.
    915     RefPtr<Element> spanElement = document->createElement(spanTag, false);
    916     spanElement->setAttribute(classAttr, AppleTabSpanClass);
    917     spanElement->setAttribute(styleAttr, "white-space:pre");
    918 
    919     // Add tab text to that span.
    920     if (!tabTextNode)
    921         tabTextNode = document->createEditingTextNode("\t");
    922 
    923     ExceptionCode ec = 0;
    924     spanElement->appendChild(tabTextNode, ec);
    925     ASSERT(ec == 0);
    926 
    927     return spanElement.release();
    928 }
    929 
    930 PassRefPtr<Element> createTabSpanElement(Document* document, const String& tabText)
    931 {
    932     return createTabSpanElement(document, document->createTextNode(tabText));
    933 }
    934 
    935 PassRefPtr<Element> createTabSpanElement(Document* document)
    936 {
    937     return createTabSpanElement(document, PassRefPtr<Node>());
    938 }
    939 
    940 bool isNodeRendered(const Node *node)
    941 {
    942     if (!node)
    943         return false;
    944 
    945     RenderObject *renderer = node->renderer();
    946     if (!renderer)
    947         return false;
    948 
    949     return renderer->style()->visibility() == VISIBLE;
    950 }
    951 
    952 unsigned numEnclosingMailBlockquotes(const Position& p)
    953 {
    954     unsigned num = 0;
    955     for (Node* n = p.deprecatedNode(); n; n = n->parentNode())
    956         if (isMailBlockquote(n))
    957             num++;
    958 
    959     return num;
    960 }
    961 
    962 bool isMailBlockquote(const Node *node)
    963 {
    964     if (!node || !node->hasTagName(blockquoteTag))
    965         return false;
    966 
    967     return static_cast<const Element *>(node)->getAttribute("type") == "cite";
    968 }
    969 
    970 int caretMinOffset(const Node* n)
    971 {
    972     RenderObject* r = n->renderer();
    973     ASSERT(!n->isCharacterDataNode() || !r || r->isText()); // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
    974     return r ? r->caretMinOffset() : 0;
    975 }
    976 
    977 // If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise
    978 // return the number of children for container nodes and the length for unrendered text nodes.
    979 int caretMaxOffset(const Node* n)
    980 {
    981     // For rendered text nodes, return the last position that a caret could occupy.
    982     if (n->isTextNode() && n->renderer())
    983         return n->renderer()->caretMaxOffset();
    984     // For containers return the number of children.  For others do the same as above.
    985     return lastOffsetForEditing(n);
    986 }
    987 
    988 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition)
    989 {
    990     return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream());
    991 }
    992 
    993 bool lineBreakExistsAtPosition(const Position& position)
    994 {
    995     if (position.isNull())
    996         return false;
    997 
    998     if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPositionForNode())
    999         return true;
   1000 
   1001     if (!position.anchorNode()->renderer())
   1002         return false;
   1003 
   1004     if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer()->style()->preserveNewline())
   1005         return false;
   1006 
   1007     Text* textNode = static_cast<Text*>(position.anchorNode());
   1008     unsigned offset = position.offsetInContainerNode();
   1009     return offset < textNode->length() && textNode->data()[offset] == '\n';
   1010 }
   1011 
   1012 // Modifies selections that have an end point at the edge of a table
   1013 // that contains the other endpoint so that they don't confuse
   1014 // code that iterates over selected paragraphs.
   1015 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original)
   1016 {
   1017     VisibleSelection newSelection(original);
   1018     VisiblePosition startOfSelection(newSelection.visibleStart());
   1019     VisiblePosition endOfSelection(newSelection.visibleEnd());
   1020 
   1021     // If the end of the selection to modify is just after a table, and
   1022     // if the start of the selection is inside that table, then the last paragraph
   1023     // that we'll want modify is the last one inside the table, not the table itself
   1024     // (a table is itself a paragraph).
   1025     if (Node* table = isFirstPositionAfterTable(endOfSelection))
   1026         if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
   1027             newSelection = VisibleSelection(startOfSelection, endOfSelection.previous(CannotCrossEditingBoundary));
   1028 
   1029     // If the start of the selection to modify is just before a table,
   1030     // and if the end of the selection is inside that table, then the first paragraph
   1031     // we'll want to modify is the first one inside the table, not the paragraph
   1032     // containing the table itself.
   1033     if (Node* table = isLastPositionBeforeTable(startOfSelection))
   1034         if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
   1035             newSelection = VisibleSelection(startOfSelection.next(CannotCrossEditingBoundary), endOfSelection);
   1036 
   1037     return newSelection;
   1038 }
   1039 
   1040 
   1041 int indexForVisiblePosition(const VisiblePosition& visiblePosition)
   1042 {
   1043     if (visiblePosition.isNull())
   1044         return 0;
   1045     Position p(visiblePosition.deepEquivalent());
   1046     RefPtr<Range> range = Range::create(p.anchorNode()->document(), firstPositionInNode(p.anchorNode()->document()->documentElement()),
   1047                                         p.parentAnchoredEquivalent());
   1048     return TextIterator::rangeLength(range.get(), true);
   1049 }
   1050 
   1051 // Determines whether two positions are visibly next to each other (first then second)
   1052 // while ignoring whitespaces and unrendered nodes
   1053 bool isVisiblyAdjacent(const Position& first, const Position& second)
   1054 {
   1055     return VisiblePosition(first) == VisiblePosition(second.upstream());
   1056 }
   1057 
   1058 // Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range.
   1059 // Call this function to determine whether a node is visibly fit inside selectedRange
   1060 bool isNodeVisiblyContainedWithin(Node* node, const Range* selectedRange)
   1061 {
   1062     ASSERT(node);
   1063     ASSERT(selectedRange);
   1064     // If the node is inside the range, then it surely is contained within
   1065     ExceptionCode ec = 0;
   1066     if (selectedRange->compareNode(node, ec) == Range::NODE_INSIDE)
   1067         return true;
   1068 
   1069     bool startIsVisuallySame = visiblePositionBeforeNode(node) == selectedRange->startPosition();
   1070     if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node), selectedRange->endPosition()) < 0)
   1071         return true;
   1072 
   1073     bool endIsVisuallySame = visiblePositionAfterNode(node) == selectedRange->endPosition();
   1074     if (endIsVisuallySame && comparePositions(selectedRange->startPosition(), positionInParentBeforeNode(node)) < 0)
   1075         return true;
   1076 
   1077     return startIsVisuallySame && endIsVisuallySame;
   1078 }
   1079 
   1080 bool isRenderedAsNonInlineTableImageOrHR(const Node* node)
   1081 {
   1082     if (!node)
   1083         return false;
   1084     RenderObject* renderer = node->renderer();
   1085     return renderer && ((renderer->isTable() && !renderer->isInline()) || (renderer->isImage() && !renderer->isInline()) || renderer->isHR());
   1086 }
   1087 
   1088 PassRefPtr<Range> avoidIntersectionWithNode(const Range* range, Node* node)
   1089 {
   1090     if (!range)
   1091         return 0;
   1092 
   1093     Document* document = range->ownerDocument();
   1094 
   1095     Node* startContainer = range->startContainer();
   1096     int startOffset = range->startOffset();
   1097     Node* endContainer = range->endContainer();
   1098     int endOffset = range->endOffset();
   1099 
   1100     if (!startContainer)
   1101         return 0;
   1102 
   1103     ASSERT(endContainer);
   1104 
   1105     if (startContainer == node || startContainer->isDescendantOf(node)) {
   1106         ASSERT(node->parentNode());
   1107         startContainer = node->parentNode();
   1108         startOffset = node->nodeIndex();
   1109     }
   1110     if (endContainer == node || endContainer->isDescendantOf(node)) {
   1111         ASSERT(node->parentNode());
   1112         endContainer = node->parentNode();
   1113         endOffset = node->nodeIndex();
   1114     }
   1115 
   1116     return Range::create(document, startContainer, startOffset, endContainer, endOffset);
   1117 }
   1118 
   1119 VisibleSelection avoidIntersectionWithNode(const VisibleSelection& selection, Node* node)
   1120 {
   1121     if (selection.isNone())
   1122         return VisibleSelection(selection);
   1123 
   1124     VisibleSelection updatedSelection(selection);
   1125     Node* base = selection.base().deprecatedNode();
   1126     Node* extent = selection.extent().deprecatedNode();
   1127     ASSERT(base);
   1128     ASSERT(extent);
   1129 
   1130     if (base == node || base->isDescendantOf(node)) {
   1131         ASSERT(node->parentNode());
   1132         updatedSelection.setBase(positionInParentBeforeNode(node));
   1133     }
   1134 
   1135     if (extent == node || extent->isDescendantOf(node)) {
   1136         ASSERT(node->parentNode());
   1137         updatedSelection.setExtent(positionInParentBeforeNode(node));
   1138     }
   1139 
   1140     return updatedSelection;
   1141 }
   1142 
   1143 } // namespace WebCore
   1144