Commit 635ec2aa authored by lweintraub's avatar lweintraub

LayoutTests:

        Reviewed by justin

        <rdar://problem/4622763> Deleting from beginning of paragraph following a table deletes rather than selects the table

        * editing/deleting/delete-block-table-expected.checksum: Added.
        * editing/deleting/delete-block-table-expected.png: Added.
        * editing/deleting/delete-block-table-expected.txt: Added.
        * editing/deleting/delete-block-table.html: Added.
        * editing/deleting/delete-hr-expected.checksum: Added.
        * editing/deleting/delete-hr-expected.png: Added.
        * editing/deleting/delete-hr-expected.txt: Added.
        * editing/deleting/delete-hr.html: Added.
        * editing/deleting/delete-to-select-table-expected.png:
        * editing/execCommand/insertHorizontalRule-expected.txt:
        * fast/lists/markers-in-selection-expected.txt:

WebCore:

        Reviewed by justin

        <rdar://problem/4622763> Deleting from beginning of paragraph following a table deletes rather than selects the table

        * editing/DeleteSelectionCommand.cpp:
        (WebCore::DeleteSelectionCommand::initializeStartEnd): Added selection expansion for HRs.
        (WebCore::DeleteSelectionCommand::initializePositionData): Now uses enclosingBlockFlowOrTableElement
        instead of enclosingBlockFlowElement.
        (WebCore::DeleteSelectionCommand::removeNode): Use to identify that we need a placeholder
        when the start or end block is removed.
        (WebCore::DeleteSelectionCommand::handleGeneralDelete): Added check for canHaveChildrenForEditing
        to keep things like HRs from being given children.
        (WebCore::DeleteSelectionCommand::doApply): Switched to use member variable for needPlaceholder.
        * editing/DeleteSelectionCommand.h: Made needPlaceholder a member variable.
        * editing/TypingCommand.cpp:
        (WebCore::TypingCommand::deleteKeyPressed): Fixed selection bug for tables and open typing commands.
        (WebCore::TypingCommand::forwardDeleteKeyPressed): Ditto.
        * editing/htmlediting.cpp:
        (WebCore::editingIgnoresContent): Added check for HRs, since it's not considered a widget.
        * editing/visible_units.cpp:
        (WebCore::startOfParagraph): Fix for HRs and tables.
        (WebCore::endOfParagraph): Ditto.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@15408 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4c033e2b
2006-07-13 Levi Weintraub <lweintraub@apple.com>
Reviewed by justin
<rdar://problem/4622763> Deleting from beginning of paragraph following a table deletes rather than selects the table
* editing/deleting/delete-block-table-expected.checksum: Added.
* editing/deleting/delete-block-table-expected.png: Added.
* editing/deleting/delete-block-table-expected.txt: Added.
* editing/deleting/delete-block-table.html: Added.
* editing/deleting/delete-hr-expected.checksum: Added.
* editing/deleting/delete-hr-expected.png: Added.
* editing/deleting/delete-hr-expected.txt: Added.
* editing/deleting/delete-hr.html: Added.
* editing/deleting/delete-to-select-table-expected.png:
* editing/execCommand/insertHorizontalRule-expected.txt:
* fast/lists/markers-in-selection-expected.txt:
2006-07-12 Mitz Pettel <opendarwin.org@mitzpettel.com>
Reviewed by Adele.
2fd485862090aecc8236f85c20c323fa
\ No newline at end of file
EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document toDOMRange:range from 0 of TABLE > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of TABLE > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
RenderBlock {HTML} at (0,0) size 800x600
RenderBody {BODY} at (8,8) size 784x584
RenderBlock {DIV} at (0,0) size 784x36
RenderBlock {DIV} at (0,0) size 784x18
RenderText {#text} at (0,0) size 43x18
text run at (0,0) width 43: "Before"
RenderBlock (anonymous) at (0,18) size 784x18
RenderInline {SPAN} at (0,0) size 21x18
RenderText {#text} at (0,0) size 21x18
text run at (0,0) width 21: "fter"
RenderText {#text} at (0,0) size 0x0
caret: position 0 of child 0 {#text} of child 3 {SPAN} of child 0 {DIV} of child 2 {BODY} of child 0 {HTML} of document
<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
<script>
function editingTest() {
var selection = window.getSelection();
var s = document.getElementById("start");
selection.setPosition(s, 0);
execMoveSelectionForwardByCharacterCommand();
for (i = 0; i < 3; i++) {
deleteCommand();
}
}
</script>
<div contenteditable="true" id="test">
<div>Before</div>
<table style="border:3px solid #aaa;">
<tr>
<td>
Foo
</td>
<td>
baz
</td>
</tr>
<tr>
<td>
bar
</td>
<td>
buffalo
</td>
</tr>
</table>
<span id="start">after</span>
</div>
<script>
runEditingTest();
</script>
\ No newline at end of file
2fd485862090aecc8236f85c20c323fa
\ No newline at end of file
EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 7 of DIV > BODY > HTML > #document
EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: shouldDeleteDOMRange:range from 4 of DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document
EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document toDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x600
RenderBlock {HTML} at (0,0) size 800x600
RenderBody {BODY} at (8,8) size 784x584
RenderBlock {DIV} at (0,0) size 784x36
RenderBlock {DIV} at (0,0) size 784x18
RenderText {#text} at (0,0) size 43x18
text run at (0,0) width 43: "Before"
RenderBlock (anonymous) at (0,18) size 784x18
RenderInline {SPAN} at (0,0) size 21x18
RenderText {#text} at (0,0) size 21x18
text run at (0,0) width 21: "fter"
RenderText {#text} at (0,0) size 0x0
caret: position 0 of child 0 {#text} of child 3 {SPAN} of child 0 {DIV} of child 2 {BODY} of child 0 {HTML} of document
<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
<script>
function editingTest() {
var selection = window.getSelection();
var s = document.getElementById("start");
selection.setPosition(s, 0);
execMoveSelectionForwardByCharacterCommand();
for (i = 0; i < 2; i++) {
deleteCommand();
}
}
</script>
<div contenteditable="true" id="test">
<div>Before</div>
<hr>
<span id="start">after</span>
</div>
<script>
runEditingTest();
</script>
\ No newline at end of file
......@@ -4,7 +4,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of HR > DIV > BODY > HTML > #document to 0 of HR > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of DIV > BODY > HTML > #document to 2 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: shouldEndEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 3 of DIV > BODY > HTML > #document
......@@ -15,7 +15,7 @@ EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotificatio
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of HR > DIV > BODY > HTML > #document to 0 of HR > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of DIV > BODY > HTML > #document to 2 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
layer at (0,0) size 800x600
......
......@@ -68,4 +68,4 @@ layer at (0,0) size 800x600
RenderText {#text} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
selection start: position 0 of child 7 {HR} of child 1 {BODY} of child 0 {HTML} of document
selection end: position 0 of child 21 {HR} of child 1 {BODY} of child 0 {HTML} of document
selection end: position 1 of child 21 {HR} of child 1 {BODY} of child 0 {HTML} of document
2006-07-12 Levi Weintraub <lweintraub@apple.com>
Reviewed by justin
<rdar://problem/4622763> Deleting from beginning of paragraph following a table deletes rather than selects the table
* editing/DeleteSelectionCommand.cpp:
(WebCore::DeleteSelectionCommand::initializeStartEnd): Added selection expansion for HRs.
(WebCore::DeleteSelectionCommand::initializePositionData): Now uses enclosingBlockFlowOrTableElement
instead of enclosingBlockFlowElement.
(WebCore::DeleteSelectionCommand::removeNode): Use to identify that we need a placeholder
when the start or end block is removed.
(WebCore::DeleteSelectionCommand::handleGeneralDelete): Added check for canHaveChildrenForEditing
to keep things like HRs from being given children.
(WebCore::DeleteSelectionCommand::doApply): Switched to use member variable for needPlaceholder.
* editing/DeleteSelectionCommand.h: Made needPlaceholder a member variable.
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::deleteKeyPressed): Fixed selection bug for tables and open typing commands.
(WebCore::TypingCommand::forwardDeleteKeyPressed): Ditto.
* editing/htmlediting.cpp:
(WebCore::editingIgnoresContent): Added check for HRs, since it's not considered a widget.
* editing/visible_units.cpp:
(WebCore::startOfParagraph): Fix for HRs and tables.
(WebCore::endOfParagraph): Ditto.
2006-07-13 Alexey Proskuryakov <ap@nypop.com>
Reviewed by Darin.
......
......@@ -1591,40 +1591,6 @@
FAE04190097596C9000540BE /* SVGImageLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE0418E097596C9000540BE /* SVGImageLoader.h */; };
/* End PBXBuildFile section */
/* Begin PBXBuildStyle section */
D098D47C0A65E2F400D1917D /* Development */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = NO;
};
name = Development;
};
D098D47D0A65E2F400D1917D /* Deployment */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = YES;
};
name = Deployment;
};
/* End PBXBuildStyle section */
/* Begin PBXBuildStyle section */
D098D45B0A65D5A600D1917D /* Development */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = NO;
};
name = Development;
};
D098D45C0A65D5A600D1917D /* Deployment */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = YES;
};
name = Deployment;
};
/* End PBXBuildStyle section */
/* Begin PBXContainerItemProxy section */
DD041FF009D9E3250010AF2A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
......@@ -6444,12 +6410,6 @@
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
buildSettings = {
};
buildStyles = (
D098D47C0A65E2F400D1917D /* Development */,
D098D47D0A65E2F400D1917D /* Deployment */,
);
hasScannedForEncodings = 1;
knownRegions = (
English,
......
......@@ -77,6 +77,13 @@ void DeleteSelectionCommand::initializeStartEnd()
Position start = m_selectionToDelete.start();
Position end = m_selectionToDelete.end();
// For HR's, we'll get a position at (HR,1) when hitting delete from the beginning of the previous line, or (HR,0) when forward deleting,
// but in these cases, we want to delete it, so manually expand the selection
if (start.node()->hasTagName(hrTag))
start = Position(start.node(), 0);
else if (end.node()->hasTagName(hrTag))
end = Position(end.node(), 1);
while (1) {
startSpecialContainer = 0;
endSpecialContainer = 0;
......@@ -156,8 +163,8 @@ void DeleteSelectionCommand::initializePositionData()
//
// Handle setting start and end blocks and the start node.
//
m_startBlock = m_downstreamStart.node()->enclosingBlockFlowElement();
m_endBlock = m_upstreamEnd.node()->enclosingBlockFlowElement();
m_startBlock = m_downstreamStart.node()->enclosingBlockFlowOrTableElement();
m_endBlock = m_upstreamEnd.node()->enclosingBlockFlowOrTableElement();
}
void DeleteSelectionCommand::saveTypingStyleState()
......@@ -227,6 +234,11 @@ void DeleteSelectionCommand::removeNode(Node *node)
return;
}
if (node == m_startBlock && !isEndOfBlock(VisiblePosition(m_startBlock.get(), 0, DOWNSTREAM).previous()))
m_needPlaceholder = true;
else if (node == m_endBlock && !isStartOfBlock(VisiblePosition(m_endBlock.get(), maxDeepOffset(m_endBlock.get()), DOWNSTREAM).next()))
m_needPlaceholder = true;
// FIXME: Update the endpoints of the range being deleted.
updatePositionForNodeRemoval(node, m_endingPosition);
updatePositionForNodeRemoval(node, m_leadingWhitespace);
......@@ -260,9 +272,9 @@ void DeleteSelectionCommand::handleGeneralDelete()
{
int startOffset = m_upstreamStart.offset();
Node* startNode = m_upstreamStart.node();
// Never remove the start block.
if (startNode == m_startBlock && startOffset == 0) {
// Never remove the start block unless it's a table, in which case we won't merge content in.
if (startNode == m_startBlock && startOffset == 0 && canHaveChildrenForEditing(startNode) && !startNode->hasTagName(tableTag)) {
startOffset = 0;
startNode = startNode->traverseNextNode();
}
......@@ -512,9 +524,9 @@ void DeleteSelectionCommand::doApply()
EAffinity affinity = m_selectionToDelete.affinity();
Position downstreamEnd = m_selectionToDelete.end().downstream();
bool needPlaceholder = isStartOfParagraph(m_selectionToDelete.visibleStart()) &&
isEndOfParagraph(m_selectionToDelete.visibleEnd()) &&
!(downstreamEnd.node()->hasTagName(brTag) && downstreamEnd.offset() == 0);
m_needPlaceholder = isStartOfParagraph(m_selectionToDelete.visibleStart()) &&
isEndOfParagraph(m_selectionToDelete.visibleEnd()) &&
!(downstreamEnd.node()->hasTagName(brTag) && downstreamEnd.offset() == 0);
// set up our state
initializePositionData();
......@@ -546,10 +558,11 @@ void DeleteSelectionCommand::doApply()
handleGeneralDelete();
fixupWhitespace();
RefPtr<Node> placeholder = m_needPlaceholder ? createBreakElement(document()) : 0;
mergeParagraphs();
RefPtr<Node> placeholder = needPlaceholder ? createBreakElement(document()) : 0;
if (placeholder)
insertNodeAt(placeholder.get(), m_endingPosition.node(), m_endingPosition.offset());
......
......@@ -59,6 +59,7 @@ private:
bool m_hasSelectionToDelete;
bool m_smartDelete;
bool m_mergeBlocksAfterDelete;
bool m_needPlaceholder;
// This data is transient and should be cleared at the end of the doApply function.
Selection m_selectionToDelete;
......
......@@ -335,9 +335,13 @@ void TypingCommand::deleteKeyPressed()
SelectionController sc = SelectionController(endingSelection().start(), endingSelection().end(), SEL_DEFAULT_AFFINITY);
sc.modify(SelectionController::EXTEND, SelectionController::BACKWARD, m_granularity);
Position upstreamStart = endingSelection().start().upstream();
VisiblePosition visibleStart = endingSelection().visibleStart();
if (visibleStart == startOfParagraph(visibleStart))
upstreamStart = visibleStart.previous(true).deepEquivalent().upstream();
// When deleting tables: Select the table first, then perform the deletion
if (upstreamStart.node()->renderer() && upstreamStart.node()->renderer()->isTable() && upstreamStart.offset() == maxDeepOffset(upstreamStart.node())) {
setEndingSelection(Selection(Position(upstreamStart.node(), 0), upstreamStart, DOWNSTREAM));
setEndingSelection(Selection(Position(upstreamStart.node(), 0), endingSelection().start(), DOWNSTREAM));
typingAddedToOpenCommand();
return;
}
selectionToDelete = sc.selection();
......@@ -370,9 +374,13 @@ void TypingCommand::forwardDeleteKeyPressed()
SelectionController sc = SelectionController(endingSelection().start(), endingSelection().end(), SEL_DEFAULT_AFFINITY);
sc.modify(SelectionController::EXTEND, SelectionController::FORWARD, m_granularity);
Position downstreamEnd = endingSelection().end().downstream();
VisiblePosition visibleEnd = endingSelection().visibleEnd();
if (visibleEnd == endOfParagraph(visibleEnd))
downstreamEnd = visibleEnd.next(true).deepEquivalent().downstream();
// When deleting tables: Select the table first, then perform the deletion
if (downstreamEnd.node()->renderer() && downstreamEnd.node()->renderer()->isTable() && downstreamEnd.offset() == 0) {
setEndingSelection(Selection(downstreamEnd, Position(downstreamEnd.node(), maxDeepOffset(downstreamEnd.node())), DOWNSTREAM));
setEndingSelection(Selection(endingSelection().end(), Position(downstreamEnd.node(), maxDeepOffset(downstreamEnd.node())), DOWNSTREAM));
typingAddedToOpenCommand();
return;
}
selectionToDelete = sc.selection();
......
......@@ -60,12 +60,13 @@ bool editingIgnoresContent(const Node *node)
return true;
if (node->renderer())
return node->renderer()->isWidget() || node->renderer()->isImage() || node->renderer()->isFormElement();
return node->renderer()->isWidget() || node->renderer()->isImage() || node->renderer()->isHR();
return node->hasTagName(appletTag) ||
node->hasTagName(embedTag) ||
node->hasTagName(iframeTag) ||
node->hasTagName(imgTag) ||
node->hasTagName(hrTag) ||
static_cast<const HTMLElement *>(node)->isGenericFormElement();
}
......
......@@ -544,8 +544,15 @@ VisiblePosition startOfParagraph(const VisiblePosition &c)
{
Position p = c.deepEquivalent();
Node *startNode = p.node();
if (!startNode)
return VisiblePosition();
if (startNode->renderer()
&& ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
|| startNode->renderer()->isHR())
&& p.offset() == maxDeepOffset(startNode))
return VisiblePosition(Position(startNode, 0));
Node *startBlock = startNode->enclosingBlockFlowElement();
......@@ -594,12 +601,19 @@ VisiblePosition startOfParagraph(const VisiblePosition &c)
}
VisiblePosition endOfParagraph(const VisiblePosition &c)
{
{
if (c.isNull())
return VisiblePosition();
Position p = c.deepEquivalent();
Node *startNode = p.node();
Node* startNode = p.node();
if (startNode->renderer()
&& ((startNode->renderer()->isTable() && !startNode->renderer()->isInline())
|| startNode->renderer()->isHR())
&& p.offset() == 0)
return VisiblePosition(Position(startNode, maxDeepOffset(startNode)));
Node *startBlock = startNode->enclosingBlockFlowElement();
Node *stayInsideBlock = startBlock;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment