Reviewed by Kevin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Mar 2005 00:51:41 +0000 (00:51 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Mar 2005 00:51:41 +0000 (00:51 +0000)
<rdar://problem/4026787> text typed after a link (pasted or Mail Link to this Page) is part of the link, underlined and colored blue

The concept of this change is every time you type at the very
start or very end of a link (even if nested in further inner
elements), the typed text goes outside the link instead of inside.

* khtml/editing/htmlediting.cpp:
        (khtml::InsertTextCommand::prepareForTextInsertion): Check whether
we are at the first visible position or last visible position of a
special element. For now this only includes HTML A elements that
are links (i.e. they have an href).
(khtml::isSpecialElement): Helper function that identifies special
elements (for now only links).
        (khtml::isFirstVisiblePositionInSpecialElement): Checks if a given DOM
position is equivalent to the first visible position in some containing
editable special element.
        (khtml::positionBeforeNode): Returns the DOM position immediately
before a node.
        (khtml::positionBeforeContainingSpecialElement): Gives a DOM
position immediately before the outermost editable containing
special element where the passed-in position is equivalent to the
first visible position.
        (khtml::maxRangeOffset): Helper to get the maximum allowed
range/position offset for a node, does the right thing based on
whether the node would use a character offset or child offset.
        (khtml::isLastVisiblePositionInSpecialElement): Similar to above,
but for end of node instead of start.
        (khtml::positionAfterNode): Ditto.
        (khtml::positionAfterContainingSpecialElement): Ditto.

Some layout tests changed - I looked over all the diffs and found
that the only changes were "junk nodes" like empty spans and text
nodes moving from one spot in the tree to another. These changes
are all harmless and do not affect layout or future editing.

        * layout-tests/editing/inserting/typing-003-expected.txt:
        * layout-tests/editing/style/remove-underline-across-paragraph-expected.txt:
        * layout-tests/editing/style/remove-underline-across-paragraph-in-bold-expected.txt:
        * layout-tests/editing/style/remove-underline-after-paragraph-expected.txt:
        * layout-tests/editing/style/remove-underline-after-paragraph-in-bold-expected.txt:
        * layout-tests/editing/style/remove-underline-expected.txt:
        * layout-tests/editing/style/remove-underline-from-stylesheet-expected.txt:
        * layout-tests/editing/style/remove-underline-in-bold-expected.txt:
        * layout-tests/editing/style/typing-style-003-expected.txt:
        * layout-tests/editing/style/unbold-in-bold-expected.txt:
        * layout-tests/editing/style/underline-expected.txt:

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

13 files changed:
LayoutTests/editing/inserting/typing-003-expected.txt
LayoutTests/editing/style/remove-underline-across-paragraph-expected.txt
LayoutTests/editing/style/remove-underline-across-paragraph-in-bold-expected.txt
LayoutTests/editing/style/remove-underline-after-paragraph-expected.txt
LayoutTests/editing/style/remove-underline-after-paragraph-in-bold-expected.txt
LayoutTests/editing/style/remove-underline-expected.txt
LayoutTests/editing/style/remove-underline-from-stylesheet-expected.txt
LayoutTests/editing/style/remove-underline-in-bold-expected.txt
LayoutTests/editing/style/typing-style-003-expected.txt
LayoutTests/editing/style/unbold-in-bold-expected.txt
LayoutTests/editing/style/underline-expected.txt
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting.cpp

index b497fd257ea83d49fda1faeb19e419d1a7d2f3bc..b23d7de5d9a1449e254b37fb208d37f6e6e47065 100644 (file)
@@ -4,14 +4,14 @@ 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 #FF0000)]
-        RenderInline {SPAN} at (0,0) size 0x0
-        RenderText {TEXT} at (0,0) size 0x0
         RenderText {TEXT} at (14,14) size 732x112
           text run at (14,14) width 696: "xxxx x xx xxxx xxxxxx xxxxx xxxxxx xxx xx xxxx xxx xxx xx x xxxxx"
           text run at (14,42) width 732: "xxxxxxxxxxxx xxxxxxxx xxx xxxx xxxxx xx xxx xxxx xxxx xxxxx xxxxxx"
           text run at (14,70) width 714: "xxx xx xxxx xxx xxx xx xxxxxx xxxxx xxxxxx xxx xx xxxx xxx xxx xx x"
           text run at (14,98) width 360: "xxxxx xxxxxxxxxxxx xxxxxxxx xxx "
+        RenderInline {SPAN} at (0,0) size 0x28
+        RenderText {TEXT} at (0,0) size 0x0
 selection is CARET:
-start:      position 233 of child 4 {TEXT} of root {DIV}
-upstream:   position 233 of child 4 {TEXT} of root {DIV}
-downstream: position 233 of child 4 {TEXT} of root {DIV}
+start:      position 233 of child 1 {TEXT} of root {DIV}
+upstream:   position 233 of child 1 {TEXT} of root {DIV}
+downstream: position 1 of child 4 {TEXT} of root {DIV}
index dea9012e2261be900f5e81ea93cecfb509542bc8..7e05e3e8304507fe9da9b625de624e10eadce3c3 100644 (file)
@@ -5,13 +5,13 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #FF0000)]
         RenderBlock (anonymous) at (14,14) size 756x28
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderInline {SPAN} at (0,0) size 78x28
             RenderText {TEXT} at (0,0) size 78x28
               text run at (0,0) width 78: "xxxxxx "
           RenderText {TEXT} at (78,0) size 72x28
             text run at (78,0) width 72: "xxxxxx"
+          RenderInline {SPAN} at (0,0) size 0x28
+          RenderText {TEXT} at (0,0) size 0x0
         RenderBlock {DIV} at (14,42) size 756x28
           RenderText {TEXT} at (0,0) size 78x28
             text run at (0,0) width 78: " xxxxxx"
@@ -19,9 +19,9 @@ layer at (0,0) size 800x600
             RenderText {TEXT} at (78,0) size 78x28
               text run at (78,0) width 78: " xxxxxx"
 selection is RANGE:
-start:      position 0 of child 5 {TEXT} of root {DIV}
-upstream:   position 7 of child 1 {TEXT} of child 4 {SPAN} of root {DIV}
-downstream: position 0 of child 5 {TEXT} of root {DIV}
+start:      position 0 of child 2 {TEXT} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 2 {TEXT} of root {DIV}
 end:        position 7 of child 1 {TEXT} of child 6 {DIV} of root {DIV}
 upstream:   position 7 of child 1 {TEXT} of child 6 {DIV} of root {DIV}
 downstream: position 0 of child 1 {TEXT} of child 2 {SPAN} of child 6 {DIV} of root {DIV}
index 801c43f710c8873562390382520fab8809ad8fcd..5cacbb307a0893de5967e6e2593a24bb044787dc 100644 (file)
@@ -5,8 +5,6 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #FF0000)]
         RenderBlock (anonymous) at (14,14) size 756x28
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderInline {SPAN} at (0,0) size 150x28
             RenderInline {B} at (0,0) size 78x28
               RenderText {TEXT} at (0,0) size 78x28
@@ -14,6 +12,8 @@ layer at (0,0) size 800x600
             RenderInline {B} at (0,0) size 72x28
               RenderText {TEXT} at (78,0) size 72x28
                 text run at (78,0) width 72: "xxxxxx"
+          RenderInline {SPAN} at (0,0) size 0x28
+          RenderText {TEXT} at (0,0) size 0x0
         RenderBlock {DIV} at (14,42) size 756x28
           RenderInline {SPAN} at (0,0) size 156x28
             RenderInline {B} at (0,0) size 78x28
@@ -23,9 +23,9 @@ layer at (0,0) size 800x600
               RenderText {TEXT} at (78,0) size 78x28
                 text run at (78,0) width 78: " xxxxxx"
 selection is RANGE:
-start:      position 0 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
-upstream:   position 7 of child 1 {TEXT} of child 1 {B} of child 4 {SPAN} of root {DIV}
-downstream: position 0 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
+start:      position 0 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {B} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
 end:        position 7 of child 1 {TEXT} of child 1 {B} of child 1 {SPAN} of child 5 {DIV} of root {DIV}
 upstream:   position 7 of child 1 {TEXT} of child 1 {B} of child 1 {SPAN} of child 5 {DIV} of root {DIV}
 downstream: position 0 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of child 5 {DIV} of root {DIV}
index 0a157600c365294046f26c26e295bac413e3a968..9409da44f9de664e1cdd44f5f21ee04b7381b5c8 100644 (file)
@@ -5,11 +5,11 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #FF0000)]
         RenderBlock (anonymous) at (14,14) size 756x28
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderInline {SPAN} at (0,0) size 150x28
             RenderText {TEXT} at (0,0) size 150x28
               text run at (0,0) width 150: "xxxxxx xxxxxx"
+          RenderInline {SPAN} at (0,0) size 0x28
+          RenderText {TEXT} at (0,0) size 0x0
         RenderBlock {DIV} at (14,42) size 756x28
           RenderText {TEXT} at (0,0) size 156x28
             text run at (0,0) width 156: " xxxxxx xxxxxx"
index 8964b8529e928b1a957d65a88e95cb8620297b32..2e491bfe7c4ba60ad9e94f2be17240006bbbf9eb 100644 (file)
@@ -5,12 +5,12 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #FF0000)]
         RenderBlock (anonymous) at (14,14) size 756x28
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderInline {SPAN} at (0,0) size 150x28
             RenderInline {B} at (0,0) size 150x28
               RenderText {TEXT} at (0,0) size 150x28
                 text run at (0,0) width 150: "xxxxxx xxxxxx"
+          RenderInline {SPAN} at (0,0) size 0x28
+          RenderText {TEXT} at (0,0) size 0x0
         RenderBlock {DIV} at (14,42) size 756x28
           RenderInline {B} at (0,0) size 156x28
             RenderText {TEXT} at (0,0) size 156x28
index c44f6371d0f5bddabfd3801265b9cb420da7620e..887a0ebad4175ac98e9dcdea496b0a4944db03da 100644 (file)
@@ -4,8 +4,6 @@ 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 784x56 [border: (2px solid #FF0000)]
-        RenderInline {SPAN} at (0,0) size 0x0
-        RenderText {TEXT} at (0,0) size 0x0
         RenderInline {SPAN} at (0,0) size 78x28
           RenderText {TEXT} at (14,14) size 78x28
             text run at (14,14) width 78: "xxxxxx "
@@ -14,10 +12,12 @@ layer at (0,0) size 800x600
         RenderInline {SPAN} at (0,0) size 78x28
           RenderText {TEXT} at (164,14) size 78x28
             text run at (164,14) width 78: " xxxxxx"
+        RenderInline {SPAN} at (0,0) size 0x28
+        RenderText {TEXT} at (0,0) size 0x0
 selection is RANGE:
-start:      position 0 of child 5 {TEXT} of root {DIV}
-upstream:   position 7 of child 1 {TEXT} of child 4 {SPAN} of root {DIV}
-downstream: position 0 of child 5 {TEXT} of root {DIV}
-end:        position 6 of child 5 {TEXT} of root {DIV}
-upstream:   position 6 of child 5 {TEXT} of root {DIV}
-downstream: position 0 of child 1 {TEXT} of child 6 {SPAN} of root {DIV}
+start:      position 0 of child 2 {TEXT} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 2 {TEXT} of root {DIV}
+end:        position 6 of child 2 {TEXT} of root {DIV}
+upstream:   position 6 of child 2 {TEXT} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 3 {SPAN} of root {DIV}
index 416551ecf390f3d13b6e1a333b0f62188a5bdf70..2bb04d47d92265ea46d920bda1196c7dc534c7c6 100644 (file)
@@ -5,9 +5,6 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
         RenderInline {SPAN} at (0,0) size 78x28
-          RenderText {TEXT} at (0,0) size 0x0
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderText {TEXT} at (14,14) size 78x28
             text run at (14,14) width 78: "xxxxxx "
         RenderText {TEXT} at (92,14) size 72x28
@@ -15,9 +12,12 @@ layer at (0,0) size 800x600
         RenderInline {SPAN} at (0,0) size 78x28
           RenderText {TEXT} at (164,14) size 78x28
             text run at (164,14) width 78: " xxxxxx"
+          RenderText {TEXT} at (0,0) size 0x0
+          RenderInline {SPAN} at (0,0) size 0x0
+          RenderText {TEXT} at (0,0) size 0x0
 selection is RANGE:
 start:      position 0 of child 2 {TEXT} of root {DIV}
-upstream:   position 7 of child 4 {TEXT} of child 1 {SPAN} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
 downstream: position 0 of child 2 {TEXT} of root {DIV}
 end:        position 6 of child 2 {TEXT} of root {DIV}
 upstream:   position 6 of child 2 {TEXT} of root {DIV}
index 59d2a3b214a6f0112aac6af6b7163f1f3389becf..6d0a99899c7cd6faa0e6a3b72c2621d0c3a3f676 100644 (file)
@@ -4,8 +4,6 @@ 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 784x56 [border: (2px solid #FF0000)]
-        RenderInline {SPAN} at (0,0) size 0x0
-        RenderText {TEXT} at (0,0) size 0x0
         RenderInline {SPAN} at (0,0) size 228x28
           RenderInline {B} at (0,0) size 78x28
             RenderText {TEXT} at (14,14) size 78x28
@@ -16,10 +14,12 @@ layer at (0,0) size 800x600
           RenderInline {B} at (0,0) size 78x28
             RenderText {TEXT} at (164,14) size 78x28
               text run at (164,14) width 78: " xxxxxx"
+        RenderInline {SPAN} at (0,0) size 0x28
+        RenderText {TEXT} at (0,0) size 0x0
 selection is RANGE:
-start:      position 0 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
-upstream:   position 7 of child 1 {TEXT} of child 1 {B} of child 4 {SPAN} of root {DIV}
-downstream: position 0 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
-end:        position 6 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
-upstream:   position 6 of child 1 {TEXT} of child 2 {B} of child 4 {SPAN} of root {DIV}
-downstream: position 0 of child 1 {TEXT} of child 3 {B} of child 4 {SPAN} of root {DIV}
+start:      position 0 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {B} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
+end:        position 6 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
+upstream:   position 6 of child 1 {TEXT} of child 2 {B} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 3 {B} of child 1 {SPAN} of root {DIV}
index 86b33fe6ba8ced5b500325c29dbe8d1f688a79f7..a051ea5f0645ad99a42e528b94e0033642818574 100644 (file)
@@ -5,9 +5,6 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
         RenderInline {SPAN} at (0,0) size 177x28
-          RenderText {TEXT} at (0,0) size 0x0
-          RenderInline {SPAN} at (0,0) size 0x0
-          RenderText {TEXT} at (0,0) size 0x0
           RenderText {TEXT} at (14,14) size 36x28
             text run at (14,14) width 36: "xxx"
           RenderInline {B} at (0,0) size 141x28
@@ -22,7 +19,10 @@ layer at (0,0) size 800x600
                 RenderInline {SPAN} at (0,0) size 36x28
                   RenderText {TEXT} at (155,14) size 36x28
                     text run at (155,14) width 36: "xxx"
+          RenderText {TEXT} at (0,0) size 0x0
+          RenderInline {SPAN} at (0,0) size 0x0
+          RenderText {TEXT} at (0,0) size 0x0
 selection is CARET:
-start:      position 3 of child 1 {TEXT} of child 2 {SPAN} of child 2 {SPAN} of child 2 {I} of child 5 {B} of child 1 {SPAN} of root {DIV}
-upstream:   position 3 of child 1 {TEXT} of child 2 {SPAN} of child 2 {SPAN} of child 2 {I} of child 5 {B} of child 1 {SPAN} of root {DIV}
-downstream: position 3 of child 1 {TEXT} of child 2 {SPAN} of child 2 {SPAN} of child 2 {I} of child 5 {B} of child 1 {SPAN} of root {DIV}
+start:      position 3 of child 1 {TEXT} of child 2 {SPAN} of child 2 {SPAN} of child 2 {I} of child 2 {B} of child 1 {SPAN} of root {DIV}
+upstream:   position 3 of child 1 {TEXT} of child 2 {SPAN} of child 2 {SPAN} of child 2 {I} of child 2 {B} of child 1 {SPAN} of root {DIV}
+downstream: position 1 of child 5 {TEXT} of child 1 {SPAN} of root {DIV}
index 7b214890abcf0142e36ce3a04ab0ff6758bcf524..307e531fa7d328f611b599c09e5dbd0823c2d2bb 100644 (file)
@@ -4,8 +4,6 @@ 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 784x56 [border: (2px solid #FF0000)]
-        RenderInline {SPAN} at (0,0) size 0x0
-        RenderText {TEXT} at (0,0) size 0x0
         RenderInline {B} at (0,0) size 78x28
           RenderText {TEXT} at (14,14) size 78x28
             text run at (14,14) width 78: "xxxxxx "
@@ -14,10 +12,12 @@ layer at (0,0) size 800x600
         RenderInline {B} at (0,0) size 78x28
           RenderText {TEXT} at (164,14) size 78x28
             text run at (164,14) width 78: " xxxxxx"
+        RenderInline {SPAN} at (0,0) size 0x28
+        RenderText {TEXT} at (0,0) size 0x0
 selection is RANGE:
-start:      position 0 of child 5 {TEXT} of root {DIV}
-upstream:   position 7 of child 1 {TEXT} of child 4 {B} of root {DIV}
-downstream: position 0 of child 5 {TEXT} of root {DIV}
-end:        position 6 of child 5 {TEXT} of root {DIV}
-upstream:   position 6 of child 5 {TEXT} of root {DIV}
-downstream: position 0 of child 1 {TEXT} of child 6 {B} of root {DIV}
+start:      position 0 of child 2 {TEXT} of root {DIV}
+upstream:   position 7 of child 1 {TEXT} of child 1 {B} of root {DIV}
+downstream: position 0 of child 2 {TEXT} of root {DIV}
+end:        position 6 of child 2 {TEXT} of root {DIV}
+upstream:   position 6 of child 2 {TEXT} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 3 {B} of root {DIV}
index f5d0e13b35c39dca3d13163264ec66e575a32485..42a9e5c9dff4e6a1b9cb73c9f52f8b43895264ea 100644 (file)
@@ -4,12 +4,12 @@ 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 784x56 [border: (2px solid #FF0000)]
-        RenderInline {SPAN} at (0,0) size 0x0
-        RenderText {TEXT} at (0,0) size 0x0
         RenderInline {SPAN} at (0,0) size 228x28
           RenderText {TEXT} at (14,14) size 228x28
             text run at (14,14) width 228: "xxxxxx xxxxxx xxxxxx"
+        RenderInline {SPAN} at (0,0) size 0x28
+        RenderText {TEXT} at (0,0) size 0x0
 selection is CARET:
-start:      position 20 of child 1 {TEXT} of child 4 {SPAN} of root {DIV}
-upstream:   position 20 of child 1 {TEXT} of child 4 {SPAN} of root {DIV}
-downstream: position 20 of child 1 {TEXT} of child 4 {SPAN} of root {DIV}
+start:      position 20 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+upstream:   position 20 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+downstream: position 1 of child 4 {TEXT} of root {DIV}
index 7d5db2ea241d48a04713f9870fc2b2b04f198936..7479a30c878e6c8bdd3e4cc2b2cef68680c320da 100644 (file)
@@ -1,3 +1,54 @@
+2005-03-11  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Kevin.
+
+       <rdar://problem/4026787> text typed after a link (pasted or Mail Link to this Page) is part of the link, underlined and colored blue
+        
+       The concept of this change is every time you type at the very
+       start or very end of a link (even if nested in further inner
+       elements), the typed text goes outside the link instead of inside.
+       
+       * khtml/editing/htmlediting.cpp:
+        (khtml::InsertTextCommand::prepareForTextInsertion): Check whether
+       we are at the first visible position or last visible position of a
+       special element. For now this only includes HTML A elements that
+       are links (i.e. they have an href).
+       (khtml::isSpecialElement): Helper function that identifies special
+       elements (for now only links).
+        (khtml::isFirstVisiblePositionInSpecialElement): Checks if a given DOM
+       position is equivalent to the first visible position in some containing 
+       editable special element.
+        (khtml::positionBeforeNode): Returns the DOM position immediately
+       before a node.
+        (khtml::positionBeforeContainingSpecialElement): Gives a DOM
+       position immediately before the outermost editable containing
+       special element where the passed-in position is equivalent to the
+       first visible position.
+        (khtml::maxRangeOffset): Helper to get the maximum allowed
+       range/position offset for a node, does the right thing based on
+       whether the node would use a character offset or child offset.
+        (khtml::isLastVisiblePositionInSpecialElement): Similar to above,
+       but for end of node instead of start.
+        (khtml::positionAfterNode): Ditto.
+        (khtml::positionAfterContainingSpecialElement): Ditto.
+
+       Some layout tests changed - I looked over all the diffs and found
+       that the only changes were "junk nodes" like empty spans and text
+       nodes moving from one spot in the tree to another. These changes
+       are all harmless and do not affect layout or future editing.
+
+        * layout-tests/editing/inserting/typing-003-expected.txt:
+        * layout-tests/editing/style/remove-underline-across-paragraph-expected.txt:
+        * layout-tests/editing/style/remove-underline-across-paragraph-in-bold-expected.txt:
+        * layout-tests/editing/style/remove-underline-after-paragraph-expected.txt:
+        * layout-tests/editing/style/remove-underline-after-paragraph-in-bold-expected.txt:
+        * layout-tests/editing/style/remove-underline-expected.txt:
+        * layout-tests/editing/style/remove-underline-from-stylesheet-expected.txt:
+        * layout-tests/editing/style/remove-underline-in-bold-expected.txt:
+        * layout-tests/editing/style/typing-style-003-expected.txt:
+        * layout-tests/editing/style/unbold-in-bold-expected.txt:
+        * layout-tests/editing/style/underline-expected.txt:
+
 2005-03-11  Adele Amchan  <adele@apple.com>
 
         backing out fix for <rdar://problem/4021711> REGRESSION (125-188): blank pages when browsing forum at cooperativeresearch.org - cached external script problem
index c184124044f4d8b7c981a761b0f2b5fa859b576d..4286d03b0a4500d3cb28dd4b0694495a0c8c1878 100644 (file)
@@ -38,6 +38,7 @@
 #include "dom_positioniterator.h"
 #include "dom_stringimpl.h"
 #include "dom_textimpl.h"
+#include "dom2_range.h"
 #include "dom2_rangeimpl.h"
 #include "html_elementimpl.h"
 #include "html_imageimpl.h"
@@ -3546,6 +3547,120 @@ void InsertTextCommand::doApply()
 {
 }
 
+static bool isSpecialElement(NodeImpl *n)
+{
+    if (!n->isHTMLElement())
+        return false;
+
+    if (n->id() == ID_A && n->hasAnchor())
+        return true;
+
+    return false;
+}
+
+static bool isFirstVisiblePositionInSpecialElement(const Position& pos)
+{
+    VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
+
+    for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
+        if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
+            return false;
+        if (n->rootEditableElement() == NULL)
+            return false;
+        if (isSpecialElement(n))
+            return true;
+    }
+
+    return false;
+}
+
+Position positionBeforeNode(NodeImpl *node)
+{
+    return Position(node->parentNode(), node->nodeIndex());
+}
+
+Position positionBeforeContainingSpecialElement(const Position& pos)
+{
+    ASSERT(isFirstVisiblePositionInSpecialElement(pos));
+
+    VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
+    
+    NodeImpl *outermostSpecialElement = NULL;
+
+    for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
+        if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
+            break;
+        if (n->rootEditableElement() == NULL)
+            break;
+        if (isSpecialElement(n))
+            outermostSpecialElement = n;
+    }
+    
+    ASSERT(outermostSpecialElement);
+
+    return positionBeforeNode(outermostSpecialElement);
+}
+
+static int maxRangeOffset(NodeImpl *n)
+{
+    if (DOM::offsetInCharacters(n->nodeType()))
+        return n->maxOffset();
+
+    if (n->isElementNode())
+        return n->childNodeCount();
+
+    return 1;
+}
+
+static bool isLastVisiblePositionInSpecialElement(const Position& pos)
+{
+    // make sure to get a range-compliant version of the position
+    Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
+
+    VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
+
+    for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
+        if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
+            return false;
+        if (n->rootEditableElement() == NULL)
+            return false;
+        if (isSpecialElement(n))
+            return true;
+    }
+
+    return false;
+}
+
+Position positionAfterNode(NodeImpl *node)
+{
+    return Position(node->parentNode(), node->nodeIndex() + 1);
+}
+
+Position positionAfterContainingSpecialElement(const Position& pos)
+{
+    ASSERT(isLastVisiblePositionInSpecialElement(pos));
+
+    // make sure to get a range-compliant version of the position
+    Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
+
+    VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
+
+    NodeImpl *outermostSpecialElement = NULL;
+
+    for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
+        if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
+            break;
+        if (n->rootEditableElement() == NULL)
+            break;
+        if (isSpecialElement(n))
+            outermostSpecialElement = n;
+    }
+    
+    ASSERT(outermostSpecialElement);
+
+    return positionAfterNode(outermostSpecialElement);
+}
+
 Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
 {
     // Prepare for text input by looking at the current position.
@@ -3561,14 +3676,20 @@ Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
     
     Selection typingStyleRange;
 
+    if (isFirstVisiblePositionInSpecialElement(pos)) {
+        pos = positionBeforeContainingSpecialElement(pos);
+    } else if (isLastVisiblePositionInSpecialElement(pos)) {
+        pos = positionAfterContainingSpecialElement(pos);
+    }
+
     if (!pos.node()->isTextNode()) {
         NodeImpl *textNode = document()->createEditingTextNode("");
         NodeImpl *nodeToInsert = textNode;
 
         // Now insert the node in the right place
-        if (pos.node()->isEditableBlock()) {
+        if (pos.node()->rootEditableElement() != NULL) {
             LOG(Editing, "prepareForTextInsertion case 1");
-            appendNode(nodeToInsert, pos.node());
+            insertNodeAt(nodeToInsert, pos.node(), pos.offset());
         }
         else if (pos.node()->caretMinOffset() == pos.offset()) {
             LOG(Editing, "prepareForTextInsertion case 2");