Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Unified Diff: Source/core/editing/InsertTextCommand.cpp

Issue 1294543005: Move execCommand related files in core/editing/ related files into core/editing/commands/ (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: 2015-08-18T14:20:58 Rebase for merging code style fixes Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/editing/InsertTextCommand.cpp
diff --git a/Source/core/editing/InsertTextCommand.cpp b/Source/core/editing/InsertTextCommand.cpp
deleted file mode 100644
index a62339f3af83b25f33b8bf6ca150f2ec31de6881..0000000000000000000000000000000000000000
--- a/Source/core/editing/InsertTextCommand.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "core/editing/InsertTextCommand.h"
-
-#include "core/dom/Document.h"
-#include "core/dom/Element.h"
-#include "core/dom/Text.h"
-#include "core/editing/EditingUtilities.h"
-#include "core/editing/Editor.h"
-#include "core/editing/VisibleUnits.h"
-#include "core/frame/LocalFrame.h"
-#include "core/html/HTMLSpanElement.h"
-
-namespace blink {
-
-InsertTextCommand::InsertTextCommand(Document& document, const String& text, bool selectInsertedText, RebalanceType rebalanceType)
- : CompositeEditCommand(document)
- , m_text(text)
- , m_selectInsertedText(selectInsertedText)
- , m_rebalanceType(rebalanceType)
-{
-}
-
-Position InsertTextCommand::positionInsideTextNode(const Position& p)
-{
- Position pos = p;
- if (isTabHTMLSpanElementTextNode(pos.anchorNode())) {
- RefPtrWillBeRawPtr<Text> textNode = document().createEditingTextNode("");
- insertNodeAtTabSpanPosition(textNode.get(), pos);
- return firstPositionInNode(textNode.get());
- }
-
- // Prepare for text input by looking at the specified position.
- // It may be necessary to insert a text node to receive characters.
- if (!pos.computeContainerNode()->isTextNode()) {
- RefPtrWillBeRawPtr<Text> textNode = document().createEditingTextNode("");
- insertNodeAt(textNode.get(), pos);
- return firstPositionInNode(textNode.get());
- }
-
- return pos;
-}
-
-void InsertTextCommand::setEndingSelectionWithoutValidation(const Position& startPosition, const Position& endPosition)
-{
- // We could have inserted a part of composed character sequence,
- // so we are basically treating ending selection as a range to avoid validation.
- // <http://bugs.webkit.org/show_bug.cgi?id=15781>
- VisibleSelection forcedEndingSelection;
- forcedEndingSelection.setWithoutValidation(startPosition, endPosition);
- forcedEndingSelection.setIsDirectional(endingSelection().isDirectional());
- setEndingSelection(forcedEndingSelection);
-}
-
-// This avoids the expense of a full fledged delete operation, and avoids a layout that typically results
-// from text removal.
-bool InsertTextCommand::performTrivialReplace(const String& text, bool selectInsertedText)
-{
- if (!endingSelection().isRange())
- return false;
-
- if (text.contains('\t') || text.contains(' ') || text.contains('\n'))
- return false;
-
- Position start = endingSelection().start();
- Position endPosition = replaceSelectedTextInNode(text);
- if (endPosition.isNull())
- return false;
-
- setEndingSelectionWithoutValidation(start, endPosition);
- if (!selectInsertedText)
- setEndingSelection(VisibleSelection(endingSelection().visibleEnd(), endingSelection().isDirectional()));
-
- return true;
-}
-
-bool InsertTextCommand::performOverwrite(const String& text, bool selectInsertedText)
-{
- Position start = endingSelection().start();
- if (start.isNull() || !start.isOffsetInAnchor() || !start.computeContainerNode()->isTextNode())
- return false;
- RefPtrWillBeRawPtr<Text> textNode = toText(start.computeContainerNode());
- if (!textNode)
- return false;
-
- unsigned count = std::min(text.length(), textNode->length() - start.offsetInContainerNode());
- if (!count)
- return false;
-
- replaceTextInNode(textNode, start.offsetInContainerNode(), count, text);
-
- Position endPosition = Position(textNode.release(), start.offsetInContainerNode() + text.length());
- setEndingSelectionWithoutValidation(start, endPosition);
- if (!selectInsertedText)
- setEndingSelection(VisibleSelection(endingSelection().visibleEnd(), endingSelection().isDirectional()));
-
- return true;
-}
-
-void InsertTextCommand::doApply()
-{
- ASSERT(m_text.find('\n') == kNotFound);
-
- if (!endingSelection().isNonOrphanedCaretOrRange())
- return;
-
- // Delete the current selection.
- // FIXME: This delete operation blows away the typing style.
- if (endingSelection().isRange()) {
- if (performTrivialReplace(m_text, m_selectInsertedText))
- return;
- bool endOfSelectionWasAtStartOfBlock = isStartOfBlock(endingSelection().visibleEnd());
- deleteSelection(false, true, false, false);
- // deleteSelection eventually makes a new endingSelection out of a Position. If that Position doesn't have
- // a layoutObject (e.g. it is on a <frameset> in the DOM), the VisibleSelection cannot be canonicalized to
- // anything other than NoSelection. The rest of this function requires a real endingSelection, so bail out.
- if (endingSelection().isNone())
- return;
- if (endOfSelectionWasAtStartOfBlock) {
- if (EditingStyle* typingStyle = document().frame()->selection().typingStyle())
- typingStyle->removeBlockProperties();
- }
- } else if (document().frame()->editor().isOverwriteModeEnabled()) {
- if (performOverwrite(m_text, m_selectInsertedText))
- return;
- }
-
- Position startPosition(endingSelection().start());
-
- Position placeholder;
- // We want to remove preserved newlines and brs that will collapse (and thus become unnecessary) when content
- // is inserted just before them.
- // FIXME: We shouldn't really have to do this, but removing placeholders is a workaround for 9661.
- // If the caret is just before a placeholder, downstream will normalize the caret to it.
- Position downstream(startPosition.downstream());
- if (lineBreakExistsAtPosition(downstream)) {
- // FIXME: This doesn't handle placeholders at the end of anonymous blocks.
- VisiblePosition caret(startPosition);
- if (isEndOfBlock(caret) && isStartOfParagraph(caret))
- placeholder = downstream;
- // Don't remove the placeholder yet, otherwise the block we're inserting into would collapse before
- // we get a chance to insert into it. We check for a placeholder now, though, because doing so requires
- // the creation of a VisiblePosition, and if we did that post-insertion it would force a layout.
- }
-
- // Insert the character at the leftmost candidate.
- startPosition = startPosition.upstream();
-
- // It is possible for the node that contains startPosition to contain only unrendered whitespace,
- // and so deleteInsignificantText could remove it. Save the position before the node in case that happens.
- ASSERT(startPosition.computeContainerNode());
- Position positionBeforeStartNode(positionInParentBeforeNode(*startPosition.computeContainerNode()));
- deleteInsignificantText(startPosition, startPosition.downstream());
- if (!startPosition.inDocument())
- startPosition = positionBeforeStartNode;
- if (!startPosition.isCandidate())
- startPosition = startPosition.downstream();
-
- startPosition = positionAvoidingSpecialElementBoundary(startPosition);
-
- Position endPosition;
-
- if (m_text == "\t") {
- endPosition = insertTab(startPosition);
- startPosition = endPosition.previous();
- if (placeholder.isNotNull())
- removePlaceholderAt(placeholder);
- } else {
- // Make sure the document is set up to receive m_text
- startPosition = positionInsideTextNode(startPosition);
- ASSERT(startPosition.isOffsetInAnchor());
- ASSERT(startPosition.computeContainerNode());
- ASSERT(startPosition.computeContainerNode()->isTextNode());
- if (placeholder.isNotNull())
- removePlaceholderAt(placeholder);
- RefPtrWillBeRawPtr<Text> textNode = toText(startPosition.computeContainerNode());
- const unsigned offset = startPosition.offsetInContainerNode();
-
- insertTextIntoNode(textNode, offset, m_text);
- endPosition = Position(textNode, offset + m_text.length());
-
- if (m_rebalanceType == RebalanceLeadingAndTrailingWhitespaces) {
- // The insertion may require adjusting adjacent whitespace, if it is present.
- rebalanceWhitespaceAt(endPosition);
- // Rebalancing on both sides isn't necessary if we've inserted only spaces.
- if (!shouldRebalanceLeadingWhitespaceFor(m_text))
- rebalanceWhitespaceAt(startPosition);
- } else {
- ASSERT(m_rebalanceType == RebalanceAllWhitespaces);
- if (canRebalance(startPosition) && canRebalance(endPosition))
- rebalanceWhitespaceOnTextSubstring(textNode, startPosition.offsetInContainerNode(), endPosition.offsetInContainerNode());
- }
- }
-
- setEndingSelectionWithoutValidation(startPosition, endPosition);
-
- // Handle the case where there is a typing style.
- if (RefPtrWillBeRawPtr<EditingStyle> typingStyle = document().frame()->selection().typingStyle()) {
- typingStyle->prepareToApplyAt(endPosition, EditingStyle::PreserveWritingDirection);
- if (!typingStyle->isEmpty())
- applyStyle(typingStyle.get());
- }
-
- if (!m_selectInsertedText)
- setEndingSelection(VisibleSelection(endingSelection().end(), endingSelection().affinity(), endingSelection().isDirectional()));
-}
-
-Position InsertTextCommand::insertTab(const Position& pos)
-{
- Position insertPos = VisiblePosition(pos, DOWNSTREAM).deepEquivalent();
- if (insertPos.isNull())
- return pos;
-
- Node* node = insertPos.computeContainerNode();
- unsigned offset = node->isTextNode() ? insertPos.offsetInContainerNode() : 0;
-
- // keep tabs coalesced in tab span
- if (isTabHTMLSpanElementTextNode(node)) {
- RefPtrWillBeRawPtr<Text> textNode = toText(node);
- insertTextIntoNode(textNode, offset, "\t");
- return Position(textNode.release(), offset + 1);
- }
-
- // create new tab span
- RefPtrWillBeRawPtr<HTMLSpanElement> spanElement = createTabSpanElement(document());
-
- // place it
- if (!node->isTextNode()) {
- insertNodeAt(spanElement.get(), insertPos);
- } else {
- RefPtrWillBeRawPtr<Text> textNode = toText(node);
- if (offset >= textNode->length()) {
- insertNodeAfter(spanElement, textNode.release());
- } else {
- // split node to make room for the span
- // NOTE: splitTextNode uses textNode for the
- // second node in the split, so we need to
- // insert the span before it.
- if (offset > 0)
- splitTextNode(textNode, offset);
- insertNodeBefore(spanElement, textNode.release());
- }
- }
-
- // return the position following the new tab
- return lastPositionInNode(spanElement.get());
-}
-
-}

Powered by Google App Engine
This is Rietveld 408576698