Reviewed by John
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jan 2005 23:54:09 +0000 (23:54 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jan 2005 23:54:09 +0000 (23:54 +0000)
        Fix for this bug:

        <rdar://problem/3959727> REGRESSION (Mail): Style not preserved on blank lines

        * khtml/editing/htmlediting.cpp:
        (khtml::CompositeEditCommand::applyStyle):
        (khtml::CompositeEditCommand::insertBlockPlaceholder): New function that unconditionally adds a block placeholder.
        (khtml::CompositeEditCommand::insertBlockPlaceholderIfNeeded): Now returns bool based on whether
        placeholder was added or not.
        (khtml::CompositeEditCommand::removeBlockPlaceholderIfNeeded): Now searches all the descendents of a block
        looking for a placeholder. The old code, which just looked at the last child of a node, started missing
        once block placeholders became styled (which started happening with this patch).
        (khtml::DeleteSelectionCommand::calculateTypingStyleAfterDelete): Now handles applying typing style
        to a block placeholder at call time, rather than setting the typing style as a latent style that
        might be applied later. This is an important part of the bug fix.
        (khtml::DeleteSelectionCommand::doApply): Now uses bool return value from insertBlockPlaceholderIfNeeded()
        and passes it along to calculateStyleBeforeInsertion, so the case where a block placeholder needs to
        be styled can be detected.
        (khtml::InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand): Changed the way this class
        managed style. Before it would calculate and set typing style for the block added. This is not
        sufficient. Added blocks need to styled immediately. Some name changes to instance variables in
        this class due to the change to accommodate this change.
        (khtml::InsertParagraphSeparatorCommand::~InsertParagraphSeparatorCommand): Name changes, as above.
        (khtml::InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion): Ditto.
        (khtml::InsertParagraphSeparatorCommand::applyStyleAfterInsertion): Ditto.
        (khtml::InsertParagraphSeparatorCommand::doApply): Ditto.
        (khtml::ReplaceSelectionCommand::doApply): Improve check for testing when a placeholder
        block can be removed in its entirety after the insertion.
        * khtml/editing/htmlediting.h: Update header accordingly.
        * khtml/khtml_part.cpp:
        (KHTMLPart::selectionComputedStyle): Move position for computed style check downstream before
        doing check when the position is in an empty block (this makes sure any style on any block
        placeholder is accounted for).

        New layout tests to check bug fix.

        * layout-tests/editing/style/block-style-004-expected.txt: Added.
        * layout-tests/editing/style/block-style-004.html: Added.
        * layout-tests/editing/style/block-style-005-expected.txt: Added.
        * layout-tests/editing/style/block-style-005.html: Added.
        * layout-tests/editing/style/block-style-006-expected.txt: Added.
        * layout-tests/editing/style/block-style-006.html: Added.

        Results updated to reflect new block placeholder code.

        * layout-tests/editing/inserting/insert-div-004-expected.txt
        * layout-tests/editing/inserting/insert-div-005-expected.txt
        * layout-tests/editing/inserting/insert-div-006-expected.txt
        * layout-tests/editing/inserting/insert-div-008-expected.txt
        * layout-tests/editing/inserting/insert-div-011-expected.txt
        * layout-tests/editing/inserting/insert-div-012-expected.txt
        * layout-tests/editing/inserting/insert-div-013-expected.txt
        * layout-tests/editing/inserting/insert-div-014-expected.txt
        * layout-tests/editing/inserting/insert-div-015-expected.txt
        * layout-tests/editing/inserting/insert-div-016-expected.txt
        * layout-tests/editing/inserting/insert-div-017-expected.txt
        * layout-tests/editing/inserting/insert-div-018-expected.txt
        * layout-tests/editing/inserting/insert-div-019-expected.txt
        * layout-tests/editing/inserting/insert-div-021-expected.txt
        * layout-tests/editing/inserting/insert-div-022-expected.txt
        * layout-tests/editing/inserting/insert-div-023-expected.txt
        * layout-tests/editing/inserting/insert-div-024-expected.txt

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8404 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
LayoutTests/editing/inserting/insert-div-004-expected.txt
LayoutTests/editing/inserting/insert-div-005-expected.txt
LayoutTests/editing/inserting/insert-div-006-expected.txt
LayoutTests/editing/inserting/insert-div-008-expected.txt
LayoutTests/editing/inserting/insert-div-011-expected.txt
LayoutTests/editing/inserting/insert-div-012-expected.txt
LayoutTests/editing/inserting/insert-div-013-expected.txt
LayoutTests/editing/inserting/insert-div-014-expected.txt
LayoutTests/editing/inserting/insert-div-015-expected.txt
LayoutTests/editing/inserting/insert-div-016-expected.txt
LayoutTests/editing/inserting/insert-div-017-expected.txt
LayoutTests/editing/inserting/insert-div-018-expected.txt
LayoutTests/editing/inserting/insert-div-019-expected.txt
LayoutTests/editing/inserting/insert-div-021-expected.txt
LayoutTests/editing/inserting/insert-div-022-expected.txt
LayoutTests/editing/inserting/insert-div-023-expected.txt
LayoutTests/editing/inserting/insert-div-024-expected.txt
LayoutTests/editing/style/block-style-004-expected.txt [new file with mode: 0644]
LayoutTests/editing/style/block-style-004.html [new file with mode: 0644]
LayoutTests/editing/style/block-style-005-expected.txt [new file with mode: 0644]
LayoutTests/editing/style/block-style-005.html [new file with mode: 0644]
LayoutTests/editing/style/block-style-006-expected.txt [new file with mode: 0644]
LayoutTests/editing/style/block-style-006.html [new file with mode: 0644]
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting.cpp
WebCore/khtml/editing/htmlediting.h
WebCore/khtml/khtml_part.cpp

index 4a01910..0ff796c 100644 (file)
@@ -6,9 +6,11 @@ layer at (0,0) size 800x600
       RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "test"
-      RenderBlock {DIV} at (0,56) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,84) size 784x28 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,56) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,112) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
-start:      position 0 of child 3 {DIV} of root {BODY}
+start:      position 0 of child 1 {BR} of child 3 {DIV} of root {BODY}
 upstream:   position 0 of child 3 {DIV} of root {BODY}
-downstream: position 1 of child 3 {DIV} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 3 {DIV} of root {BODY}
index 1d06357..ce9926e 100644 (file)
@@ -6,8 +6,9 @@ layer at (0,0) size 800x600
       RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "test"
-      RenderBlock {DIV} at (0,56) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,84) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,56) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,112) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 12x28
           text run at (14,14) width 12: "x"
 selection is CARET:
index ddeb6ca..a16b130 100644 (file)
@@ -3,8 +3,9 @@ layer 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 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,28) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,56) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 46x28
           text run at (14,14) width 46: "xtest"
 selection is CARET:
index 43c87fc..09ccb03 100644 (file)
@@ -3,8 +3,9 @@ layer 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 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,28) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,56) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 44x28
           text run at (14,14) width 44: "xfoo"
 selection is CARET:
index 60e75f0..dcebfcf 100644 (file)
@@ -7,17 +7,18 @@ layer at (0,0) size 800x600
         RenderText {TEXT} at (0,0) size 629x28
           text run at (0,0) width 629: "Test inserting paragraphs: should see empty red box above \"baz\""
       RenderBlock {DIV} at (0,28) size 784x12
-      RenderBlock {DIV} at (0,40) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,68) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,40) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,96) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "baz"
-      RenderBlock (anonymous) at (0,124) size 784x28
+      RenderBlock (anonymous) at (0,152) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {DIV} at (0,152) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
 start:      position 0 of child 1 {TEXT} of child 5 {DIV} of root {BODY}
index e85a149..7c5b1b1 100644 (file)
@@ -10,16 +10,17 @@ layer at (0,0) size 800x600
       RenderBlock {DIV} at (0,40) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "baz"
-      RenderBlock {DIV} at (0,96) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock (anonymous) at (0,124) size 784x28
+      RenderBlock {DIV} at (0,96) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock (anonymous) at (0,152) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {DIV} at (0,152) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
-start:      position 0 of child 5 {DIV} of root {BODY}
+start:      position 0 of child 1 {BR} of child 5 {DIV} of root {BODY}
 upstream:   position 0 of child 5 {DIV} of root {BODY}
-downstream: position 1 of child 5 {DIV} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 5 {DIV} of root {BODY}
index 8ef4bee..0fb4924 100644 (file)
@@ -10,14 +10,15 @@ layer at (0,0) size 800x600
       RenderBlock {DIV} at (0,40) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "baz"
-      RenderBlock {P} at (0,96) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock (anonymous) at (0,124) size 784x28
+      RenderBlock {P} at (0,96) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock (anonymous) at (0,152) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {DIV} at (0,152) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
 start:      position 0 of child 6 {TEXT} of root {BODY}
index d11c36c..4484605 100644 (file)
@@ -13,13 +13,14 @@ layer at (0,0) size 800x600
       RenderBlock (anonymous) at (0,96) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {P} at (0,124) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock {DIV} at (0,152) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {P} at (0,124) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
-start:      position 0 of child 6 {P} of root {BODY}
+start:      position 0 of child 1 {BR} of child 6 {P} of root {BODY}
 upstream:   position 0 of child 6 {P} of root {BODY}
-downstream: position 1 of child 6 {P} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 6 {P} of root {BODY}
index 8864017..719c9a3 100644 (file)
@@ -13,11 +13,12 @@ layer at (0,0) size 800x600
       RenderBlock (anonymous) at (0,96) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {DIV} at (0,124) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,152) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,124) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
 start:      position 0 of child 1 {TEXT} of child 7 {DIV} of root {BODY}
index dc9d8dc..37518ae 100644 (file)
@@ -16,10 +16,11 @@ layer at (0,0) size 800x600
       RenderBlock {DIV} at (0,124) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {DIV} at (0,180) size 784x28 [border: (2px solid #FF0000)]
-      RenderBlock {DIV} at (0,208) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
-start:      position 0 of child 7 {DIV} of root {BODY}
+start:      position 0 of child 1 {BR} of child 7 {DIV} of root {BODY}
 upstream:   position 0 of child 7 {DIV} of root {BODY}
-downstream: position 1 of child 7 {DIV} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 7 {DIV} of root {BODY}
index df63bee..90a260d 100644 (file)
@@ -18,8 +18,9 @@ layer at (0,0) size 800x600
           text run at (14,14) width 32: "foo"
       RenderBlock {DIV} at (0,180) size 784x56 [border: (2px solid #FF0000)]
         RenderBR {BR} at (14,14) size 0x28
-      RenderBlock {DIV} at (0,236) size 784x28 [border: (2px solid #FF0000)]
+      RenderBlock {DIV} at (0,236) size 784x56 [border: (2px solid #FF0000)]
+        RenderBR {BR} at (14,14) size 0x28
 selection is CARET:
-start:      position 0 of child 9 {DIV} of root {BODY}
+start:      position 0 of child 1 {BR} of child 9 {DIV} of root {BODY}
 upstream:   position 0 of child 9 {DIV} of root {BODY}
-downstream: position 1 of child 9 {DIV} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 9 {DIV} of root {BODY}
index 63dae57..0c2aced 100644 (file)
@@ -10,11 +10,12 @@ layer at (0,0) size 800x600
       RenderBlock (anonymous) at (0,40) size 784x28
         RenderText {TEXT} at (0,0) size 31x28
           text run at (0,0) width 31: "bar"
-      RenderBlock {P} at (0,68) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock {DIV} at (0,96) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {P} at (0,68) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {DIV} at (0,124) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 34x28
           text run at (14,14) width 34: "baz"
 selection is CARET:
-start:      position 0 of child 4 {P} of root {BODY}
+start:      position 0 of child 1 {BR} of child 4 {P} of root {BODY}
 upstream:   position 0 of child 4 {P} of root {BODY}
-downstream: position 1 of child 4 {P} of root {BODY}
+downstream: position 0 of child 1 {BR} of child 4 {P} of root {BODY}
index a426256..2de7b68 100644 (file)
@@ -11,10 +11,11 @@ layer at (0,0) size 800x600
       RenderBlock {P} at (0,92) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 32x28
           text run at (14,14) width 32: "foo"
-      RenderBlock {P} at (0,172) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock (anonymous) at (0,200) size 784x28
+      RenderBlock {P} at (0,172) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock (anonymous) at (0,228) size 784x28
         RenderBR {BR} at (0,0) size 0x28
-      RenderBlock {P} at (0,252) size 784x56 [border: (2px solid #FF0000)]
+      RenderBlock {P} at (0,280) size 784x56 [border: (2px solid #FF0000)]
         RenderText {TEXT} at (14,14) size 31x28
           text run at (14,14) width 31: "bar"
 selection is CARET:
index 9d9a4e8..6a17bec 100644 (file)
@@ -19,8 +19,9 @@ layer at (0,0) size 800x600
         RenderInline {SPAN} at (0,0) size 32x28
           RenderText {TEXT} at (0,0) size 32x28
             text run at (0,0) width 32: "foo"
-      RenderBlock {P} at (0,152) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock {P} at (0,180) size 784x56 [border: (2px solid #0000FF)]
+      RenderBlock {P} at (0,152) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {P} at (0,208) size 784x56 [border: (2px solid #0000FF)]
         RenderText {TEXT} at (14,14) size 31x28
           text run at (14,14) width 31: "bar"
 selection is CARET:
index 8d967e2..88a632c 100644 (file)
@@ -23,10 +23,10 @@ layer at (0,0) size 800x600
         RenderInline {B} at (0,0) size 12x28
           RenderText {TEXT} at (14,14) size 12x28
             text run at (14,14) width 12: "x"
-        RenderBR {BR} at (0,0) size 0x0
+          RenderBR {BR} at (0,0) size 0x0
         RenderText {TEXT} at (14,42) size 31x28
           text run at (14,42) width 31: "bar"
 selection is CARET:
 start:      position 1 of child 1 {TEXT} of child 1 {B} of child 7 {P} of root {BODY}
 upstream:   position 1 of child 1 {TEXT} of child 1 {B} of child 7 {P} of root {BODY}
-downstream: position 0 of child 2 {BR} of child 7 {P} of root {BODY}
+downstream: position 0 of child 2 {BR} of child 1 {B} of child 7 {P} of root {BODY}
index 9c96a24..84bfc6d 100644 (file)
@@ -1,8 +1,8 @@
-layer at (0,0) size 800x660
+layer at (0,0) size 800x688
   RenderCanvas at (0,0) size 800x600
-layer at (0,0) size 800x660
-  RenderBlock {HTML} at (0,0) size 800x660
-    RenderBody {BODY} at (8,8) size 784x628
+layer at (0,0) size 800x688
+  RenderBlock {HTML} at (0,0) size 800x688
+    RenderBody {BODY} at (8,8) size 784x656
       RenderBlock (anonymous) at (0,0) size 784x84
         RenderText {TEXT} at (0,0) size 766x56
           text run at (0,0) width 766: "Test inserting paragraphs and managing typing style correctly: \"x\" under \"line "
@@ -23,14 +23,16 @@ layer at (0,0) size 800x660
         RenderInline {B} at (0,0) size 56x28
           RenderText {TEXT} at (14,14) size 56x28
             text run at (14,14) width 56: "line 2"
-      RenderBlock {P} at (0,360) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock {P} at (0,412) size 784x56 [border: (2px solid #0000FF)]
+      RenderBlock {P} at (0,360) size 784x56 [border: (2px solid #0000FF)]
+        RenderInline {B} at (0,0) size 0x28
+          RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {P} at (0,440) size 784x56 [border: (2px solid #0000FF)]
         RenderInline {B} at (0,0) size 12x28
           RenderText {TEXT} at (14,14) size 12x28
             text run at (14,14) width 12: "x"
-      RenderBlock {P} at (0,492) size 784x56 [border: (2px solid #0000FF)]
+      RenderBlock {P} at (0,520) size 784x56 [border: (2px solid #0000FF)]
         RenderBR {BR} at (14,14) size 0x28
-      RenderBlock {P} at (0,572) size 784x56 [border: (2px solid #0000FF)]
+      RenderBlock {P} at (0,600) size 784x56 [border: (2px solid #0000FF)]
         RenderText {TEXT} at (14,14) size 55x28
           text run at (14,14) width 55: "line 3"
 selection is CARET:
index a240d0e..eded054 100644 (file)
@@ -19,10 +19,13 @@ layer at (0,0) size 800x600
           RenderText {TEXT} at (14,14) size 56x28
             text run at (14,14) width 56: "line 1"
       RenderBlock {P} at (0,228) size 784x56 [border: (2px solid #0000FF)]
-        RenderText {TEXT} at (14,14) size 36x28
-          text run at (14,14) width 36: "xxx"
-      RenderBlock {P} at (0,308) size 784x28 [border: (2px solid #0000FF)]
-      RenderBlock {P} at (0,360) size 784x56 [border: (2px solid #0000FF)]
+        RenderInline {B} at (0,0) size 36x28
+          RenderInline {SPAN} at (0,0) size 36x28
+            RenderText {TEXT} at (14,14) size 36x28
+              text run at (14,14) width 36: "xxx"
+      RenderBlock {P} at (0,308) size 784x56 [border: (2px solid #0000FF)]
+        RenderBR {BR} at (14,14) size 0x28
+      RenderBlock {P} at (0,388) size 784x56 [border: (2px solid #0000FF)]
         RenderText {TEXT} at (14,14) size 36x28
           text run at (14,14) width 36: "xxx"
 selection is CARET:
diff --git a/LayoutTests/editing/style/block-style-004-expected.txt b/LayoutTests/editing/style/block-style-004-expected.txt
new file mode 100644 (file)
index 0000000..cb023f1
--- /dev/null
@@ -0,0 +1,39 @@
+layer at (0,0) size 800x600
+  RenderCanvas 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 784x140 [border: (2px solid #0000FF)]
+        RenderText {TEXT} at (14,14) size 742x56
+          text run at (14,14) width 742: "You should see one \"x\" followed by two blank lines, then one more \"x\". The"
+          text run at (14,42) width 740: "blank lines in between the characters should be the same height. The second"
+        RenderInline {B} at (0,0) size 50x28
+          RenderText {TEXT} at (14,70) size 50x28
+            text run at (14,70) width 50: "must"
+        RenderText {TEXT} at (64,70) size 369x28
+          text run at (64,70) width 369: " be the same height as the first. See: <"
+        RenderInline {A} at (0,0) size 232x28 [color=#0000EE]
+          RenderText {TEXT} at (433,70) size 232x28
+            text run at (433,70) width 232: "rdar://problem/3959727"
+        RenderText {TEXT} at (665,70) size 665x56
+          text run at (665,70) width 14: ">"
+          text run at (14,98) width 557: "REGRESSION (Mail): Style not preserved on blank lines"
+      RenderBlock {DIV} at (0,164) size 784x276
+        RenderBlock {DIV} at (0,0) size 784x69
+          RenderInline {SPAN} at (0,0) size 30x69
+            RenderText {TEXT} at (0,0) size 30x69
+              text run at (0,0) width 30: "x"
+        RenderBlock {DIV} at (0,69) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+        RenderBlock {DIV} at (0,138) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+        RenderBlock {DIV} at (0,207) size 784x69
+          RenderInline {SPAN} at (0,0) size 30x69
+            RenderText {TEXT} at (0,0) size 30x69
+              text run at (0,0) width 30: "x"
+selection is CARET:
+start:      position 0 of child 1 {BR} of child 1 {SPAN} of child 3 {DIV} of root {DIV}
+upstream:   position 0 of child 3 {DIV} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 1 {SPAN} of child 3 {DIV} of root {DIV}
diff --git a/LayoutTests/editing/style/block-style-004.html b/LayoutTests/editing/style/block-style-004.html
new file mode 100644 (file)
index 0000000..1d0a9a9
--- /dev/null
@@ -0,0 +1,52 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    font-size: 16px; 
+}
+.explanation { 
+    border: 2px solid blue; 
+    padding: 12px; 
+    font-size: 24px; 
+    margin-bottom: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    moveSelectionForwardByCharacterCommand();
+    insertParagraphCommand();
+    insertParagraphCommand();
+    typeCharacterCommand();
+    for (i = 0; i < 3; i++)
+        extendSelectionBackwardByLineCommand();
+    fontSizeCommand("60px");
+    moveSelectionBackwardByCharacterCommand();
+    moveSelectionForwardByLineCommand();
+    insertParagraphCommand();
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div class="explanation">
+You should see one "x" followed by two blank lines, then one more "x". The blank lines in between the characters
+should be the same height. The second <b>must</b> be the same height as the first.
+See: &lt;<a href="rdar://problem/3959727">rdar://problem/3959727</a>&gt; REGRESSION (Mail): Style not preserved on blank lines
+</div>
+
+<div contenteditable="true" id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">x</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/style/block-style-005-expected.txt b/LayoutTests/editing/style/block-style-005-expected.txt
new file mode 100644 (file)
index 0000000..9ae916b
--- /dev/null
@@ -0,0 +1,37 @@
+layer at (0,0) size 800x600
+  RenderCanvas 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 784x140 [border: (2px solid #0000FF)]
+        RenderText {TEXT} at (14,14) size 735x56
+          text run at (14,14) width 735: "You should see one \"x\" followed by two blank lines. The blank lines should"
+          text run at (14,42) width 194: "be the same height. "
+          text run at (208,42) width 160: "The second line "
+        RenderInline {B} at (0,0) size 50x28
+          RenderText {TEXT} at (368,42) size 50x28
+            text run at (368,42) width 50: "must"
+        RenderText {TEXT} at (418,42) size 753x56
+          text run at (418,42) width 349: " be the same height as the first. See:"
+          text run at (14,70) width 14: "<"
+        RenderInline {A} at (0,0) size 232x28 [color=#0000EE]
+          RenderText {TEXT} at (28,70) size 232x28
+            text run at (28,70) width 232: "rdar://problem/3959727"
+        RenderText {TEXT} at (260,70) size 711x56
+          text run at (260,70) width 465: "> REGRESSION (Mail): Style not preserved on"
+          text run at (14,98) width 106: "blank lines"
+      RenderBlock {DIV} at (0,164) size 784x207
+        RenderBlock {DIV} at (0,0) size 784x69
+          RenderInline {SPAN} at (0,0) size 30x69
+            RenderText {TEXT} at (0,0) size 30x69
+              text run at (0,0) width 30: "x"
+        RenderBlock {DIV} at (0,69) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+        RenderBlock {DIV} at (0,138) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+selection is CARET:
+start:      position 0 of child 1 {BR} of child 1 {SPAN} of child 3 {DIV} of root {DIV}
+upstream:   position 0 of child 3 {DIV} of root {DIV}
+downstream: position 0 of child 1 {BR} of child 1 {SPAN} of child 3 {DIV} of root {DIV}
diff --git a/LayoutTests/editing/style/block-style-005.html b/LayoutTests/editing/style/block-style-005.html
new file mode 100644 (file)
index 0000000..2ed63f0
--- /dev/null
@@ -0,0 +1,52 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    font-size: 16px; 
+}
+.explanation { 
+    border: 2px solid blue; 
+    padding: 12px; 
+    font-size: 24px; 
+    margin-bottom: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    moveSelectionForwardByCharacterCommand();
+    insertParagraphCommand();
+    insertParagraphCommand();
+    typeCharacterCommand();
+    for (i = 0; i < 3; i++)
+        extendSelectionBackwardByLineCommand();
+    fontSizeCommand("60px");
+    for (i = 0; i < 3; i++)
+        moveSelectionForwardByLineCommand();
+    deleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div class="explanation">
+You should see one "x" followed by two blank lines. The blank lines should be the same height. 
+The second line <b>must</b> be the same height as the first.
+See: &lt;<a href="rdar://problem/3959727">rdar://problem/3959727</a>&gt; REGRESSION (Mail): Style not preserved on blank lines
+</div>
+
+<div contenteditable="true" id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">x</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/style/block-style-006-expected.txt b/LayoutTests/editing/style/block-style-006-expected.txt
new file mode 100644 (file)
index 0000000..b7113d0
--- /dev/null
@@ -0,0 +1,41 @@
+layer at (0,0) size 800x600
+  RenderCanvas 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 784x140 [border: (2px solid #0000FF)]
+        RenderText {TEXT} at (14,14) size 742x56
+          text run at (14,14) width 742: "You should see one \"x\" followed by two blank lines, then one more \"x\". The"
+          text run at (14,42) width 376: "blank lines should be the same height. "
+          text run at (390,42) width 262: "The second and third lines "
+        RenderInline {B} at (0,0) size 50x28
+          RenderText {TEXT} at (652,42) size 50x28
+            text run at (652,42) width 50: "must"
+        RenderText {TEXT} at (702,42) size 753x56
+          text run at (702,42) width 65: " be the"
+          text run at (14,70) width 191: "same height. See: <"
+        RenderInline {A} at (0,0) size 232x28 [color=#0000EE]
+          RenderText {TEXT} at (205,70) size 232x28
+            text run at (205,70) width 232: "rdar://problem/3959727"
+        RenderText {TEXT} at (437,70) size 721x56
+          text run at (437,70) width 298: "> REGRESSION (Mail): Style"
+          text run at (14,98) width 273: "not preserved on blank lines"
+      RenderBlock {DIV} at (0,164) size 784x276
+        RenderBlock {DIV} at (0,0) size 784x69
+          RenderInline {SPAN} at (0,0) size 30x69
+            RenderText {TEXT} at (0,0) size 30x69
+              text run at (0,0) width 30: "x"
+        RenderBlock {DIV} at (0,69) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+        RenderBlock {DIV} at (0,138) size 784x69
+          RenderInline {SPAN} at (0,0) size 0x69
+            RenderBR {BR} at (0,0) size 0x69
+        RenderBlock {DIV} at (0,207) size 784x69
+          RenderInline {SPAN} at (0,0) size 30x69
+            RenderText {TEXT} at (0,0) size 30x69
+              text run at (0,0) width 30: "x"
+selection is CARET:
+start:      position 0 of child 1 {TEXT} of child 1 {SPAN} of child 4 {DIV} of root {DIV}
+upstream:   position 0 of child 4 {DIV} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 1 {SPAN} of child 4 {DIV} of root {DIV}
diff --git a/LayoutTests/editing/style/block-style-006.html b/LayoutTests/editing/style/block-style-006.html
new file mode 100644 (file)
index 0000000..c405c62
--- /dev/null
@@ -0,0 +1,53 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    font-size: 16px; 
+}
+.explanation { 
+    border: 2px solid blue; 
+    padding: 12px; 
+    font-size: 24px; 
+    margin-bottom: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    moveSelectionForwardByCharacterCommand();
+    insertParagraphCommand();
+    insertParagraphCommand();
+    typeCharacterCommand();
+    for (i = 0; i < 3; i++)
+        extendSelectionBackwardByLineCommand();
+    fontSizeCommand("60px");
+    for (i = 0; i < 3; i++)
+        moveSelectionForwardByLineCommand();
+    moveSelectionBackwardByCharacterCommand();
+    insertParagraphCommand();
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div class="explanation">
+You should see one "x" followed by two blank lines, then one more "x". The blank lines should be the same height. 
+The second and third lines <b>must</b> be the same height.
+See: &lt;<a href="rdar://problem/3959727">rdar://problem/3959727</a>&gt; REGRESSION (Mail): Style not preserved on blank lines
+</div>
+
+<div contenteditable="true" id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">x</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
index 6a394fb..fc1f8e9 100644 (file)
@@ -1,3 +1,70 @@
+2005-01-19  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by John
+
+        Fix for this bug:
+        
+        <rdar://problem/3959727> REGRESSION (Mail): Style not preserved on blank lines
+
+        * khtml/editing/htmlediting.cpp:
+        (khtml::CompositeEditCommand::applyStyle):
+        (khtml::CompositeEditCommand::insertBlockPlaceholder): New function that unconditionally adds a block placeholder.
+        (khtml::CompositeEditCommand::insertBlockPlaceholderIfNeeded): Now returns bool based on whether
+        placeholder was added or not.
+        (khtml::CompositeEditCommand::removeBlockPlaceholderIfNeeded): Now searches all the descendents of a block
+        looking for a placeholder. The old code, which just looked at the last child of a node, started missing
+        once block placeholders became styled (which started happening with this patch).
+        (khtml::DeleteSelectionCommand::calculateTypingStyleAfterDelete): Now handles applying typing style
+        to a block placeholder at call time, rather than setting the typing style as a latent style that
+        might be applied later. This is an important part of the bug fix.
+        (khtml::DeleteSelectionCommand::doApply): Now uses bool return value from insertBlockPlaceholderIfNeeded()
+        and passes it along to calculateStyleBeforeInsertion, so the case where a block placeholder needs to
+        be styled can be detected.
+        (khtml::InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand): Changed the way this class
+        managed style. Before it would calculate and set typing style for the block added. This is not
+        sufficient. Added blocks need to styled immediately. Some name changes to instance variables in 
+        this class due to the change to accommodate this change.
+        (khtml::InsertParagraphSeparatorCommand::~InsertParagraphSeparatorCommand): Name changes, as above.
+        (khtml::InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion): Ditto.
+        (khtml::InsertParagraphSeparatorCommand::applyStyleAfterInsertion): Ditto.
+        (khtml::InsertParagraphSeparatorCommand::doApply): Ditto.
+        (khtml::ReplaceSelectionCommand::doApply): Improve check for testing when a placeholder
+        block can be removed in its entirety after the insertion.
+        * khtml/editing/htmlediting.h: Update header accordingly.
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::selectionComputedStyle): Move position for computed style check downstream before
+        doing check when the position is in an empty block (this makes sure any style on any block
+        placeholder is accounted for).
+
+        New layout tests to check bug fix.
+
+        * layout-tests/editing/style/block-style-004-expected.txt: Added.
+        * layout-tests/editing/style/block-style-004.html: Added.
+        * layout-tests/editing/style/block-style-005-expected.txt: Added.
+        * layout-tests/editing/style/block-style-005.html: Added.
+        * layout-tests/editing/style/block-style-006-expected.txt: Added.
+        * layout-tests/editing/style/block-style-006.html: Added.
+
+        Results updated to reflect new block placeholder code.
+
+        * layout-tests/editing/inserting/insert-div-004-expected.txt 
+        * layout-tests/editing/inserting/insert-div-005-expected.txt
+        * layout-tests/editing/inserting/insert-div-006-expected.txt
+        * layout-tests/editing/inserting/insert-div-008-expected.txt
+        * layout-tests/editing/inserting/insert-div-011-expected.txt
+        * layout-tests/editing/inserting/insert-div-012-expected.txt
+        * layout-tests/editing/inserting/insert-div-013-expected.txt
+        * layout-tests/editing/inserting/insert-div-014-expected.txt
+        * layout-tests/editing/inserting/insert-div-015-expected.txt
+        * layout-tests/editing/inserting/insert-div-016-expected.txt
+        * layout-tests/editing/inserting/insert-div-017-expected.txt
+        * layout-tests/editing/inserting/insert-div-018-expected.txt
+        * layout-tests/editing/inserting/insert-div-019-expected.txt
+        * layout-tests/editing/inserting/insert-div-021-expected.txt
+        * layout-tests/editing/inserting/insert-div-022-expected.txt
+        * layout-tests/editing/inserting/insert-div-023-expected.txt
+        * layout-tests/editing/inserting/insert-div-024-expected.txt
+
 2005-01-19  David Hyatt  <hyatt@apple.com>
 
        Dont null-check the renderer before submitting, since a script can set it to display:none and still expect the
index a1d7e7c..196958c 100644 (file)
@@ -635,6 +635,12 @@ void CompositeEditCommand::applyCommandToComposite(EditCommandPtr &cmd)
     m_cmds.append(cmd);
 }
 
+void CompositeEditCommand::applyStyle(CSSStyleDeclarationImpl *style, EditAction editingAction)
+{
+    EditCommandPtr cmd(new ApplyStyleCommand(document(), style, editingAction));
+    applyCommandToComposite(cmd);
+}
+
 void CompositeEditCommand::insertParagraphSeparator()
 {
     EditCommandPtr cmd(new InsertParagraphSeparatorCommand(document()));
@@ -952,21 +958,32 @@ void CompositeEditCommand::deleteInsignificantTextDownstream(const DOM::Position
     deleteInsignificantText(pos, end);
 }
 
-void CompositeEditCommand::insertBlockPlaceholderIfNeeded(NodeImpl *node)
+void CompositeEditCommand::insertBlockPlaceholder(NodeImpl *node)
 {
     if (!node)
         return;
 
+    ASSERT(node->renderer() && node->renderer()->isBlockFlow());
+
+    appendNode(createBlockPlaceholderElement(document()), node);
+}
+
+bool CompositeEditCommand::insertBlockPlaceholderIfNeeded(NodeImpl *node)
+{
+    if (!node)
+        return false;
+
     document()->updateLayout();
 
     RenderObject *renderer = node->renderer();
     if (!renderer || !renderer->isBlockFlow())
-        return;
+        return false;
     
     if (renderer->height() > 0)
-        return;
+        return false;
 
-    appendNode(createBlockPlaceholderElement(document()), node);
+    insertBlockPlaceholder(node);
+    return true;
 }
 
 bool CompositeEditCommand::removeBlockPlaceholderIfNeeded(NodeImpl *node)
@@ -980,18 +997,16 @@ bool CompositeEditCommand::removeBlockPlaceholderIfNeeded(NodeImpl *node)
     if (!renderer || !renderer->isBlockFlow())
         return false;
 
-    // This code will remove a block placeholder if it still is at the end
-    // of a block, where we placed it in insertBlockPlaceholderIfNeeded().
-    // Of course, a person who hand-edits an HTML file could move a 
-    // placeholder around, but it seems OK to be unconcerned about that case.
-    NodeImpl *last = node->lastChild();
-    if (last && last->isHTMLElement()) {
-        ElementImpl *element = static_cast<ElementImpl *>(last);
-        if (element->getAttribute(ATTR_CLASS) == blockPlaceholderClassString()) {
-            removeNode(element);
-            return true;
+    for (NodeImpl *checkMe = node; checkMe; checkMe = checkMe->traverseNextNode(node)) {
+        if (checkMe->isElementNode()) {
+            ElementImpl *element = static_cast<ElementImpl *>(checkMe);
+            if (element->getAttribute(ATTR_CLASS) == blockPlaceholderClassString()) {
+                removeNode(element);
+                return true;
+            }
         }
     }
+    
     return false;
 }
 
@@ -2192,7 +2207,7 @@ void DeleteSelectionCommand::calculateEndingPosition()
     m_endingPosition = Position(document()->documentElement(), 0);
 }
 
-void DeleteSelectionCommand::calculateTypingStyleAfterDelete()
+void DeleteSelectionCommand::calculateTypingStyleAfterDelete(bool insertedPlaceholder)
 {
     // Compute the difference between the style before the delete and the style now
     // after the delete has been done. Set this style on the part, so other editing
@@ -2207,6 +2222,20 @@ void DeleteSelectionCommand::calculateTypingStyleAfterDelete()
         m_typingStyle->deref();
         m_typingStyle = 0;
     }
+    if (insertedPlaceholder && m_typingStyle) {
+        // Apply style to the placeholder. This makes sure that the single line in the
+        // paragraph has the right height, and that the paragraph takes on the style
+        // of the preceding line and retains it even if you click away, click back, and
+        // then start typing. In this case, the typing style is applied right now, and
+        // is not retained until the next typing action.
+        Position pastPlaceholder = endOfParagraph(VisiblePosition(m_endingPosition)).deepEquivalent();
+        setEndingSelection(Selection(m_endingPosition, pastPlaceholder));
+        applyStyle(m_typingStyle, EditActionUnspecified);
+        m_typingStyle->deref();
+        m_typingStyle = 0;
+    }
+    // Set m_typingStyle as the typing style.
+    // It's perfectly OK for m_typingStyle to be null.
     document()->part()->setTypingStyle(m_typingStyle);
     setTypingStyle(m_typingStyle);
 }
@@ -2280,10 +2309,10 @@ void DeleteSelectionCommand::doApply()
 
     // If the delete emptied a block, add in a placeholder so the block does not
     // seem to disappear.
-    insertBlockPlaceholderIfNeeded(m_endingPosition.node());
-    calculateTypingStyleAfterDelete();
-    setEndingSelection(m_endingPosition);
+    bool insertedPlaceholder = insertBlockPlaceholderIfNeeded(m_endingPosition.node());
+    calculateTypingStyleAfterDelete(insertedPlaceholder);
     debugPosition("endingPosition   ", m_endingPosition);
+    setEndingSelection(m_endingPosition);
     clearTransientState();
     rebalanceWhitespace();
 }
@@ -2517,15 +2546,15 @@ void InsertNodeBeforeCommand::doUnapply()
 // InsertParagraphSeparatorCommand
 
 InsertParagraphSeparatorCommand::InsertParagraphSeparatorCommand(DocumentImpl *document) 
-    : CompositeEditCommand(document), m_fullTypingStyle(0)
+    : CompositeEditCommand(document), m_style(0)
 {
 }
 
 InsertParagraphSeparatorCommand::~InsertParagraphSeparatorCommand() 
 {
     derefNodesInList(clonedNodes);
-    if (m_fullTypingStyle)
-        m_fullTypingStyle->deref();
+    if (m_style)
+        m_style->deref();
 }
 
 bool InsertParagraphSeparatorCommand::preservesTypingStyle() const
@@ -2541,38 +2570,39 @@ ElementImpl *InsertParagraphSeparatorCommand::createParagraphElement()
     return element;
 }
 
-void InsertParagraphSeparatorCommand::setFullTypingStyleBeforeInsertion(const Position &pos)
+void InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Position &pos)
 {
     // FIXME: Improve typing style.
     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
     CSSComputedStyleDeclarationImpl *computedStyle = pos.computedStyle();
     computedStyle->ref();
-    if (m_fullTypingStyle)
-        m_fullTypingStyle->deref();
-    m_fullTypingStyle = computedStyle->copyInheritableProperties();
-    m_fullTypingStyle->ref();
+    if (m_style)
+        m_style->deref();
+    m_style = computedStyle->copyInheritableProperties();
+    m_style->ref();
     computedStyle->deref();
     
     CSSMutableStyleDeclarationImpl *typingStyle = document()->part()->typingStyle();
     if (typingStyle)
-        m_fullTypingStyle->merge(typingStyle);
+        m_style->merge(typingStyle);
 }
 
-void InsertParagraphSeparatorCommand::calculateAndSetTypingStyleAfterInsertion()
+void InsertParagraphSeparatorCommand::applyStyleAfterInsertion()
 {
     // FIXME: Improve typing style.
     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
-    if (!m_fullTypingStyle)
+    if (!m_style)
         return;
 
     CSSComputedStyleDeclarationImpl endingStyle(endingSelection().start().node());
-    endingStyle.diff(m_fullTypingStyle);
-    if (!m_fullTypingStyle->length()) {
-        m_fullTypingStyle->deref();
-        m_fullTypingStyle = 0;
+    endingStyle.diff(m_style);
+    if (!m_style->length()) {
+        m_style->deref();
+        m_style = 0;
+    }
+    else {
+        applyStyle(m_style);
     }
-    document()->part()->setTypingStyle(m_fullTypingStyle);
-    setTypingStyle(m_fullTypingStyle);
 }
 
 void InsertParagraphSeparatorCommand::doApply()
@@ -2593,19 +2623,19 @@ void InsertParagraphSeparatorCommand::doApply()
         NodeImpl *startBlockBeforeDelete = selection.start().node()->enclosingBlockFlowElement();
         NodeImpl *endBlockBeforeDelete = selection.end().node()->enclosingBlockFlowElement();
         bool doneAfterDelete = startBlockBeforeDelete != endBlockBeforeDelete;
-        setFullTypingStyleBeforeInsertion(pos);
+        calculateStyleBeforeInsertion(pos);
         deleteSelection(false, false);
         if (doneAfterDelete) {
             document()->updateLayout();
             setEndingSelection(endingSelection().start().downstream());
             rebalanceWhitespace();
-            calculateAndSetTypingStyleAfterInsertion();
+            applyStyleAfterInsertion();
             return;
         }
         pos = endingSelection().start();
     }
 
-    setFullTypingStyleBeforeInsertion(pos);
+    calculateStyleBeforeInsertion(pos);
 
     // Find the start block.
     NodeImpl *startNode = pos.node();
@@ -2628,15 +2658,15 @@ void InsertParagraphSeparatorCommand::doApply()
         if (startBlockIsRoot) {
             NodeImpl *extraBlock = createParagraphElement();
             appendNode(extraBlock, startBlock);
-            insertBlockPlaceholderIfNeeded(extraBlock);
+            insertBlockPlaceholder(extraBlock);
             appendNode(blockToInsert, startBlock);
         }
         else {
             insertNodeAfter(blockToInsert, startBlock);
         }
-        insertBlockPlaceholderIfNeeded(blockToInsert);
+        insertBlockPlaceholder(blockToInsert);
         setEndingSelection(Position(blockToInsert, 0));
-        calculateAndSetTypingStyleAfterInsertion();
+        applyStyleAfterInsertion();
         return;
     }
 
@@ -2649,9 +2679,10 @@ void InsertParagraphSeparatorCommand::doApply()
         pos = pos.downstream(StayInBlock);
         NodeImpl *refNode = isFirstInBlock && !startBlockIsRoot ? startBlock : pos.node();
         insertNodeBefore(blockToInsert, refNode);
-        insertBlockPlaceholderIfNeeded(blockToInsert);
+        insertBlockPlaceholder(blockToInsert);
+        setEndingSelection(Position(blockToInsert, 0));
+        applyStyleAfterInsertion();
         setEndingSelection(pos);
-        calculateAndSetTypingStyleAfterInsertion();
         return;
     }
 
@@ -2663,9 +2694,9 @@ void InsertParagraphSeparatorCommand::doApply()
         LOG(Editing, "insert paragraph separator: last in block case");
         NodeImpl *refNode = isLastInBlock && !startBlockIsRoot ? startBlock : pos.node();
         insertNodeAfter(blockToInsert, refNode);
-        insertBlockPlaceholderIfNeeded(blockToInsert);
+        insertBlockPlaceholder(blockToInsert);
         setEndingSelection(Position(blockToInsert, 0));
-        calculateAndSetTypingStyleAfterInsertion();
+        applyStyleAfterInsertion();
         return;
     }
 
@@ -2767,7 +2798,7 @@ void InsertParagraphSeparatorCommand::doApply()
 
     setEndingSelection(Position(blockToInsert, 0));
     rebalanceWhitespace();
-    calculateAndSetTypingStyleAfterInsertion();
+    applyStyleAfterInsertion();
 }
 
 //------------------------------------------------------------------------------------------
@@ -3965,8 +3996,10 @@ void ReplaceSelectionCommand::doApply()
         completeHTMLReplacement(firstNodeInserted, lastNodeInserted);
     }
     
-    if (placeholderBlock && placeholderBlock->childNodeCount() == 0) {
-        removeNode(placeholderBlock);
+    if (placeholderBlock) {
+        document()->updateLayout();
+        if (!placeholderBlock->renderer() || placeholderBlock->renderer()->height() == 0)
+            removeNode(placeholderBlock);
     }
 }
 
index b1a5575..71ff0c1 100644 (file)
@@ -190,6 +190,7 @@ protected:
     //
     void appendNode(DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
     void applyCommandToComposite(EditCommandPtr &);
+    void applyStyle(DOM::CSSStyleDeclarationImpl *style, EditAction editingAction=EditActionChangeAttributes);
     void deleteKeyPressed();
     void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
     void deleteSelection(const Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
@@ -217,7 +218,8 @@ protected:
     void deleteInsignificantText(const DOM::Position &start, const DOM::Position &end);
     void deleteInsignificantTextDownstream(const DOM::Position &);
 
-    void insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
+    void insertBlockPlaceholder(DOM::NodeImpl *);
+    bool insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
     bool removeBlockPlaceholderIfNeeded(DOM::NodeImpl *);
 
     void moveParagraphContentsToNewBlockIfNecessary(const DOM::Position &);
@@ -336,7 +338,7 @@ private:
     void fixupWhitespace();
     void moveNodesAfterNode();
     void calculateEndingPosition();
-    void calculateTypingStyleAfterDelete();
+    void calculateTypingStyleAfterDelete(bool insertedPlaceholder);
     void clearTransientState();
 
     bool m_hasSelectionToDelete;
@@ -430,14 +432,14 @@ public:
 
 private:
     DOM::ElementImpl *createParagraphElement();
-    void setFullTypingStyleBeforeInsertion(const DOM::Position &);
-    void calculateAndSetTypingStyleAfterInsertion();
+    void calculateStyleBeforeInsertion(const DOM::Position &);
+    void applyStyleAfterInsertion();
 
     virtual bool preservesTypingStyle() const;
 
     QPtrList<DOM::NodeImpl> ancestors;
     QPtrList<DOM::NodeImpl> clonedNodes;
-    DOM::CSSMutableStyleDeclarationImpl *m_fullTypingStyle;
+    DOM::CSSMutableStyleDeclarationImpl *m_style;
 };
 
 //------------------------------------------------------------------------------------------
index fc9301f..9bd7db3 100644 (file)
@@ -5557,8 +5557,16 @@ CSSComputedStyleDeclarationImpl *KHTMLPart::selectionComputedStyle(NodeImpl *&no
         return 0;
 
     Range range(d->m_selection.toRange());
-    Position pos(range.startContainer().handle(), range.startOffset());
+    Position pos = Position(range.startContainer().handle(), range.startOffset());
     assert(pos.isNotNull());
+
+    // If the position is in an empty block, which this test checks, then move the position
+    // for the style check downstream. There may be a block placeholder in this block
+    // which has been styled, and we want to use that for the style calculation.
+    VisiblePosition visiblePos(pos);
+    if (isFirstVisiblePositionInBlock(visiblePos) && isLastVisiblePositionInBlock(visiblePos))
+        pos = pos.downstream(StayInBlock);
+
     ElementImpl *elem = pos.element();
     if (!elem)
         return 0;