Changeset 41863 in webkit


Ignore:
Timestamp:
Mar 20, 2009 11:45:15 AM (15 years ago)
Author:
eric@webkit.org
Message:

Reviewed by Justin Garcia.

maxDeepOffset is confusing and should be removed
https://bugs.webkit.org/show_bug.cgi?id=24586

Abstract some hard-to-read (but shared) logic into a new renderedAsNonInlineTableOrHR function.
Add first/lastDeepEditingPositionForNode Position creation functions
and deploy them to places we used to call maxDeepOffset.

Rename Position::atStart and atEnd to atStartOfTree atEndOfTree
Add a new Position::atFirst/atLastEditingPositionForNode() and use these
to replace a few more callers for maxDeepOffset()

Rename maxDeepOffset to lastEditingOffsetForNode (so that we mere mortals have some clue what it does)

"Editing positions" are confusing because they have one
of two behaviors, depending on if the container node is ignored
by editing (if editingIgnoresContent(node) returns true) or not.
Positions referring to nodes ignored by editing are
neighbor-relative (they are before or after the node) where as
positions reffering to other nodes are container-relative
(they are between two child nodes of the container, identified
by the offset() member). I will be fixing this confusion in
future patches. These renames hopefully make the current behavior clearer.

  • dom/Position.cpp: (WebCore::Position::previous): (WebCore::Position::next): (WebCore::Position::atFirstEditingPositionForNode): (WebCore::Position::atLastEditingPositionForNode): (WebCore::Position::atStartOfTree): (WebCore::Position::atEndOfTree): (WebCore::Position::previousCharacterPosition): (WebCore::Position::nextCharacterPosition): (WebCore::Position::upstream): (WebCore::Position::isCandidate): (WebCore::firstDeepEditingPositionForNode): (WebCore::lastDeepEditingPositionForNode):
  • dom/Position.h:
  • dom/PositionIterator.cpp: (WebCore::PositionIterator::operator Position): (WebCore::PositionIterator::increment): (WebCore::PositionIterator::decrement): (WebCore::PositionIterator::atEnd): (WebCore::PositionIterator::atEndOfNode):
  • editing/CompositeEditCommand.cpp: (WebCore::CompositeEditCommand::positionAvoidingSpecialElementBoundary):
  • editing/DeleteSelectionCommand.cpp: (WebCore::isTableCellEmpty): (WebCore::DeleteSelectionCommand::removeNode): (WebCore::DeleteSelectionCommand::handleGeneralDelete):
  • editing/Editor.cpp: (WebCore::Editor::advanceToNextMisspelling):
  • editing/InsertLineBreakCommand.cpp: (WebCore::InsertLineBreakCommand::doApply):
  • editing/InsertListCommand.cpp: (WebCore::InsertListCommand::doApply):
  • editing/ReplaceSelectionCommand.cpp: (WebCore::ReplaceSelectionCommand::positionAtEndOfInsertedContent):
  • editing/TypingCommand.cpp: (WebCore::TypingCommand::forwardDeleteKeyPressed):
  • editing/VisiblePosition.cpp: (WebCore::VisiblePosition::previous): (WebCore::VisiblePosition::leftVisuallyDistinctCandidate): (WebCore::VisiblePosition::left): (WebCore::VisiblePosition::rightVisuallyDistinctCandidate): (WebCore::VisiblePosition::right):
  • editing/VisibleSelection.cpp: (WebCore::VisibleSelection::selectionFromContentsOfNode): (WebCore::VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries):
  • editing/htmlediting.cpp: (WebCore::nextVisuallyDistinctCandidate): (WebCore::previousVisuallyDistinctCandidate): (WebCore::firstEditablePositionAfterPositionInRoot): (WebCore::lastEditablePositionBeforePositionInRoot): (WebCore::lastOffsetForEditing): (WebCore::isFirstPositionAfterTable): (WebCore::isLastPositionBeforeTable): (WebCore::positionBeforeNode): (WebCore::positionAfterNode): (WebCore::enclosingEmptyListItem): (WebCore::caretMaxOffset):
  • editing/htmlediting.h:
  • editing/visible_units.cpp: (WebCore::renderedAsNonInlineTableOrHR): (WebCore::startOfParagraph): (WebCore::endOfParagraph): (WebCore::startOfEditableContent): (WebCore::endOfEditableContent):
  • page/AccessibilityObject.cpp: (WebCore::endOfStyleRange):
  • page/AccessibilityRenderObject.cpp: (WebCore::AccessibilityRenderObject::visiblePositionRange):
  • rendering/RenderBox.cpp: (WebCore::RenderBox::positionForPoint):
Location:
trunk/WebCore
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r41862 r41863  
     12009-03-20  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Justin Garcia.
     4
     5        maxDeepOffset is confusing and should be removed
     6        https://bugs.webkit.org/show_bug.cgi?id=24586
     7
     8        Abstract some hard-to-read (but shared) logic into a new renderedAsNonInlineTableOrHR function.
     9        Add first/lastDeepEditingPositionForNode Position creation functions
     10        and deploy them to places we used to call maxDeepOffset.
     11
     12        Rename Position::atStart and atEnd to atStartOfTree atEndOfTree
     13        Add a new Position::atFirst/atLastEditingPositionForNode() and use these
     14        to replace a few more callers for maxDeepOffset()
     15       
     16        Rename maxDeepOffset to lastEditingOffsetForNode (so that we mere mortals have some clue what it does)
     17
     18        "Editing positions" are confusing because they have one
     19        of two behaviors, depending on if the container node is ignored
     20        by editing (if editingIgnoresContent(node) returns true) or not.
     21        Positions referring to nodes ignored by editing are
     22        neighbor-relative (they are before or after the node) where as
     23        positions reffering to other nodes are container-relative
     24        (they are between two child nodes of the container, identified
     25        by the offset() member).  I will be fixing this confusion in
     26        future patches.  These renames hopefully make the current behavior clearer.
     27
     28        * dom/Position.cpp:
     29        (WebCore::Position::previous):
     30        (WebCore::Position::next):
     31        (WebCore::Position::atFirstEditingPositionForNode):
     32        (WebCore::Position::atLastEditingPositionForNode):
     33        (WebCore::Position::atStartOfTree):
     34        (WebCore::Position::atEndOfTree):
     35        (WebCore::Position::previousCharacterPosition):
     36        (WebCore::Position::nextCharacterPosition):
     37        (WebCore::Position::upstream):
     38        (WebCore::Position::isCandidate):
     39        (WebCore::firstDeepEditingPositionForNode):
     40        (WebCore::lastDeepEditingPositionForNode):
     41        * dom/Position.h:
     42        * dom/PositionIterator.cpp:
     43        (WebCore::PositionIterator::operator Position):
     44        (WebCore::PositionIterator::increment):
     45        (WebCore::PositionIterator::decrement):
     46        (WebCore::PositionIterator::atEnd):
     47        (WebCore::PositionIterator::atEndOfNode):
     48        * editing/CompositeEditCommand.cpp:
     49        (WebCore::CompositeEditCommand::positionAvoidingSpecialElementBoundary):
     50        * editing/DeleteSelectionCommand.cpp:
     51        (WebCore::isTableCellEmpty):
     52        (WebCore::DeleteSelectionCommand::removeNode):
     53        (WebCore::DeleteSelectionCommand::handleGeneralDelete):
     54        * editing/Editor.cpp:
     55        (WebCore::Editor::advanceToNextMisspelling):
     56        * editing/InsertLineBreakCommand.cpp:
     57        (WebCore::InsertLineBreakCommand::doApply):
     58        * editing/InsertListCommand.cpp:
     59        (WebCore::InsertListCommand::doApply):
     60        * editing/ReplaceSelectionCommand.cpp:
     61        (WebCore::ReplaceSelectionCommand::positionAtEndOfInsertedContent):
     62        * editing/TypingCommand.cpp:
     63        (WebCore::TypingCommand::forwardDeleteKeyPressed):
     64        * editing/VisiblePosition.cpp:
     65        (WebCore::VisiblePosition::previous):
     66        (WebCore::VisiblePosition::leftVisuallyDistinctCandidate):
     67        (WebCore::VisiblePosition::left):
     68        (WebCore::VisiblePosition::rightVisuallyDistinctCandidate):
     69        (WebCore::VisiblePosition::right):
     70        * editing/VisibleSelection.cpp:
     71        (WebCore::VisibleSelection::selectionFromContentsOfNode):
     72        (WebCore::VisibleSelection::adjustSelectionToAvoidCrossingEditingBoundaries):
     73        * editing/htmlediting.cpp:
     74        (WebCore::nextVisuallyDistinctCandidate):
     75        (WebCore::previousVisuallyDistinctCandidate):
     76        (WebCore::firstEditablePositionAfterPositionInRoot):
     77        (WebCore::lastEditablePositionBeforePositionInRoot):
     78        (WebCore::lastOffsetForEditing):
     79        (WebCore::isFirstPositionAfterTable):
     80        (WebCore::isLastPositionBeforeTable):
     81        (WebCore::positionBeforeNode):
     82        (WebCore::positionAfterNode):
     83        (WebCore::enclosingEmptyListItem):
     84        (WebCore::caretMaxOffset):
     85        * editing/htmlediting.h:
     86        * editing/visible_units.cpp:
     87        (WebCore::renderedAsNonInlineTableOrHR):
     88        (WebCore::startOfParagraph):
     89        (WebCore::endOfParagraph):
     90        (WebCore::startOfEditableContent):
     91        (WebCore::endOfEditableContent):
     92        * page/AccessibilityObject.cpp:
     93        (WebCore::endOfStyleRange):
     94        * page/AccessibilityRenderObject.cpp:
     95        (WebCore::AccessibilityRenderObject::visiblePositionRange):
     96        * rendering/RenderBox.cpp:
     97        (WebCore::RenderBox::positionForPoint):
     98
    1992009-03-20  Dmitry Titov  <dimich@chromium.org>
    2100
  • trunk/WebCore/dom/Position.cpp

    r41553 r41863  
    111111        Node* child = n->childNode(o - 1);
    112112        if (child)
    113             return Position(child, maxDeepOffset(child));
     113            return lastDeepEditingPositionForNode(child);
    114114
    115115        // There are two reasons child might be 0:
     
    148148
    149149    Node* child = n->childNode(o);
    150     if (child || !n->hasChildNodes() && o < maxDeepOffset(n)) {
     150    if (child || !n->hasChildNodes() && o < lastOffsetForEditing(n)) {
    151151        if (child)
    152             return Position(child, 0);
    153            
     152            return firstDeepEditingPositionForNode(child);
     153
    154154        // There are two reasons child might be 0:
    155155        //   1) The node is node like a text node that is not an element, and therefore has no children.
     
    182182}
    183183
    184 bool Position::atStart() const
    185 {
    186     Node *n = node();
    187     if (!n)
     184bool Position::atFirstEditingPositionForNode() const
     185{
     186    if (isNull())
    188187        return true;
    189    
    190     return m_offset <= 0 && n->parent() == 0;
    191 }
    192 
    193 bool Position::atEnd() const
    194 {
    195     Node *n = node();
    196     if (!n)
     188    return m_offset <= 0;
     189}
     190
     191bool Position::atLastEditingPositionForNode() const
     192{
     193    if (isNull())
    197194        return true;
    198    
    199     return n->parent() == 0 && m_offset >= maxDeepOffset(n);
     195    return m_offset >= lastOffsetForEditing(node());
     196}
     197
     198bool Position::atStartOfTree() const
     199{
     200    if (isNull())
     201        return true;
     202    return !node()->parentNode() && m_offset <= 0;
     203}
     204
     205bool Position::atEndOfTree() const
     206{
     207    if (isNull())
     208        return true;
     209    return !node()->parentNode() && m_offset >= lastOffsetForEditing(node());
    200210}
    201211
     
    236246   
    237247    Position currentPos = *this;
    238     while (!currentPos.atStart()) {
     248    while (!currentPos.atStartOfTree()) {
    239249        currentPos = currentPos.previous();
    240250
     
    264274   
    265275    Position currentPos = *this;
    266     while (!currentPos.atEnd()) {
     276    while (!currentPos.atEndOfTree()) {
    267277        currentPos = currentPos.next();
    268278
     
    280290}
    281291
    282 // Whether or not [node, 0] and [node, maxDeepOffset(node)] are their own VisiblePositions.
     292// Whether or not [node, 0] and [node, lastOffsetForEditing(node)] are their own VisiblePositions.
    283293// If true, adjacent candidates are visually distinct.
    284294// FIXME: Disregard nodes with renderers that have no height, as we do in isCandidate.
     
    374384        if (editingIgnoresContent(currentNode) || isTableElement(currentNode)) {
    375385            if (currentPos.atEndOfNode())
    376                 return Position(currentNode, maxDeepOffset(currentNode));
     386                return lastDeepEditingPositionForNode(currentNode);
    377387            continue;
    378388        }
     
    581591
    582592    if (isTableElement(node()) || editingIgnoresContent(node()))
    583         return (m_offset == 0 || m_offset == maxDeepOffset(node())) && !nodeIsUserSelectNone(node()->parent());
     593        return (atFirstEditingPositionForNode() || atLastEditingPositionForNode()) && !nodeIsUserSelectNone(node()->parent());
    584594
    585595    if (!node()->hasTagName(htmlTag) && renderer->isBlockFlow() && !hasRenderedNonAnonymousDescendantsWithHeight(renderer) &&
    586596       (toRenderBox(renderer)->height() || node()->hasTagName(bodyTag)))
    587         return m_offset == 0 && !nodeIsUserSelectNone(node());
     597        return atFirstEditingPositionForNode() && !nodeIsUserSelectNone(node());
    588598   
    589599    return false;
     
    9991009}
    10001010
     1011// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0])
     1012// for elements which editing "ignores".  the rest of the editing code will treat [img, 0]
     1013// as "the last position before the img"
     1014Position firstDeepEditingPositionForNode(Node* node)
     1015{
     1016    return Position(node, 0);
     1017}
     1018
     1019Position lastDeepEditingPositionForNode(Node* node)
     1020{
     1021    return Position(node, lastOffsetForEditing(node));
     1022}
     1023
    10011024} // namespace WebCore
    10021025
  • trunk/WebCore/dom/Position.h

    r41553 r41863  
    7979    static int uncheckedNextOffset(const Node*, int current);
    8080
    81     bool atStart() const;
    82     bool atEnd() const;
     81    // These can be either inside or just before/after the node, depending on
     82    // if the node is ignored by editing or not.
     83    bool atFirstEditingPositionForNode() const;
     84    bool atLastEditingPositionForNode() const;
     85
     86    bool atStartOfTree() const;
     87    bool atEndOfTree() const;
    8388
    8489    // FIXME: Make these non-member functions and put them somewhere in the editing directory.
     
    129134Position endPosition(const Range*);
    130135
     136// NOTE: first/lastDeepEditingPositionForNode can return "editing positions" (like [img, 0])
     137// for elements which editing "ignores".  the rest of the editing code will treat [img, 0]
     138// as "the last position before the img"
     139Position firstDeepEditingPositionForNode(Node*);
     140Position lastDeepEditingPositionForNode(Node*);
     141
    131142} // namespace WebCore
    132143
  • trunk/WebCore/dom/PositionIterator.cpp

    r40409 r41863  
    3737PositionIterator::operator Position() const
    3838{
    39     return Position(m_parent, m_child ? m_child->nodeIndex() : (m_parent->hasChildNodes() ? maxDeepOffset(m_parent) : m_offset));
     39    if (m_child) {
     40        ASSERT(m_child->parentNode() == m_parent);
     41        return positionBeforeNode(m_child);
     42    }
     43    if (m_parent->hasChildNodes())
     44        return lastDeepEditingPositionForNode(m_parent);
     45    return Position(m_parent, m_offset);
    4046}
    4147
     
    5258    }
    5359
    54     if (!m_parent->hasChildNodes() && m_offset < maxDeepOffset(m_parent))
     60    if (!m_parent->hasChildNodes() && m_offset < lastOffsetForEditing(m_parent))
    5561        m_offset = Position::uncheckedNextOffset(m_parent, m_offset);
    5662    else {
     
    7177        if (m_parent) {
    7278            m_child = 0;
    73             m_offset = m_parent->hasChildNodes() ? 0 : maxDeepOffset(m_parent);
     79            m_offset = m_parent->hasChildNodes() ? 0 : lastOffsetForEditing(m_parent);
    7480        } else {
    7581            m_child = m_child->parentNode();
     
    8692            m_parent = m_parent->lastChild();
    8793            if (!m_parent->hasChildNodes())
    88                 m_offset = maxDeepOffset(m_parent);
     94                m_offset = lastOffsetForEditing(m_parent);
    8995        } else {
    9096            m_child = m_parent;
     
    109115    if (m_child)
    110116        return false;
    111     return !m_parent->parentNode() && (m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent));
     117    return !m_parent->parentNode() && (m_parent->hasChildNodes() || m_offset >= lastOffsetForEditing(m_parent));
    112118}
    113119
     
    127133    if (m_child)
    128134        return false;
    129     return m_parent->hasChildNodes() || m_offset >= maxDeepOffset(m_parent);
     135    return m_parent->hasChildNodes() || m_offset >= lastOffsetForEditing(m_parent);
    130136}
    131137
  • trunk/WebCore/editing/CompositeEditCommand.cpp

    r41645 r41863  
    980980    // Don't avoid block level anchors, because that would insert content into the wrong paragraph.
    981981    if (enclosingAnchor && !isBlock(enclosingAnchor)) {
    982         VisiblePosition firstInAnchor(Position(enclosingAnchor, 0));
    983         VisiblePosition lastInAnchor(Position(enclosingAnchor, maxDeepOffset(enclosingAnchor)));
     982        VisiblePosition firstInAnchor(firstDeepEditingPositionForNode(enclosingAnchor));
     983        VisiblePosition lastInAnchor(lastDeepEditingPositionForNode(enclosingAnchor));
    984984        // If visually just after the anchor, insert *inside* the anchor unless it's the last
    985985        // VisiblePosition in the document, to match NSTextView.
  • trunk/WebCore/editing/DeleteSelectionCommand.cpp

    r41553 r41863  
    5757{
    5858    ASSERT(isTableCell(cell));
    59     VisiblePosition firstInCell(Position(cell, 0));
    60     VisiblePosition lastInCell(Position(cell, maxDeepOffset(cell)));
    61     return firstInCell == lastInCell;
     59    return VisiblePosition(firstDeepEditingPositionForNode(cell)) == VisiblePosition(lastDeepEditingPositionForNode(cell));
    6260}
    6361
     
    364362    }
    365363   
    366     if (node == m_startBlock && !isEndOfBlock(VisiblePosition(m_startBlock.get(), 0, DOWNSTREAM).previous()))
     364    if (node == m_startBlock && !isEndOfBlock(VisiblePosition(firstDeepEditingPositionForNode(m_startBlock.get())).previous()))
    367365        m_needPlaceholder = true;
    368     else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(m_endBlock.get(), maxDeepOffset(m_endBlock.get()), DOWNSTREAM).next()))
     366    else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(lastDeepEditingPositionForNode(m_startBlock.get())).next()))
    369367        m_needPlaceholder = true;
    370368   
     
    414412    }
    415413
    416     if (startOffset >= maxDeepOffset(startNode)) {
     414    if (startOffset >= lastOffsetForEditing(startNode)) {
    417415        startNode = startNode->traverseNextSibling();
    418416        startOffset = 0;
     
    425423    if (startNode == m_downstreamEnd.node()) {
    426424        // The selection to delete is all in one node.
    427         if (!startNode->renderer() ||
    428             (startOffset == 0 && m_downstreamEnd.m_offset >= maxDeepOffset(startNode))) {
     425        if (!startNode->renderer() || (startOffset == 0 && m_downstreamEnd.atLastEditingPositionForNode())) {
    429426            // just delete
    430427            removeNode(startNode);
     
    432429            if (startNode->isTextNode()) {
    433430                // in a text node that needs to be trimmed
    434                 Text *text = static_cast<Text *>(startNode);
     431                Text* text = static_cast<Text*>(startNode);
    435432                deleteTextFromNode(text, startOffset, m_downstreamEnd.m_offset - startOffset);
    436433            } else {
     
    482479       
    483480        if (m_downstreamEnd.node() != startNode && !m_upstreamStart.node()->isDescendantOf(m_downstreamEnd.node()) && m_downstreamEnd.node()->inDocument() && m_downstreamEnd.m_offset >= caretMinOffset(m_downstreamEnd.node())) {
    484             if (m_downstreamEnd.m_offset >= maxDeepOffset(m_downstreamEnd.node()) && !canHaveChildrenForEditing(m_downstreamEnd.node())) {
     481            if (m_downstreamEnd.atLastEditingPositionForNode() && !canHaveChildrenForEditing(m_downstreamEnd.node())) {
    485482                // The node itself is fully selected, not just its contents.  Delete it.
    486483                removeNode(m_downstreamEnd.node());
  • trunk/WebCore/editing/Editor.cpp

    r41791 r41863  
    17031703    // topNode defines the whole range we want to operate on
    17041704    Node* topNode = highestEditableRoot(position);
    1705     spellingSearchRange->setEnd(topNode, maxDeepOffset(topNode), ec);
     1705    // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
     1706    spellingSearchRange->setEnd(topNode, lastOffsetForEditing(topNode), ec);
    17061707
    17071708    // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
  • trunk/WebCore/editing/InsertLineBreakCommand.cpp

    r41553 r41863  
    171171        // FIXME: We shouldn't always apply the typing style to the line break here,
    172172        // see <rdar://problem/5794462>.
    173         applyStyle(typingStyle, Position(nodeToInsert.get(), 0),
    174                                 Position(nodeToInsert.get(), maxDeepOffset(nodeToInsert.get())));
     173        applyStyle(typingStyle, firstDeepEditingPositionForNode(nodeToInsert.get()), lastDeepEditingPositionForNode(nodeToInsert.get()));
    175174        // Even though this applyStyle operates on a Range, it still sets an endingSelection().
    176175        // It tries to set a VisibleSelection around the content it operated on. So, that VisibleSelection
  • trunk/WebCore/editing/InsertListCommand.cpp

    r41034 r41863  
    149149        VisiblePosition end;
    150150        if (listChildNode->hasTagName(liTag)) {
    151             start = VisiblePosition(Position(listChildNode, 0));
    152             end = VisiblePosition(Position(listChildNode, maxDeepOffset(listChildNode)));
     151            start = firstDeepEditingPositionForNode(listChildNode);
     152            end = lastDeepEditingPositionForNode(listChildNode);
    153153            nextListChild = listChildNode->nextSibling();
    154154            previousListChild = listChildNode->previousSibling();
  • trunk/WebCore/editing/ReplaceSelectionCommand.cpp

    r41677 r41863  
    510510{
    511511    Node* lastNode = m_lastLeafInserted.get();
    512     Node* enclosingSelect = enclosingNodeWithTag(Position(lastNode, 0), selectTag);
     512    // FIXME: Why is this hack here?  What's special about <select> tags?
     513    Node* enclosingSelect = enclosingNodeWithTag(firstDeepEditingPositionForNode(lastNode), selectTag);
    513514    if (enclosingSelect)
    514515        lastNode = enclosingSelect;
    515     return VisiblePosition(Position(lastNode, maxDeepOffset(lastNode)));
     516    return lastDeepEditingPositionForNode(lastNode);
    516517}
    517518
  • trunk/WebCore/editing/TypingCommand.cpp

    r41553 r41863  
    478478            // When deleting tables: Select the table first, then perform the deletion
    479479            if (downstreamEnd.node() && downstreamEnd.node()->renderer() && downstreamEnd.node()->renderer()->isTable() && downstreamEnd.m_offset == 0) {
    480                 setEndingSelection(VisibleSelection(endingSelection().end(), Position(downstreamEnd.node(), maxDeepOffset(downstreamEnd.node())), DOWNSTREAM));
     480                setEndingSelection(VisibleSelection(endingSelection().end(), lastDeepEditingPositionForNode(downstreamEnd.node()), DOWNSTREAM));
    481481                typingAddedToOpenCommand();
    482482                return;
  • trunk/WebCore/editing/VisiblePosition.cpp

    r41553 r41863  
    8282   
    8383    // return null visible position if there is no previous visible position
    84     if (pos.atStart())
     84    if (pos.atStartOfTree())
    8585        return VisiblePosition();
    8686       
     
    224224        p = Position(renderer->node(), offset);
    225225
    226         if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
     226        if (p.isCandidate() && p.downstream() != downstreamStart || p.atStartOfTree() || p.atEndOfTree())
    227227            return p;
    228228    }
     
    232232{
    233233    Position pos = leftVisuallyDistinctCandidate();
    234     if (pos.atStart() || pos.atEnd())
     234    // FIXME: Why can't we move left from the last position in a tree?
     235    if (pos.atStartOfTree() || pos.atEndOfTree())
    235236        return VisiblePosition();
    236237
     
    366367        p = Position(renderer->node(), offset);
    367368
    368         if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
     369        if (p.isCandidate() && p.downstream() != downstreamStart || p.atStartOfTree() || p.atEndOfTree())
    369370            return p;
    370371    }
     
    374375{
    375376    Position pos = rightVisuallyDistinctCandidate();
    376     if (pos.atStart() || pos.atEnd())
     377    // FIXME: Why can't we move left from the last position in a tree?
     378    if (pos.atStartOfTree() || pos.atEndOfTree())
    377379        return VisiblePosition();
    378380
  • trunk/WebCore/editing/VisibleSelection.cpp

    r41553 r41863  
    9797VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node)
    9898{
    99     return VisibleSelection(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);
     99    return VisibleSelection(firstDeepEditingPositionForNode(node), lastDeepEditingPositionForNode(node), DOWNSTREAM);
    100100}
    101101
     
    503503            Node* shadowAncestor = endRoot ? endRoot->shadowAncestorNode() : 0;
    504504            if (p.isNull() && endRoot && (shadowAncestor != endRoot))
    505                 p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));
     505                p = lastDeepEditingPositionForNode(shadowAncestor);
    506506            while (p.isNotNull() && !(lowestEditableAncestor(p.node()) == baseEditableAncestor && !isEditablePosition(p))) {
    507507                Node* root = editableRootForPosition(p);
     
    509509                p = isAtomicNode(p.node()) ? positionBeforeNode(p.node()) : previousVisuallyDistinctCandidate(p);
    510510                if (p.isNull() && (shadowAncestor != root))
    511                     p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));
     511                    p = lastDeepEditingPositionForNode(shadowAncestor);
    512512            }
    513513            VisiblePosition previous(p);
  • trunk/WebCore/editing/htmlediting.cpp

    r41553 r41863  
    222222    Position p = position;
    223223    Position downstreamStart = p.downstream();
    224     while (!p.atEnd()) {
     224    while (!p.atEndOfTree()) {
    225225        p = p.next(Character);
    226226        if (p.isCandidate() && p.downstream() != downstreamStart)
     
    245245    Position p = position;
    246246    Position downstreamStart = p.downstream();
    247     while (!p.atStart()) {
     247    while (!p.atStartOfTree()) {
    248248        p = p.previous(Character);
    249249        if (p.isCandidate() && p.downstream() != downstreamStart)
     
    256256{
    257257    // position falls before highestRoot.
    258     if (comparePositions(position, Position(highestRoot, 0)) == -1 && highestRoot->isContentEditable())
    259         return VisiblePosition(Position(highestRoot, 0));
    260        
     258    if (comparePositions(position, firstDeepEditingPositionForNode(highestRoot)) == -1 && highestRoot->isContentEditable())
     259        return firstDeepEditingPositionForNode(highestRoot);
     260
    261261    Position p = position;
    262262   
    263263    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
    264264        if (shadowAncestor != p.node())
    265             p = Position(shadowAncestor, maxDeepOffset(shadowAncestor));
     265            p = lastDeepEditingPositionForNode(shadowAncestor);
    266266   
    267267    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
     
    277277{
    278278    // When position falls after highestRoot, the result is easy to compute.
    279     if (comparePositions(position, Position(highestRoot, maxDeepOffset(highestRoot))) == 1)
    280         return VisiblePosition(Position(highestRoot, maxDeepOffset(highestRoot)));
    281        
     279    if (comparePositions(position, lastDeepEditingPositionForNode(highestRoot)) == 1)
     280        return lastDeepEditingPositionForNode(highestRoot);
     281
    282282    Position p = position;
    283283   
    284284    if (Node* shadowAncestor = p.node()->shadowAncestorNode())
    285285        if (shadowAncestor != p.node())
    286             p = Position(shadowAncestor, 0);
     286            p = firstDeepEditingPositionForNode(shadowAncestor);
    287287   
    288288    while (p.node() && !isEditablePosition(p) && p.node()->isDescendantOf(highestRoot))
     
    295295}
    296296
     297// FIXME: The method name, comment, and code say three different things here!
    297298// Whether or not content before and after this node will collapse onto the same line as it.
    298299bool isBlock(const Node* node)
     
    362363// creates technically invalid DOM Positions.  Be sure to call rangeCompliantEquivalent
    363364// on a Position before using it to create a DOM Range, or an exception will be thrown.
    364 int maxDeepOffset(const Node *node)
     365int lastOffsetForEditing(const Node* node)
    365366{
    366367    ASSERT(node);
     
    542543{
    543544    Position upstream(visiblePosition.deepEquivalent().upstream());
    544     if (upstream.node() && upstream.node()->renderer() && upstream.node()->renderer()->isTable() && upstream.m_offset == maxDeepOffset(upstream.node()))
     545    if (upstream.node() && upstream.node()->renderer() && upstream.node()->renderer()->isTable() && upstream.atLastEditingPositionForNode())
    545546        return upstream.node();
    546547   
     
    551552{
    552553    Position downstream(visiblePosition.deepEquivalent().downstream());
    553     if (downstream.node() && downstream.node()->renderer() && downstream.node()->renderer()->isTable() && downstream.m_offset == 0)
     554    if (downstream.node() && downstream.node()->renderer() && downstream.node()->renderer()->isTable() && downstream.atFirstEditingPositionForNode())
    554555        return downstream.node();
    555556   
     
    557558}
    558559
    559 Position positionBeforeNode(const Node *node)
    560 {
     560Position positionBeforeNode(const Node* node)
     561{
     562    // FIXME: This should ASSERT(node->parentNode())
    561563    return Position(node->parentNode(), node->nodeIndex());
    562564}
    563565
    564 Position positionAfterNode(const Node *node)
    565 {
     566Position positionAfterNode(const Node* node)
     567{
     568    // FIXME: This should ASSERT(node->parentNode())
    566569    return Position(node->parentNode(), node->nodeIndex() + 1);
    567570}
     
    700703}
    701704
     705// FIXME: This method should not need to call isStartOfParagraph/isEndOfParagraph
    702706Node* enclosingEmptyListItem(const VisiblePosition& visiblePos)
    703707{
     
    706710    if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(visiblePos))
    707711        return 0;
    708        
    709     VisiblePosition firstInListChild(Position(listChildNode, 0));
    710     VisiblePosition lastInListChild(Position(listChildNode, maxDeepOffset(listChildNode)));
    711    
     712
     713    VisiblePosition firstInListChild(firstDeepEditingPositionForNode(listChildNode));
     714    VisiblePosition lastInListChild(lastDeepEditingPositionForNode(listChildNode));
     715
    712716    if (firstInListChild != visiblePos || lastInListChild != visiblePos)
    713717        return 0;
     
    900904        return n->renderer()->caretMaxOffset();
    901905    // For containers return the number of children.  For others do the same as above.
    902     return maxDeepOffset(n);
     906    return lastOffsetForEditing(n);
    903907}
    904908
  • trunk/WebCore/editing/htmlediting.h

    r40793 r41863  
    4444Position rangeCompliantEquivalent(const Position&);
    4545Position rangeCompliantEquivalent(const VisiblePosition&);
    46 int maxDeepOffset(const Node*);
     46int lastOffsetForEditing(const Node*);
    4747bool isAtomicNode(const Node*);
    4848bool editingIgnoresContent(const Node*);
  • trunk/WebCore/editing/visible_units.cpp

    r41749 r41863  
    734734}
    735735
     736static bool renderedAsNonInlineTableOrHR(RenderObject* renderer)
     737{
     738    return renderer && ((renderer->isTable() && !renderer->isInline()) || renderer->isHR());
     739}
     740
    736741// FIXME: Broken for positions before/after images that aren't inline (5027702)
    737 VisiblePosition startOfParagraph(const VisiblePosition &c)
     742VisiblePosition startOfParagraph(const VisiblePosition& c)
    738743{
    739744    Position p = c.deepEquivalent();
     
    743748        return VisiblePosition();
    744749   
    745     if (startNode->renderer()
    746         && ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
    747             || startNode->renderer()->isHR())
    748         && p.m_offset == maxDeepOffset(startNode))
    749         return VisiblePosition(Position(startNode, 0));
     750    if (renderedAsNonInlineTableOrHR(startNode->renderer()) && p.atLastEditingPositionForNode())
     751        return firstDeepEditingPositionForNode(startNode);
    750752
    751753    Node* startBlock = enclosingBlock(startNode);
     
    806808    Node* startNode = p.node();
    807809
    808     if (startNode->renderer()
    809         && ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
    810             || startNode->renderer()->isHR())
    811         && p.m_offset == 0)
    812         return VisiblePosition(Position(startNode, maxDeepOffset(startNode)));
     810    if (renderedAsNonInlineTableOrHR(startNode->renderer()) && p.atFirstEditingPositionForNode())
     811        return lastDeepEditingPositionForNode(startNode);
    813812   
    814813    Node* startBlock = enclosingBlock(startNode);
     
    852851        } else if (editingIgnoresContent(n) || isTableElement(n)) {
    853852            node = n;
    854             offset = maxDeepOffset(n);
     853            offset = lastOffsetForEditing(n);
    855854            n = n->traverseNextSibling(stayInsideBlock);
    856855        } else
     
    10111010        return VisiblePosition();
    10121011
    1013     return VisiblePosition(highestRoot, 0, DOWNSTREAM);
     1012    return firstDeepEditingPositionForNode(highestRoot);
    10141013}
    10151014
     
    10201019        return VisiblePosition();
    10211020
    1022     return VisiblePosition(highestRoot, maxDeepOffset(highestRoot), DOWNSTREAM);
    1023 }
    1024 
    1025 }
     1021    return lastDeepEditingPositionForNode(highestRoot);
     1022}
     1023
     1024}
  • trunk/WebCore/page/AccessibilityObject.cpp

    r41553 r41863  
    519519}
    520520
    521 static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos)
     521static VisiblePosition endOfStyleRange(const VisiblePosition& visiblePos)
    522522{
    523523    RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
     
    539539    }
    540540
    541     return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY);
     541    return lastDeepEditingPositionForNode(endRenderer->node());
    542542}
    543543
  • trunk/WebCore/page/AccessibilityRenderObject.cpp

    r41553 r41863  
    16011601    if (!node)
    16021602        return VisiblePositionRange();
    1603    
    1604     VisiblePosition startPos = VisiblePosition(node, 0, VP_DEFAULT_AFFINITY);
    1605     VisiblePosition endPos = VisiblePosition(node, maxDeepOffset(node), VP_DEFAULT_AFFINITY);
    1606    
     1603
     1604    VisiblePosition startPos = firstDeepEditingPositionForNode(node);
     1605    VisiblePosition endPos = lastDeepEditingPositionForNode(node);
     1606
    16071607    // the VisiblePositions are equal for nodes like buttons, so adjust for that
     1608    // FIXME: Really?  [button, 0] and [button, 1] are distinct (before and after the button)
     1609    // I expect this code is only hit for things like empty divs?  In which case I don't think
     1610    // the behavior is correct here -- eseidel
    16081611    if (startPos == endPos) {
    16091612        endPos = endPos.next();
     
    16111614            endPos = startPos;
    16121615    }
    1613    
     1616
    16141617    return VisiblePositionRange(startPos, endPos);
    16151618}
  • trunk/WebCore/rendering/RenderBox.cpp

    r41531 r41863  
    26752675    // no children...return this render object's element, if there is one, and offset 0
    26762676    if (!firstChild())
    2677         return VisiblePosition(node(), 0, DOWNSTREAM);
     2677        return firstDeepEditingPositionForNode(node());
    26782678
    26792679    int xPos = point.x();
     
    26862686        if (xPos < 0 || xPos > right || yPos < 0 || yPos > bottom) {
    26872687            if (xPos <= right / 2)
    2688                 return VisiblePosition(Position(node(), 0));
    2689             else
    2690                 return VisiblePosition(Position(node(), maxDeepOffset(node())));
     2688                return firstDeepEditingPositionForNode(node());
     2689            return lastDeepEditingPositionForNode(node());
    26912690        }
    26922691    }
     
    27592758        return closestRenderer->positionForCoordinates(newX - closestRenderer->x(), newY - closestRenderer->y());
    27602759   
    2761     return VisiblePosition(node(), 0, DOWNSTREAM);
     2760    return firstDeepEditingPositionForNode(node());
    27622761}
    27632762
Note: See TracChangeset for help on using the changeset viewer.