| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "core/editing/VisibleUnits.h" | 37 #include "core/editing/VisibleUnits.h" |
| 38 #include "core/editing/htmlediting.h" | 38 #include "core/editing/htmlediting.h" |
| 39 #include "core/html/HTMLElement.h" | 39 #include "core/html/HTMLElement.h" |
| 40 #include "core/rendering/RenderObject.h" | 40 #include "core/rendering/RenderObject.h" |
| 41 #include <wtf/StdLibExtras.h> | 41 #include <wtf/StdLibExtras.h> |
| 42 | 42 |
| 43 namespace WebCore { | 43 namespace WebCore { |
| 44 | 44 |
| 45 using namespace HTMLNames; | 45 using namespace HTMLNames; |
| 46 | 46 |
| 47 static bool isListOrIndentBlockquote(const Node* node) | 47 static bool isListOrIndentBlockquote(const Handle<const Node>& node) |
| 48 { | 48 { |
| 49 return node && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->
hasTagName(blockquoteTag)); | 49 return node && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->
hasTagName(blockquoteTag)); |
| 50 } | 50 } |
| 51 | 51 |
| 52 IndentOutdentCommand::IndentOutdentCommand(const Handle<Document>& document, EIn
dentType typeOfAction, int marginInPixels) | 52 IndentOutdentCommand::IndentOutdentCommand(const Handle<Document>& document, EIn
dentType typeOfAction, int marginInPixels) |
| 53 : ApplyBlockElementCommand(document, blockquoteTag, "margin: 0 0 0 40px; bor
der: none; padding: 0px;") | 53 : ApplyBlockElementCommand(document, blockquoteTag, "margin: 0 0 0 40px; bor
der: none; padding: 0px;") |
| 54 , m_typeOfAction(typeOfAction) | 54 , m_typeOfAction(typeOfAction) |
| 55 , m_marginInPixels(marginInPixels) | 55 , m_marginInPixels(marginInPixels) |
| 56 { | 56 { |
| 57 } | 57 } |
| 58 | 58 |
| 59 bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const P
osition& end) | 59 bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const P
osition& end) |
| 60 { | 60 { |
| 61 // If our selection is not inside a list, bail out. | 61 // If our selection is not inside a list, bail out. |
| 62 Handle<Node> lastNodeInSelectedParagraph = start.deprecatedNode(); | 62 Handle<Node> lastNodeInSelectedParagraph = start.deprecatedNode(); |
| 63 Handle<Element> listNode = enclosingList(lastNodeInSelectedParagraph.raw()); | 63 Handle<Element> listNode = enclosingList(lastNodeInSelectedParagraph); |
| 64 if (!listNode) | 64 if (!listNode) |
| 65 return false; | 65 return false; |
| 66 | 66 |
| 67 // Find the block that we want to indent. If it's not a list item (e.g., a
div inside a list item), we bail out. | 67 // Find the block that we want to indent. If it's not a list item (e.g., a
div inside a list item), we bail out. |
| 68 Handle<Element> selectedListItem = enclosingBlock(lastNodeInSelectedParagrap
h.raw()); | 68 Handle<Element> selectedListItem = enclosingBlock(lastNodeInSelectedParagrap
h); |
| 69 | 69 |
| 70 // FIXME: we need to deal with the case where there is no li (malformed HTML
) | 70 // FIXME: we need to deal with the case where there is no li (malformed HTML
) |
| 71 if (!selectedListItem->hasTagName(liTag)) | 71 if (!selectedListItem->hasTagName(liTag)) |
| 72 return false; | 72 return false; |
| 73 | 73 |
| 74 // FIXME: previousElementSibling does not ignore non-rendered content like <
span></span>. Should we? | 74 // FIXME: previousElementSibling does not ignore non-rendered content like <
span></span>. Should we? |
| 75 Handle<Element> previousList = selectedListItem->previousElementSibling(); | 75 Handle<Element> previousList = selectedListItem->previousElementSibling(); |
| 76 Handle<Element> nextList = selectedListItem->nextElementSibling(); | 76 Handle<Element> nextList = selectedListItem->nextElementSibling(); |
| 77 | 77 |
| 78 Handle<Element> newList = document()->createElement(listNode->tagQName(), fa
lse); | 78 Handle<Element> newList = document()->createElement(listNode->tagQName(), fa
lse); |
| 79 insertNodeBefore(newList, selectedListItem); | 79 insertNodeBefore(newList, selectedListItem); |
| 80 | 80 |
| 81 moveParagraphWithClones(start, end, newList, selectedListItem); | 81 moveParagraphWithClones(start, end, newList, selectedListItem); |
| 82 | 82 |
| 83 if (canMergeLists(previousList, newList)) | 83 if (canMergeLists(previousList, newList)) |
| 84 mergeIdenticalElements(previousList, newList); | 84 mergeIdenticalElements(previousList, newList); |
| 85 if (canMergeLists(newList, nextList)) | 85 if (canMergeLists(newList, nextList)) |
| 86 mergeIdenticalElements(newList, nextList); | 86 mergeIdenticalElements(newList, nextList); |
| 87 | 87 |
| 88 return true; | 88 return true; |
| 89 } | 89 } |
| 90 | 90 |
| 91 void IndentOutdentCommand::indentIntoBlockquote(const Position& start, const Pos
ition& end, Handle<Element>& targetBlockquote) | 91 void IndentOutdentCommand::indentIntoBlockquote(const Position& start, const Pos
ition& end, Handle<Element>& targetBlockquote) |
| 92 { | 92 { |
| 93 Node* enclosingCell = enclosingNodeOfType(start, &isTableCell); | 93 Handle<Node> enclosingCell = enclosingNodeOfType(start, &isTableCell); |
| 94 Handle<Node> nodeToSplitTo; | 94 Handle<Node> nodeToSplitTo; |
| 95 if (enclosingCell) | 95 if (enclosingCell) |
| 96 nodeToSplitTo = adoptRawResult(enclosingCell); | 96 nodeToSplitTo = enclosingCell; |
| 97 else if (enclosingList(start.containerNode().handle().raw())) | 97 else if (enclosingList(start.containerNode())) |
| 98 nodeToSplitTo = enclosingBlock(start.containerNode().handle().raw()); | 98 nodeToSplitTo = enclosingBlock(start.containerNode()); |
| 99 else | 99 else |
| 100 nodeToSplitTo = editableRootForPosition(start); | 100 nodeToSplitTo = editableRootForPosition(start); |
| 101 | 101 |
| 102 if (!nodeToSplitTo) | 102 if (!nodeToSplitTo) |
| 103 return; | 103 return; |
| 104 | 104 |
| 105 Handle<Node> nodeAfterStart = start.computeNodeAfterPosition(); | 105 Handle<Node> nodeAfterStart = start.computeNodeAfterPosition(); |
| 106 Handle<Node> outerBlock = (start.containerNode() == nodeToSplitTo) ? start.c
ontainerNode() : splitTreeToNode(start.containerNode(), nodeToSplitTo); | 106 Handle<Node> outerBlock = (start.containerNode() == nodeToSplitTo) ? start.c
ontainerNode() : splitTreeToNode(start.containerNode(), nodeToSplitTo); |
| 107 | 107 |
| 108 VisiblePosition startOfContents = start; | 108 VisiblePosition startOfContents = start; |
| 109 if (!targetBlockquote) { | 109 if (!targetBlockquote) { |
| 110 // Create a new blockquote and insert it as a child of the root editable
element. We accomplish | 110 // Create a new blockquote and insert it as a child of the root editable
element. We accomplish |
| 111 // this by splitting all parents of the current paragraph up to that poi
nt. | 111 // this by splitting all parents of the current paragraph up to that poi
nt. |
| 112 targetBlockquote = createBlockElement(); | 112 targetBlockquote = createBlockElement(); |
| 113 if (outerBlock == start.containerNode().handle().raw()) | 113 if (outerBlock == start.containerNode().handle().raw()) |
| 114 insertNodeAt(targetBlockquote, start); | 114 insertNodeAt(targetBlockquote, start); |
| 115 else | 115 else |
| 116 insertNodeBefore(targetBlockquote, outerBlock); | 116 insertNodeBefore(targetBlockquote, outerBlock); |
| 117 startOfContents = positionInParentAfterNode(targetBlockquote); | 117 startOfContents = positionInParentAfterNode(targetBlockquote); |
| 118 } | 118 } |
| 119 | 119 |
| 120 moveParagraphWithClones(startOfContents, end, targetBlockquote, outerBlock); | 120 moveParagraphWithClones(startOfContents, end, targetBlockquote, outerBlock); |
| 121 } | 121 } |
| 122 | 122 |
| 123 void IndentOutdentCommand::outdentParagraph() | 123 void IndentOutdentCommand::outdentParagraph() |
| 124 { | 124 { |
| 125 VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection()
.visibleStart()); | 125 VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection()
.visibleStart()); |
| 126 VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagra
ph); | 126 VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagra
ph); |
| 127 | 127 |
| 128 Handle<Node> enclosingNode = adoptRawResult(enclosingNodeOfType(visibleStart
OfParagraph.deepEquivalent(), &isListOrIndentBlockquote)); | 128 Handle<Node> enclosingNode = enclosingNodeOfType(visibleStartOfParagraph.dee
pEquivalent(), &isListOrIndentBlockquote); |
| 129 if (!enclosingNode || !enclosingNode->parentNode()->rendererIsEditable()) //
We can't outdent if there is no place to go! | 129 if (!enclosingNode || !enclosingNode->parentNode()->rendererIsEditable()) //
We can't outdent if there is no place to go! |
| 130 return; | 130 return; |
| 131 | 131 |
| 132 // Use InsertListCommand to remove the selection from the list | 132 // Use InsertListCommand to remove the selection from the list |
| 133 if (enclosingNode->hasTagName(olTag)) { | 133 if (enclosingNode->hasTagName(olTag)) { |
| 134 applyCommandToComposite(InsertListCommand::create(document(), InsertList
Command::OrderedList)); | 134 applyCommandToComposite(InsertListCommand::create(document(), InsertList
Command::OrderedList)); |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 if (enclosingNode->hasTagName(ulTag)) { | 137 if (enclosingNode->hasTagName(ulTag)) { |
| 138 applyCommandToComposite(InsertListCommand::create(document(), InsertList
Command::UnorderedList)); | 138 applyCommandToComposite(InsertListCommand::create(document(), InsertList
Command::UnorderedList)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 165 document()->updateLayoutIgnorePendingStylesheets(); | 165 document()->updateLayoutIgnorePendingStylesheets(); |
| 166 visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEq
uivalent()); | 166 visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEq
uivalent()); |
| 167 visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquiva
lent()); | 167 visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquiva
lent()); |
| 168 if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleSt
artOfParagraph)) | 168 if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleSt
artOfParagraph)) |
| 169 insertNodeAt(createBreakElement(document()), visibleStartOfParagraph
.deepEquivalent()); | 169 insertNodeAt(createBreakElement(document()), visibleStartOfParagraph
.deepEquivalent()); |
| 170 if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfP
aragraph)) | 170 if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfP
aragraph)) |
| 171 insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.d
eepEquivalent()); | 171 insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.d
eepEquivalent()); |
| 172 | 172 |
| 173 return; | 173 return; |
| 174 } | 174 } |
| 175 Handle<Node> enclosingBlockFlow = enclosingBlock(visibleStartOfParagraph.dee
pEquivalent().deprecatedNode().handle().raw()); | 175 Handle<Node> enclosingBlockFlow = enclosingBlock(visibleStartOfParagraph.dee
pEquivalent().deprecatedNode()); |
| 176 Handle<Node> splitBlockquoteNode = enclosingNode; | 176 Handle<Node> splitBlockquoteNode = enclosingNode; |
| 177 if (enclosingBlockFlow != enclosingNode) | 177 if (enclosingBlockFlow != enclosingNode) |
| 178 splitBlockquoteNode = splitTreeToNode(enclosingBlockFlow, enclosingNode,
true); | 178 splitBlockquoteNode = splitTreeToNode(enclosingBlockFlow, enclosingNode,
true); |
| 179 else { | 179 else { |
| 180 // We split the blockquote at where we start outdenting. | 180 // We split the blockquote at where we start outdenting. |
| 181 Handle<Node> highestInlineNode = adoptRawResult(highestEnclosingNodeOfTy
pe(visibleStartOfParagraph.deepEquivalent(), isInline, CannotCrossEditingBoundar
y, enclosingBlockFlow.raw())); | 181 Handle<Node> highestInlineNode = highestEnclosingNodeOfType(visibleStart
OfParagraph.deepEquivalent(), isInline, CannotCrossEditingBoundary, enclosingBlo
ckFlow); |
| 182 splitElement(toElement(enclosingNode), highestInlineNode ? highestInline
Node : visibleStartOfParagraph.deepEquivalent().deprecatedNode().handle()); | 182 splitElement(toElement(enclosingNode), highestInlineNode ? highestInline
Node : visibleStartOfParagraph.deepEquivalent().deprecatedNode().handle()); |
| 183 } | 183 } |
| 184 Handle<Node> placeholder = createBreakElement(document()); | 184 Handle<Node> placeholder = createBreakElement(document()); |
| 185 insertNodeBefore(placeholder, splitBlockquoteNode); | 185 insertNodeBefore(placeholder, splitBlockquoteNode); |
| 186 moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visi
bleEndOfParagraph), positionBeforeNode(placeholder), true); | 186 moveParagraph(startOfParagraph(visibleStartOfParagraph), endOfParagraph(visi
bleEndOfParagraph), positionBeforeNode(placeholder), true); |
| 187 } | 187 } |
| 188 | 188 |
| 189 // FIXME: We should merge this function with ApplyBlockElementCommand::formatSel
ection | 189 // FIXME: We should merge this function with ApplyBlockElementCommand::formatSel
ection |
| 190 void IndentOutdentCommand::outdentRegion(const VisiblePosition& startOfSelection
, const VisiblePosition& endOfSelection) | 190 void IndentOutdentCommand::outdentRegion(const VisiblePosition& startOfSelection
, const VisiblePosition& endOfSelection) |
| 191 { | 191 { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 233 |
| 234 void IndentOutdentCommand::formatRange(const Position& start, const Position& en
d, const Position&, Handle<Element>& blockquoteForNextIndent) | 234 void IndentOutdentCommand::formatRange(const Position& start, const Position& en
d, const Position&, Handle<Element>& blockquoteForNextIndent) |
| 235 { | 235 { |
| 236 if (tryIndentingAsListItem(start, end)) | 236 if (tryIndentingAsListItem(start, end)) |
| 237 blockquoteForNextIndent = nullptr; | 237 blockquoteForNextIndent = nullptr; |
| 238 else | 238 else |
| 239 indentIntoBlockquote(start, end, blockquoteForNextIndent); | 239 indentIntoBlockquote(start, end, blockquoteForNextIndent); |
| 240 } | 240 } |
| 241 | 241 |
| 242 } | 242 } |
| OLD | NEW |