15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/ApplyBlockElementCommand.h" 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h" 311fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "bindings/v8/ExceptionState.h" 328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include "core/dom/NodeRenderStyle.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Text.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisiblePosition.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisibleUnits.h" 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/htmlediting.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderObject.h" 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/RenderStyle.h" 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames; 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 458abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)ApplyBlockElementCommand::ApplyBlockElementCommand(Document& document, const QualifiedName& tagName, const AtomicString& inlineStyle) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : CompositeEditCommand(document) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_tagName(tagName) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_inlineStyle(inlineStyle) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 528abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)ApplyBlockElementCommand::ApplyBlockElementCommand(Document& document, const QualifiedName& tagName) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : CompositeEditCommand(document) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_tagName(tagName) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ApplyBlockElementCommand::doApply() 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!endingSelection().rootEditableElement()) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition visibleEnd = endingSelection().visibleEnd(); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition visibleStart = endingSelection().visibleStart(); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull() || visibleEnd.isOrphan()) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // When a selection ends at the start of a paragraph, we rarely paint 6902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // the selection gap before that paragraph, because there often is no gap. 7002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // In a case like this, it's not obvious to the user that the selection 7102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // ends "inside" that paragraph, so it would be confusing if Indent/Outdent 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // operated on that paragraph. 7302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // FIXME: We paint the gap before some paragraphs that are indented with left 7402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // margin/padding, but not others. We should make the gap painting more consistent and 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // then use a left margin/padding rule here. 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd)) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary), endingSelection().isDirectional())); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisibleSelection selection = selectionForParagraphIteration(endingSelection()); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition startOfSelection = selection.visibleStart(); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition endOfSelection = selection.visibleEnd(); 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!startOfSelection.isNull()); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!endOfSelection.isNull()); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<ContainerNode> startScope; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startIndex = indexForVisiblePosition(startOfSelection, startScope); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<ContainerNode> endScope; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int endIndex = indexForVisiblePosition(endOfSelection, endScope); 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) formatSelection(startOfSelection, endOfSelection); 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 918abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document().updateLayoutIgnorePendingStylesheets(); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(startScope == endScope); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(startIndex >= 0); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(startIndex <= endIndex); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (startScope == endScope && startIndex >= 0 && startIndex <= endIndex) { 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition start(visiblePositionForIndex(startIndex, startScope.get())); 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition end(visiblePositionForIndex(endIndex, endScope.get())); 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (start.isNotNull() && end.isNotNull()) 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(start, end, endingSelection().isDirectional())); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ApplyBlockElementCommand::formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Special case empty unsplittable elements because there's nothing to split 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and there's nothing to move. 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position start = startOfSelection.deepEquivalent().downstream(); 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isAtUnsplittableElement(start)) { 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Element> blockquote = createBlockElement(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) insertNodeAt(blockquote, start); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Element> placeholder = createBreakElement(document()); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendNode(placeholder, blockquote); 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setEndingSelection(VisibleSelection(positionBeforeNode(placeholder.get()), DOWNSTREAM, endingSelection().isDirectional())); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Element> blockquoteForNextIndent; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection); 120a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) VisiblePosition endOfLastParagraph = endOfParagraph(endOfSelection); 121a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) VisiblePosition endAfterSelection = endOfParagraph(endOfLastParagraph.next()); 122a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_endOfLastParagraph = endOfLastParagraph.deepEquivalent(); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool atEnd = false; 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position end; 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (endOfCurrentParagraph != endAfterSelection && !atEnd) { 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (endOfCurrentParagraph.deepEquivalent() == m_endOfLastParagraph) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) atEnd = true; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rangeForParagraphSplittingTextNodesIfNeeded(endOfCurrentParagraph, start, end); 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) endOfCurrentParagraph = end; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* enclosingCell = enclosingNodeOfType(start, &isTableCell); 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition endOfNextParagraph = endOfNextParagrahSplittingTextNodesIfNeeded(endOfCurrentParagraph, start, end); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) formatRange(start, end, m_endOfLastParagraph, blockquoteForNextIndent); 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 13802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch // Don't put the next paragraph in the blockquote we just created for this paragraph unless 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // the next paragraph is in the same cell. 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (enclosingCell && enclosingCell != enclosingNodeOfType(endOfNextParagraph.deepEquivalent(), &isTableCell)) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) blockquoteForNextIndent = 0; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // indentIntoBlockquote could move more than one paragraph if the paragraph 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // is in a list item or a table. As a result, endAfterSelection could refer to a position 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // no longer in the document. 1468abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (endAfterSelection.isNotNull() && !endAfterSelection.deepEquivalent().inDocument()) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Sanity check: Make sure our moveParagraph calls didn't remove endOfNextParagraph.deepEquivalent().deprecatedNode() 1491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // If somehow, e.g. mutation event handler, we did, return to prevent crashes. 1501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) if (endOfNextParagraph.isNotNull() && !endOfNextParagraph.deepEquivalent().inDocument()) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) endOfCurrentParagraph = endOfNextParagraph; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isNewLineAtPosition(const Position& position) 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* textNode = position.containerNode(); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int offset = position.offsetInContainerNode(); 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!textNode || !textNode->isTextNode() || offset < 0 || offset >= textNode->maxCharacterOffset()) 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) TrackExceptionState exceptionState; 16451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) String textAtPosition = toText(textNode)->substringData(offset, 1, exceptionState); 16551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) if (exceptionState.hadException()) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return textAtPosition[0] == '\n'; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static RenderStyle* renderStyleOfEnclosingTextNode(const Position& position) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1738abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) if (position.anchorType() != Position::PositionIsOffsetInAnchor || !position.containerNode() || !position.containerNode()->isTextNode()) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 1758abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) return position.containerNode()->renderStyle(); 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded(const VisiblePosition& endOfCurrentParagraph, Position& start, Position& end) 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start = startOfParagraph(endOfCurrentParagraph).deepEquivalent(); 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = endOfCurrentParagraph.deepEquivalent(); 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1838abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document().updateStyleIfNeeded(); 1848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isStartAndEndOnSameNode = false; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (RenderStyle* startStyle = renderStyleOfEnclosingTextNode(start)) { 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) isStartAndEndOnSameNode = renderStyleOfEnclosingTextNode(end) && start.containerNode() == end.containerNode(); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isStartAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && start.containerNode() == m_endOfLastParagraph.containerNode(); 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Avoid obtanining the start of next paragraph for start 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (startStyle->preserveNewline() && isNewLineAtPosition(start) && !isNewLineAtPosition(start.previous()) && start.offsetInContainerNode() > 0) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start = startOfParagraph(end.previous()).deepEquivalent(); 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If start is in the middle of a text node, split. 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!startStyle->collapseWhiteSpace() && start.offsetInContainerNode() > 0) { 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startOffset = start.offsetInContainerNode(); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Text* startText = start.containerText(); 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) splitTextNode(startText, startOffset); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start = firstPositionInNode(startText); 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isStartAndEndOnSameNode) { 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(end.offsetInContainerNode() >= startOffset); 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = Position(startText, end.offsetInContainerNode() - startOffset); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isStartAndEndOfLastParagraphOnSameNode) { 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_endOfLastParagraph.offsetInContainerNode() >= startOffset); 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = Position(startText, m_endOfLastParagraph.offsetInContainerNode() - startOffset); 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2118abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) document().updateStyleIfNeeded(); 2128abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (RenderStyle* endStyle = renderStyleOfEnclosingTextNode(end)) { 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool isEndAndEndOfLastParagraphOnSameNode = renderStyleOfEnclosingTextNode(m_endOfLastParagraph) && end.deprecatedNode() == m_endOfLastParagraph.deprecatedNode(); 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Include \n at the end of line if we're at an empty paragraph 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (endStyle->preserveNewline() && start == end && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) { 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int endOffset = end.offsetInContainerNode(); 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isNewLineAtPosition(end.previous()) && isNewLineAtPosition(end)) 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = Position(end.containerText(), endOffset + 1); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isEndAndEndOfLastParagraphOnSameNode && end.offsetInContainerNode() >= m_endOfLastParagraph.offsetInContainerNode()) 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = end; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If end is in the middle of a text node, split. 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!endStyle->collapseWhiteSpace() && end.offsetInContainerNode() && end.offsetInContainerNode() < end.containerNode()->maxCharacterOffset()) { 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Text> endContainer = end.containerText(); 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) splitTextNode(endContainer, end.offsetInContainerNode()); 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isStartAndEndOnSameNode) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start = firstPositionInOrBeforeNode(endContainer->previousSibling()); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isEndAndEndOfLastParagraphOnSameNode) { 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_endOfLastParagraph.offsetInContainerNode() == end.offsetInContainerNode()) 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = lastPositionInOrAfterNode(endContainer->previousSibling()); 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = Position(endContainer, m_endOfLastParagraph.offsetInContainerNode() - end.offsetInContainerNode()); 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = lastPositionInNode(endContainer->previousSibling()); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)VisiblePosition ApplyBlockElementCommand::endOfNextParagrahSplittingTextNodesIfNeeded(VisiblePosition& endOfCurrentParagraph, Position& start, Position& end) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VisiblePosition endOfNextParagraph = endOfParagraph(endOfCurrentParagraph.next()); 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Position position = endOfNextParagraph.deepEquivalent(); 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderStyle* style = renderStyleOfEnclosingTextNode(position); 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style) 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return endOfNextParagraph; 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Text> text = position.containerText(); 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!style->preserveNewline() || !position.offsetInContainerNode() || !isNewLineAtPosition(firstPositionInNode(text.get()))) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return endOfNextParagraph; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // \n at the beginning of the text node immediately following the current paragraph is trimmed by moveParagraphWithClones. 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If endOfNextParagraph was pointing at this same text node, endOfNextParagraph will be shifted by one paragraph. 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Avoid this by splitting "\n" 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) splitTextNode(text, 1); 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text == start.containerNode() && text->previousSibling() && text->previousSibling()->isTextNode()) { 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(start.offsetInContainerNode() < position.offsetInContainerNode()); 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) start = Position(toText(text->previousSibling()), start.offsetInContainerNode()); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text == end.containerNode() && text->previousSibling() && text->previousSibling()->isTextNode()) { 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(end.offsetInContainerNode() < position.offsetInContainerNode()); 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) end = Position(toText(text->previousSibling()), end.offsetInContainerNode()); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text == m_endOfLastParagraph.containerNode()) { 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_endOfLastParagraph.offsetInContainerNode() < position.offsetInContainerNode()) { 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We can only fix endOfLastParagraph if the previous node was still text and hasn't been modified by script. 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (text->previousSibling()->isTextNode() 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) && static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) <= toText(text->previousSibling())->length()) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = Position(toText(text->previousSibling()), m_endOfLastParagraph.offsetInContainerNode()); 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_endOfLastParagraph = Position(text.get(), m_endOfLastParagraph.offsetInContainerNode() - 1); 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Position(text.get(), position.offsetInContainerNode() - 1); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<Element> ApplyBlockElementCommand::createBlockElement() const 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Element> element = createHTMLElement(document(), m_tagName); 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_inlineStyle.length()) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) element->setAttribute(styleAttr, m_inlineStyle); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return element.release(); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 288