Commit 187d292f authored by justing's avatar justing

LayoutTests:

        Reviewed by Antti.
        
        <rdar://problem/5206311> 
        Whitespace can't be removed when editing text pasted into from web page

        * editing/deleting/5206311-1-expected.checksum: Added.
        * editing/deleting/5206311-1-expected.png: Added.
        * editing/deleting/5206311-1-expected.txt: Added.
        * editing/deleting/5206311-1.html: Added.
        * editing/deleting/5206311-2-expected.checksum: Added.
        * editing/deleting/5206311-2-expected.png: Added.
        * editing/deleting/5206311-2-expected.txt: Added.
        * editing/deleting/5206311-2.html: Added.

WebCore:

        Reviewed by Antti.

        <rdar://problem/5206311> 
        Whitespace can't be removed when editing text pasted into from web page
        
        The whitespace comes from table rows that aren't being removed after they are
        emptied out during a deletion.

        * editing/DeleteSelectionCommand.cpp:
        (WebCore::isTableCell):
        (WebCore::isTableRow):
        (WebCore::isTableCellEmpty):
        (WebCore::isTableRowEmpty):
        (WebCore::DeleteSelectionCommand::initializePositionData): Remember the table
        rows that contained the start and end of the selection.
        (WebCore::DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows):
        Remove table rows that come before the end of the selection
        that was removed (except for the row that contained the start of the selection
        and any before that).
        Remove table rows that are come after the start of the selection
        that was removed (except for the row that contained the end of the selection
        and any after that).
        (WebCore::DeleteSelectionCommand::doApply): Call the new function.
        * editing/DeleteSelectionCommand.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@24375 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e89032a9
2007-07-17 Justin Garcia <justin.garcia@apple.com>
Reviewed by Antti.
<rdar://problem/5206311>
Whitespace can't be removed when editing text pasted into from web page
* editing/deleting/5206311-1-expected.checksum: Added.
* editing/deleting/5206311-1-expected.png: Added.
* editing/deleting/5206311-1-expected.txt: Added.
* editing/deleting/5206311-1.html: Added.
* editing/deleting/5206311-2-expected.checksum: Added.
* editing/deleting/5206311-2-expected.png: Added.
* editing/deleting/5206311-2-expected.txt: Added.
* editing/deleting/5206311-2.html: Added.
2007-07-17 Sam Weinig <sam@webkit.org> 2007-07-17 Sam Weinig <sam@webkit.org>
Reviewed by Adam Roben. Reviewed by Adam Roben.
732ca3caec94fff6ff2d6d1c0a733999
\ No newline at end of file
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 {P} at (0,0) size 784x36
RenderText {#text} at (0,0) size 350x18
text run at (0,0) width 209: "This empties a row (the second). "
text run at (209,0) width 141: "It should be removed. "
RenderInline {B} at (0,0) size 768x36
RenderText {#text} at (350,0) size 768x36
text run at (350,0) width 418: "This demonstrates a bug: the two cells that contained the ends"
text run at (0,18) width 646: "of the selection aren't given a placeholder and so appear differently than the other emptied cells."
RenderBlock {DIV} at (0,52) size 784x52
RenderTable {TABLE} at (0,0) size 38x52 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 36x50
RenderTableRow {TR} at (0,2) size 36x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "1"
RenderTableCell {TD} at (16,2) size 4x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (22,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableRow {TR} at (0,26) size 36x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (16,26) size 4x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (22,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "9"
RenderBlock {P} at (0,120) size 784x18
RenderText {#text} at (0,0) size 593x18
text run at (0,0) width 593: "This empties a row (the second), but it still contains the selection and so shouldn't be removed."
RenderBlock {DIV} at (0,154) size 784x76
RenderTable {TABLE} at (0,0) size 46x76 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 44x74
RenderTableRow {TR} at (0,2) size 44x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "1"
RenderTableCell {TD} at (16,2) size 12x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "2"
RenderTableCell {TD} at (30,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "3"
RenderTableRow {TR} at (0,26) size 44x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (16,26) size 12x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (30,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableRow {TR} at (0,50) size 44x22
RenderTableCell {TD} at (2,50) size 12x22 [border: (1px inset #808080)] [r=2 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "7"
RenderTableCell {TD} at (16,50) size 12x22 [border: (1px inset #808080)] [r=2 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "8"
RenderTableCell {TD} at (30,50) size 12x22 [border: (1px inset #808080)] [r=2 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "9"
RenderBlock {P} at (0,246) size 784x18
RenderText {#text} at (0,0) size 304x18
text run at (0,0) width 304: "This empties the first row, it should be removed."
RenderBlock {DIV} at (0,280) size 784x70
RenderBlock {DIV} at (0,0) size 784x18
RenderText {#text} at (0,0) size 39x18
text run at (0,0) width 39: "Hello "
RenderTable {TABLE} at (0,18) size 46x52 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 44x50
RenderTableRow {TR} at (0,2) size 44x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (16,2) size 12x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (30,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "6"
RenderTableRow {TR} at (0,26) size 44x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "7"
RenderTableCell {TD} at (16,26) size 12x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "8"
RenderTableCell {TD} at (30,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "9"
caret: position 6 of child 0 {#text} of child 1 {DIV} of child 14 {DIV} of child 1 {BODY} of child 0 {HTML} of document
<script>
function runTest(num)
{
sel = window.getSelection();
start = document.getElementById("test" + num + "start");
end = document.getElementById("test" + num + "end");
sel.setBaseAndExtent(start, 0, end, end.childNodes.length);
document.execCommand("Delete");
}
</script>
<p>This empties a row (the second). It should be removed. <b>This demonstrates a bug: the two cells that contained the ends of the selection aren't given a placeholder and so appear differently than the other emptied cells.</b></p>
<div contenteditable="true">
<table border="1">
<tr><td>1</td><td id="test1start">2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td id="test1end">8</td><td>9</td></tr>
</table>
</div>
<script>runTest(1);</script>
<p>This empties a row (the second), but it still contains the selection and so shouldn't be removed.</p>
<div contenteditable="true">
<table border="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td id="test2start">4</td><td>5</td><td id="test2end">6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
</div>
<script>runTest(2);</script>
<p>This empties the first row, it should be removed.</p>
<div contenteditable="true">
<div>Hello <span id="test3start">world!</span></div>
<table border="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td id="test3end">5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
</div>
<script>runTest(3);</script>
d90f218ca09158c0b8a2e78ac1905556
\ No newline at end of file
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 {P} at (0,0) size 784x18
RenderText {#text} at (0,0) size 746x18
text run at (0,0) width 746: "This empties the last row, it should be removed. 'world!' should also be brought into the second cell of the second row."
RenderBlock {DIV} at (0,34) size 784x52
RenderTable {TABLE} at (0,0) size 80x52 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 78x50
RenderTableRow {TR} at (0,2) size 78x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "1"
RenderTableCell {TD} at (16,2) size 46x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "2"
RenderTableCell {TD} at (64,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "3"
RenderTableRow {TR} at (0,26) size 78x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "4"
RenderTableCell {TD} at (16,26) size 46x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderInline {SPAN} at (0,0) size 42x18
RenderText {#text} at (2,2) size 42x18
text run at (2,2) width 42: "world!"
RenderTableCell {TD} at (64,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderBlock {P} at (0,102) size 784x18
RenderText {#text} at (0,0) size 631x18
text run at (0,0) width 631: "This empties a the last row of the first table and the first of the second, they should both be removed."
RenderBlock {DIV} at (0,136) size 784x104
RenderTable {TABLE} at (0,0) size 46x52 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 44x50
RenderTableRow {TR} at (0,2) size 44x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "1"
RenderTableCell {TD} at (16,2) size 12x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "2"
RenderTableCell {TD} at (30,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "3"
RenderTableRow {TR} at (0,26) size 44x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "4"
RenderTableCell {TD} at (16,26) size 12x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (30,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTable {TABLE} at (0,52) size 46x52 [border: (1px outset #808080)]
RenderTableSection {TBODY} at (1,1) size 44x50
RenderTableRow {TR} at (0,2) size 44x22
RenderTableCell {TD} at (2,2) size 12x22 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (16,2) size 12x22 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
RenderBR {BR} at (2,2) size 0x18
RenderTableCell {TD} at (30,2) size 12x22 [border: (1px inset #808080)] [r=0 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "6"
RenderTableRow {TR} at (0,26) size 44x22
RenderTableCell {TD} at (2,26) size 12x22 [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "7"
RenderTableCell {TD} at (16,26) size 12x22 [border: (1px inset #808080)] [r=1 c=1 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "8"
RenderTableCell {TD} at (30,26) size 12x22 [border: (1px inset #808080)] [r=1 c=2 rs=1 cs=1]
RenderText {#text} at (2,2) size 8x18
text run at (2,2) width 8: "9"
caret: position 0 of child 0 {BR} of child 1 {TD} of child 2 {TR} of child 1 {TBODY} of child 1 {TABLE} of child 8 {DIV} of child 1 {BODY} of child 0 {HTML} of document
<script>
function runTest(num)
{
sel = window.getSelection();
start = document.getElementById("test" + num + "start");
end = document.getElementById("test" + num + "end");
sel.setBaseAndExtent(start, 0, end, end.childNodes.length);
document.execCommand("Delete");
}
</script>
<p>This empties the last row, it should be removed. 'world!' should also be brought into the second cell of the second row.</p>
<div contenteditable="true">
<table border="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td id="test1start">5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
<div><span id="test1end">Hello </span>world!</div>
</div>
<script>runTest(1);</script>
<p>This empties a the last row of the first table and the first of the second, they should both be removed.</p>
<div contenteditable="true">
<table border="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td id="test2start">5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
<div>Hello world!</div>
<table border="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td id="test2end">5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
</div>
<script>runTest(2);</script>
2007-07-17 Justin Garcia <justin.garcia@apple.com>
Reviewed by Antti.
<rdar://problem/5206311>
Whitespace can't be removed when editing text pasted into from web page
The whitespace comes from table rows that aren't being removed after they are
emptied out during a deletion.
* editing/DeleteSelectionCommand.cpp:
(WebCore::isTableCell):
(WebCore::isTableRow):
(WebCore::isTableCellEmpty):
(WebCore::isTableRowEmpty):
(WebCore::DeleteSelectionCommand::initializePositionData): Remember the table
rows that contained the start and end of the selection.
(WebCore::DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows):
Remove table rows that come before the end of the selection
that was removed (except for the row that contained the start of the selection
and any before that).
Remove table rows that are come after the start of the selection
that was removed (except for the row that contained the end of the selection
and any after that).
(WebCore::DeleteSelectionCommand::doApply): Call the new function.
* editing/DeleteSelectionCommand.h:
2007-07-17 Geoffrey Garen <ggaren@apple.com> 2007-07-17 Geoffrey Garen <ggaren@apple.com>
Build fix. Build fix.
...@@ -46,6 +46,36 @@ namespace WebCore { ...@@ -46,6 +46,36 @@ namespace WebCore {
using namespace HTMLNames; using namespace HTMLNames;
bool isTableCell(Node* node)
{
return node && (node->hasTagName(tdTag) || node->hasTagName(thTag));
}
bool isTableRow(Node* node)
{
return node && node->hasTagName(trTag);
}
bool isTableCellEmpty(Node* cell)
{
ASSERT(isTableCell(cell));
VisiblePosition firstInCell(Position(cell, 0));
VisiblePosition lastInCell(Position(cell, maxDeepOffset(cell)));
return firstInCell == lastInCell;
}
bool isTableRowEmpty(Node* row)
{
if (!isTableRow(row))
return false;
for (Node* child = row->firstChild(); child; child = child->nextSibling())
if (isTableCell(child) && !isTableCellEmpty(child))
return false;
return true;
}
DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements) DeleteSelectionCommand::DeleteSelectionCommand(Document *document, bool smartDelete, bool mergeBlocksAfterDelete, bool replace, bool expandForSpecialElements)
: CompositeEditCommand(document), : CompositeEditCommand(document),
m_hasSelectionToDelete(false), m_hasSelectionToDelete(false),
...@@ -140,6 +170,9 @@ void DeleteSelectionCommand::initializePositionData() ...@@ -140,6 +170,9 @@ void DeleteSelectionCommand::initializePositionData()
m_startRoot = editableRootForPosition(start); m_startRoot = editableRootForPosition(start);
m_endRoot = editableRootForPosition(end); m_endRoot = editableRootForPosition(end);
m_startTableRow = enclosingNodeOfType(start.node(), &isTableRow);
m_endTableRow = enclosingNodeOfType(end.node(), &isTableRow);
Node* startCell = enclosingTableCell(m_upstreamStart); Node* startCell = enclosingTableCell(m_upstreamStart);
Node* endCell = enclosingTableCell(m_downstreamEnd); Node* endCell = enclosingTableCell(m_downstreamEnd);
// Don't move content out of a table cell. // Don't move content out of a table cell.
...@@ -509,6 +542,35 @@ void DeleteSelectionCommand::mergeParagraphs() ...@@ -509,6 +542,35 @@ void DeleteSelectionCommand::mergeParagraphs()
m_endingPosition = endingSelection().start(); m_endingPosition = endingSelection().start();
} }
void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows()
{
if (m_endTableRow && m_endTableRow->inDocument()) {
Node* row = m_endTableRow.get();
// Do not remove the row that contained the start of the selection,
// since it now contains the selection.
while (row && row != m_startTableRow.get()) {
RefPtr<Node> previousRow = row->previousSibling();
if (isTableRowEmpty(row))
// Use a raw removeNode, instead of DeleteSelectionCommand's, because
// that won't remove rows, it only empties them in preparation for this function.
CompositeEditCommand::removeNode(row);
row = previousRow.get();
}
}
if (m_startTableRow && m_startTableRow->inDocument()) {
// Do not remove the row that contained the start of the selection,
// since it now contains the selection.
Node* row = m_startTableRow->nextSibling();
while (row) {
RefPtr<Node> nextRow = row->nextSibling();
if (isTableRowEmpty(row))
CompositeEditCommand::removeNode(row);
row = nextRow.get();
}
}
}
void DeleteSelectionCommand::calculateTypingStyleAfterDelete(Node *insertedPlaceholder) void DeleteSelectionCommand::calculateTypingStyleAfterDelete(Node *insertedPlaceholder)
{ {
// Compute the difference between the style before the delete and the style now // Compute the difference between the style before the delete and the style now
...@@ -647,6 +709,8 @@ void DeleteSelectionCommand::doApply() ...@@ -647,6 +709,8 @@ void DeleteSelectionCommand::doApply()
mergeParagraphs(); mergeParagraphs();
removePreviouslySelectedEmptyTableRows();
if (placeholder) if (placeholder)
insertNodeAt(placeholder.get(), m_endingPosition); insertNodeAt(placeholder.get(), m_endingPosition);
......
...@@ -50,6 +50,7 @@ private: ...@@ -50,6 +50,7 @@ private:
void handleGeneralDelete(); void handleGeneralDelete();
void fixupWhitespace(); void fixupWhitespace();
void mergeParagraphs(); void mergeParagraphs();
void removePreviouslySelectedEmptyTableRows();
void calculateEndingPosition(); void calculateEndingPosition();
void calculateTypingStyleAfterDelete(Node*); void calculateTypingStyleAfterDelete(Node*);
void clearTransientState(); void clearTransientState();
...@@ -78,6 +79,8 @@ private: ...@@ -78,6 +79,8 @@ private:
RefPtr<CSSMutableStyleDeclaration> m_deleteIntoBlockquoteStyle; RefPtr<CSSMutableStyleDeclaration> m_deleteIntoBlockquoteStyle;
RefPtr<Node> m_startRoot; RefPtr<Node> m_startRoot;
RefPtr<Node> m_endRoot; RefPtr<Node> m_endRoot;
RefPtr<Node> m_startTableRow;
RefPtr<Node> m_endTableRow;
}; };
} // namespace WebCore } // namespace WebCore
......
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