summaryrefslogtreecommitdiff
path: root/Source/WebCore/editing/InsertListCommand.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/editing/InsertListCommand.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/editing/InsertListCommand.cpp')
-rw-r--r--Source/WebCore/editing/InsertListCommand.cpp109
1 files changed, 58 insertions, 51 deletions
diff --git a/Source/WebCore/editing/InsertListCommand.cpp b/Source/WebCore/editing/InsertListCommand.cpp
index d3ead9780..894a7cffc 100644
--- a/Source/WebCore/editing/InsertListCommand.cpp
+++ b/Source/WebCore/editing/InsertListCommand.cpp
@@ -10,10 +10,10 @@
* 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
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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
@@ -24,15 +24,16 @@
*/
#include "config.h"
-#include "Element.h"
-#include "ElementTraversal.h"
#include "InsertListCommand.h"
-#include "ExceptionCodePlaceholder.h"
-#include "htmlediting.h"
-#include "HTMLElement.h"
+
+#include "ElementTraversal.h"
+#include "HTMLBRElement.h"
+#include "HTMLLIElement.h"
#include "HTMLNames.h"
-#include "TextIterator.h"
+#include "HTMLUListElement.h"
+#include "Range.h"
#include "VisibleUnits.h"
+#include "htmlediting.h"
namespace WebCore {
@@ -46,7 +47,7 @@ static Node* enclosingListChild(Node* node, Node* listNode)
return listChild;
}
-PassRefPtr<HTMLElement> InsertListCommand::insertList(Document& document, Type type)
+RefPtr<HTMLElement> InsertListCommand::insertList(Document& document, Type type)
{
RefPtr<InsertListCommand> insertCommand = create(document, type);
insertCommand->apply();
@@ -55,15 +56,15 @@ PassRefPtr<HTMLElement> InsertListCommand::insertList(Document& document, Type t
HTMLElement* InsertListCommand::fixOrphanedListChild(Node* node)
{
- RefPtr<HTMLElement> listElement = createUnorderedListElement(document());
- insertNodeBefore(listElement, node);
+ auto listElement = HTMLUListElement::create(document());
+ insertNodeBefore(listElement.copyRef(), node);
removeNode(node);
- appendNode(node, listElement);
- m_listElement = listElement;
- return listElement.get();
+ appendNode(node, listElement.copyRef());
+ m_listElement = listElement.copyRef();
+ return listElement.ptr();
}
-PassRefPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtr<HTMLElement> passedList)
+RefPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtr<HTMLElement> passedList)
{
RefPtr<HTMLElement> list = passedList;
Element* previousList = list->previousElementSibling();
@@ -71,17 +72,17 @@ PassRefPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists(PassRefPtr<
mergeIdenticalElements(previousList, list);
if (!list)
- return 0;
- Element* sibling = ElementTraversal::nextSibling(list.get());
- if (!sibling || !sibling->isHTMLElement())
- return list.release();
+ return nullptr;
+ Element* sibling = ElementTraversal::nextSibling(*list);
+ if (!is<HTMLElement>(sibling))
+ return list;
- RefPtr<HTMLElement> nextList = toHTMLElement(sibling);
+ RefPtr<HTMLElement> nextList = downcast<HTMLElement>(sibling);
if (canMergeLists(list.get(), nextList.get())) {
mergeIdenticalElements(list, nextList);
- return nextList.release();
+ return nextList;
}
- return list.release();
+ return list;
}
bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection, const QualifiedName& listTag)
@@ -110,12 +111,9 @@ InsertListCommand::InsertListCommand(Document& document, Type type)
void InsertListCommand::doApply()
{
- if (!endingSelection().isNonOrphanedCaretOrRange())
+ if (endingSelection().isNoneOrOrphaned() || !endingSelection().isContentRichlyEditable())
return;
- if (!endingSelection().rootEditableElement())
- return;
-
VisiblePosition visibleEnd = endingSelection().visibleEnd();
VisiblePosition visibleStart = endingSelection().visibleStart();
// When a selection ends at the start of a paragraph, we rarely paint
@@ -126,10 +124,13 @@ void InsertListCommand::doApply()
// FIXME: We paint the gap before some paragraphs that are indented with left
// margin/padding, but not others. We should make the gap painting more consistent and
// then use a left margin/padding rule here.
- if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd, CanSkipOverEditingBoundary))
+ if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd, CanSkipOverEditingBoundary)) {
setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary), endingSelection().isDirectional()));
+ if (!endingSelection().rootEditableElement())
+ return;
+ }
- const QualifiedName& listTag = (m_type == OrderedList) ? olTag : ulTag;
+ auto& listTag = (m_type == OrderedList) ? olTag : ulTag;
if (endingSelection().isRange()) {
VisibleSelection selection = selectionForParagraphIteration(endingSelection());
ASSERT(selection.isRange());
@@ -148,7 +149,7 @@ void InsertListCommand::doApply()
// infinite loop and because there is no more work to be done.
// FIXME(<rdar://problem/5983974>): The endingSelection() may be incorrect here. Compute
// the new location of endOfSelection and use it as the end of the new selection.
- if (!startOfLastParagraph.deepEquivalent().anchorNode()->inDocument())
+ if (!startOfLastParagraph.deepEquivalent().anchorNode()->isConnected())
return;
setEndingSelection(startOfCurrentParagraph);
@@ -191,7 +192,12 @@ void InsertListCommand::doApply()
doApplyForSingleParagraph(false, listTag, endingSelection().firstRange().get());
}
-void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const QualifiedName& listTag, Range* currentSelection)
+EditAction InsertListCommand::editingAction() const
+{
+ return m_type == OrderedList ? EditActionInsertOrderedList : EditActionInsertUnorderedList;
+}
+
+void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HTMLQualifiedName& listTag, Range* currentSelection)
{
// FIXME: This will produce unexpected results for a selection that starts just before a
// table and ends inside the first cell, selectionForParagraphIteration should probably
@@ -206,31 +212,32 @@ void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const Qu
listNode = fixOrphanedListChild(listChildNode);
listNode = mergeWithNeighboringLists(listNode);
}
- if (!listNode->hasTagName(listTag))
+ if (!listNode->hasTagName(listTag)) {
// listChildNode will be removed from the list and a list of type m_type will be created.
switchListType = true;
+ }
// If the list is of the desired type, and we are not removing the list, then exit early.
if (!switchListType && forceCreateList)
return;
// If the entire list is selected, then convert the whole list.
- if (switchListType && isNodeVisiblyContainedWithin(listNode.get(), currentSelection)) {
- bool rangeStartIsInList = visiblePositionBeforeNode(listNode.get()) == currentSelection->startPosition();
- bool rangeEndIsInList = visiblePositionAfterNode(listNode.get()) == currentSelection->endPosition();
+ if (switchListType && isNodeVisiblyContainedWithin(*listNode, *currentSelection)) {
+ bool rangeStartIsInList = visiblePositionBeforeNode(*listNode) == currentSelection->startPosition();
+ bool rangeEndIsInList = visiblePositionAfterNode(*listNode) == currentSelection->endPosition();
RefPtr<HTMLElement> newList = createHTMLElement(document(), listTag);
insertNodeBefore(newList, listNode);
- Node* firstChildInList = enclosingListChild(VisiblePosition(firstPositionInNode(listNode.get())).deepEquivalent().deprecatedNode(), listNode.get());
- Node* outerBlock = isBlockFlowElement(firstChildInList) ? firstChildInList : listNode.get();
+ auto* firstChildInList = enclosingListChild(VisiblePosition(firstPositionInNode(listNode.get())).deepEquivalent().deprecatedNode(), listNode.get());
+ Node* outerBlock = firstChildInList && isBlockFlowElement(*firstChildInList) ? firstChildInList : listNode.get();
moveParagraphWithClones(firstPositionInNode(listNode.get()), lastPositionInNode(listNode.get()), newList.get(), outerBlock);
// Manually remove listNode because moveParagraphWithClones sometimes leaves it behind in the document.
// See the bug 33668 and editing/execCommand/insert-list-orphaned-item-with-nested-lists.html.
// FIXME: This might be a bug in moveParagraphWithClones or deleteSelection.
- if (listNode && listNode->inDocument())
+ if (listNode && listNode->isConnected())
removeNode(listNode);
newList = mergeWithNeighboringLists(newList);
@@ -238,9 +245,9 @@ void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const Qu
// Restore the start and the end of current selection if they started inside listNode
// because moveParagraphWithClones could have removed them.
if (rangeStartIsInList && newList)
- currentSelection->setStart(newList, 0, IGNORE_EXCEPTION);
+ currentSelection->setStart(*newList, 0);
if (rangeEndIsInList && newList)
- currentSelection->setEnd(newList, lastOffsetInNode(newList.get()), IGNORE_EXCEPTION);
+ currentSelection->setEnd(*newList, lastOffsetInNode(newList.get()));
setEndingSelection(VisiblePosition(firstPositionInNode(newList.get())));
@@ -276,12 +283,12 @@ void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart,
}
// When removing a list, we must always create a placeholder to act as a point of insertion
// for the list content being removed.
- RefPtr<Element> placeholder = createBreakElement(document());
+ RefPtr<Element> placeholder = HTMLBRElement::create(document());
RefPtr<Element> nodeToInsert = placeholder;
// If the content of the list item will be moved into another list, put it in a list item
// so that we don't create an orphaned list child.
if (enclosingList(listNode)) {
- nodeToInsert = createListItemElement(document());
+ nodeToInsert = HTMLLIElement::create(document());
appendNode(placeholder, nodeToInsert);
}
@@ -329,7 +336,7 @@ static Element* adjacentEnclosingList(const VisiblePosition& pos, const VisibleP
return listNode;
}
-PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePosition& originalStart, const QualifiedName& listTag)
+RefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePosition& originalStart, const QualifiedName& listTag)
{
VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBoundary);
VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary);
@@ -338,29 +345,29 @@ PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePositio
return 0;
// Check for adjoining lists.
- RefPtr<HTMLElement> listItemElement = createListItemElement(document());
- RefPtr<HTMLElement> placeholder = createBreakElement(document());
- appendNode(placeholder, listItemElement);
+ auto listItemElement = HTMLLIElement::create(document());
+ auto placeholder = HTMLBRElement::create(document());
+ appendNode(placeholder.copyRef(), listItemElement.copyRef());
// Place list item into adjoining lists.
Element* previousList = adjacentEnclosingList(start.deepEquivalent(), start.previous(CannotCrossEditingBoundary), listTag);
Element* nextList = adjacentEnclosingList(start.deepEquivalent(), end.next(CannotCrossEditingBoundary), listTag);
RefPtr<HTMLElement> listElement;
if (previousList)
- appendNode(listItemElement, previousList);
+ appendNode(WTFMove(listItemElement), previousList);
else if (nextList)
- insertNodeAt(listItemElement, positionBeforeNode(nextList));
+ insertNodeAt(WTFMove(listItemElement), positionBeforeNode(nextList));
else {
// Create the list.
listElement = createHTMLElement(document(), listTag);
- appendNode(listItemElement, listElement);
+ appendNode(WTFMove(listItemElement), listElement);
if (start == end && isBlock(start.deepEquivalent().deprecatedNode())) {
// Inserting the list into an empty paragraph that isn't held open
// by a br or a '\n', will invalidate start and end. Insert
// a placeholder and then recompute start and end.
- RefPtr<Node> placeholder = insertBlockPlaceholder(start.deepEquivalent());
- start = positionBeforeNode(placeholder.get());
+ auto blockPlaceholder = insertBlockPlaceholder(start.deepEquivalent());
+ start = positionBeforeNode(blockPlaceholder.get());
end = start;
}
@@ -388,7 +395,7 @@ PassRefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePositio
}
}
- moveParagraph(start, end, positionBeforeNode(placeholder.get()), true);
+ moveParagraph(start, end, positionBeforeNode(placeholder.ptr()), true);
if (listElement)
return mergeWithNeighboringLists(listElement);