1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/*
2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010 Google Inc. All rights reserved.
4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Redistribution and use in source and binary forms, with or without
6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modification, are permitted provided that the following conditions
7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * are met:
8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1. Redistributions of source code must retain the above copyright
9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    notice, this list of conditions and the following disclaimer.
10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright
11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    notice, this list of conditions and the following disclaimer in the
12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    documentation and/or other materials provided with the distribution.
13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */
26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h"
28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "ApplyBlockElementCommand.h"
29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "HTMLElement.h"
31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "HTMLNames.h"
32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "Text.h"
33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "TextIterator.h"
34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "VisiblePosition.h"
35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "htmlediting.h"
36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "visible_units.h"
37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore {
39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochusing namespace HTMLNames;
41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
42a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochApplyBlockElementCommand::ApplyBlockElementCommand(Document* document, const QualifiedName& tagName, const AtomicString& className, const AtomicString& inlineStyle)
43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    : CompositeEditCommand(document)
44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_tagName(tagName)
45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_className(className)
46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_inlineStyle(inlineStyle)
47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
50a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochApplyBlockElementCommand::ApplyBlockElementCommand(Document* document, const QualifiedName& tagName)
51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    : CompositeEditCommand(document)
52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_tagName(tagName)
53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid ApplyBlockElementCommand::doApply()
57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!endingSelection().isNonOrphanedCaretOrRange())
59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!endingSelection().rootEditableElement())
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition visibleEnd = endingSelection().visibleEnd();
65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition visibleStart = endingSelection().visibleStart();
66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // When a selection ends at the start of a paragraph, we rarely paint
67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // the selection gap before that paragraph, because there often is no gap.
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // In a case like this, it's not obvious to the user that the selection
69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // ends "inside" that paragraph, so it would be confusing if Indent/Outdent
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // operated on that paragraph.
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: We paint the gap before some paragraphs that are indented with left
72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // margin/padding, but not others.  We should make the gap painting more consistent and
73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // then use a left margin/padding rule here.
74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd))
752bde8e466a4451c7319e3a072d118917957d6554Steve Block        setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary)));
76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisibleSelection selection = selectionForParagraphIteration(endingSelection());
78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition startOfSelection = selection.visibleStart();
79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition endOfSelection = selection.visibleEnd();
80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!startOfSelection.isNull());
81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!endOfSelection.isNull());
82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int startIndex = indexForVisiblePosition(startOfSelection);
83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int endIndex = indexForVisiblePosition(endOfSelection);
84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    formatSelection(startOfSelection, endOfSelection);
86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    updateLayout();
88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<Range> startRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), startIndex, 0, true);
90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<Range> endRange = TextIterator::rangeFromLocationAndLength(document()->documentElement(), endIndex, 0, true);
91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startRange && endRange)
92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        setEndingSelection(VisibleSelection(startRange->startPosition(), endRange->startPosition(), DOWNSTREAM));
93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid ApplyBlockElementCommand::formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection)
96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Special case empty unsplittable elements because there's nothing to split
98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // and there's nothing to move.
99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Position start = startOfSelection.deepEquivalent().downstream();
100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (isAtUnsplittableElement(start)) {
101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        RefPtr<Element> blockquote = createBlockElement();
102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        insertNodeAt(blockquote, start);
103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        RefPtr<Element> placeholder = createBreakElement(document());
104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        appendNode(placeholder, blockquote);
10565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        setEndingSelection(VisibleSelection(positionBeforeNode(placeholder.get()), DOWNSTREAM));
106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<Element> blockquoteForNextIndent;
110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection);
111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition endAfterSelection = endOfParagraph(endOfParagraph(endOfSelection).next());
112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_endOfLastParagraph = endOfParagraph(endOfSelection).deepEquivalent();
113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool atEnd = false;
115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Position end;
116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    while (endOfCurrentParagraph != endAfterSelection && !atEnd) {
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (endOfCurrentParagraph.deepEquivalent() == m_endOfLastParagraph)
118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            atEnd = true;
119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        rangeForParagraphSplittingTextNodesIfNeeded(endOfCurrentParagraph, start, end);
121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        endOfCurrentParagraph = end;
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        Position afterEnd = end.next();
124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        Node* enclosingCell = enclosingNodeOfType(start, &isTableCell);
125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        VisiblePosition endOfNextParagraph = endOfNextParagrahSplittingTextNodesIfNeeded(endOfCurrentParagraph, start, end);
126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        formatRange(start, end, m_endOfLastParagraph, blockquoteForNextIndent);
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Don't put the next paragraph in the blockquote we just created for this paragraph unless
130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // the next paragraph is in the same cell.
131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (enclosingCell && enclosingCell != enclosingNodeOfType(endOfNextParagraph.deepEquivalent(), &isTableCell))
132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            blockquoteForNextIndent = 0;
133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // indentIntoBlockquote could move more than one paragraph if the paragraph
135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // is in a list item or a table. As a result, endAfterSelection could refer to a position
136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // no longer in the document.
13781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (endAfterSelection.isNotNull() && !endAfterSelection.deepEquivalent().anchorNode()->inDocument())
138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        // Sanity check: Make sure our moveParagraph calls didn't remove endOfNextParagraph.deepEquivalent().deprecatedNode()
140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // If somehow we did, return to prevent crashes.
14181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (endOfNextParagraph.isNotNull() && !endOfNextParagraph.deepEquivalent().anchorNode()->inDocument()) {
142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT_NOT_REACHED();
143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return;
144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        endOfCurrentParagraph = endOfNextParagraph;
146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic bool isNewLineAtPosition(const Position& position)
150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (position.anchorType() != Position::PositionIsOffsetInAnchor)
152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
153a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
154a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Node* textNode = position.containerNode();
155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int offset = position.offsetInContainerNode();
156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!textNode || !textNode->isTextNode() || offset < 0 || offset >= textNode->maxCharacterOffset())
157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ExceptionCode ec = 0;
160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    String textAtPosition = static_cast<Text*>(textNode)->substringData(offset, 1, ec);
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (ec)
162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return textAtPosition[0] == '\n';
165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic RenderStyle* renderStyleOfEnclosingTextNode(const Position& position)
168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (position.anchorType() != Position::PositionIsOffsetInAnchor
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        || !position.containerNode()
171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        || !position.containerNode()->isTextNode()
172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        || !position.containerNode()->renderer())
173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return 0;
174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return position.containerNode()->renderer()->style();
175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded(const VisiblePosition& endOfCurrentParagraph, Position& start, Position& end)
178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    start = startOfParagraph(endOfCurrentParagraph).deepEquivalent();
180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    end = endOfCurrentParagraph.deepEquivalent();
181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* startStyle = renderStyleOfEnclosingTextNode(start);
183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    bool isStartAndEndOnSameNode = false;
184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startStyle) {
18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        isStartAndEndOnSameNode = renderStyleOfEnclosingTextNode(end) && start.deprecatedNode() == end.deprecatedNode();
18681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        bool isStartAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && start.deprecatedNode() == m_endOfLastParagraph.deprecatedNode();
187f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Avoid obtanining the start of next paragraph for start
189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (startStyle->preserveNewline() && isNewLineAtPosition(start) && !isNewLineAtPosition(start.previous()) && start.offsetInContainerNode() > 0)
190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            start = startOfParagraph(end.previous()).deepEquivalent();
191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // If start is in the middle of a text node, split.
193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!startStyle->collapseWhiteSpace() && start.offsetInContainerNode() > 0) {
194a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            int startOffset = start.offsetInContainerNode();
19581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            splitTextNode(static_cast<Text*>(start.deprecatedNode()), startOffset);
1962bde8e466a4451c7319e3a072d118917957d6554Steve Block            start = firstPositionInOrBeforeNode(start.deprecatedNode());
197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (isStartAndEndOnSameNode) {
198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                ASSERT(end.offsetInContainerNode() >= startOffset);
19981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                end = Position(end.deprecatedNode(), end.offsetInContainerNode() - startOffset, Position::PositionIsOffsetInAnchor);
200a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (isStartAndEndOfLastParagraphOnSameNode) {
202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                ASSERT(m_endOfLastParagraph.offsetInContainerNode() >= startOffset);
20381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                m_endOfLastParagraph = Position(m_endOfLastParagraph.deprecatedNode(), m_endOfLastParagraph.offsetInContainerNode() - startOffset,
204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                    Position::PositionIsOffsetInAnchor);
205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            }
206a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
208a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
209a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* endStyle = renderStyleOfEnclosingTextNode(end);
210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (endStyle) {
21181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        bool isEndAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && end.deprecatedNode() == m_endOfLastParagraph.deprecatedNode();
212a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Include \n at the end of line if we're at an empty paragraph
213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (endStyle->preserveNewline() && start == end
214a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) {
215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            int endOffset = end.offsetInContainerNode();
216a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!isNewLineAtPosition(end.previous()) && isNewLineAtPosition(end))
21781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                end = Position(end.deprecatedNode(), endOffset + 1, Position::PositionIsOffsetInAnchor);
218f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (isEndAndEndOfLastParagraphOnSameNode && end.offsetInContainerNode() >= m_endOfLastParagraph.offsetInContainerNode())
219f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                m_endOfLastParagraph = end;
220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
222a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // If end is in the middle of a text node, split.
223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!endStyle->collapseWhiteSpace() && end.offsetInContainerNode()
224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) {
22581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            splitTextNode(static_cast<Text*>(end.deprecatedNode()), end.offsetInContainerNode());
226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (isStartAndEndOnSameNode)
2272bde8e466a4451c7319e3a072d118917957d6554Steve Block                start = firstPositionInOrBeforeNode(end.deprecatedNode()->previousSibling());
228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (isEndAndEndOfLastParagraphOnSameNode) {
229f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                if (m_endOfLastParagraph.offsetInContainerNode() == end.offsetInContainerNode())
23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    m_endOfLastParagraph = lastPositionInNode(end.deprecatedNode()->previousSibling());
231f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                else
23281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    m_endOfLastParagraph = Position(end.deprecatedNode(), m_endOfLastParagraph.offsetInContainerNode() - end.offsetInContainerNode(),
233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                                                    Position::PositionIsOffsetInAnchor);
234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            }
23581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            end = lastPositionInNode(end.deprecatedNode()->previousSibling());
236a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
237a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
238a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
240a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochVisiblePosition ApplyBlockElementCommand::endOfNextParagrahSplittingTextNodesIfNeeded(VisiblePosition& endOfCurrentParagraph, Position& start, Position& end)
241a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
242a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    VisiblePosition endOfNextParagraph = endOfParagraph(endOfCurrentParagraph.next());
243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Position position = endOfNextParagraph.deepEquivalent();
244a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* style = renderStyleOfEnclosingTextNode(position);
245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!style)
246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return endOfNextParagraph;
247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
248a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<Node> containerNode = position.containerNode();
249a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!style->preserveNewline() || !position.offsetInContainerNode()
250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        || !isNewLineAtPosition(Position(containerNode.get(), 0, Position::PositionIsOffsetInAnchor)))
251a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return endOfNextParagraph;
252a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
253a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // \n at the beginning of the text node immediately following the current paragraph is trimmed by moveParagraphWithClones.
254a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // If endOfNextParagraph was pointing at this same text node, endOfNextParagraph will be shifted by one paragraph.
255a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Avoid this by splitting "\n"
256a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    splitTextNode(static_cast<Text*>(containerNode.get()), 1);
257a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
258a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (start.anchorType() == Position::PositionIsOffsetInAnchor && containerNode.get() == start.containerNode()) {
259a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(start.offsetInContainerNode() < position.offsetInContainerNode());
260a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        start = Position(containerNode->previousSibling(), start.offsetInContainerNode(), Position::PositionIsOffsetInAnchor);
261a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
262a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (end.anchorType() == Position::PositionIsOffsetInAnchor && containerNode.get() == end.containerNode()) {
263a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(end.offsetInContainerNode() < position.offsetInContainerNode());
264a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        end = Position(containerNode->previousSibling(), end.offsetInContainerNode(), Position::PositionIsOffsetInAnchor);
265a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (m_endOfLastParagraph.anchorType() == Position::PositionIsOffsetInAnchor && containerNode.get() == m_endOfLastParagraph.containerNode()) {
267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (m_endOfLastParagraph.offsetInContainerNode() < position.offsetInContainerNode())
268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            m_endOfLastParagraph = Position(containerNode->previousSibling(), m_endOfLastParagraph.offsetInContainerNode(), Position::PositionIsOffsetInAnchor);
269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        else
270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            m_endOfLastParagraph = Position(containerNode, m_endOfLastParagraph.offsetInContainerNode() - 1, Position::PositionIsOffsetInAnchor);
271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
272a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
273a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return Position(containerNode.get(), position.offsetInContainerNode() - 1, Position::PositionIsOffsetInAnchor);
274a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
275a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
276a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochPassRefPtr<Element> ApplyBlockElementCommand::createBlockElement() const
277a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
278a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<Element> element = createHTMLElement(document(), m_tagName);
279a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (m_className.length())
280a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        element->setAttribute(classAttr, m_className);
281a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (m_inlineStyle.length())
282a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        element->setAttribute(styleAttr, m_inlineStyle);
283a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return element.release();
284a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
285a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
286a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
287