Changeset 15617 in webkit


Ignore:
Timestamp:
Jul 24, 2006 9:39:25 PM (18 years ago)
Author:
darin
Message:

LayoutTests:

Reviewed by Adele and Justin.

  • fast/forms/textarea-type-spaces-expected.txt: Added.
  • fast/forms/textarea-type-spaces.html: Added.
  • fast/forms/textarea-paste-newline-expected.txt: Added.
  • fast/forms/textarea-paste-newline.html: Added.
  • updated tests affected by above changes, results are equivalent or better
  • editing/pasteboard/4641033-expected.checksum:
  • editing/pasteboard/4641033-expected.png:
  • editing/pasteboard/4641033-expected.txt:
  • editing/pasteboard/paste-table-003-expected.checksum:
  • editing/pasteboard/paste-table-003-expected.png:
  • editing/pasteboard/paste-table-003-expected.txt:
  • editing/pasteboard/paste-text-016-expected.txt:
  • editing/pasteboard/quirks-mode-br-1-expected.txt:
  • editing/pasteboard/quirks-mode-br-2-expected.txt:
  • fast/forms/textarea-scrolled-type-expected.checksum:
  • fast/forms/textarea-scrolled-type-expected.png:
  • fast/forms/textarea-scrolled-type-expected.txt:
  • changed a test to be a "dump as text" test
  • fast/forms/paste-into-textarea-expected.txt:
  • fast/forms/paste-into-textarea.html:
  • fast/forms/paste-into-textarea-expected.checksum: Removed.
  • fast/forms/paste-into-textarea-expected.png: Removed.
  • changed a test to be a "dump as text" test, improved test a bit and also checked in new results
  • fast/forms/textarea-scrolled-endline-caret-expected.txt:
  • fast/forms/textarea-scrolled-endline-caret.html:
  • fixed a test that was raising an exception every time it ran
  • fast/forms/attributed-strings-expected.txt:
  • fast/forms/attributed-strings.html:
  • corrected checksums on a bunch of tests (pngs were right, but checksums wrong, apparently)
  • editing/deleting/delete-to-select-table-expected.checksum:
  • editing/selection/3690719-expected.checksum:
  • editing/selection/clear-selection-expected.checksum:
  • editing/undo/undo-misspellings-expected.checksum:
  • added some missing pixel test results
  • editing/pasteboard/nested-blocks-with-text-area-expected.checksum: Added.
  • editing/pasteboard/nested-blocks-with-text-area-expected.png: Added.
  • editing/pasteboard/nested-blocks-with-text-field-expected.checksum: Added.
  • editing/pasteboard/nested-blocks-with-text-field-expected.png: Added.

WebCore:

Reviewed by Adele and Justin.

Test: fast/forms/textarea-type-spaces.html
Test: fast/forms/textarea-paste-newline.html

  • bindings/objc/DOMHTML.mm: (-[DOMHTMLDocument createDocumentFragmentWithText:]): Updated call to pass a range -- in this case it is the range of the entire document, so this will not handle the whitespace properly.
  • bridge/mac/WebCoreFrameBridge.h: Added range context parameter to the documentFragmentWithText: method, so we can handle whitespace properly.
  • bridge/mac/WebCoreFrameBridge.mm: (-[WebCoreFrameBridge nodesFromList:]): Changed from DeprecatedPtrList to Vector. (-[WebCoreFrameBridge markupStringFromNode:nodes:]): Ditto. (-[WebCoreFrameBridge markupStringFromRange:nodes:]): Ditto. (-[WebCoreFrameBridge documentFragmentWithText:inContext:]): Added range context parameter -- pass it on to createFragmentFromText. (-[WebCoreFrameBridge documentFragmentWithNodesAsParagraphs:]): Changed from DeprecatedPtrList to Vector. (-[WebCoreFrameBridge replaceSelectionWithText:selectReplacement:smartReplace:]): Pass the range of the current selection as context when creating the fragment.
  • dom/Position.cpp: (WebCore::Position::inRenderedText): Replace range check with a call to the new containsCaretOffset function -- helps make the caret work right when it is past the end of the last line in a textarea.
  • editing/CompositeEditCommand.cpp: (WebCore::CompositeEditCommand::rebalanceWhitespaceAt): Don't do anything if the style does not call for collapsing whitespace. (WebCore::CompositeEditCommand::rebalanceWhitespace): Call replaceWhitespaceAt to share code, including the new logic mentioned above.
  • editing/InsertLineBreakCommand.cpp: (WebCore::InsertLineBreakCommand::doApply): Use a text node instead of a break element when inserting and the style is preserveNewline.
  • editing/JSEditor.cpp: (WebCore::execRemoveFormat): Pass the selection range to createFragmentFromText.
  • editing/RebalanceWhitespaceCommand.cpp: (WebCore::RebalanceWhitespaceCommand::doApply): Assert that we're in a style that collapses whitespace. It's the caller's responsibility not to call otherwise.
  • editing/ReplaceSelectionCommand.h: Removed unused destructor, type, isSingleTextNode, isTreeFragment, m_type, and added a context parameter to inertFragmentForTestRendering. Also changed the constructor to take a selection rather than a pointer to the root editable element, replaced removeEndBRIfNeeded with shouldRemoveEndBR and removed an unused parameter from shouldMergeEnd.
  • editing/ReplaceSelectionCommand.cpp: (WebCore::ReplacementFragment::ReplacementFragment): Removed code to set up m_type. Compute root editable element from passed-in selection. Used the start of the selection as a base node for style purposes for the test rendering. Removed the special case "single text node" alternative to createFragmentFromText in the plain text case, since createFragmentFromText now handles that correctly. (WebCore::ReplacementFragment::insertFragmentForTestRendering): Copy the whitespace property from the source location when creating a temporary element for test rendering. (WebCore::ReplacementFragment::shouldMergeEnd): Removed unneeded boolean parameter fragmentHadInterchangeNewlineAtEnd, which is always false. (WebCore::ReplaceSelectionCommand::doApply): Update for ReplacementFragment changes, change code to not remove end BR when it can be re-used instead, don't call the paragraph separator insertion when the position is at the start of a paragraph already, removed redundant computation of identical "next" value, removed unneeded boolean parameter to shouldMergeEnd, add case for merging when all we need to do is to delete a newline character, removed unneeded code to set insertionPos after all code that uses it, and use spaces instead of non-breaking spaces when doing smart paste if the context is one where we do not collapse white space. (WebCore::ReplaceSelectionCommand::shouldRemoveEndBR): Renamed and changed to return a boolean instead of doing the removal.
  • editing/markup.h: Use Vector instead of DeprecatedPtrList. Change the createFragmentFromText function to take a range for context instead of a document.
  • editing/markup.cpp: (WebCore::markup): Use Vector instead of DeprecatedPtrList. (WebCore::createMarkup): Ditto. (WebCore::createParagraphContentsFromString): Remove unneeded document parameter and changed a couple places to use isEmpty instead of comparing with "". (WebCore::createFragmentFromText): Given the new context parameter, if the context is one that preserves newlines, then use "\n" instead of <br> elements. (WebCore::createFragmentFromNodes): Use Vector instead of DeprecatedPtrList.
  • html/HTMLElement.cpp: (WebCore::HTMLElement::setInnerText): Do not use <br> elements if the context of this node is one where we preserve newlines.
  • rendering/InlineTextBox.h:
  • rendering/InlineTextBox.cpp: (WebCore::InlineTextBox::containsCaretOffset): Added. Implements the appropriate rule for determining if a caret position is in this line or not. Returns true for both one line and the next in cases where affinity must be considered to determine which line the caret is on.
  • rendering/RenderText.h: Make atLineWrap no longer be a member function.
  • rendering/RenderText.cpp: (WebCore::atLineWrap): Remove special rule about preserveNewline and isLineBreak, which will no longer apply due to the new containsCaretOffset function logic. (WebCore::RenderText::caretRect): Use containsCaretOffset. (WebCore::RenderText::inlineBox): Ditto.
  • rendering/RenderTextControl.cpp: (WebCore::RenderTextControl::updateFromElement): Make a placeholder <br> element after calling setInnerText so that the last newline in the string has the effect we expect outside the HTML world (an additional line). (WebCore::RenderTextControl::setSelectionRange): Set granularity of the selection too. The layout tests caught this problem, which needs a better solution long term. (WebCore::RenderTextControl::text): Call textContent with the parameter false so it will not include newlines for <br> elements. Now the only <br> element that will ever be in the shadow DOM tree is the one to prevent collapsing, and that one should not show up in the text value.
  • rendering/bidi.cpp: (WebCore::RenderBlock::findNextLineBreak): Took a rule that specifically called out the pre whitespace mode and made it work for all the modes that preserve newlines. This makes sure we get a last line box for text after the last "\n" even in cases where there is no <br> afterward.
  • editing/DeleteSelectionCommand.cpp: (WebCore::DeleteSelectionCommand::fixupWhitespace):
  • editing/InsertParagraphSeparatorCommand.cpp: (WebCore::InsertParagraphSeparatorCommand::doApply): Added assertions to make sure we don't do anything when we're not collapsing whitespace.
  • html/HTMLTextAreaElement.cpp: (WebCore::HTMLTextAreaElement::setDefaultValue): Changed to use Vector instead of DeprecatedPtrList.
  • editing/HTMLInterchange.cpp: Removed obsolete comment.
  • loader/Cache.h: Removed a stray include.

WebKit:

Reviewed by Adele and Justin.

  • update for change to require context when creating fragments from text (needed to handle whitespace properly)
  • WebView/WebHTMLView.m: (-[WebHTMLView _documentFragmentFromPasteboard:inContext:allowPlainText:chosePlainText:]): Added context parameter, pass through to bridge. (-[WebHTMLView _pasteWithPasteboard:allowPlainText:]): Pass selection range as context when calling above method. (-[WebHTMLView concludeDragForDraggingInfo:actionMask:]): Pass drag caret as context when calling above method.
Location:
trunk
Files:
8 added
2 deleted
50 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r15616 r15617  
     12006-07-24  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Adele and Justin.
     4
     5        - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=9630
     6          REGRESSION: some spaces typed in <textarea> are posted as non-breaking spaces
     7
     8        * fast/forms/textarea-type-spaces-expected.txt: Added.
     9        * fast/forms/textarea-type-spaces.html: Added.
     10
     11        - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=9939
     12          REGRESSION: Pasting text into native text area with newline at end does not preserve newline
     13
     14        * fast/forms/textarea-paste-newline-expected.txt: Added.
     15        * fast/forms/textarea-paste-newline.html: Added.
     16
     17        - updated tests affected by above changes, results are equivalent or better
     18
     19        * editing/pasteboard/4641033-expected.checksum:
     20        * editing/pasteboard/4641033-expected.png:
     21        * editing/pasteboard/4641033-expected.txt:
     22        * editing/pasteboard/paste-table-003-expected.checksum:
     23        * editing/pasteboard/paste-table-003-expected.png:
     24        * editing/pasteboard/paste-table-003-expected.txt:
     25        * editing/pasteboard/paste-text-016-expected.txt:
     26        * editing/pasteboard/quirks-mode-br-1-expected.txt:
     27        * editing/pasteboard/quirks-mode-br-2-expected.txt:
     28        * fast/forms/textarea-scrolled-type-expected.checksum:
     29        * fast/forms/textarea-scrolled-type-expected.png:
     30        * fast/forms/textarea-scrolled-type-expected.txt:
     31
     32        - changed a test to be a "dump as text" test
     33
     34        * fast/forms/paste-into-textarea-expected.txt:
     35        * fast/forms/paste-into-textarea.html:
     36        * fast/forms/paste-into-textarea-expected.checksum: Removed.
     37        * fast/forms/paste-into-textarea-expected.png: Removed.
     38
     39        - changed a test to be a "dump as text" test, improved test a bit and also checked in new results
     40
     41        * fast/forms/textarea-scrolled-endline-caret-expected.txt:
     42        * fast/forms/textarea-scrolled-endline-caret.html:
     43
     44        - fixed a test that was raising an exception every time it ran
     45
     46        * fast/forms/attributed-strings-expected.txt:
     47        * fast/forms/attributed-strings.html:
     48
     49        - corrected checksums on a bunch of tests (pngs were right, but checksums wrong, apparently)
     50
     51        * editing/deleting/delete-to-select-table-expected.checksum:
     52        * editing/selection/3690719-expected.checksum:
     53        * editing/selection/clear-selection-expected.checksum:
     54        * editing/undo/undo-misspellings-expected.checksum:
     55
     56        - added some missing pixel test results
     57
     58        * editing/pasteboard/nested-blocks-with-text-area-expected.checksum: Added.
     59        * editing/pasteboard/nested-blocks-with-text-area-expected.png: Added.
     60        * editing/pasteboard/nested-blocks-with-text-field-expected.checksum: Added.
     61        * editing/pasteboard/nested-blocks-with-text-field-expected.png: Added.
     62
    1632006-07-24  Adele Peterson  <adele@apple.com>
    264
  • trunk/LayoutTests/editing/deleting/delete-to-select-table-expected.checksum

    r15206 r15617  
    1 4f3c4bb088358dbb7dd79f971a4a41b8
     16ac121385e85689201493f064d0014f2
  • trunk/LayoutTests/editing/pasteboard/4641033-expected.checksum

    r15556 r15617  
    1 827eed3249a8431338e7c6ea96dc90d8
     19a95881ba32b5b25fa40bd8cf30fa1d4
  • trunk/LayoutTests/editing/pasteboard/4641033-expected.txt

    r15556 r15617  
    44EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    55EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
    6 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > DIV > BODY > HTML > #document to 0 of DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     6EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 3 of DIV > BODY > HTML > #document to 3 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    77EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    88EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     
    2828          RenderText {#text} at (635,0) size 4x18
    2929            text run at (635,0) width 4: "."
    30       RenderBlock {DIV} at (0,86) size 784x128
    31         RenderBlock (anonymous) at (0,0) size 784x110
    32           RenderImage {IMG} at (0,0) size 76x103
    33           RenderText {#text} at (76,89) size 4x18
    34             text run at (76,89) width 4: " "
    35           RenderMenuList {SELECT} at (82,90) size 36x18
    36         RenderBlock {DIV} at (0,110) size 784x18
    37           RenderBR {BR} at (0,0) size 0x18
    38       RenderBlock (anonymous) at (0,214) size 784x110
     30      RenderBlock {DIV} at (0,86) size 784x110
     31        RenderImage {IMG} at (0,0) size 76x103
     32        RenderText {#text} at (76,89) size 4x18
     33          text run at (76,89) width 4: " "
     34        RenderMenuList {SELECT} at (82,90) size 36x18
     35      RenderBlock (anonymous) at (0,196) size 784x110
    3936        RenderImage {IMG} at (0,0) size 76x103
    4037        RenderText {#text} at (76,89) size 4x18
     
    4643        RenderText {#text} at (0,0) size 0x0
    4744        RenderText {#text} at (0,0) size 0x0
    48 caret: position 0 of child 0 {BR} of child 3 {DIV} of child 4 {DIV} of child 0 {BODY} of child 0 {HTML} of document
     45caret: position 1 of child 2 {SELECT} of child 4 {DIV} of child 0 {BODY} of child 0 {HTML} of document
  • trunk/LayoutTests/editing/pasteboard/paste-table-003-expected.checksum

    r15525 r15617  
    1 00eb248dca688216f1341399284e4d66
     19697e5aa6aff2be0a6d9c1e2098d3c89
  • trunk/LayoutTests/editing/pasteboard/paste-table-003-expected.txt

    r15525 r15617  
    55EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    66EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 9 of #text > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
    7 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 2 of TD > TR > TBODY > TABLE > DIV > BODY > HTML > #document to 2 of TD > TR > TBODY > TABLE > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     7EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    88EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    99EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     
    2222              RenderText {#text} at (1,1) size 24x18
    2323                text run at (1,1) width 24: "two"
    24       RenderBlock {DIV} at (0,24) size 784x60
    25         RenderTable {TABLE} at (0,0) size 57x42
    26           RenderTableSection {TBODY} at (0,0) size 57x42
    27             RenderTableRow {TR} at (0,2) size 57x38
    28               RenderTableCell {TD} at (2,11) size 25x20 [r=0 c=0 rs=1 cs=1]
     24      RenderBlock {DIV} at (0,24) size 784x42
     25        RenderTable {TABLE} at (0,0) size 57x24
     26          RenderTableSection {TBODY} at (0,0) size 57x24
     27            RenderTableRow {TR} at (0,2) size 57x20
     28              RenderTableCell {TD} at (2,2) size 25x20 [r=0 c=0 rs=1 cs=1]
    2929                RenderText {#text} at (1,1) size 23x18
    3030                  text run at (1,1) width 23: "one"
    31               RenderTableCell {TD} at (29,2) size 26x38 [r=0 c=1 rs=1 cs=1]
     31              RenderTableCell {TD} at (29,2) size 26x20 [r=0 c=1 rs=1 cs=1]
    3232                RenderText {#text} at (1,1) size 24x18
    3333                  text run at (1,1) width 24: "two"
    34                 RenderBR {BR} at (25,15) size 0x0
    35                 RenderBR {BR} at (1,19) size 0x18
    36         RenderBlock (anonymous) at (0,42) size 784x18
     34        RenderBlock (anonymous) at (0,24) size 784x18
    3735          RenderBR {BR} at (0,0) size 0x18
    38 caret: position 0 of child 2 {BR} of child 1 {TD} of child 0 {TR} of child 0 {TBODY} of child 0 {TABLE} of child 2 {DIV} of child 1 {BODY} of child 0 {HTML} of document
     36      RenderBlock {DIV} at (0,66) size 784x18
     37        RenderBR {BR} at (0,0) size 0x18
     38caret: position 0 of child 0 {BR} of child 3 {DIV} of child 1 {BODY} of child 0 {HTML} of document
  • trunk/LayoutTests/editing/pasteboard/paste-text-016-expected.txt

    r14684 r15617  
    1919EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2020EDITING DELEGATE: shouldInsertNode:#document-fragment replacingDOMRange:range from 2 of P > DIV > DIV > BODY > HTML > #document to 2 of P > DIV > DIV > BODY > HTML > #document givenAction:WebViewInsertActionPasted
    21 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of P > P > DIV > DIV > BODY > HTML > #document to 0 of P > P > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    22 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     21EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of P > DIV > DIV > BODY > HTML > #document to 3 of P > DIV > DIV > BODY > HTML > #document toDOMRange:range from 3 of P > DIV > DIV > BODY > HTML > #document to 3 of P > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    2322EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    2423layer at (0,0) size 800x600
     
    4948              RenderText {#text} at (0,0) size 130x28
    5049                text run at (0,0) width 130: "***TEST***"
    51             RenderBlock {P} at (0,56) size 756x28
     50            RenderBlock (anonymous) at (0,56) size 756x56
    5251              RenderBR {BR} at (0,0) size 0x28
    53             RenderBlock (anonymous) at (0,84) size 756x28
    54               RenderText {#text} at (0,0) size 128x28
    55                 text run at (0,0) width 128: "Another line."
     52              RenderText {#text} at (0,28) size 128x28
     53                text run at (0,28) width 128: "Another line."
    5654          RenderBlock {P} at (14,126) size 756x0
    5755          RenderBlock (anonymous) at (14,126) size 756x28
     
    6462          RenderBlock {P} at (14,182) size 756x28
    6563            RenderBR {BR} at (0,0) size 0x28
    66 caret: position 0 of child 0 {BR} of child 3 {P} of child 0 {P} of child 1 {DIV} of child 7 {DIV} of child 1 {BODY} of child 0 {HTML} of document
     64caret: position 0 of child 3 {BR} of child 0 {P} of child 1 {DIV} of child 7 {DIV} of child 1 {BODY} of child 0 {HTML} of document
  • trunk/LayoutTests/editing/pasteboard/quirks-mode-br-1-expected.txt

    r14684 r15617  
    2121            text run at (0,0) width 370: "The test should add a single blank line after this paragraph."
    2222          RenderBR {BR} at (370,14) size 0x0
     23          RenderInline {SPAN} at (0,0) size 0x0
    2324          RenderBR {BR} at (0,18) size 0x18
    24           RenderInline {SPAN} at (0,0) size 0x0
    25 caret: position 0 of child 2 {BR} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
     25caret: position 0 of child 3 {BR} of child 0 {DIV} of child 2 {DIV} of child 0 {BODY} of child 0 {HTML} of document
  • trunk/LayoutTests/editing/pasteboard/quirks-mode-br-2-expected.txt

    r14684 r15617  
    22EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
    33EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    4 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 1 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    5 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     4EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document toDOMRange:range from 1 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    65EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    76layer at (0,0) size 800x600
  • trunk/LayoutTests/editing/selection/3690719-expected.checksum

    r15245 r15617  
    1 2762a21712500c513288a4796e7c6f0d
     1e93d8592f6229d3c0681c600617c9f4d
  • trunk/LayoutTests/editing/selection/clear-selection-expected.checksum

    r15397 r15617  
    1 675958ca1760e67d565768737724a7ed
     1b6430b633335a2e5a40c5bae7d791546
  • trunk/LayoutTests/editing/undo/undo-misspellings-expected.checksum

    r15399 r15617  
    1 2a251ca75a4ee28206fbc9f203a921e3
     18a9b3e46242b36500276135ba1c29d62
  • trunk/LayoutTests/fast/forms/attributed-strings-expected.txt

    r14172 r15617  
    18180.5
    1919undefined
    20 undefined
    2120NSDeviceRGBColorSpace 1 0.5 1 0.5
    2221
  • trunk/LayoutTests/fast/forms/attributed-strings.html

    r14172 r15617  
    5050                        log(attrString.getAttributeValueAtIndex("NSObliqueness", 0));
    5151                        log(attrString.getAttributeValueAtIndex("NSObliqueness", 3));
    52                         log(attrString.getAttributeValueAtIndex("NSObliqueness", 10));
    5352
    5453                        log(attrString.getAttributeValueAtIndex("NSForegroundColor", 1));
  • trunk/LayoutTests/fast/forms/paste-into-textarea-expected.txt

    r15528 r15617  
    11EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 57 of #text > DIV to 57 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     2EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > DIV to 1 of #text > DIV toDOMRange:range from 57 of #text > DIV to 57 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    33EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    44EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    5 layer at (0,0) size 800x600
    6   RenderView at (0,0) size 800x600
    7 layer at (0,0) size 800x600
    8   RenderBlock {HTML} at (0,0) size 800x600
    9     RenderBody {BODY} at (8,8) size 784x584
    10       RenderBlock {P} at (0,0) size 784x18
    11         RenderText {#text} at (0,0) size 757x18
    12           text run at (0,0) width 757: "This tests for a bug where text pasted into a textarea would appear one character before the position where it was pasted."
    13       RenderBlock (anonymous) at (0,34) size 784x71
    14         RenderTextField {TEXTAREA} at (2,2) size 163x67 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
    15         RenderText {#text} at (0,0) size 0x0
    16 layer at (11,45) size 161x65
    17   RenderBlock {DIV} at (1,1) size 161x65
    18     RenderText {#text} at (3,0) size 7x13
    19       text run at (3,0) width 7: "x"
    20     RenderText {#text} at (10,0) size 140x39
    21       text run at (10,0) width 133: "(There should be one 'x' "
    22       text run at (3,13) width 112: "before and after this "
    23       text run at (3,26) width 55: "sentence.)"
    24     RenderText {#text} at (58,26) size 7x13
    25       text run at (58,26) width 7: "x"
    26 caret: position 57 of child 1 {#text} of child 0 {DIV} of child 2 {TEXTAREA} of child 0 {BODY} of child 0 {HTML} of document
     5This tests for a bug where text pasted into a textarea would appear one character before the position where it was pasted.
     6
     7Hooray, test succeeded.
     8
     9
  • trunk/LayoutTests/fast/forms/paste-into-textarea.html

    r15528 r15617  
    11<p>This tests for a bug where text pasted into a textarea would appear one character before the position where it was pasted.</p>
    22<textarea rows=5 id="test">xx</textarea>
    3 
    43<script>
     4if (window.layoutTestController)
     5    layoutTestController.dumpAsText();
    56var e = document.getElementById("test");
    67e.setSelectionRange(1, 1);
    7 
    88document.execCommand("InsertHTML", false, "(There should be one 'x' before and after this sentence.)");
     9if (e.value == "x(There should be one 'x' before and after this sentence.)x")
     10    document.write("<p>Hooray, test succeeded.</p>");
     11else
     12    document.write("<p>Test failed, value is '" + e.value + "'.</p>");
    913</script>
  • trunk/LayoutTests/fast/forms/textarea-scrolled-endline-caret-expected.txt

    r15569 r15617  
    11EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > DIV to 2 of #text > DIV toDOMRange:range from 1 of #text > DIV to 1 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     2EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 20 of #text > DIV to 20 of #text > DIV toDOMRange:range from 17 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    33EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    44Test Succeeded
     5
  • trunk/LayoutTests/fast/forms/textarea-scrolled-endline-caret.html

    r15569 r15617  
    33function test()
    44{
     5    if (window.layoutTestController)
     6        layoutTestController.dumpAsText();
    57    var ta = document.getElementById('ta')
     8    var res = document.getElementById('res');
    69    ta.focus();
    710    // click
    8     if (window.layoutTestController) {
    9         layoutTestController.dumpAsText();
     11    if (window.eventSender) {
    1012        eventSender.mouseMoveTo(90, 20);
    1113        eventSender.mouseDown();
    1214        eventSender.mouseUp();
     15        if (ta.selectionEnd == 17)
     16            res.innerHTML = "Test Succeeded";
     17        else
     18            res.innerHTML = "Test Failed: caret is at " + ta.selectionEnd;
     19    } else {
     20        res.innerHTML = "Test can't run without event sender (part of DumpRenderTree). "
     21            + "To test manually, click at the middle of the line marked 9 and check that the caret appears after the 9.";
    1322    }
    14     var res = document.getElementById('res');
    15     if (ta.selectionEnd == 17)
    16         res.innerHTML = "Test Succeeded";
    17     else
    18         res.innerHTML = "Test Failed: caret is at " + ta.selectionEnd;
    1923}
    2024</script>
     
    31358
    32369
    33 10
    34 </textarea>
     3710</textarea>
    3538<div id="res"></div>
     39</body>
  • trunk/LayoutTests/fast/forms/textarea-scrolled-type-expected.checksum

    r15581 r15617  
    1 7f38cf2e654f194ce1a95e256537fbfe
     1bb1e86fd2232a0b2c6bda501f303b1de
  • trunk/LayoutTests/fast/forms/textarea-scrolled-type-expected.txt

    r15581 r15617  
    11EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    22EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    3 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 2 of #text > DIV to 2 of #text > DIV toDOMRange:range from 3 of #text > DIV to 3 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     3EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 44 of #text > DIV to 44 of #text > DIV toDOMRange:range from 45 of #text > DIV to 45 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    44EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    55EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    6 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 3 of #text > DIV to 3 of #text > DIV toDOMRange:range from 4 of #text > DIV to 4 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     6EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 45 of #text > DIV to 45 of #text > DIV toDOMRange:range from 46 of #text > DIV to 46 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    77EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    88EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    9 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 4 of #text > DIV to 4 of #text > DIV toDOMRange:range from 5 of #text > DIV to 5 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     9EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 46 of #text > DIV to 46 of #text > DIV toDOMRange:range from 47 of #text > DIV to 47 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    1010EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    1111EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    12 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 5 of #text > DIV to 5 of #text > DIV toDOMRange:range from 6 of #text > DIV to 6 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     12EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 47 of #text > DIV to 47 of #text > DIV toDOMRange:range from 48 of #text > DIV to 48 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    1313EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    1414EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    15 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 6 of #text > DIV to 6 of #text > DIV toDOMRange:range from 7 of #text > DIV to 7 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     15EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 48 of #text > DIV to 48 of #text > DIV toDOMRange:range from 49 of #text > DIV to 49 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    1616EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    1717EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     
    3030        RenderBR {BR} at (171,115) size 0x0
    3131      RenderBlock {DIV} at (0,119) size 784x0
    32 layer at (11,29) size 161x91 clip at (11,29) size 146x91 scrollY 169 scrollHeight 260
     32layer at (11,29) size 161x91 clip at (11,29) size 146x91 scrollY 182 scrollHeight 273
    3333  RenderBlock {DIV} at (1,1) size 161x91
    34     RenderText {#text} at (3,0) size 7x13
     34    RenderText {#text} at (3,0) size 41x260
    3535      text run at (3,0) width 7: "1"
    36     RenderBR {BR} at (10,11) size 0x0
    37     RenderText {#text} at (3,13) size 7x13
     36      text run at (10,0) width 0: " "
    3837      text run at (3,13) width 7: "2"
    39     RenderBR {BR} at (10,24) size 0x0
    40     RenderText {#text} at (3,26) size 7x13
     38      text run at (10,13) width 0: " "
    4139      text run at (3,26) width 7: "3"
    42     RenderBR {BR} at (10,37) size 0x0
    43     RenderText {#text} at (3,39) size 7x13
     40      text run at (10,26) width 0: " "
    4441      text run at (3,39) width 7: "4"
    45     RenderBR {BR} at (10,50) size 0x0
    46     RenderText {#text} at (3,52) size 7x13
     42      text run at (10,39) width 0: " "
    4743      text run at (3,52) width 7: "5"
    48     RenderBR {BR} at (10,63) size 0x0
    49     RenderText {#text} at (3,65) size 7x13
     44      text run at (10,52) width 0: " "
    5045      text run at (3,65) width 7: "6"
    51     RenderBR {BR} at (10,76) size 0x0
    52     RenderText {#text} at (3,78) size 7x13
     46      text run at (10,65) width 0: " "
    5347      text run at (3,78) width 7: "7"
    54     RenderBR {BR} at (10,89) size 0x0
    55     RenderText {#text} at (3,91) size 7x13
     48      text run at (10,78) width 0: " "
    5649      text run at (3,91) width 7: "8"
    57     RenderBR {BR} at (10,102) size 0x0
    58     RenderText {#text} at (3,104) size 7x13
     50      text run at (10,91) width 0: " "
    5951      text run at (3,104) width 7: "9"
    60     RenderBR {BR} at (10,115) size 0x0
    61     RenderText {#text} at (3,117) size 14x13
     52      text run at (10,104) width 0: " "
    6253      text run at (3,117) width 14: "10"
    63     RenderBR {BR} at (17,128) size 0x0
    64     RenderText {#text} at (3,130) size 14x13
     54      text run at (17,117) width 0: " "
    6555      text run at (3,130) width 14: "11"
    66     RenderBR {BR} at (17,141) size 0x0
    67     RenderText {#text} at (3,143) size 14x13
     56      text run at (17,130) width 0: " "
    6857      text run at (3,143) width 14: "12"
    69     RenderBR {BR} at (17,154) size 0x0
    70     RenderText {#text} at (3,156) size 14x13
     58      text run at (17,143) width 0: " "
    7159      text run at (3,156) width 14: "13"
    72     RenderBR {BR} at (17,167) size 0x0
    73     RenderText {#text} at (3,169) size 14x13
     60      text run at (17,156) width 0: " "
    7461      text run at (3,169) width 14: "14"
    75     RenderBR {BR} at (17,180) size 0x0
    76     RenderText {#text} at (3,182) size 14x13
     62      text run at (17,169) width 0: " "
    7763      text run at (3,182) width 14: "15"
    78     RenderBR {BR} at (17,193) size 0x0
    79     RenderText {#text} at (3,195) size 14x13
     64      text run at (17,182) width 0: " "
    8065      text run at (3,195) width 14: "16"
    81     RenderBR {BR} at (17,206) size 0x0
    82     RenderText {#text} at (3,208) size 14x13
     66      text run at (17,195) width 0: " "
    8367      text run at (3,208) width 14: "17"
    84     RenderBR {BR} at (17,219) size 0x0
    85     RenderText {#text} at (3,221) size 41x13
     68      text run at (17,208) width 0: " "
    8669      text run at (3,221) width 41: "18 Pass"
    87     RenderBR {BR} at (44,232) size 0x0
    88     RenderText {#text} at (3,234) size 14x13
     70      text run at (44,221) width 0: " "
    8971      text run at (3,234) width 14: "19"
    90     RenderBR {BR} at (17,245) size 0x0
    91     RenderText {#text} at (3,247) size 14x13
     72      text run at (17,234) width 0: " "
    9273      text run at (3,247) width 14: "20"
    93     RenderBR {BR} at (17,258) size 0x0
    94 caret: position 7 of child 34 {#text} of child 0 {DIV} of child 3 {TEXTAREA} of child 1 {BODY} of child 0 {HTML} of document
     74      text run at (17,247) width 0: " "
     75    RenderBR {BR} at (3,260) size 0x13
     76caret: position 49 of child 0 {#text} of child 0 {DIV} of child 3 {TEXTAREA} of child 1 {BODY} of child 0 {HTML} of document
  • trunk/WebCore/ChangeLog

    r15616 r15617  
     12006-07-24  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Adele and Justin.
     4
     5        - fix <rdar://problem/4613616> REGRESSION: some spaces typed in <textarea> are posted as non-breaking spaces (9630)
     6          http://bugzilla.opendarwin.org/show_bug.cgi?id=9630
     7        - also fixes http://bugzilla.opendarwin.org/show_bug.cgi?id=9939
     8          REGRESSION: Pasting text into native text area with newline at end does not preserve newline
     9        - removed some uses of DeprecatedPtrList in the markup code
     10
     11        Test: fast/forms/textarea-type-spaces.html
     12        Test: fast/forms/textarea-paste-newline.html
     13
     14        * bindings/objc/DOMHTML.mm: (-[DOMHTMLDocument createDocumentFragmentWithText:]):
     15        Updated call to pass a range -- in this case it is the range of the entire document,
     16        so this will not handle the whitespace properly.
     17
     18        * bridge/mac/WebCoreFrameBridge.h: Added range context parameter to the
     19        documentFragmentWithText: method, so we can handle whitespace properly.
     20        * bridge/mac/WebCoreFrameBridge.mm:
     21        (-[WebCoreFrameBridge nodesFromList:]): Changed from DeprecatedPtrList to Vector.
     22        (-[WebCoreFrameBridge markupStringFromNode:nodes:]): Ditto.
     23        (-[WebCoreFrameBridge markupStringFromRange:nodes:]): Ditto.
     24        (-[WebCoreFrameBridge documentFragmentWithText:inContext:]): Added range context
     25        parameter -- pass it on to createFragmentFromText.
     26        (-[WebCoreFrameBridge documentFragmentWithNodesAsParagraphs:]): Changed from
     27        DeprecatedPtrList to Vector.
     28        (-[WebCoreFrameBridge replaceSelectionWithText:selectReplacement:smartReplace:]):
     29        Pass the range of the current selection as context when creating the fragment.
     30
     31        * dom/Position.cpp: (WebCore::Position::inRenderedText): Replace range check with
     32        a call to the new containsCaretOffset function -- helps make the caret work right when
     33        it is past the end of the last line in a textarea.
     34
     35        * editing/CompositeEditCommand.cpp:
     36        (WebCore::CompositeEditCommand::rebalanceWhitespaceAt): Don't do anything if the
     37        style does not call for collapsing whitespace.
     38        (WebCore::CompositeEditCommand::rebalanceWhitespace): Call replaceWhitespaceAt
     39        to share code, including the new logic mentioned above.
     40
     41        * editing/InsertLineBreakCommand.cpp: (WebCore::InsertLineBreakCommand::doApply):
     42        Use a text node instead of a break element when inserting and the style is preserveNewline.
     43
     44        * editing/JSEditor.cpp: (WebCore::execRemoveFormat): Pass the selection range
     45        to createFragmentFromText.
     46
     47        * editing/RebalanceWhitespaceCommand.cpp: (WebCore::RebalanceWhitespaceCommand::doApply):
     48        Assert that we're in a style that collapses whitespace. It's the caller's responsibility
     49        not to call otherwise.
     50
     51        * editing/ReplaceSelectionCommand.h: Removed unused destructor, type, isSingleTextNode,
     52        isTreeFragment, m_type, and added a context parameter to inertFragmentForTestRendering.
     53        Also changed the constructor to take a selection rather than a pointer to the root
     54        editable element, replaced removeEndBRIfNeeded with shouldRemoveEndBR and removed an
     55        unused parameter from shouldMergeEnd.
     56        * editing/ReplaceSelectionCommand.cpp:
     57        (WebCore::ReplacementFragment::ReplacementFragment): Removed code to set up m_type.
     58        Compute root editable element from passed-in selection. Used the start of the selection
     59        as a base node for style purposes for the test rendering. Removed the special case
     60        "single text node" alternative to createFragmentFromText in the plain text case, since
     61        createFragmentFromText now handles that correctly.
     62        (WebCore::ReplacementFragment::insertFragmentForTestRendering): Copy the whitespace
     63        property from the source location when creating a temporary element for test rendering.
     64        (WebCore::ReplacementFragment::shouldMergeEnd): Removed unneeded boolean
     65        parameter fragmentHadInterchangeNewlineAtEnd, which is always false.
     66        (WebCore::ReplaceSelectionCommand::doApply): Update for ReplacementFragment changes,
     67        change code to not remove end BR when it can be re-used instead, don't call the
     68        paragraph separator insertion when the position is at the start of a paragraph already,
     69        removed redundant computation of identical "next" value, removed unneeded boolean
     70        parameter to shouldMergeEnd, add case for merging when all we need to do is to delete
     71        a newline character, removed unneeded code to set insertionPos after all code that uses
     72        it, and  use spaces instead of non-breaking spaces when doing smart paste if the
     73        context is one where we do not collapse white space.
     74        (WebCore::ReplaceSelectionCommand::shouldRemoveEndBR): Renamed and changed to return
     75        a boolean instead of doing the removal.
     76
     77        * editing/markup.h: Use Vector instead of DeprecatedPtrList. Change the
     78        createFragmentFromText function to take a range for context instead of a document.
     79        * editing/markup.cpp:
     80        (WebCore::markup): Use Vector instead of DeprecatedPtrList.
     81        (WebCore::createMarkup): Ditto.
     82        (WebCore::createParagraphContentsFromString): Remove unneeded document parameter
     83        and changed a couple places to use isEmpty instead of comparing with "".
     84        (WebCore::createFragmentFromText): Given the new context parameter, if the context
     85        is one that preserves newlines, then use "\n" instead of <br> elements.
     86        (WebCore::createFragmentFromNodes): Use Vector instead of DeprecatedPtrList.
     87
     88        * html/HTMLElement.cpp: (WebCore::HTMLElement::setInnerText): Do not use <br>
     89        elements if the context of this node is one where we preserve newlines.
     90
     91        * rendering/InlineTextBox.h:
     92        * rendering/InlineTextBox.cpp: (WebCore::InlineTextBox::containsCaretOffset):
     93        Added. Implements the appropriate rule for determining if a caret position is
     94        in this line or not. Returns true for both one line and the next in cases where
     95        affinity must be considered to determine which line the caret is on.
     96
     97        * rendering/RenderText.h: Make atLineWrap no longer be a member function.
     98        * rendering/RenderText.cpp:
     99        (WebCore::atLineWrap): Remove special rule about preserveNewline and isLineBreak,
     100        which will no longer apply due to the new containsCaretOffset function logic.
     101        (WebCore::RenderText::caretRect): Use containsCaretOffset.
     102        (WebCore::RenderText::inlineBox): Ditto.
     103
     104        * rendering/RenderTextControl.cpp:
     105        (WebCore::RenderTextControl::updateFromElement): Make a placeholder <br> element
     106        after calling setInnerText so that the last newline in the string has the effect
     107        we expect outside the HTML world (an additional line).
     108        (WebCore::RenderTextControl::setSelectionRange): Set granularity of the selection
     109        too. The layout tests caught this problem, which needs a better solution long term.
     110        (WebCore::RenderTextControl::text): Call textContent with the parameter false
     111        so it will not include newlines for <br> elements. Now the only <br> element
     112        that will ever be in the shadow DOM tree is the one to prevent collapsing, and
     113        that one should not show up in the text value.
     114
     115        * rendering/bidi.cpp: (WebCore::RenderBlock::findNextLineBreak): Took a rule
     116        that specifically called out the pre whitespace mode and made it work for all
     117        the modes that preserve newlines. This makes sure we get a last line box for
     118        text after the last "\n" even in cases where there is no <br> afterward.
     119
     120        * editing/DeleteSelectionCommand.cpp:
     121        (WebCore::DeleteSelectionCommand::fixupWhitespace):
     122        * editing/InsertParagraphSeparatorCommand.cpp:
     123        (WebCore::InsertParagraphSeparatorCommand::doApply):
     124        Added assertions to make sure we don't do anything when we're not collapsing
     125        whitespace.
     126
     127        * html/HTMLTextAreaElement.cpp: (WebCore::HTMLTextAreaElement::setDefaultValue):
     128        Changed to use Vector instead of DeprecatedPtrList.
     129
     130        * editing/HTMLInterchange.cpp: Removed obsolete comment.
     131
     132        * loader/Cache.h: Removed a stray include.
     133
    11342006-07-24  Adele Peterson  <adele@apple.com>
    2135
  • trunk/WebCore/bindings/objc/DOMHTML.mm

    r15276 r15617  
    2727#import "DOMHTML.h"
    2828
     29#import "DOMExtensions.h"
    2930#import "DOMHTMLInternal.h"
    3031#import "DOMInternal.h"
    3132#import "DOMPrivate.h"
    32 #import "DOMExtensions.h"
    3333#import "DocumentFragment.h"
    3434#import "FoundationExtras.h"
     35#import "FrameView.h"
    3536#import "HTMLAppletElement.h"
    3637#import "HTMLAreaElement.h"
     38#import "HTMLBRElement.h"
    3739#import "HTMLBaseElement.h"
    3840#import "HTMLBaseFontElement.h"
    3941#import "HTMLBodyElement.h"
    40 #import "HTMLBRElement.h"
    4142#import "HTMLButtonElement.h"
     43#import "HTMLDListElement.h"
    4244#import "HTMLDirectoryElement.h"
    4345#import "HTMLDivElement.h"
    44 #import "HTMLDListElement.h"
    4546#import "HTMLDocument.h"
    4647#import "HTMLEmbedElement.h"
     
    5051#import "HTMLFormElement.h"
    5152#import "HTMLFrameSetElement.h"
     53#import "HTMLHRElement.h"
    5254#import "HTMLHeadElement.h"
    5355#import "HTMLHeadingElement.h"
    54 #import "HTMLHRElement.h"
    5556#import "HTMLHtmlElement.h"
    5657#import "HTMLIFrameElement.h"
    5758#import "HTMLImageElement.h"
    5859#import "HTMLIsIndexElement.h"
     60#import "HTMLLIElement.h"
    5961#import "HTMLLabelElement.h"
    6062#import "HTMLLegendElement.h"
    61 #import "HTMLLIElement.h"
    6263#import "HTMLLinkElement.h"
    6364#import "HTMLMapElement.h"
     
    6566#import "HTMLMetaElement.h"
    6667#import "HTMLNames.h"
     68#import "HTMLOListElement.h"
    6769#import "HTMLObjectElement.h"
    68 #import "HTMLOListElement.h"
    6970#import "HTMLOptGroupElement.h"
    7071#import "HTMLOptionElement.h"
    7172#import "HTMLOptionsCollection.h"
     73#import "HTMLParagraphElement.h"
    7274#import "HTMLParamElement.h"
    73 #import "HTMLParagraphElement.h"
    7475#import "HTMLPreElement.h"
    7576#import "HTMLScriptElement.h"
    7677#import "HTMLSelectElement.h"
    7778#import "HTMLStyleElement.h"
    78 #import "HTMLTableElement.h"
    7979#import "HTMLTableCaptionElement.h"
    8080#import "HTMLTableCellElement.h"
    8181#import "HTMLTableColElement.h"
     82#import "HTMLTableElement.h"
    8283#import "HTMLTableRowElement.h"
    8384#import "HTMLTableSectionElement.h"
     
    8586#import "HTMLTitleElement.h"
    8687#import "HTMLUListElement.h"
     88#import "KURL.h"
    8789#import "NameNodeList.h"
     90#import "Range.h"
     91#import "RenderTextControl.h"
     92#import "csshelper.h"
    8893#import "markup.h"
    89 #import "RenderTextControl.h"
    90 #import "FrameView.h"
    91 #import "csshelper.h"
    92 #import "KURL.h"
    9394
    9495using namespace WebCore;
     
    606607- (DOMDocumentFragment *)createDocumentFragmentWithText:(NSString *)text
    607608{
    608     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText([self _document], DeprecatedString::fromNSString(text)).get()];
     609    // FIXME: Since this is not a contextual fragment, it won't handle whitespace properly.
     610    return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText([self _document]->createRange().get(), text).get()];
    609611}
    610612
  • trunk/WebCore/bridge/mac/WebCoreFrameBridge.h

    r15547 r15617  
    419419
    420420- (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString;
    421 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text;
     421- (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text inContext:(DOMRange *)context;
    422422- (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes;
    423423
  • trunk/WebCore/bridge/mac/WebCoreFrameBridge.mm

    r15564 r15617  
    772772}
    773773
    774 - (NSArray *)nodesFromList:(DeprecatedPtrList<Node> *)nodeList
    775 {
    776     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:nodeList->count()];
    777     for (DeprecatedPtrListIterator<Node> i(*nodeList); i.current(); ++i)
    778         [nodes addObject:[DOMNode _nodeWith:i.current()]];
    779 
     774- (NSArray *)nodesFromList:(Vector<Node*> *)nodesVector
     775{
     776    size_t size = nodesVector->size();
     777    NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
     778    for (size_t i = 0; i < size; ++i)
     779        [nodes addObject:[DOMNode _nodeWith:(*nodesVector)[i]]];
    780780    return nodes;
    781781}
     
    784784{
    785785    // FIXME: This is never "for interchange". Is that right? See the next method.
    786     DeprecatedPtrList<Node> nodeList;
     786    Vector<Node*> nodeList;
    787787    NSString *markupString = createMarkup([node _node], IncludeNode, nodes ? &nodeList : 0).getNSString();
    788788    if (nodes)
     
    795795{
    796796    // FIXME: This is always "for interchange". Is that right? See the previous method.
    797     DeprecatedPtrList<Node> nodeList;
     797    Vector<Node*> nodeList;
    798798    NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange).getNSString();
    799799    if (nodes)
     
    19441944}
    19451945
    1946 - (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text
    1947 {
    1948     if (!m_frame || !m_frame->document() || !text)
    1949         return 0;
    1950    
    1951     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText(m_frame->document(), DeprecatedString::fromNSString(text)).get()];
     1946- (DOMDocumentFragment *)documentFragmentWithText:(NSString *)text inContext:(DOMRange *)context
     1947{
     1948    return [DOMDocumentFragment _documentFragmentWith:createFragmentFromText([context _range], DeprecatedString::fromNSString(text)).get()];
    19521949}
    19531950
    19541951- (DOMDocumentFragment *)documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
    19551952{
    1956     NSEnumerator *nodeEnum = [nodes objectEnumerator];
    1957     DOMNode *node;
    1958     DeprecatedPtrList<Node> nodeList;
    1959    
    19601953    if (!m_frame || !m_frame->document())
    19611954        return 0;
    19621955   
    1963     while ((node = [nodeEnum nextObject])) {
    1964         nodeList.append([node _node]);
    1965     }
    1966    
    1967     return [DOMDocumentFragment _documentFragmentWith:createFragmentFromNodeList(m_frame->document(), nodeList).get()];
     1956    NSEnumerator *nodeEnum = [nodes objectEnumerator];
     1957    Vector<Node*> nodesVector;
     1958    DOMNode *node;
     1959    while ((node = [nodeEnum nextObject]))
     1960        nodesVector.append([node _node]);
     1961   
     1962    return [DOMDocumentFragment _documentFragmentWith:createFragmentFromNodes(m_frame->document(), nodesVector).get()];
    19681963}
    19691964
     
    19921987- (void)replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
    19931988{
    1994     [self replaceSelectionWithFragment:[self documentFragmentWithText:text] selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
     1989    [self replaceSelectionWithFragment:[self documentFragmentWithText:text
     1990        inContext:[DOMRange _rangeWith:m_frame->selection().toRange().get()]]
     1991        selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
    19951992}
    19961993
  • trunk/WebCore/dom/Position.cpp

    r15531 r15617  
    483483            return false;
    484484        }
    485         if (offset() >= box->m_start && offset() <= box->m_start + box->m_len)
     485        if (box->containsCaretOffset(offset()))
    486486            // Return false for offsets inside composed characters.
    487487            return offset() == 0 || offset() == textRenderer->nextOffset(textRenderer->previousOffset(offset()));
  • trunk/WebCore/editing/CompositeEditCommand.cpp

    r15585 r15617  
    373373}
    374374
    375 void CompositeEditCommand::rebalanceWhitespaceAt(const Position &position)
    376 {
     375void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
     376{
     377    Node* textNode = position.node();
     378    if (!textNode || !textNode->isTextNode())
     379        return;
     380    if (static_cast<Text*>(textNode)->length() == 0)
     381        return;
     382    RenderObject* renderer = textNode->renderer();
     383    if (renderer && !renderer->style()->collapseWhiteSpace())
     384        return;
    377385    EditCommandPtr cmd(new RebalanceWhitespaceCommand(document(), position));
    378386    applyCommandToComposite(cmd);   
     
    383391    Selection selection = endingSelection();
    384392    if (selection.isCaretOrRange()) {
    385         EditCommandPtr startCmd(new RebalanceWhitespaceCommand(document(), endingSelection().start()));
    386         applyCommandToComposite(startCmd);
    387         if (selection.isRange()) {
    388             EditCommandPtr endCmd(new RebalanceWhitespaceCommand(document(), endingSelection().end()));
    389             applyCommandToComposite(endCmd);
    390         }
     393        rebalanceWhitespaceAt(endingSelection().start());
     394        if (selection.isRange())
     395            rebalanceWhitespaceAt(endingSelection().end());
    391396    }
    392397}
  • trunk/WebCore/editing/DeleteSelectionCommand.cpp

    r15563 r15617  
    396396    // FIXME: isRenderedCharacter should be removed, and we should use VisiblePosition::characterAfter and VisiblePosition::characterBefore
    397397    if (m_leadingWhitespace.isNotNull() && !m_leadingWhitespace.isRenderedCharacter()) {
    398         Text *textNode = static_cast<Text *>(m_leadingWhitespace.node());
     398        Text* textNode = static_cast<Text*>(m_leadingWhitespace.node());
     399        ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace());
    399400        replaceTextInNode(textNode, m_leadingWhitespace.offset(), 1, nonBreakingSpaceString());
    400401    }
    401402    if (m_trailingWhitespace.isNotNull() && !m_trailingWhitespace.isRenderedCharacter()) {
    402         Text *textNode = static_cast<Text *>(m_trailingWhitespace.node());
     403        Text* textNode = static_cast<Text*>(m_trailingWhitespace.node());
     404        ASSERT(!textNode->renderer() ||textNode->renderer()->style()->collapseWhiteSpace());
    403405        replaceTextInNode(textNode, m_trailingWhitespace.offset(), 1, nonBreakingSpaceString());
    404406    }
  • trunk/WebCore/editing/HTMLInterchange.cpp

    r15286 r15617  
    4949} // end anonymous namespace
    5050
    51 // FIXME: convertHTMLTextToInterchangeFormat should probably be in the khtml namespace.
    5251// FIXME: Can't really do this work without taking whitespace mode into account.
    5352// This means that eventually this function needs to be eliminated or at least have
  • trunk/WebCore/editing/InsertLineBreakCommand.cpp

    r14768 r15617  
    8686        return;
    8787
    88     RefPtr<Element> breakNode = createBreakElement(document());
    89     Node* nodeToInsert = breakNode.get();
    90    
    9188    Position pos(selection.start().upstream());
    9289
    9390    pos = positionAvoidingSpecialElementBoundary(pos);
    9491
    95     if (isTabSpanTextNode(pos.node())) {
    96         insertNodeAtTabSpanPosition(nodeToInsert, pos);
     92    Node* styleNode = pos.node();
     93    bool isTabSpan = isTabSpanTextNode(styleNode);
     94    if (isTabSpan)
     95        styleNode = styleNode->parentNode()->parentNode();
     96    RenderObject* styleRenderer = styleNode->renderer();
     97    bool useBreakElement = !styleRenderer || !styleRenderer->style()->preserveNewline();
     98
     99    RefPtr<Node> nodeToInsert;
     100    if (useBreakElement)
     101        nodeToInsert = createBreakElement(document());
     102    else
     103        nodeToInsert = document()->createTextNode("\n");
     104        // FIXME: Need to merge text nodes when inserting just after or before text.
     105   
     106    if (isTabSpan) {
     107        insertNodeAtTabSpanPosition(nodeToInsert.get(), pos);
    97108        setEndingSelection(Position(nodeToInsert->traverseNextNode(), 0), DOWNSTREAM);
    98109    } else if (isEndOfBlock(VisiblePosition(pos, selection.affinity()))) {
    99        
    100110        Node* block = pos.node()->enclosingBlockFlowElement();
    101111       
    102         // Insert an extra br if the inserted one will collapsed because of quirks mode.
    103         if (!document()->inStrictMode() && !(pos.downstream().node()->hasTagName(brTag) && pos.downstream().offset() == 0)) {
    104             insertNodeAt(nodeToInsert, pos.node(), pos.offset());
    105             insertNodeAfter(createBreakElement(document()).get(), nodeToInsert);
    106         } else
    107             insertNodeAt(nodeToInsert, pos.node(), pos.offset());
     112        // Insert an extra break element so that there will be a blank line after the last
     113        // inserted line break. In HTML, a line break at the end of a block ends the last
     114        // line in the block, while in editable text, a line break at the end of block
     115        // creates a last blank line. We need an extra break element to get HTML to act
     116        // the way editable text would.
     117        bool haveBreak = pos.downstream().node()->hasTagName(brTag) && pos.downstream().offset() == 0;
     118        insertNodeAt(nodeToInsert.get(), pos.node(), pos.offset());
     119        if (!haveBreak)
     120            insertNodeAfter(createBreakElement(document()).get(), nodeToInsert.get());
    108121           
    109122        setEndingSelection(Position(block, maxDeepOffset(block)), DOWNSTREAM);
    110     }
    111     else if (pos.offset() <= pos.node()->caretMinOffset()) {
     123    } else if (pos.offset() <= pos.node()->caretMinOffset()) {
    112124        LOG(Editing, "input newline case 2");
    113125        // Insert node before downstream position, and place caret there as well.
    114126        Position endingPosition = pos.downstream();
    115         insertNodeBeforePosition(nodeToInsert, endingPosition);
     127        insertNodeBeforePosition(nodeToInsert.get(), endingPosition);
    116128        setEndingSelection(endingPosition, DOWNSTREAM);
    117129    } else if (pos.offset() >= pos.node()->caretMaxOffset()) {
     
    120132        // of the current position, reckoned before inserting the BR in between.
    121133        Position endingPosition = pos.downstream();
    122         insertNodeAfterPosition(nodeToInsert, pos);
     134        insertNodeAfterPosition(nodeToInsert.get(), pos);
    123135        setEndingSelection(endingPosition, DOWNSTREAM);
    124136    } else {
     
    133145        deleteTextFromNode(textNode, 0, pos.offset());
    134146        insertNodeBefore(textBeforeNode.get(), textNode);
    135         insertNodeBefore(nodeToInsert, textNode);
     147        insertNodeBefore(nodeToInsert.get(), textNode);
    136148        Position endingPosition = Position(textNode, 0);
    137149       
     
    141153            // Clear out all whitespace and insert one non-breaking space
    142154            deleteInsignificantTextDownstream(endingPosition);
     155            ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace());
    143156            insertTextIntoNode(textNode, 0, nonBreakingSpaceString());
    144157        }
     
    155168    if (typingStyle && typingStyle->length() > 0) {
    156169        Selection selectionBeforeStyle = endingSelection();
    157         applyStyle(typingStyle, Position(nodeToInsert, 0), Position(nodeToInsert, maxDeepOffset(nodeToInsert)));
     170        applyStyle(typingStyle, Position(nodeToInsert.get(), 0),
     171            Position(nodeToInsert.get(), maxDeepOffset(nodeToInsert.get())));
    158172        setEndingSelection(selectionBeforeStyle);
    159173    }
  • trunk/WebCore/editing/InsertParagraphSeparatorCommand.cpp

    r15563 r15617  
    214214    // after the preserved newline, causing the newline to be turned into a nbsp.
    215215    if (leadingWhitespace.isNotNull()) {
    216         Text *textNode = static_cast<Text *>(leadingWhitespace.node());
     216        Text* textNode = static_cast<Text*>(leadingWhitespace.node());
     217        ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace());
    217218        replaceTextInNode(textNode, leadingWhitespace.offset(), 1, nonBreakingSpaceString());
    218219    }
     
    285286        if (!pos.isRenderedCharacter()) {
    286287            // Clear out all whitespace and insert one non-breaking space
    287             ASSERT(startNode && startNode->isTextNode());
     288            ASSERT(startNode);
     289            ASSERT(startNode->isTextNode());
     290            ASSERT(!startNode->renderer() || startNode->renderer()->style()->collapseWhiteSpace());
    288291            deleteInsignificantTextDownstream(pos);
    289             insertTextIntoNode(static_cast<Text *>(startNode), 0, nonBreakingSpaceString());
     292            insertTextIntoNode(static_cast<Text*>(startNode), 0, nonBreakingSpaceString());
    290293        }
    291294    }
  • trunk/WebCore/editing/JSEditor.cpp

    r15286 r15617  
    416416bool execRemoveFormat(Frame* frame, bool userInterface, const String& value)
    417417{
    418     RefPtr<DocumentFragment> fragment = createFragmentFromText(frame->document(), frame->selection().toString().deprecatedString());
     418    RefPtr<DocumentFragment> fragment = createFragmentFromText(frame->selection().toRange().get(), frame->selection().toString());
    419419    EditCommandPtr(new ReplaceSelectionCommand(frame->document(), fragment.get(), false, false, false, false, EditActionUnspecified)).apply();
    420420    return true;
  • trunk/WebCore/editing/RebalanceWhitespaceCommand.cpp

    r14751 r15617  
    5050    if (m_position.isNull() || !m_position.node()->isTextNode())
    5151        return;
    52        
    53     Text *textNode = static_cast<Text *>(m_position.node());
     52
     53    Text* textNode = static_cast<Text*>(m_position.node());
    5454    String text = textNode->data();
    55     if (text.length() == 0)
    56         return;
    57    
     55    ASSERT(!text.isEmpty());
     56    ASSERT(!textNode->renderer() || textNode->renderer()->style()->collapseWhiteSpace());
     57
    5858    int offset = m_position.offset();
    5959    // If neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
     
    103103
    104104} // namespace WebCore
    105 
  • trunk/WebCore/editing/ReplaceSelectionCommand.cpp

    r15457 r15617  
    4949using namespace HTMLNames;
    5050
    51 ReplacementFragment::ReplacementFragment(Document *document, DocumentFragment *fragment, bool matchStyle, Element* editableRoot)
     51ReplacementFragment::ReplacementFragment(Document* document, DocumentFragment* fragment, bool matchStyle, const Selection& selection)
    5252    : m_document(document),
    5353      m_fragment(fragment),
     
    5959    if (!m_document)
    6060        return;
    61 
    62     if (!m_fragment) {
    63         m_type = EmptyFragment;
    64         return;
    65     }
    66 
     61    if (!m_fragment)
     62        return;
    6763    Node* firstChild = m_fragment->firstChild();
    68     Node* lastChild = m_fragment->lastChild();
    69 
    70     if (!firstChild) {
    71         m_type = EmptyFragment;
    72         return;
    73     }
    74    
    75     m_type = firstChild == lastChild && firstChild->isTextNode() ? SingleTextNodeFragment : TreeFragment;
    76    
     64    if (!firstChild)
     65        return;
     66   
     67    Element* editableRoot = selection.rootEditableElement();
    7768    ASSERT(editableRoot);
    7869    if (!editableRoot)
    7970        return;
    80            
    81     RefPtr<Node> holder = insertFragmentForTestRendering();
     71
     72    Node* styleNode = selection.base().node();
     73    RefPtr<Node> holder = insertFragmentForTestRendering(styleNode);
    8274   
    8375    RefPtr<Range> range = Selection::selectionFromContentsOfNode(holder.get()).toRange();
     
    8981    ASSERT(ec == 0);
    9082    if (text != evt->text() || !editableRoot->isContentRichlyEditable()) {
    91         // If the root is in plain-text mode, and white-space shouldn't be collapsed, then contruct a fragment that contains one text node
    92         if (!editableRoot->isContentRichlyEditable() && editableRoot->renderer() && !editableRoot->renderer()->style()->collapseWhiteSpace()) {
    93             RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
    94             fragment->appendChild(document->createTextNode(evt->text()), ec);
    95             ASSERT(ec == 0);
    96             m_fragment = fragment;
    97         } else
    98             m_fragment = createFragmentFromText(document, evt->text().deprecatedString());
     83        restoreTestRenderingNodesToFragment(holder.get());
     84        removeNode(holder);
     85
     86        m_fragment = createFragmentFromText(selection.toRange().get(), evt->text());
    9987        firstChild = m_fragment->firstChild();
    100         lastChild = m_fragment->firstChild();
    101        
    102         removeNode(holder);
    103         holder = insertFragmentForTestRendering();
    104     }
    105    
     88        if (!firstChild)
     89            return;
     90        holder = insertFragmentForTestRendering(styleNode);
     91    }
     92
    10693    Node *node = firstChild;
    10794    Node *newlineAtStartNode = 0;
     
    145132}
    146133
    147 ReplacementFragment::~ReplacementFragment()
    148 {
     134bool ReplacementFragment::isEmpty() const
     135{
     136    return (!m_fragment || !m_fragment->firstChild()) && !m_hasInterchangeNewlineAtStart && !m_hasInterchangeNewlineAtEnd;
    149137}
    150138
     
    233221}
    234222
    235 PassRefPtr<Node> ReplacementFragment::insertFragmentForTestRendering()
    236 {
    237     Node *body = m_document->body();
     223PassRefPtr<Node> ReplacementFragment::insertFragmentForTestRendering(Node* context)
     224{
     225    Node* body = m_document->body();
    238226    if (!body)
    239227        return 0;
    240228
    241     RefPtr<Node> holder = createDefaultParagraphElement(m_document.get());
     229    RefPtr<StyledElement> holder = static_pointer_cast<StyledElement>(createDefaultParagraphElement(m_document.get()));
    242230   
    243231    ExceptionCode ec = 0;
     232
     233    // Copy the whitespace style from the context onto this element.
     234    Node* n = context;
     235    while (n && !n->isElementNode())
     236        n = n->parentNode();
     237    if (n) {
     238        RefPtr<CSSComputedStyleDeclaration> contextStyle = new CSSComputedStyleDeclaration(static_cast<Element*>(n));
     239        CSSStyleDeclaration* style = holder->style();
     240        style->setProperty(CSS_PROP_WHITE_SPACE, contextStyle->getPropertyValue(CSS_PROP_WHITE_SPACE), false, ec);
     241        ASSERT(ec == 0);
     242    }
     243   
    244244    holder->appendChild(m_fragment, ec);
    245245    ASSERT(ec == 0);
     
    506506}
    507507
    508 bool ReplaceSelectionCommand::shouldMergeEnd(const VisiblePosition& endOfInsertedContent, bool fragmentHadInterchangeNewlineAtEnd, bool selectionEndWasEndOfParagraph)
     508bool ReplaceSelectionCommand::shouldMergeEnd(const VisiblePosition& endOfInsertedContent, bool selectionEndWasEndOfParagraph)
    509509{
    510510    Node* endNode = endOfInsertedContent.deepEquivalent().node();
     
    512512    // FIXME: Unify the naming scheme for these enclosing element getters.
    513513    return !selectionEndWasEndOfParagraph &&
    514            !fragmentHadInterchangeNewlineAtEnd &&
    515514           isEndOfParagraph(endOfInsertedContent) &&
    516515           nearestMailBlockquote(endNode) == nearestMailBlockquote(nextNode) &&
     
    533532   
    534533    Element* currentRoot = selection.rootEditableElement();
    535     ReplacementFragment fragment(document(), m_documentFragment.get(), m_matchStyle, currentRoot);
    536    
    537     if (fragment.type() == EmptyFragment)
     534    ReplacementFragment fragment(document(), m_documentFragment.get(), m_matchStyle, selection);
     535   
     536    if (fragment.isEmpty())
    538537        return;
    539538   
     
    715714        insertionPos = Position(m_lastNodeInserted.get(), m_lastNodeInserted->caretMaxOffset());
    716715    }
    717    
    718     removeEndBRIfNeeded(endBR);
     716
     717    Position lastPositionToSelect;
     718   
     719    bool interchangeNewlineAtEnd = fragment.hasInterchangeNewlineAtEnd();
     720    bool lastNodeInsertedWasBR = m_lastNodeInserted->hasTagName(brTag);
     721
     722    if (shouldRemoveEndBR(endBR)) {
     723        if (interchangeNewlineAtEnd || lastNodeInsertedWasBR) {
     724            interchangeNewlineAtEnd = false;
     725            lastNodeInsertedWasBR = false;
     726            m_lastNodeInserted = endBR;
     727            lastPositionToSelect = VisiblePosition(Position(m_lastNodeInserted.get(), 0)).deepEquivalent();
     728        } else
     729            removeNodeAndPruneAncestors(endBR);
     730    }
    719731   
    720732    // Styles were removed during the test insertion.  Restore them.
     
    725737    VisiblePosition startOfInsertedContent(Position(m_firstNodeInserted.get(), 0));   
    726738   
    727     Position lastPositionToSelect;
    728    
    729     if (fragment.hasInterchangeNewlineAtEnd()) {
     739    if (interchangeNewlineAtEnd) {
    730740        VisiblePosition pos(insertionPos);
    731741        VisiblePosition next = pos.next();
    732            
    733         if (endWasEndOfParagraph || !isEndOfParagraph(pos) || next.isNull() || next.rootEditableElement() != currentRoot) {
    734             setEndingSelection(insertionPos, DOWNSTREAM);
    735             insertParagraphSeparator();
    736 
    737             // Select up to the paragraph separator that was added.
    738             lastPositionToSelect = endingSelection().visibleStart().deepEquivalent();
    739             updateNodesInserted(lastPositionToSelect.node());
     742
     743        if (endWasEndOfParagraph || !isEndOfParagraph(pos) || next.rootEditableElement() != currentRoot) {
     744            if (!isStartOfParagraph(pos)) {
     745                setEndingSelection(pos.deepEquivalent().downstream(), DOWNSTREAM);
     746                insertParagraphSeparator();
     747
     748                // Select up to the paragraph separator that was added.
     749                lastPositionToSelect = endingSelection().visibleStart().deepEquivalent();
     750                updateNodesInserted(lastPositionToSelect.node());
     751            }
    740752        } else {
    741753            // Select up to the beginning of the next paragraph.
    742             VisiblePosition next = pos.next();
    743754            lastPositionToSelect = next.deepEquivalent().downstream();
    744755        }
    745        
    746     } else if (m_lastNodeInserted->hasTagName(brTag)) {
     756
     757    } else if (lastNodeInsertedWasBR) {
    747758        // We want to honor the last incoming line break, so, if it will collapse away because of quirks mode,
    748759        // add an extra one.
     
    752763            insertNodeBeforeAndUpdateNodesInserted(createBreakElement(document()).get(), m_lastNodeInserted.get());
    753764           
    754     } else if (shouldMergeEnd(endOfInsertedContent, fragment.hasInterchangeNewlineAtEnd(), endWasEndOfParagraph)) {
     765    } else if (shouldMergeEnd(endOfInsertedContent, endWasEndOfParagraph)) {
    755766        // Make sure that content after the end of the selection being pasted into is in the same paragraph as the
    756767        // last bit of content that was inserted.
    757768       
    758         // Merging two paragraphs will destroy the moved one's block styles.  Always move forward to preserve
    759         // the block style of the paragraph already in the document, unless the paragraph to move would include the
    760         // what was the start of the selection that was pasted into.
    761         bool mergeForward = !inSameParagraph(startOfInsertedContent, endOfInsertedContent);
    762        
    763         VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : endOfInsertedContent;
    764         VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(endOfInsertedContent) : endOfInsertedContent.next();
    765 
    766         moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove), destination);
    767         // Merging forward will remove m_lastNodeInserted from the document.
    768         // FIXME: Maintain positions for the start and end of inserted content instead of keeping nodes.  The nodes are
    769         // only ever used to create positions where inserted content starts/ends.
    770         if (mergeForward)
    771             m_lastNodeInserted = destination.previous().deepEquivalent().node();
     769        Position downstreamEnd = endOfInsertedContent.deepEquivalent().downstream();
     770        Position upstreamOnePastEnd = endOfInsertedContent.next().deepEquivalent().upstream();
     771        Node* node = downstreamEnd.node();
     772        int offset = downstreamEnd.offset();
     773        if (node && node == upstreamOnePastEnd.node() && offset + 1 == upstreamOnePastEnd.offset() && node->isTextNode()) {
     774            // Special case for removing a newline character.
     775            Text* textNode = static_cast<Text*>(node);
     776            if (textNode->length() == 1)
     777                removeNodeAndPruneAncestors(textNode);
     778            else
     779                deleteTextFromNode(textNode, offset, 1);
     780        } else {
     781            // Merging two paragraphs will destroy the moved one's block styles.  Always move forward to preserve
     782            // the block style of the paragraph already in the document, unless the paragraph to move would include the
     783            // what was the start of the selection that was pasted into.
     784            bool mergeForward = !inSameParagraph(startOfInsertedContent, endOfInsertedContent);
     785           
     786            VisiblePosition destination = mergeForward ? endOfInsertedContent.next() : endOfInsertedContent;
     787            VisiblePosition startOfParagraphToMove = mergeForward ? startOfParagraph(endOfInsertedContent) : endOfInsertedContent.next();
     788
     789            moveParagraph(startOfParagraphToMove, endOfParagraph(startOfParagraphToMove), destination);
     790            // Merging forward will remove m_lastNodeInserted from the document.
     791            // FIXME: Maintain positions for the start and end of inserted content instead of keeping nodes.  The nodes are
     792            // only ever used to create positions where inserted content starts/ends.
     793            if (mergeForward)
     794                m_lastNodeInserted = destination.previous().deepEquivalent().node();
     795        }
    772796    }
    773797   
     
    780804                                  !frame->isCharacterSmartReplaceExempt(endOfInsertedContent.characterAfter(), false);
    781805        if (needsTrailingSpace) {
     806            RenderObject* renderer = m_lastNodeInserted->renderer();
     807            bool collapseWhiteSpace = !renderer || renderer->style()->collapseWhiteSpace();
    782808            if (m_lastNodeInserted->isTextNode()) {
    783                 Text *text = static_cast<Text *>(m_lastNodeInserted.get());
    784                 insertTextIntoNode(text, text->length(), nonBreakingSpaceString());
    785                 insertionPos = Position(text, text->length());
     809                Text* text = static_cast<Text*>(m_lastNodeInserted.get());
     810                insertTextIntoNode(text, text->length(), collapseWhiteSpace ? nonBreakingSpaceString() : " ");
    786811            } else {
    787                 RefPtr<Node> node = document()->createEditingTextNode(nonBreakingSpaceString());
     812                RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " ");
    788813                insertNodeAfterAndUpdateNodesInserted(node.get(), m_lastNodeInserted.get());
    789                 insertionPos = Position(node.get(), 1);
    790814            }
    791815        }
     
    794818                                 !frame->isCharacterSmartReplaceExempt(startOfInsertedContent.previous().characterAfter(), true);
    795819        if (needsLeadingSpace) {
     820            RenderObject* renderer = m_lastNodeInserted->renderer();
     821            bool collapseWhiteSpace = !renderer || renderer->style()->collapseWhiteSpace();
    796822            if (m_firstNodeInserted->isTextNode()) {
    797                 Text *text = static_cast<Text *>(m_firstNodeInserted.get());
    798                 insertTextIntoNode(text, 0, nonBreakingSpaceString());
     823                Text* text = static_cast<Text*>(m_firstNodeInserted.get());
     824                insertTextIntoNode(text, 0, collapseWhiteSpace ? nonBreakingSpaceString() : " ");
    799825            } else {
    800                 RefPtr<Node> node = document()->createEditingTextNode(nonBreakingSpaceString());
     826                RefPtr<Node> node = document()->createEditingTextNode(collapseWhiteSpace ? nonBreakingSpaceString() : " ");
    801827                // Don't updateNodesInserted.  Doing so would set m_lastNodeInserted to be the node containing the
    802828                // leading space, but m_lastNodeInserted is supposed to mark the end of pasted content.
     
    811837}
    812838
    813 void ReplaceSelectionCommand::removeEndBRIfNeeded(Node* endBR)
     839bool ReplaceSelectionCommand::shouldRemoveEndBR(Node* endBR)
    814840{
    815841    if (!endBR || !endBR->inDocument())
    816         return;
     842        return false;
    817843       
    818844    VisiblePosition visiblePos(Position(endBR, 0));
    819845   
    820     if (// The br is collapsed away and so is unnecessary.
     846    return
     847        // The br is collapsed away and so is unnecessary.
    821848        !document()->inStrictMode() && isEndOfBlock(visiblePos) && !isStartOfParagraph(visiblePos) ||
    822849        // A br that was originally holding a line open should be displaced by inserted content.
    823850        // A br that was originally acting as a line break should still be acting as a line break, not as a placeholder.
    824         isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos))
    825         removeNodeAndPruneAncestors(endBR);
     851        isStartOfParagraph(visiblePos) && isEndOfParagraph(visiblePos);
    826852}
    827853
  • trunk/WebCore/editing/ReplaceSelectionCommand.h

    r15286 r15617  
    5353// --- ReplacementFragment helper class
    5454
    55 class ReplacementFragment
     55class ReplacementFragment : Noncopyable
    5656{
    5757public:
    58     ReplacementFragment(Document*, DocumentFragment*, bool, Element*);
    59     ~ReplacementFragment();
     58    ReplacementFragment(Document*, DocumentFragment*, bool matchStyle, const Selection&);
    6059
    61     Node *firstChild() const;
    62     Node *lastChild() const;
     60    Node* firstChild() const;
     61    Node* lastChild() const;
    6362
    64     Node *mergeStartNode() const;
     63    Node* mergeStartNode() const;
    6564
    6665    const RenderingInfoMap& renderingInfo() const { return m_renderingInfo; }
    6766    const NodeVector& nodes() const { return m_nodes; }
    6867
    69     EFragmentType type() const { return m_type; }
    70     bool isEmpty() const { return m_type == EmptyFragment; }
    71     bool isSingleTextNode() const { return m_type == SingleTextNodeFragment; }
    72     bool isTreeFragment() const { return m_type == TreeFragment; }
     68    bool isEmpty() const;
    7369
    7470    bool hasMoreThanOneBlock() const { return m_hasMoreThanOneBlock; }
     
    8076    void removeNode(PassRefPtr<Node>);
    8177
    82 private:
    83     // no copy construction or assignment
    84     ReplacementFragment(const ReplacementFragment &);
    85     ReplacementFragment &operator=(const ReplacementFragment &);
     78private:   
     79    static bool isInterchangeNewlineNode(const Node*);
     80    static bool isInterchangeConvertedSpaceSpan(const Node*);
    8681   
    87     static bool isInterchangeNewlineNode(const Node *);
    88     static bool isInterchangeConvertedSpaceSpan(const Node *);
    89    
    90     PassRefPtr<Node> insertFragmentForTestRendering();
     82    PassRefPtr<Node> insertFragmentForTestRendering(Node* context);
    9183    void saveRenderingInfo(Node*);
    9284    void computeStylesUsingTestRendering(Node*);
     
    9688    void removeStyleNodes();
    9789
    98     Node *enclosingBlock(Node *) const;
    99     void removeNodePreservingChildren(Node *);
    100     void insertNodeBefore(Node *node, Node *refNode);
     90    Node* enclosingBlock(Node*) const;
     91    void removeNodePreservingChildren(Node*);
     92    void insertNodeBefore(Node* node, Node* refNode);
    10193
    102     EFragmentType m_type;
    10394    RefPtr<Document> m_document;
    10495    RefPtr<DocumentFragment> m_fragment;
     
    129120    void updateNodesInserted(Node *);
    130121    void fixupNodeStyles(const NodeVector&, const RenderingInfoMap&);
    131     void removeEndBRIfNeeded(Node*);
     122    bool shouldRemoveEndBR(Node*);
    132123   
    133124    bool shouldMergeStart(const ReplacementFragment&, const Selection&);
    134     bool shouldMergeEnd(const VisiblePosition&, bool, bool);
     125    bool shouldMergeEnd(const VisiblePosition&, bool selectionEndWasEndOfParagraph);
    135126
    136127    RefPtr<Node> m_firstNodeInserted;
  • trunk/WebCore/editing/markup.cpp

    r15556 r15617  
    243243}
    244244
    245 static DeprecatedString markup(const Node *startNode, bool onlyIncludeChildren, bool includeSiblings, DeprecatedPtrList<Node> *nodes)
     245static DeprecatedString markup(Node* startNode, bool onlyIncludeChildren, bool includeSiblings, Vector<Node*> *nodes)
    246246{
    247247    // Doesn't make sense to only include children and include siblings.
    248248    ASSERT(!(onlyIncludeChildren && includeSiblings));
    249249    DeprecatedString me = "";
    250     for (const Node *current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
     250    for (Node* current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
    251251        if (!onlyIncludeChildren) {
    252252            if (nodes)
     
    285285// FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForInterchange?
    286286// FIXME: At least, annotation and style info should probably not be included in range.markupString()
    287 DeprecatedString createMarkup(const Range *range, DeprecatedPtrList<Node> *nodes, EAnnotateForInterchange annotate)
     287DeprecatedString createMarkup(const Range *range, Vector<Node*>* nodes, EAnnotateForInterchange annotate)
    288288{
    289289    if (!range || range->isDetached())
     
    311311    Node *pastEnd = range->pastEndNode();
    312312    Node *lastClosed = 0;
    313     DeprecatedPtrList<Node> ancestorsToClose;
     313    Vector<Node*> ancestorsToClose;
    314314
    315315    // calculate the "default style" for this markup
     
    371371                if (!ancestorsToClose.isEmpty()) {
    372372                    // Close up the ancestors.
    373                     while (Node *ancestor = ancestorsToClose.last()) {
     373                    do {
     374                        Node *ancestor = ancestorsToClose.last();
    374375                        if (next != pastEnd && next->isAncestor(ancestor))
    375376                            break;
     
    378379                        lastClosed = ancestor;
    379380                        ancestorsToClose.removeLast();
    380                     }
     381                    } while (!ancestorsToClose.isEmpty());
    381382                } else {
    382383                    if (next != pastEnd) {
     
    475476}
    476477
    477 DeprecatedString createMarkup(const Node *node, EChildrenOnly includeChildren,
    478     DeprecatedPtrList<Node> *nodes, EAnnotateForInterchange annotate)
     478DeprecatedString createMarkup(const Node* node, EChildrenOnly includeChildren,
     479    Vector<Node*>* nodes, EAnnotateForInterchange annotate)
    479480{
    480481    ASSERT(annotate == DoNotAnnotateForInterchange); // annotation not yet implemented for this code path
    481482    node->document()->updateLayoutIgnorePendingStylesheets();
    482     return markup(node, includeChildren, false, nodes);
    483 }
    484 
    485 static void createParagraphContentsFromString(Document *document, Element *paragraph, const DeprecatedString &string)
    486 {
     483    return markup(const_cast<Node*>(node), includeChildren, false, nodes);
     484}
     485
     486static void createParagraphContentsFromString(Element* paragraph, const DeprecatedString& string)
     487{
     488    Document* document = paragraph->document();
     489
    487490    ExceptionCode ec = 0;
    488491    if (string.isEmpty()) {
     
    502505        // append the non-tab textual part
    503506        if (!s.isEmpty()) {
    504             if (tabText != "") {
     507            if (!tabText.isEmpty()) {
    505508                paragraph->appendChild(createTabSpanElement(document, tabText), ec);
    506509                ASSERT(ec == 0);
     
    515518        // there is a tab after every entry, except the last entry
    516519        // (if the last character is a tab, the list gets an extra empty entry)
    517         if (!tabList.isEmpty()) {
     520        if (!tabList.isEmpty())
    518521            tabText += '\t';
    519         } else if (tabText != "") {
     522        else if (!tabText.isEmpty()) {
    520523            paragraph->appendChild(createTabSpanElement(document, tabText), ec);
    521524            ASSERT(ec == 0);
     
    524527}
    525528
    526 PassRefPtr<DocumentFragment> createFragmentFromText(Document *document, const DeprecatedString &text)
    527 {
    528     if (!document)
     529PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String& text)
     530{
     531    if (!context)
    529532        return 0;
    530533
     534    Node* styleNode = context->startNode();
     535    if (!styleNode) {
     536        styleNode = context->startPosition().node();
     537        if (!styleNode)
     538            return 0;
     539    }
     540
     541    Document* document = styleNode->document();
    531542    RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
    532543   
    533     if (!text.isEmpty()) {
    534         DeprecatedString string = text;
    535 
    536         // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
    537         string.replace("\r\n", "\n");
    538         string.replace('\r', '\n');
    539         DeprecatedStringList list = DeprecatedStringList::split('\n', string, true); // true gets us empty strings in the list
    540         while (!list.isEmpty()) {
    541             DeprecatedString s = list.first();
    542             list.pop_front();
    543 
    544             ExceptionCode ec = 0;
     544    if (text.isEmpty())
     545        return fragment.release();
     546
     547    DeprecatedString string = text.deprecatedString();
     548    string.replace("\r\n", "\n");
     549    string.replace('\r', '\n');
     550
     551    ExceptionCode ec = 0;
     552    RenderObject* renderer = styleNode->renderer();
     553    if (renderer && renderer->style()->preserveNewline()) {
     554        fragment->appendChild(document->createTextNode(string), ec);
     555        ASSERT(ec == 0);
     556        if (string.endsWith("\n")) {
    545557            RefPtr<Element> element;
    546             if (s.isEmpty() && list.isEmpty()) {
    547                 // For last line, use the "magic BR" rather than a P.
    548                 element = document->createElementNS(xhtmlNamespaceURI, "br", ec);
    549                 ASSERT(ec == 0);
    550                 element->setAttribute(classAttr, AppleInterchangeNewline);           
    551             } else {
    552                 element = createDefaultParagraphElement(document);
    553                 createParagraphContentsFromString(document, element.get(), s);
    554             }
    555             fragment->appendChild(element.get(), ec);
     558            element = document->createElementNS(xhtmlNamespaceURI, "br", ec);
    556559            ASSERT(ec == 0);
    557         }
     560            element->setAttribute(classAttr, AppleInterchangeNewline);           
     561            fragment->appendChild(element.release(), ec);
     562            ASSERT(ec == 0);
     563        }
     564        return fragment.release();
     565    }
     566
     567    // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
     568    DeprecatedStringList list = DeprecatedStringList::split('\n', string, true); // true gets us empty strings in the list
     569    while (!list.isEmpty()) {
     570        DeprecatedString s = list.first();
     571        list.pop_front();
     572
     573        RefPtr<Element> element;
     574        if (s.isEmpty() && list.isEmpty()) {
     575            // For last line, use the "magic BR" rather than a P.
     576            element = document->createElementNS(xhtmlNamespaceURI, "br", ec);
     577            ASSERT(ec == 0);
     578            element->setAttribute(classAttr, AppleInterchangeNewline);           
     579        } else {
     580            element = createDefaultParagraphElement(document);
     581            createParagraphContentsFromString(element.get(), s);
     582        }
     583        fragment->appendChild(element.release(), ec);
     584        ASSERT(ec == 0);
    558585    }
    559586    return fragment.release();
    560587}
    561588
    562 PassRefPtr<DocumentFragment> createFragmentFromNodeList(Document *document, const DeprecatedPtrList<Node> &nodeList)
     589PassRefPtr<DocumentFragment> createFragmentFromNodes(Document *document, const Vector<Node*>& nodes)
    563590{
    564591    if (!document)
     
    568595
    569596    ExceptionCode ec = 0;
    570     for (DeprecatedPtrListIterator<Node> i(nodeList); i.current(); ++i) {
     597    size_t size = nodes.size();
     598    for (size_t i = 0; i < size; ++i) {
    571599        RefPtr<Element> element = createDefaultParagraphElement(document);
    572         element->appendChild(i.current(), ec);
     600        element->appendChild(nodes[i], ec);
    573601        ASSERT(ec == 0);
    574602        fragment->appendChild(element.release(), ec);
  • trunk/WebCore/editing/markup.h

    r15286 r15617  
    2929#include "HTMLInterchange.h"
    3030#include <wtf/Forward.h>
     31#include <wtf/Vector.h>
    3132
    3233namespace WebCore {
     
    3839    class String;
    3940
    40     template <class T> class DeprecatedPtrList;
    41 
    4241    enum EChildrenOnly { IncludeNode, ChildrenOnly };
    4342
    44     PassRefPtr<DocumentFragment> createFragmentFromText(Document*, const DeprecatedString &text);
    45     PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document*, const String &markup, const String &baseURL);
    46     PassRefPtr<DocumentFragment> createFragmentFromNodeList(Document*, const DeprecatedPtrList<Node> &nodeList);
     43    PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String& text);
     44    PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document*, const String& markup, const String& baseURL);
     45    PassRefPtr<DocumentFragment> createFragmentFromNodes(Document*, const Vector<Node*>&);
    4746
    48     DeprecatedString createMarkup(const Range *range,
    49         DeprecatedPtrList<Node> *nodes = 0, EAnnotateForInterchange = DoNotAnnotateForInterchange);
    50     DeprecatedString createMarkup(const Node *node, EChildrenOnly = IncludeNode,
    51         DeprecatedPtrList<Node> *nodes = 0, EAnnotateForInterchange = DoNotAnnotateForInterchange);
     47    DeprecatedString createMarkup(const Range*,
     48        Vector<Node*>* = 0, EAnnotateForInterchange = DoNotAnnotateForInterchange);
     49    DeprecatedString createMarkup(const Node*, EChildrenOnly = IncludeNode,
     50        Vector<Node*>* = 0, EAnnotateForInterchange = DoNotAnnotateForInterchange);
    5251
    5352}
  • trunk/WebCore/html/HTMLElement.cpp

    r15194 r15617  
    301301    }
    302302
     303    // FIXME: Add special case for when we had one text child and we just want to set its text?
     304    // FIXME: Add special case for cases where we can use replaceChild?
     305
    303306    removeChildren();
    304307    appendChild(fragment.release(), ec);
     
    320323    }
    321324
    322     // FIXME: Why doesn't this have code to merge neighboring text nodes the
    323     // way setOuterText does?
     325    // FIXME: Add special case for when we had one text child and we just want to set its text?
     326    // FIXME: Why doesn't this have code to merge neighboring text nodes the way setOuterText does?
    324327    parent->replaceChild(fragment.release(), this, ec);
    325328}
     
    340343    }
    341344
     345    // FIXME: This doesn't take whitespace collapsing into account at all.
     346    // FIXME: Add special case for when we had one text child and we just want to set its text?
     347    // FIXME: Add special case for cases where we can use replaceChild?
     348
    342349    removeChildren();
    343350
     351    if (!text.contains('\n') && !text.contains('\r')) {
     352        if (text.isEmpty())
     353            return;
     354        appendChild(new Text(document(), text), ec);
     355        return;
     356    }
     357
     358    // FIXME: Do we need to be able to detect preserveNewline style even when there's no renderer?
     359    // FIXME: Can the renderer be out of date here? Do we need to call updateRendering?
     360    // For example, for the contents of textarea elements that are display:none?
     361    RenderObject* r = renderer();
     362    if (r && r->style()->preserveNewline()) {
     363        if (!text.contains('\r')) {
     364            appendChild(new Text(document(), text), ec);
     365            return;
     366        }
     367        // FIXME: Stick with String once it has a replace that can do this.
     368        DeprecatedString textWithConsistentLineBreaks = text.deprecatedString();
     369        textWithConsistentLineBreaks.replace("\r\n", "\n");
     370        textWithConsistentLineBreaks.replace('\r', '\n');
     371        appendChild(new Text(document(), textWithConsistentLineBreaks), ec);
     372        return;
     373    }
     374
    344375    // Add text nodes and <br> elements.
     376    ec = 0;
     377    int lineStart = 0;
     378    UChar prev = 0;
    345379    int length = text.length();
    346     if (!text.contains('\n') && !text.contains('\r') && length)
    347         appendChild(new Text(document(), text), ec);
    348     else {
    349         ec = 0;
    350         int lineStart = 0;
    351         UChar prev = 0;
    352         for (int i = 0; i < length; ++i) {
    353             UChar c = text[i];
    354             if (c == '\n' || c == '\r') {
    355                 if (i > lineStart) {
    356                     appendChild(new Text(document(), text.substring(lineStart, i - lineStart)), ec);
    357                     if (ec)
    358                         return;
    359                 }
    360                 if (!(c == '\n' && i != 0 && prev == '\r')) {
    361                     appendChild(new HTMLBRElement(document()), ec);
    362                     if (ec)
    363                         return;
    364                 }
    365                 lineStart = i + 1;
     380    for (int i = 0; i < length; ++i) {
     381        UChar c = text[i];
     382        if (c == '\n' || c == '\r') {
     383            if (i > lineStart) {
     384                appendChild(new Text(document(), text.substring(lineStart, i - lineStart)), ec);
     385                if (ec)
     386                    return;
    366387            }
    367             prev = c;
     388            if (!(c == '\n' && i != 0 && prev == '\r')) {
     389                appendChild(new HTMLBRElement(document()), ec);
     390                if (ec)
     391                    return;
     392            }
     393            lineStart = i + 1;
    368394        }
    369         if (length > lineStart)
    370             appendChild(new Text(document(), text.substring(lineStart, length - lineStart)), ec);
    371     }
     395        prev = c;
     396    }
     397    if (length > lineStart)
     398        appendChild(new Text(document(), text.substring(lineStart, length - lineStart)), ec);
    372399}
    373400
  • trunk/WebCore/html/HTMLTextAreaElement.cpp

    r15532 r15617  
    260260void HTMLTextAreaElement::setValue(const String& value)
    261261{
    262     DeprecatedString string = value.deprecatedString();
    263262    // WebCoreTextArea normalizes line endings added by the user via the keyboard or pasting.
    264263    // We must normalize line endings coming from JS.
    265     string.replace("\r\n", "\n");
    266     string.replace("\r", "\n");
     264    DeprecatedString valueWithNormalizedLineEndings = value.deprecatedString();
     265    valueWithNormalizedLineEndings.replace("\r\n", "\n");
     266    valueWithNormalizedLineEndings.replace("\r", "\n");
    267267   
    268     m_value = String(string);
     268    m_value = valueWithNormalizedLineEndings;
    269269    setValueMatchesRenderer();
    270270    if (renderer())
     
    284284    String val = "";
    285285
    286     // there may be comments - just grab the text nodes
     286    // Since there may be comments, ignore nodes other than text nodes.
    287287    for (Node* n = firstChild(); n; n = n->nextSibling())
    288288        if (n->isTextNode())
     
    290290
    291291    // FIXME: We should only drop the first carriage return for the default
    292     // value in the original source, not defaultValues set from JS.
     292    // value in the original source, not defaultValues set from JS. This code
     293    // will do both.
    293294    if (val.length() >= 2 && val[0] == '\r' && val[1] == '\n')
    294295        val.remove(0, 2);
     
    301302void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
    302303{
    303     // there may be comments - remove all the text nodes and replace them with one
    304     DeprecatedPtrList<Node> toRemove;
    305     Node *n;
    306     for (n = firstChild(); n; n = n->nextSibling())
     304    // To preserve comments, remove all the text nodes, then add a single one.
     305    Vector<RefPtr<Node> > textNodes;
     306    for (Node* n = firstChild(); n; n = n->nextSibling())
    307307        if (n->isTextNode())
    308             toRemove.append(n);
    309     DeprecatedPtrListIterator<Node> it(toRemove);
     308            textNodes.append(n);
    310309    ExceptionCode ec = 0;
    311     for (; it.current(); ++it) {
    312         RefPtr<Node> n = it.current();
    313         removeChild(n.get(), ec);
    314     }
     310    size_t size = textNodes.size();
     311    for (size_t i = 0; i < size; ++i)
     312        removeChild(textNodes[i].get(), ec);
    315313    insertBefore(document()->createTextNode(defaultValue), firstChild(), ec);
    316314    setValue(defaultValue);
  • trunk/WebCore/loader/Cache.h

    r15286 r15617  
    2929
    3030#include "CachePolicy.h"
    31 #include "DeprecatedPtrList.h"
    3231#include "PlatformString.h"
    3332#include <wtf/HashSet.h>
  • trunk/WebCore/rendering/InlineTextBox.cpp

    r15361 r15617  
    736736}
    737737
    738 }
     738bool InlineTextBox::containsCaretOffset(int offset) const
     739{
     740    // Offsets before the box are never "in".
     741    if (offset < m_start)
     742        return false;
     743
     744    int pastEnd = m_start + m_len;
     745
     746    // Offsets inside the box (not at either edge) are always "in".
     747    if (offset < pastEnd)
     748        return true;
     749
     750    // Offsets outside the box are always "out".
     751    if (offset > pastEnd)
     752        return false;
     753
     754    // Offsets at the end are "out" for line breaks (they are on the next line).
     755    if (isLineBreak())
     756        return false;
     757
     758    // Offsets at the end are "in" for normal boxes (but the caller has to check affinity).
     759    return true;
     760}
     761
     762}
  • trunk/WebCore/rendering/InlineTextBox.h

    r14766 r15617  
    124124    int offsetForPosition(int _x, bool includePartialGlyphs = true) const;
    125125    int positionForOffset(int offset) const;
     126
     127    bool containsCaretOffset(int offset) const; // false for offset after line break
    126128   
    127129    int m_start;
  • trunk/WebCore/rendering/RenderText.cpp

    r15558 r15617  
    359359}
    360360
    361 bool RenderText::atLineWrap(InlineTextBox *box, int offset)
    362 {
    363     if (box->nextTextBox() && !box->nextOnLine() && offset == box->m_start + box->m_len) {
    364         if (!style()->preserveNewline() || !box->isLineBreak())
    365             return true;
    366     }
    367    
    368     return false;
     361static inline bool atLineWrap(InlineTextBox* box, int offset)
     362{
     363    return box->nextTextBox() && !box->nextOnLine() && offset == box->m_start + box->m_len;
    369364}
    370365
     
    377372    InlineTextBox *box = 0;
    378373    for (box = firstTextBox(); box; box = box->nextTextBox()) {
    379         if ((offset >= box->m_start) && (offset <= box->m_start + box->m_len)) {
     374        if (box->containsCaretOffset(offset)) {
    380375            // Check if downstream affinity would make us move to the next line.
    381376            if (atLineWrap(box, offset) && affinity == DOWNSTREAM) {
     
    11141109}
    11151110
    1116 InlineBox *RenderText::inlineBox(int offset, EAffinity affinity)
    1117 {
    1118     for (InlineTextBox *box = firstTextBox(); box; box = box->nextTextBox()) {
    1119         if (offset >= box->m_start && offset <= box->m_start + box->m_len) {
     1111InlineBox* RenderText::inlineBox(int offset, EAffinity affinity)
     1112{
     1113    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
     1114        if (box->containsCaretOffset(offset)) {
    11201115            if (atLineWrap(box, offset) && affinity == DOWNSTREAM)
    11211116                return box->nextTextBox();
    11221117            return box;
    11231118        }
    1124        
    1125         if (offset < box->m_start) {
     1119        if (offset < box->m_start)
    11261120            // The offset we're looking for is before this node
    11271121            // this means the offset must be in content that is
    11281122            // not rendered.
    11291123            return box->prevTextBox() ? box->prevTextBox() : firstTextBox();
    1130         }
    11311124    }
    11321125   
  • trunk/WebCore/rendering/RenderText.h

    r15253 r15617  
    150150    virtual unsigned caretMaxRenderedOffset() const;
    151151
    152     virtual int previousOffset (int current) const;
    153     virtual int nextOffset (int current) const;
     152    virtual int previousOffset(int current) const;
     153    virtual int nextOffset(int current) const;
    154154   
    155     bool atLineWrap(InlineTextBox *box, int offset);
    156     bool containsReversedText() { return m_containsReversedText; }
     155    bool containsReversedText() const { return m_containsReversedText; }
    157156   
    158157public:
  • trunk/WebCore/rendering/RenderTextControl.cpp

    r15584 r15617  
    2626#include "EventNames.h"
    2727#include "Frame.h"
     28#include "HTMLBRElement.h"
    2829#include "HTMLInputElement.h"
    2930#include "HTMLNames.h"
     
    157158            ExceptionCode ec = 0;
    158159            m_div->setInnerText(value, ec);
     160            if (value.endsWith("\n") || value.endsWith("\r"))
     161                m_div->appendChild(new HTMLBRElement(document()), ec);
    159162            if (document()->frame())
    160163                document()->frame()->clearUndoRedoOperations();
     
    216219    SelectionController sel = SelectionController(startPosition, endPosition);
    217220    document()->frame()->setSelection(sel);
     221    // FIXME: Granularity is stored separately on the frame, but also in the selection controller.
     222    // The granularity in the selection controller should be used, and then this line of code would not be needed.
     223    document()->frame()->setSelectionGranularity(CharacterGranularity);
    218224}
    219225
     
    263269{
    264270    if (m_div)
    265         return m_div->textContent(true).replace('\\', backslashAsCurrencySymbol());
     271        return m_div->textContent().replace('\\', backslashAsCurrencySymbol());
    266272    return String();
    267273}
  • trunk/WebCore/rendering/bidi.cpp

    r15612 r15617  
    24752475    if (lBreak == start && !lBreak.obj->isBR()) {
    24762476        // we just add as much as possible
    2477         if (style()->whiteSpace() == PRE) {
     2477        if (style()->preserveNewline()) {
    24782478            // FIXME: Don't really understand this case.
    24792479            if (pos != 0) {
  • trunk/WebKit/ChangeLog

    r15615 r15617  
     12006-07-24  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Adele and Justin.
     4
     5        - update for change to require context when creating fragments from text
     6          (needed to handle whitespace properly)
     7
     8        * WebView/WebHTMLView.m:
     9        (-[WebHTMLView _documentFragmentFromPasteboard:inContext:allowPlainText:chosePlainText:]):
     10        Added context parameter, pass through to bridge.
     11        (-[WebHTMLView _pasteWithPasteboard:allowPlainText:]): Pass selection range as context
     12        when calling above method.
     13        (-[WebHTMLView concludeDragForDraggingInfo:actionMask:]): Pass drag caret as context when
     14        calling above method.
     15
    1162006-07-24  Maciej Stachowiak  <mjs@apple.com>
    217
  • trunk/WebKit/WebView/WebHTMLView.m

    r15586 r15617  
    177177@interface WebHTMLView (WebHTMLViewFileInternal)
    178178- (BOOL)_imageExistsAtPaths:(NSArray *)paths;
    179 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText chosePlainText:(BOOL *)chosePlainText;
     179- (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard inContext:(DOMRange *)context allowPlainText:(BOOL)allowPlainText chosePlainText:(BOOL *)chosePlainText;
    180180- (NSString *)_plainTextFromPasteboard:(NSPasteboard *)pasteboard;
    181181- (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText;
     
    363363}
    364364
    365 - (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText chosePlainText:(BOOL *)chosePlainText
     365- (DOMDocumentFragment *)_documentFragmentFromPasteboard:(NSPasteboard *)pasteboard
     366                                               inContext:(DOMRange *)context
     367                                          allowPlainText:(BOOL)allowPlainText
     368                                          chosePlainText:(BOOL *)chosePlainText
    366369{
    367370    NSArray *types = [pasteboard types];
     
    464467    if (allowPlainText && [types containsObject:NSStringPboardType]) {
    465468        *chosePlainText = YES;
    466         return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]];
     469        return [[self _bridge] documentFragmentWithText:[pasteboard stringForType:NSStringPboardType]
     470                                              inContext:context];
    467471    }
    468472   
     
    509513- (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText
    510514{
     515    DOMRange *range = [self _selectedRange];
    511516    BOOL chosePlainText;
    512     DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard allowPlainText:allowPlainText chosePlainText:&chosePlainText];
     517    DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard
     518        inContext:range allowPlainText:allowPlainText chosePlainText:&chosePlainText];
    513519    WebFrameBridge *bridge = [self _bridge];
    514520    if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:[self _selectedRange] givenAction:WebViewInsertActionPasted]) {
     
    57265732        NSPasteboard *pasteboard = [draggingInfo draggingPasteboard];
    57275733        if ([self _isMoveDrag] || [innerBridge isDragCaretRichlyEditable]) {
     5734            DOMRange *range = [innerBridge dragCaretDOMRange];
    57285735            BOOL chosePlainText;
    5729             DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard allowPlainText:YES chosePlainText:&chosePlainText];
    5730             if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:[innerBridge dragCaretDOMRange] givenAction:WebViewInsertActionDropped]) {
     5736            DOMDocumentFragment *fragment = [self _documentFragmentFromPasteboard:pasteboard
     5737                inContext:range allowPlainText:YES chosePlainText:&chosePlainText];
     5738            if (fragment && [self _shouldInsertFragment:fragment replacingDOMRange:range givenAction:WebViewInsertActionDropped]) {
    57315739                [[webView _UIDelegateForwarder] webView:webView willPerformDragDestinationAction:WebDragDestinationActionEdit forDraggingInfo:draggingInfo];
    57325740                if ([self _isMoveDrag]) {
Note: See TracChangeset for help on using the changeset viewer.