Changeset 12789 in webkit


Ignore:
Timestamp:
Feb 13, 2006 7:29:43 PM (18 years ago)
Author:
harrison
Message:

Reviewed by Justin.

  • merge VisiblePosition:isCandidate() into Position::inRenderedContent() These functions were answering the same question in different ways! We only need one implementation.
  • khtml/editing/visible_position.cpp: (khtml::VisiblePosition::init): (khtml::VisiblePosition::previousVisiblePosition): (khtml::VisiblePosition::nextVisiblePosition): (khtml::VisiblePosition::deepEquivalent):
  • khtml/editing/visible_position.h:
  • dom/dom_position.cpp: (DOM::hasRenderedChildrenWithHeight): (DOM::Position::inRenderedContent):
  • improved table deletion. Fixes: delete back by word from just after table did not delete the table

delete forward by char or word did not delete the table
deleting back to a table and again did not delete the table

  • khtml/editing/htmlediting.cpp: (WebCore::isFirstVisiblePositionAfterTableElement): simpler implementation (WebCore::positionBeforePrecedingTableElement): simpler implementation (WebCore::isFirstVisiblePositionBeforeTableElement): new (WebCore::positionAfterFollowingTableElement): new
  • khtml/editing/htmlediting.h:
  • khtml/editing/SelectionController.cpp: (WebCore::SelectionController::modifyExtendingRightForward): select following table if granularity is char or word (WebCore::SelectionController::modifyExtendingLeftBackward): select preceding table if granularity is char or word
  • khtml/editing/typing_command.cpp: (khtml::TypingCommand::deleteKeyPressed): simpler implementation, and let other deleteKeyPressed do boundary checking (khtml::TypingCommand::forwardDeleteKeyPressed): simpler implementation, and let other forwardDeleteKeyPressed do boundary checking (khtml::TypingCommand::insertText): standard formatting (khtml::TypingCommand::insertLineBreak): standard formatting (khtml::TypingCommand::insertParagraphSeparatorInQuotedContent): standard formatting (khtml::TypingCommand::insertParagraphSeparator): standard formatting (khtml::TypingCommand::insertTextRunWithoutNewlines): standard formatting (khtml::TypingCommand::deleteKeyPressed): use SelectionController to extend selection, to get all the selection logic incl. table selection and editable/noneditable boundary checks (khtml::TypingCommand::forwardDeleteKeyPressed): use SelectionController to extend selection, to get all the selection logic incl. table selection and editable/noneditable boundary checks
Location:
trunk/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r12788 r12789  
     12006-02-07  David Harrison  <harrison@apple.com>
     2
     3        Reviewed by Justin.
     4
     5        - merge VisiblePosition:isCandidate() into Position::inRenderedContent()
     6          These functions were answering the same question in different ways!  We
     7          only need one implementation.
     8
     9        * khtml/editing/visible_position.cpp:
     10        (khtml::VisiblePosition::init):
     11        (khtml::VisiblePosition::previousVisiblePosition):
     12        (khtml::VisiblePosition::nextVisiblePosition):
     13        (khtml::VisiblePosition::deepEquivalent):
     14        * khtml/editing/visible_position.h:
     15        * dom/dom_position.cpp:
     16        (DOM::hasRenderedChildrenWithHeight):
     17        (DOM::Position::inRenderedContent):
     18
     19
     20        - improved table deletion.
     21          Fixes: delete back by word from just after table did not delete the table
     22                 delete forward by char or word did not delete the table
     23                 deleting back to a table and again did not delete the table
     24
     25        * khtml/editing/htmlediting.cpp:
     26        (WebCore::isFirstVisiblePositionAfterTableElement):
     27        simpler implementation
     28        (WebCore::positionBeforePrecedingTableElement):
     29        simpler implementation
     30        (WebCore::isFirstVisiblePositionBeforeTableElement):
     31        new
     32        (WebCore::positionAfterFollowingTableElement):
     33        new
     34        * khtml/editing/htmlediting.h:
     35        * khtml/editing/SelectionController.cpp:
     36        (WebCore::SelectionController::modifyExtendingRightForward):
     37        select following table if granularity is char or word
     38        (WebCore::SelectionController::modifyExtendingLeftBackward):
     39        select preceding table if granularity is char or word
     40        * khtml/editing/typing_command.cpp:
     41        (khtml::TypingCommand::deleteKeyPressed):
     42        simpler implementation, and let other deleteKeyPressed do boundary checking
     43        (khtml::TypingCommand::forwardDeleteKeyPressed):
     44        simpler implementation, and let other forwardDeleteKeyPressed do boundary checking
     45        (khtml::TypingCommand::insertText):
     46        standard formatting
     47        (khtml::TypingCommand::insertLineBreak):
     48        standard formatting
     49        (khtml::TypingCommand::insertParagraphSeparatorInQuotedContent):
     50        standard formatting
     51        (khtml::TypingCommand::insertParagraphSeparator):
     52        standard formatting
     53        (khtml::TypingCommand::insertTextRunWithoutNewlines):
     54        standard formatting
     55        (khtml::TypingCommand::deleteKeyPressed):
     56        use SelectionController to extend selection, to get all the selection
     57        logic incl. table selection and editable/noneditable boundary checks
     58        (khtml::TypingCommand::forwardDeleteKeyPressed):
     59        use SelectionController to extend selection, to get all the selection
     60        logic incl. table selection and editable/noneditable boundary checks
     61
    1622006-02-13  David Hyatt  <hyatt@apple.com>
    263
  • trunk/WebCore/dom/dom_position.cpp

    r12725 r12789  
    482482}
    483483
     484bool hasRenderedChildrenWithHeight(RenderObject *renderer)
     485{
     486    if (!renderer->firstChild())
     487        return false;
     488
     489    for (RenderObject *child = renderer->firstChild(); child; child = child->nextSibling())
     490        if (child->height())
     491            return true;
     492   
     493    return false;
     494}
     495
    484496bool Position::inRenderedContent() const
    485497{
     
    497509        return offset() == 0;
    498510
    499     if (renderer->isText()) {
    500         RenderText *textRenderer = static_cast<RenderText *>(renderer);
    501         for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    502             if (offset() >= box->m_start && offset() <= box->m_start + box->m_len)
    503                 return true;
    504             if (offset() < box->m_start) {
    505                 // The offset we're looking for is before this node
    506                 // this means the offset must be in content that is
    507                 // not rendered. Return false.
    508                 return false;
    509             }
    510         }
    511     } else if (offset() >= renderer->caretMinOffset() && offset() <= renderer->caretMaxOffset()) {
    512         // return true for replaced elements, for inline flows if they have a line box
    513         // and for blocks if they are empty
    514         if (renderer->isReplaced() ||
    515             (renderer->isInlineFlow() && static_cast<RenderFlow *>(renderer)->firstLineBox()) ||
    516             (renderer->isBlockFlow() && !renderer->firstChild() && renderer->height()))
    517             return true;
    518     }
     511    if (renderer->isText())
     512        return inRenderedText();
     513
     514    if (isTableElement(node()) || editingIgnoresContent(node()))
     515        return offset() == 0 || offset() == maxDeepOffset(node());
     516
     517    if (renderer->isBlockFlow() && !hasRenderedChildrenWithHeight(renderer) &&
     518       (renderer->height() || node()->hasTagName(bodyTag)))
     519        return offset() == 0;
    519520   
    520521    return false;
  • trunk/WebCore/khtml/editing/SelectionController.cpp

    r12765 r12789  
    284284    switch (granularity) {
    285285        case CHARACTER:
    286             pos = pos.next();
     286            if (isLastVisiblePositionBeforeTableElement(pos.deepEquivalent()))
     287                pos = VisiblePosition(positionAfterFollowingTableElement(pos.deepEquivalent()), VP_DEFAULT_AFFINITY);
     288            else
     289                pos = pos.next();
    287290            break;
    288291        case WORD:
    289             pos = nextWordPosition(pos);
     292            if (isLastVisiblePositionBeforeTableElement(pos.deepEquivalent()))
     293                pos = VisiblePosition(positionAfterFollowingTableElement(pos.deepEquivalent()), VP_DEFAULT_AFFINITY);
     294            else
     295                pos = nextWordPosition(pos);
    290296            break;
    291297        case PARAGRAPH:
     
    350356    VisiblePosition pos(m_sel.extent(), m_sel.affinity());
    351357       
     358    // Extending a selection backward by word or character from just after a table selects
     359    // the table.  This "makes sense" from the user perspective, esp. when deleting.
     360    // It was done here instead of in VisiblePosition because we want VPs to iterate
     361    // over everything.
    352362    switch (granularity) {
    353363        case CHARACTER:
    354             // Extending a selection backward by character from just after a table selects
    355             // the table.  This "makes sense" from the user perspective, esp. when deleting.
    356             // It was done here instead of in VisiblePosition because we want VPs to iterate
    357             // over everything.
    358364            if (isFirstVisiblePositionAfterTableElement(pos.deepEquivalent()))
    359365                pos = VisiblePosition(positionBeforePrecedingTableElement(pos.deepEquivalent()), VP_DEFAULT_AFFINITY);
     
    362368            break;
    363369        case WORD:
    364             pos = previousWordPosition(pos);
     370            if (isFirstVisiblePositionAfterTableElement(pos.deepEquivalent()))
     371                pos = VisiblePosition(positionBeforePrecedingTableElement(pos.deepEquivalent()), VP_DEFAULT_AFFINITY);
     372            else
     373                pos = previousWordPosition(pos);
    365374            break;
    366375        case PARAGRAPH:
  • trunk/WebCore/khtml/editing/htmlediting.cpp

    r12765 r12789  
    384384bool isFirstVisiblePositionAfterTableElement(const Position& pos)
    385385{
    386     VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM).previous();
    387     // FIXME: rangePos isn't being used to create DOM Ranges, so why does it need to be range compliant?
    388     Position rangePos = rangeCompliantEquivalent(vPos.deepEquivalent().downstream());
    389     for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
    390         // FIXME: can we not create a VP every time thru this loop?
    391         VisiblePosition checkVP = VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM);
    392         if (checkVP != vPos) {
    393             if (isTableElement(n) && checkVP.previous() == vPos)
    394                 return true;
    395             return false;
    396         }
    397         if (n->rootEditableElement() == NULL)
    398             return false;
    399         if (isTableElement(n))
    400             return true;
    401     }
    402 
    403     return false;
     386    return isTableElement(pos.upstream().node());
    404387}
    405388
     
    407390{
    408391    ASSERT(isFirstVisiblePositionAfterTableElement(pos));
    409     VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM).previous();
    410     // FIXME: rangePos isn't being used to create DOM Ranges, so why does it need to be range compliant?
    411     Position rangePos = rangeCompliantEquivalent(vPos);
    412     NodeImpl *outermostTableElement = NULL;
    413 
    414     for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
    415         // FIXME: can we not create a VP every time thru this loop?
    416         VisiblePosition checkVP = VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM);
    417         if (checkVP != vPos) {
    418             if (isTableElement(n) && checkVP.previous() == vPos)
    419                 outermostTableElement = n;
    420             break;
    421         }
    422         if (n->rootEditableElement() == NULL)
    423             break;
    424         if (isTableElement(n))
    425             outermostTableElement = n;
    426     }
    427    
    428     ASSERT(outermostTableElement);       
    429     Position result = positionBeforeNode(outermostTableElement);
    430    
     392    Position result = positionBeforeNode(pos.upstream().node());
     393    if (result.isNull() || !result.node()->rootEditableElement())
     394        return pos;
     395    return result;
     396}
     397
     398bool isLastVisiblePositionBeforeTableElement(const Position &pos)
     399{
     400    return isTableElement(pos.downstream().node());
     401}
     402
     403Position positionAfterFollowingTableElement(const Position &pos)
     404{
     405    ASSERT(isLastVisiblePositionBeforeTableElement(pos));
     406    Position result = positionAfterNode(pos.downstream().node());
    431407    if (result.isNull() || !result.node()->rootEditableElement())
    432408        return pos;
     
    510486        return pos;
    511487   
    512     return Position(node->parentNode(), node->nodeIndex());
     488    return positionBeforeNode(node);
    513489}
    514490
  • trunk/WebCore/khtml/editing/htmlediting.h

    r12725 r12789  
    8989bool isFirstVisiblePositionAfterTableElement(const Position&);
    9090Position positionBeforePrecedingTableElement(const Position&);
     91bool isLastVisiblePositionBeforeTableElement(const Position&);
     92Position positionAfterFollowingTableElement(const Position&);
    9193Position positionAvoidingSpecialElementBoundary(const Position&);
    9294
  • trunk/WebCore/khtml/editing/typing_command.cpp

    r12178 r12789  
    2828#include "SelectionController.h"
    2929
     30#include "htmlediting.h"
    3031#include "insert_text_command.h"
    3132#include "insert_line_break_command.h"
     
    6768    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    6869        static_cast<TypingCommand *>(lastEditCommand.get())->deleteKeyPressed();
    69     }
    70     else {
    71         Selection selection = frame->selection().selection();
    72         if (selection.isCaret() && VisiblePosition(selection.start(), selection.affinity()).previous().isNull()) {
    73             // do nothing for a delete key at the start of an editable element.
    74         }
    75         else {
    76             TypingCommand *typingCommand = new TypingCommand(document, DeleteKey);
    77             typingCommand->setSmartDelete(smartDelete);
    78             EditCommandPtr cmd(typingCommand);
    79             cmd.apply();
    80         }
    81     }
     70        return;
     71    }
     72   
     73    TypingCommand *typingCommand = new TypingCommand(document, DeleteKey);
     74    typingCommand->setSmartDelete(smartDelete);
     75    EditCommandPtr cmd(typingCommand);
     76    cmd.apply();
    8277}
    8378
     
    9287    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    9388        static_cast<TypingCommand *>(lastEditCommand.get())->forwardDeleteKeyPressed();
    94     }
    95     else {
    96         Selection selection = frame->selection().selection();
    97         if (selection.isCaret() && isEndOfDocument(VisiblePosition(selection.start(), selection.affinity()))) {
    98             // do nothing for a delete key at the start of an editable element.
    99         }
    100         else {
    101             TypingCommand *typingCommand = new TypingCommand(document, ForwardDeleteKey);
    102             typingCommand->setSmartDelete(smartDelete);
    103             EditCommandPtr cmd(typingCommand);
    104             cmd.apply();
    105         }
    106     }
     89        return;
     90    }
     91
     92    TypingCommand *typingCommand = new TypingCommand(document, ForwardDeleteKey);
     93    typingCommand->setSmartDelete(smartDelete);
     94    EditCommandPtr cmd(typingCommand);
     95    cmd.apply();
    10796}
    10897
     
    117106    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    118107        static_cast<TypingCommand *>(lastEditCommand.get())->insertText(text, selectInsertedText);
    119     }
    120     else {
    121         EditCommandPtr cmd(new TypingCommand(document, InsertText, text, selectInsertedText));
    122         cmd.apply();
    123     }
     108        return;
     109    }
     110
     111    EditCommandPtr cmd(new TypingCommand(document, InsertText, text, selectInsertedText));
     112    cmd.apply();
    124113}
    125114
     
    134123    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    135124        static_cast<TypingCommand *>(lastEditCommand.get())->insertLineBreak();
    136     }
    137     else {
    138         EditCommandPtr cmd(new TypingCommand(document, InsertLineBreak));
    139         cmd.apply();
    140     }
     125        return;
     126    }
     127
     128    EditCommandPtr cmd(new TypingCommand(document, InsertLineBreak));
     129    cmd.apply();
    141130}
    142131
     
    151140    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    152141        static_cast<TypingCommand *>(lastEditCommand.get())->insertParagraphSeparatorInQuotedContent();
    153     }
    154     else {
    155         EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparatorInQuotedContent));
    156         cmd.apply();
    157     }
     142        return;
     143    }
     144
     145    EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparatorInQuotedContent));
     146    cmd.apply();
    158147}
    159148
     
    168157    if (isOpenForMoreTypingCommand(lastEditCommand)) {
    169158        static_cast<TypingCommand *>(lastEditCommand.get())->insertParagraphSeparator();
    170     }
    171     else {
    172         EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparator));
    173         cmd.apply();
    174     }
     159        return;
     160    }
     161
     162    EditCommandPtr cmd(new TypingCommand(document, InsertParagraphSeparator));
     163    cmd.apply();
    175164}
    176165
     
    261250    int newline;
    262251    while ((newline = text.find('\n', offset)) != -1) {
    263         if (newline != offset) {
     252        if (newline != offset)
    264253            insertTextRunWithoutNewlines(text.substring(offset, newline - offset), false);
    265         }
    266254        insertParagraphSeparator();
    267255        offset = newline + 1;
    268256    }
    269     if (offset == 0) {
     257    if (offset == 0)
    270258        insertTextRunWithoutNewlines(text, selectInsertedText);
    271     } else {
     259    else {
    272260        int length = text.length();
    273261        if (length != offset) {
     
    286274        applyCommandToComposite(cmd);
    287275        impl->input(text, selectInsertedText);
    288     }
    289     else {
     276    } else {
    290277        EditCommandPtr lastCommand = m_cmds.last();
    291278        if (lastCommand.isInsertTextCommand()) {
    292279            InsertTextCommand *impl = static_cast<InsertTextCommand *>(lastCommand.get());
    293280            impl->input(text, selectInsertedText);
    294         }
    295         else {
     281        } else {
    296282            InsertTextCommand *impl = new InsertTextCommand(document());
    297283            EditCommandPtr cmd(impl);
     
    336322            // Do nothing in the case that the caret is at the start of a
    337323            // root editable element or at the start of a document.
    338             Position pos(endingSelection().start());
    339             Position start = VisiblePosition(pos, endingSelection().affinity()).previous().deepEquivalent();
    340             Position end = VisiblePosition(pos, endingSelection().affinity()).deepEquivalent();
    341             if (start.isNotNull() && end.isNotNull() && start.node()->rootEditableElement() == end.node()->rootEditableElement())
    342                 selectionToDelete = Selection(start, end, SEL_DEFAULT_AFFINITY);
     324            SelectionController sc = SelectionController(endingSelection().start(), endingSelection().end(), SEL_DEFAULT_AFFINITY);
     325            sc.modify(SelectionController::EXTEND, SelectionController::BACKWARD, CHARACTER);
     326            selectionToDelete = sc.selection();
    343327            break;
    344328        }
     
    367351            // Do nothing in the case that the caret is at the start of a
    368352            // root editable element or at the start of a document.
    369             Position pos(endingSelection().start());
    370             Position start = VisiblePosition(pos, endingSelection().affinity()).next().deepEquivalent();
    371             Position end = VisiblePosition(pos, endingSelection().affinity()).deepEquivalent();
    372             if (start.isNotNull() && end.isNotNull() && start.node()->rootEditableElement() == end.node()->rootEditableElement())
    373                 selectionToDelete = Selection(start, end, SEL_DEFAULT_AFFINITY);
     353            SelectionController sc = SelectionController(endingSelection().start(), endingSelection().end(), SEL_DEFAULT_AFFINITY);
     354            sc.modify(SelectionController::EXTEND, SelectionController::FORWARD, CHARACTER);
     355            selectionToDelete = sc.selection();
    374356            break;
    375357        }
  • trunk/WebCore/khtml/editing/visible_position.cpp

    r12765 r12789  
    7878    pos.node()->getDocument()->updateLayoutIgnorePendingStylesheets();
    7979    Position deepPos = deepEquivalent(pos);
    80     if (isCandidate(deepPos)) {
     80    if (deepPos.inRenderedContent()) {
    8181        m_deepPosition = deepPos;
    8282        Position previous = previousVisiblePosition(deepPos);
     
    150150    Position test = deepEquivalent(pos);
    151151    Position downstreamTest = test.downstream();
    152     bool acceptAnyVisiblePosition = !isCandidate(test);
     152    bool acceptAnyVisiblePosition = !test.inRenderedContent();
    153153
    154154    Position current = test;
    155155    while (!current.atStart()) {
    156156        current = current.previous(UsingComposedCharacters);
    157         if (isCandidate(current) && (acceptAnyVisiblePosition || (downstreamTest != current.downstream()))) {
     157        if (current.inRenderedContent() && (acceptAnyVisiblePosition || (downstreamTest != current.downstream()))) {
    158158            return current;
    159159        }
     
    169169
    170170    Position test = deepEquivalent(pos);
    171     bool acceptAnyVisiblePosition = !isCandidate(test);
     171    bool acceptAnyVisiblePosition = !test.inRenderedContent();
    172172
    173173    Position current = test;
     
    175175    while (!current.atEnd()) {
    176176        current = current.next(UsingComposedCharacters);
    177         if (isCandidate(current) && (acceptAnyVisiblePosition || (downstreamTest != current.downstream()))) {
     177        if (current.inRenderedContent() && (acceptAnyVisiblePosition || (downstreamTest != current.downstream()))) {
    178178            return current;
    179179        }
     
    183183}
    184184
    185 bool hasRenderedChildrenWithHeight(RenderObject *renderer)
    186 {
    187     if (!renderer->firstChild())
    188         return false;
    189 
    190     for (RenderObject *child = renderer->firstChild(); child; child = child->nextSibling())
    191         if (child->height())
    192             return true;
    193    
    194     return false;
    195 }
    196 
    197 bool VisiblePosition::isCandidate(const Position &pos)
    198 {
    199     if (pos.isNull())
    200         return false;
    201        
    202     RenderObject *renderer = pos.node()->renderer();
    203     if (!renderer)
    204         return false;
    205    
    206     if (renderer->style()->visibility() != VISIBLE)
    207         return false;
    208 
    209     if (isTableElement(pos.node()) || editingIgnoresContent(pos.node()))
    210         return pos.offset() == 0 || pos.offset() == maxDeepOffset(pos.node());
    211 
    212     if (renderer->isBR())
    213         return pos.offset() == 0;
    214    
    215     // True if at a rendered offset inside a text node
    216     if (renderer->isText()) {
    217         RenderText *textRenderer = static_cast<RenderText *>(renderer);
    218         for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
    219             if (pos.offset() >= box->m_start && pos.offset() <= box->m_start + box->m_len) {
    220                 return true;
    221             }
    222         }
    223     }
    224    
    225     if (renderer->isBlockFlow() && !hasRenderedChildrenWithHeight(renderer) &&
    226        (renderer->height() || pos.node()->hasTagName(bodyTag)))
    227        return pos.offset() == 0;
    228    
    229     return false;
    230 }
    231 
    232185Position VisiblePosition::deepEquivalent(const Position &pos)
    233186{
     
    238191        return Position();
    239192   
    240     if (isCandidate(pos) || isAtomicNode(node))
     193    if (pos.inRenderedContent() || isAtomicNode(node))
    241194        return pos;
    242195
     
    247200                break;
    248201            node = child;
    249         } while (!isCandidate(Position(node, maxDeepOffset(node))) && !isAtomicNode(node));
     202        } while (!(Position(node, maxDeepOffset(node)).inRenderedContent()) && !isAtomicNode(node));
    250203        return Position(node, maxDeepOffset(node));
    251204    }
     
    253206    node = node->childNode(offset);
    254207    ASSERT(node);
    255     while (!isCandidate(Position(node, 0)) && !isAtomicNode(node)) {
     208    while (!(Position(node, 0).inRenderedContent()) && !isAtomicNode(node)) {
    256209        NodeImpl *child = node->firstChild();
    257210        if (!child)
  • trunk/WebCore/khtml/editing/visible_position.h

    r12715 r12789  
    106106    static Position previousVisiblePosition(const Position &);
    107107    static Position nextVisiblePosition(const Position &);
    108 
    109     static bool isCandidate(const Position &);
    110108       
    111109    Position m_deepPosition;
Note: See TracChangeset for help on using the changeset viewer.