+2006-10-13 David Harrison <harrison@apple.com>
+
+ Reviewed by Justin.
+
+ <rdar://problem/4746860> Mail crash in WebCore::CSSMutableStyleDeclaration::merge(WebCore::CSSMutableStyleDeclaration*, bool)
+
+ * editing/style/style-boundary-005.html: Added. Matches steps from bug.
+ * editing/execCommand/hilitecolor-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/remove-underline-across-paragraph-in-bold-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/remove-underline-in-bold-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/typing-style-003-expected.txt: Updated (no empty Apple style spans).
+
2006-10-12 Adele Peterson <adele@apple.com>
Reviewed by Anders.
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > SPAN > SPAN > DIV > BODY > HTML > #document to 6 of #text > SPAN > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > SPAN > DIV > BODY > HTML > #document to 6 of #text > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
RenderBlock {HTML} at (0,0) size 800x600
RenderBody {BODY} at (8,8) size 784x584
RenderBlock {DIV} at (0,0) size 784x18
- RenderInline {SPAN} at (0,0) size 616x18
- RenderText {#text} at (0,0) size 29x18
- text run at (0,0) width 29: "The "
- RenderInline {SPAN} at (0,0) size 44x18 [bgcolor=#FF0000]
- RenderText {#text} at (29,0) size 44x18
- text run at (29,0) width 44: "second"
- RenderText {#text} at (73,0) size 543x18
- text run at (73,0) width 543: " word, and only the second word of this sentence should have a red background color."
-caret: position 0 of child 0 {#text} of child 0 {SPAN} of child 0 {DIV} of child 0 {BODY} of child 0 {HTML} of document
+ RenderText {#text} at (0,0) size 29x18
+ text run at (0,0) width 29: "The "
+ RenderInline {SPAN} at (0,0) size 44x18 [bgcolor=#FF0000]
+ RenderText {#text} at (29,0) size 44x18
+ text run at (29,0) width 44: "second"
+ RenderText {#text} at (73,0) size 543x18
+ text run at (73,0) width 543: " word, and only the second word of this sentence should have a red background color."
+caret: position 0 of child 0 {#text} of child 0 {DIV} of child 0 {BODY} of child 0 {HTML} of document
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of SPAN > DIV > BODY > HTML > #document to 7 of #text > B > SPAN > DIV > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > B > SPAN > DIV > BODY > HTML > #document to 7 of #text > B > SPAN > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > B > DIV > BODY > HTML > #document to 7 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
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 150x28
- RenderInline {B} at (0,0) size 78x28
- RenderText {#text} at (0,0) size 78x28
- text run at (0,0) width 78: "xxxxxx "
- RenderInline {B} at (0,0) size 72x28
- RenderText {#text} at (78,0) size 72x28
- text run at (78,0) width 72: "xxxxxx"
+ RenderInline {B} at (0,0) size 78x28
+ RenderText {#text} at (0,0) size 78x28
+ text run at (0,0) width 78: "xxxxxx "
+ 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
RenderBlock {DIV} at (14,42) size 756x28
- RenderInline {SPAN} at (0,0) size 156x28
- RenderInline {B} at (0,0) size 78x28
- RenderText {#text} at (0,0) size 78x28
- text run at (0,0) width 78: " xxxxxx"
- RenderInline {B} at (0,0) size 78x28
- RenderText {#text} at (78,0) size 78x28
- text run at (78,0) width 78: " xxxxxx"
-selection start: position 0 of child 0 {#text} of child 1 {B} of child 0 {SPAN} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 7 of child 0 {#text} of child 0 {B} of child 0 {SPAN} of child 3 {DIV} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+ RenderInline {B} at (0,0) size 78x28
+ RenderText {#text} at (0,0) size 78x28
+ text run at (0,0) width 78: " xxxxxx"
+ RenderInline {B} at (0,0) size 78x28
+ RenderText {#text} at (78,0) size 78x28
+ text run at (78,0) width 78: " xxxxxx"
+selection start: position 0 of child 0 {#text} of child 1 {B} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 7 of child 0 {#text} of child 0 {B} of child 4 {DIV} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 7 of #text > B > SPAN > DIV > BODY > HTML > #document to 0 of SPAN > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > B > SPAN > DIV > BODY > HTML > #document to 6 of #text > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > B > DIV > BODY > HTML > #document to 6 of #text > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
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 228x28
- RenderInline {B} at (0,0) size 78x28
- RenderText {#text} at (14,14) size 78x28
- text run at (14,14) width 78: "xxxxxx "
- RenderInline {B} at (0,0) size 72x28
- RenderText {#text} at (92,14) size 72x28
- text run at (92,14) width 72: "xxxxxx"
- RenderInline {B} at (0,0) size 78x28
- RenderText {#text} at (164,14) size 78x28
- text run at (164,14) width 78: " xxxxxx"
+ RenderInline {B} at (0,0) size 78x28
+ RenderText {#text} at (14,14) size 78x28
+ text run at (14,14) width 78: "xxxxxx "
+ RenderInline {B} at (0,0) size 72x28
+ RenderText {#text} at (92,14) size 72x28
+ text run at (92,14) width 72: "xxxxxx"
+ 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
-selection start: position 0 of child 0 {#text} of child 1 {B} of child 0 {SPAN} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
-selection end: position 6 of child 0 {#text} of child 1 {B} of child 0 {SPAN} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection start: position 0 of child 0 {#text} of child 1 {B} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+selection end: position 6 of child 0 {#text} of child 1 {B} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
--- /dev/null
+f11d36fc2aff123bb37aba88f7e0a150
\ No newline at end of file
--- /dev/null
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 3 of DIV > BODY > HTML > #document
+EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > B > DIV > DIV > BODY > HTML > #document to 1 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > B > DIV > DIV > BODY > HTML > #document to 1 of #text > B > DIV > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > B > DIV > DIV > BODY > HTML > #document to 2 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > B > DIV > DIV > BODY > HTML > #document to 2 of #text > B > DIV > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > B > DIV > DIV > BODY > HTML > #document to 3 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of #text > B > DIV > DIV > BODY > HTML > #document to 3 of #text > B > DIV > DIV > BODY > HTML > #document toDOMRange:range from 4 of #text > B > DIV > DIV > BODY > HTML > #document to 4 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 4 of #text > B > DIV > DIV > BODY > HTML > #document to 4 of #text > B > DIV > DIV > BODY > HTML > #document toDOMRange:range from 5 of #text > B > DIV > DIV > BODY > HTML > #document to 5 of #text > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 5 of #text > B > DIV > DIV > BODY > HTML > #document to 5 of #text > B > DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 5 of #text > B > DIV > DIV > BODY > HTML > #document to 5 of #text > B > DIV > DIV > BODY > HTML > #document toDOMRange:range from 4 of #text > SPAN > B > DIV > DIV > BODY > HTML > #document to 4 of #text > SPAN > B > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x184 [border: (2px solid #0000FF)]
+ RenderBlock {DIV} at (14,14) size 756x56
+ RenderText {#text} at (0,0) size 67x28
+ text run at (0,0) width 67: "Tests: "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderText {#text} at (0,28) size 698x28
+ text run at (0,28) width 698: "Pasting at style boundary does not crash or produce empty style span(s)."
+ RenderBlock {DIV} at (14,86) size 756x84
+ RenderBlock (anonymous) at (0,0) size 756x56
+ RenderText {#text} at (0,0) size 189x28
+ text run at (0,0) width 189: "Expected Results: "
+ RenderBR {BR} at (189,22) size 0x0
+ RenderText {#text} at (0,28) size 442x28
+ text run at (0,28) width 442: "Should see this content in the red box below: "
+ RenderBR {BR} at (442,50) size 0x0
+ RenderBlock {DIV} at (0,56) size 756x28
+ RenderText {#text} at (0,0) size 138x28
+ text run at (0,0) width 138: "one two three "
+ RenderInline {B} at (0,0) size 44x28
+ RenderText {#text} at (138,0) size 44x28
+ text run at (138,0) width 44: "four"
+ RenderText {#text} at (182,0) size 41x28
+ text run at (182,0) width 41: " one"
+ RenderBlock {DIV} at (0,208) size 784x22
+ RenderBlock {DIV} at (0,0) size 784x22 [border: (2px solid #FF0000)]
+ RenderText {#text} at (2,2) size 86x18
+ text run at (2,2) width 86: "one two three"
+ RenderInline {B} at (0,0) size 60x18
+ RenderText {#text} at (88,2) size 33x18
+ text run at (88,2) width 33: " four"
+ RenderInline {SPAN} at (0,0) size 27x18
+ RenderText {#text} at (121,2) size 27x18
+ text run at (121,2) width 27: " one"
+ RenderBlock (anonymous) at (0,22) size 784x0
+caret: position 4 of child 0 {#text} of child 1 {SPAN} of child 1 {B} of child 1 {DIV} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+.scenario { margin-bottom: 16px;}
+.scenario:first-line { font-weight: bold; margin-bottom: 16px;}
+.expected-results:first-line { font-weight: bold }
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ moveSelectionForwardByLineCommand();
+ boldCommand();
+ typeCharacterCommand(' ');
+ typeCharacterCommand('f');
+ typeCharacterCommand('o');
+ typeCharacterCommand('u');
+ typeCharacterCommand('r');
+ moveSelectionBackwardByLineCommand();
+ extendSelectionForwardByWordCommand();
+ copyCommand();
+ moveSelectionForwardByWordCommand();
+ moveSelectionForwardByWordCommand();
+ moveSelectionForwardByWordCommand();
+ pasteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+
+<div class="explanation">
+<div class="scenario">
+Tests:
+<br>
+Pasting at style boundary does not crash or produce empty style span(s).
+</div>
+<div class="expected-results">
+Expected Results:
+<br>
+Should see this content in the red box below: <br><div>one two three <b>four</b> one</div>
+</div>
+</div>
+
+<div contenteditable id="root">
+<div id="test" class="editing">one two three</div>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > B > DIV > BODY > HTML > #document to 1 of #text > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > B > DIV > BODY > HTML > #document to 1 of #text > B > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > B > DIV > BODY > HTML > #document to 2 of #text > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > B > SPAN > DIV > BODY > HTML > #document to 3 of #text > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > B > DIV > BODY > HTML > #document to 2 of #text > B > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > B > DIV > BODY > HTML > #document to 3 of #text > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > I > B > DIV > BODY > HTML > #document to 1 of #text > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > I > B > DIV > BODY > HTML > #document to 1 of #text > I > B > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > I > B > DIV > BODY > HTML > #document to 2 of #text > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > I > B > SPAN > DIV > BODY > HTML > #document to 3 of #text > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > I > B > DIV > BODY > HTML > #document to 2 of #text > I > B > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > I > B > DIV > BODY > HTML > #document to 3 of #text > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > I > B > DIV > BODY > HTML > #document to 1 of #text > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > I > B > DIV > BODY > HTML > #document to 1 of #text > SPAN > I > B > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > I > B > DIV > BODY > HTML > #document to 2 of #text > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 3 of #text > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > SPAN > I > B > DIV > BODY > HTML > #document to 2 of #text > SPAN > I > B > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > SPAN > I > B > DIV > BODY > HTML > #document to 3 of #text > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document to 1 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document toDOMRange:range from 2 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document to 3 of #text > SPAN > SPAN > I > B > SPAN > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document to 2 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document toDOMRange:range from 3 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document to 3 of #text > SPAN > SPAN > I > B > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
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 177x28
- RenderText {#text} at (14,14) size 36x28
- text run at (14,14) width 36: "xxx"
- RenderInline {B} at (0,0) size 141x28
- RenderText {#text} at (50,14) size 36x28
- text run at (50,14) width 36: "xxx"
- RenderInline {I} at (0,0) size 105x28
- RenderText {#text} at (86,14) size 36x28
- text run at (86,14) width 36: "xxx"
- RenderInline {SPAN} at (0,0) size 69x28
- RenderText {#text} at (122,14) size 33x28
- text run at (122,14) width 33: "xxx"
- RenderInline {SPAN} at (0,0) size 36x28
- RenderText {#text} at (155,14) size 36x28
- text run at (155,14) width 36: "xxx"
- RenderInline {SPAN} at (0,0) size 0x28
-caret: position 3 of child 0 {#text} of child 1 {SPAN} of child 1 {SPAN} of child 1 {I} of child 1 {B} of child 0 {SPAN} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+ RenderText {#text} at (14,14) size 36x28
+ text run at (14,14) width 36: "xxx"
+ RenderInline {B} at (0,0) size 141x28
+ RenderText {#text} at (50,14) size 36x28
+ text run at (50,14) width 36: "xxx"
+ RenderInline {I} at (0,0) size 105x28
+ RenderText {#text} at (86,14) size 36x28
+ text run at (86,14) width 36: "xxx"
+ RenderInline {SPAN} at (0,0) size 69x28
+ RenderText {#text} at (122,14) size 33x28
+ text run at (122,14) width 33: "xxx"
+ RenderInline {SPAN} at (0,0) size 36x28
+ RenderText {#text} at (155,14) size 36x28
+ text run at (155,14) width 36: "xxx"
+ RenderInline {SPAN} at (0,0) size 0x28
+caret: position 3 of child 0 {#text} of child 1 {SPAN} of child 1 {SPAN} of child 1 {I} of child 1 {B} of child 1 {DIV} of child 1 {BODY} of child 0 {HTML} of document
+2006-10-13 David Harrison <harrison@apple.com>
+
+ Reviewed by Justin.
+
+ <rdar://problem/4746860> Mail crash in WebCore::CSSMutableStyleDeclaration::merge(WebCore::CSSMutableStyleDeclaration*, bool)
+
+ Tests added or changed:
+ * editing/style/style-boundary-005.html: Added. Matches steps from bug.
+ * editing/execCommand/hilitecolor-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/remove-underline-across-paragraph-in-bold-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/remove-underline-in-bold-expected.txt: Updated (no empty Apple style spans).
+ * editing/style/typing-style-003-expected.txt: Updated (no empty Apple style spans).
+
+ * dom/Text.cpp:
+ (WebCore::Text::splitText):
+ Comment changes.
+
+ * editing/ApplyStyleCommand.cpp:
+ (WebCore::isUnstyledStyleSpan):
+ Renamed from isEmptyStyleSpan.
+
+ (WebCore::ApplyStyleCommand::applyRelativeFontStyleChange):
+ Rename emptySpans local to unstyledSpans.
+
+ (WebCore::dummySpanAncestorForNode):
+ New. To locate Apple style span created when splitting a text node.
+
+ (WebCore::ApplyStyleCommand::cleanupUnstyledAppleStyleSpans):
+ Renamed from cleanUpEmptyStyleSpans. Algorithm changed to scan children
+ of dummy span's parents, rather than traversing up from start and
+ end locations. Old algorithm would miss empty spans in the bug case.
+
+ (WebCore::ApplyStyleCommand::applyInlineStyle):
+ Use dummySpanAncestorForNode() and cleanupUnstyledAppleStyleSpans().
+
+ (WebCore::ApplyStyleCommand::removeCSSStyle):
+ Renamed isEmptyStyleSpan() to isUnstyledStyleSpan().
+
+ (WebCore::ApplyStyleCommand::mergeStartWithPreviousIfIdentical):
+ Comment changes.
+
+ * editing/ApplyStyleCommand.h:
+ Renamed cleanUpEmptyStyleSpans() to cleanupUnstyledAppleStyleSpans().
+
+ * editing/ReplaceSelectionCommand.cpp:
+ (WebCore::ReplaceSelectionCommand::removeRedundantStyles):
+ Allow for Apple style span to be unstyled, because old email may have this in the DOM.
+ Use !node->hasChildNodes() instead of !node->firstChild().
+
+ * editing/SplitTextNodeCommand.cpp:
+ (WebCore::SplitTextNodeCommand::doApply):
+ Comment changes.
+
+ * rendering/RenderTreeAsText.cpp:
+ (WebCore::isEmptyOrUnstyledAppleStyleSpan):
+ (WebCore::operator<<):
+ Flag empty or unstyled AppleStyleSpa nbecause we never want to leave them in the DOM
+
2006-10-13 Nikolas Zimmermann <zimmermann@kde.org>
Reviewed by Eric.
{
ec = 0;
+ // FIXME: This does not copy markers
+
// INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than
// the number of 16-bit units in data.
if (offset > str->length()) {
return elem->hasLocalName(spanAttr) && elem->getAttribute(classAttr) == styleSpanClassString();
}
-static bool isEmptyStyleSpan(const Node *node)
+static bool isUnstyledStyleSpan(const Node *node)
{
if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
return false;
startingFontSizes.set(node, computedFontSize(node));
// These spans were added by us. If empty after font size changes, they can be removed.
- DeprecatedPtrList<Node> emptySpans;
+ DeprecatedPtrList<Node> unstyledSpans;
Node *lastStyledNode = 0;
for (Node *node = startNode; node != beyondEnd; node = node->traverseNextNode()) {
}
if (inlineStyleDecl->length() == 0) {
removeNodeAttribute(elem, styleAttr);
- if (isEmptyStyleSpan(elem))
- emptySpans.append(elem);
+ if (isUnstyledStyleSpan(elem))
+ unstyledSpans.append(elem);
}
}
- for (DeprecatedPtrListIterator<Node> it(emptySpans); it.current(); ++it)
+ for (DeprecatedPtrListIterator<Node> it(unstyledSpans); it.current(); ++it)
removeNodePreservingChildren(it.current());
}
#undef NoFontDelta
#undef MinimumFontSize
+static Node* dummySpanAncestorForNode(const Node* node)
+{
+ while (node && !isStyleSpan(node))
+ node = node->parent();
+
+ return node ? node->parent() : 0;
+}
+
+void ApplyStyleCommand::cleanupUnstyledAppleStyleSpans(Node* dummySpanAncestor)
+{
+ if (!dummySpanAncestor)
+ return;
+
+ // Dummy spans are created when text node is split, so that style information
+ // can be propagated, which can result in more splitting. If a dummy span gets
+ // cloned/split, the new node is always a sibling of it. Therefore, we scan
+ // all the children of the dummy's parent
+ Node* next;
+ for (Node* node = dummySpanAncestor->firstChild(); node; node = next) {
+ next = node->nextSibling();
+ if (isUnstyledStyleSpan(node))
+ removeNodePreservingChildren(node);
+ node = next;
+ }
+}
+
void ApplyStyleCommand::applyInlineStyle(CSSMutableStyleDeclaration *style)
{
+ Node* startDummySpanAncestor = 0;
+ Node* endDummySpanAncestor = 0;
+
// update document layout once before removing styles
// so that we avoid the expense of updating before each and every call
// to check a computed style
updateLayout();
-
+
// adjust to the positions we want to use for applying style
Position start = startPosition();
Position end = endPosition();
if (splitStart) {
start = startPosition();
end = endPosition();
+ startDummySpanAncestor = dummySpanAncestorForNode(start.node());
}
// split the end node and containing element if the selection ends inside of it
if (splitEnd) {
start = startPosition();
end = endPosition();
+ endDummySpanAncestor = dummySpanAncestorForNode(end.node());
}
// Remove style from the selection.
}
}
- if (splitStart || splitEnd) {
- cleanUpEmptyStyleSpans(start, end);
- }
+ // remove dummy style spans created by splitting text elements
+ cleanupUnstyledAppleStyleSpans(startDummySpanAncestor);
+ if (endDummySpanAncestor != startDummySpanAncestor)
+ cleanupUnstyledAppleStyleSpans(endDummySpanAncestor);
}
bool ApplyStyleCommand::isHTMLStyleNode(CSSMutableStyleDeclaration *style, HTMLElement *elem)
removeCSSProperty(decl, propertyID);
}
- if (isEmptyStyleSpan(elem))
+ if (isUnstyledStyleSpan(elem))
removeNodePreservingChildren(elem);
}
if (start.offset() != 0)
return false;
+ // note: prior siblings could be unrendered elements. it's silly to miss the
+ // merge opportunity just for that.
if (start.node()->previousSibling())
return false;
return false;
}
-void ApplyStyleCommand::cleanUpEmptyStyleSpans(const Position &start, const Position &end)
-{
- Node *node;
- for (node = start.node(); node && !node->previousSibling(); node = node->parentNode()) {
- }
-
- if (node && isEmptyStyleSpan(node->previousSibling())) {
- removeNodePreservingChildren(node->previousSibling());
- }
-
- if (start.node() == end.node()) {
- if (start.node()->isTextNode()) {
- for (Node *last = start.node(), *cur = last->parentNode(); cur && !last->previousSibling() && !last->nextSibling(); last = cur, cur = cur->parentNode()) {
- if (isEmptyStyleSpan(cur)) {
- removeNodePreservingChildren(cur);
- break;
- }
- }
-
- }
- } else {
- if (start.node()->isTextNode()) {
- for (Node *last = start.node(), *cur = last->parentNode(); cur && !last->previousSibling(); last = cur, cur = cur->parentNode()) {
- if (isEmptyStyleSpan(cur)) {
- removeNodePreservingChildren(cur);
- break;
- }
- }
- }
-
- if (end.node()->isTextNode()) {
- for (Node *last = end.node(), *cur = last->parentNode(); cur && !last->nextSibling(); last = cur, cur = cur->parentNode()) {
- if (isEmptyStyleSpan(cur)) {
- removeNodePreservingChildren(cur);
- break;
- }
- }
- }
- }
-
- for (node = end.node(); node && !node->nextSibling(); node = node->parentNode()) {
- }
- if (node && isEmptyStyleSpan(node->nextSibling())) {
- removeNodePreservingChildren(node->nextSibling());
- }
-}
-
void ApplyStyleCommand::surroundNodeRangeWithElement(Node *startNode, Node *endNode, Element *element)
{
ASSERT(startNode);
bool splitTextElementAtEndIfNeeded(const Position& start, const Position& end);
bool mergeStartWithPreviousIfIdentical(const Position& start, const Position& end);
bool mergeEndWithNextIfIdentical(const Position& start, const Position& end);
- void cleanUpEmptyStyleSpans(const Position& start, const Position& end);
+ void cleanupUnstyledAppleStyleSpans(Node* dummySpanAncestor);
void surroundNodeRangeWithElement(Node* start, Node* end, Element* element);
float computedFontSize(const Node*);
if (isStyleSpan(child.get())) {
HTMLElement* elem = static_cast<HTMLElement*>(child.get());
CSSMutableStyleDeclaration* inlineStyleDecl = elem->inlineStyleDecl();
- inlineStyleDecl->merge(parentStyle.get(), false);
- setNodeAttribute(elem, styleAttr, inlineStyleDecl->cssText());
+ // be defensive because we used to sometimes leave unstyled Apple style spans in the DOM,
+ // and we could be processing an old email with that flaw
+ if (!inlineStyleDecl)
+ setNodeAttribute(elem, styleAttr, parentStyle->cssText());
+ else {
+ inlineStyleDecl->merge(parentStyle.get(), false);
+ setNodeAttribute(elem, styleAttr, inlineStyleDecl->cssText());
+ }
} else if (node->isElementNode()) {
RefPtr<Node> clone = node->cloneNode(false);
int index = child->nodeIndex();
Node *node = it->first;
// Remove empty style spans.
- if (isStyleSpan(node) && !node->firstChild()) {
+ if (isStyleSpan(node) && !node->hasChildNodes()) {
removeNodeAndPruneAncestors(node);
continue;
}
ExceptionCode ec = 0;
- // EDIT FIXME: This should use better smarts for figuring out which portion
- // of the split to copy (based on their comparitive sizes). We should also
- // just use the DOM's splitText function.
-
+ // NOTE: Various callers rely on the fact that the original node becomes
+ // the second node (i.e. the new node is inserted before the existing one).
+ // That is not a fundamental dependency (i.e. it could be re-coded), but
+ // rather is based on how this code happens to work.
if (!m_text1) {
// create only if needed.
// if reapplying, this object will already exist.
#include "Document.h"
#include "Frame.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
#include "InlineTextBox.h"
#include "JSEditor.h"
#include "RenderBR.h"
namespace WebCore {
+using namespace HTMLNames;
+
static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const IntRect& paintDirtyRect, int indent = 0);
#ifndef SVG_SUPPORT
return n->nodeName().deprecatedString();
}
+static bool isEmptyOrUnstyledAppleStyleSpan(const Node *node)
+{
+ if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
+ return false;
+
+ const HTMLElement *elem = static_cast<const HTMLElement *>(node);
+ if (elem->getAttribute(classAttr) != "Apple-style-span")
+ return false;
+
+ if (!node->hasChildNodes())
+ return true;
+
+ CSSMutableStyleDeclaration *inlineStyleDecl = elem->inlineStyleDecl();
+ return (!inlineStyleDecl || inlineStyleDecl->length() == 0);
+}
+
static TextStream &operator<<(TextStream &ts, const RenderObject &o)
{
ts << o.renderName();
DeprecatedString tagName = getTagName(o.element());
if (!tagName.isEmpty()) {
ts << " {" << tagName << "}";
+ // flag empty or unstyled AppleStyleSpan because we never
+ // want to leave them in the DOM
+ if (isEmptyOrUnstyledAppleStyleSpan(o.element()))
+ ts << " *empty or unstyled AppleStyleSpan*";
}
}