| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2005 Apple Computer, 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 | 96 |
| 97 // pos is a position equivalent to the caret. We use downstream() so that p
os will | 97 // pos is a position equivalent to the caret. We use downstream() so that p
os will |
| 98 // be in the first node that we need to move (there are a few exceptions to
this, see below). | 98 // be in the first node that we need to move (there are a few exceptions to
this, see below). |
| 99 Position pos = mostForwardCaretPosition(endingSelection().start()); | 99 Position pos = mostForwardCaretPosition(endingSelection().start()); |
| 100 | 100 |
| 101 // Find the top-most blockquote from the start. | 101 // Find the top-most blockquote from the start. |
| 102 HTMLQuoteElement* topBlockquote = toHTMLQuoteElement(highestEnclosingNodeOfT
ype(pos, isMailHTMLBlockquoteElement)); | 102 HTMLQuoteElement* topBlockquote = toHTMLQuoteElement(highestEnclosingNodeOfT
ype(pos, isMailHTMLBlockquoteElement)); |
| 103 if (!topBlockquote || !topBlockquote->parentNode()) | 103 if (!topBlockquote || !topBlockquote->parentNode()) |
| 104 return; | 104 return; |
| 105 | 105 |
| 106 RefPtrWillBeRawPtr<HTMLBRElement> breakElement = HTMLBRElement::create(docum
ent()); | 106 RawPtr<HTMLBRElement> breakElement = HTMLBRElement::create(document()); |
| 107 | 107 |
| 108 bool isLastVisPosInNode = isLastVisiblePositionInNode(visiblePos, topBlockqu
ote); | 108 bool isLastVisPosInNode = isLastVisiblePositionInNode(visiblePos, topBlockqu
ote); |
| 109 | 109 |
| 110 // If the position is at the beginning of the top quoted content, we don't n
eed to break the quote. | 110 // If the position is at the beginning of the top quoted content, we don't n
eed to break the quote. |
| 111 // Instead, insert the break before the blockquote, unless the position is a
s the end of the the quoted content. | 111 // Instead, insert the break before the blockquote, unless the position is a
s the end of the the quoted content. |
| 112 if (isFirstVisiblePositionInNode(visiblePos, topBlockquote) && !isLastVisPos
InNode) { | 112 if (isFirstVisiblePositionInNode(visiblePos, topBlockquote) && !isLastVisPos
InNode) { |
| 113 insertNodeBefore(breakElement.get(), topBlockquote, editingState); | 113 insertNodeBefore(breakElement.get(), topBlockquote, editingState); |
| 114 if (editingState->isAborted()) | 114 if (editingState->isAborted()) |
| 115 return; | 115 return; |
| 116 setEndingSelection(VisibleSelection(positionBeforeNode(breakElement.get(
)), TextAffinity::Downstream, endingSelection().isDirectional())); | 116 setEndingSelection(VisibleSelection(positionBeforeNode(breakElement.get(
)), TextAffinity::Downstream, endingSelection().isDirectional())); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 ASSERT(startNode); | 165 ASSERT(startNode); |
| 166 } | 166 } |
| 167 | 167 |
| 168 // If there's nothing inside topBlockquote to move, we're finished. | 168 // If there's nothing inside topBlockquote to move, we're finished. |
| 169 if (!startNode->isDescendantOf(topBlockquote)) { | 169 if (!startNode->isDescendantOf(topBlockquote)) { |
| 170 setEndingSelection(VisibleSelection(createVisiblePosition(firstPositionI
nOrBeforeNode(startNode)), endingSelection().isDirectional())); | 170 setEndingSelection(VisibleSelection(createVisiblePosition(firstPositionI
nOrBeforeNode(startNode)), endingSelection().isDirectional())); |
| 171 return; | 171 return; |
| 172 } | 172 } |
| 173 | 173 |
| 174 // Build up list of ancestors in between the start node and the top blockquo
te. | 174 // Build up list of ancestors in between the start node and the top blockquo
te. |
| 175 WillBeHeapVector<RefPtrWillBeMember<Element>> ancestors; | 175 HeapVector<Member<Element>> ancestors; |
| 176 for (Element* node = startNode->parentElement(); node && node != topBlockquo
te; node = node->parentElement()) | 176 for (Element* node = startNode->parentElement(); node && node != topBlockquo
te; node = node->parentElement()) |
| 177 ancestors.append(node); | 177 ancestors.append(node); |
| 178 | 178 |
| 179 // Insert a clone of the top blockquote after the break. | 179 // Insert a clone of the top blockquote after the break. |
| 180 RefPtrWillBeRawPtr<Element> clonedBlockquote = topBlockquote->cloneElementWi
thoutChildren(); | 180 RawPtr<Element> clonedBlockquote = topBlockquote->cloneElementWithoutChildre
n(); |
| 181 insertNodeAfter(clonedBlockquote.get(), breakElement.get(), editingState); | 181 insertNodeAfter(clonedBlockquote.get(), breakElement.get(), editingState); |
| 182 if (editingState->isAborted()) | 182 if (editingState->isAborted()) |
| 183 return; | 183 return; |
| 184 | 184 |
| 185 // Clone startNode's ancestors into the cloned blockquote. | 185 // Clone startNode's ancestors into the cloned blockquote. |
| 186 // On exiting this loop, clonedAncestor is the lowest ancestor | 186 // On exiting this loop, clonedAncestor is the lowest ancestor |
| 187 // that was cloned (i.e. the clone of either ancestors.last() | 187 // that was cloned (i.e. the clone of either ancestors.last() |
| 188 // or clonedBlockquote if ancestors is empty). | 188 // or clonedBlockquote if ancestors is empty). |
| 189 RefPtrWillBeRawPtr<Element> clonedAncestor = clonedBlockquote; | 189 RawPtr<Element> clonedAncestor = clonedBlockquote; |
| 190 for (size_t i = ancestors.size(); i != 0; --i) { | 190 for (size_t i = ancestors.size(); i != 0; --i) { |
| 191 RefPtrWillBeRawPtr<Element> clonedChild = ancestors[i - 1]->cloneElement
WithoutChildren(); | 191 RawPtr<Element> clonedChild = ancestors[i - 1]->cloneElementWithoutChild
ren(); |
| 192 // Preserve list item numbering in cloned lists. | 192 // Preserve list item numbering in cloned lists. |
| 193 if (isHTMLOListElement(*clonedChild)) { | 193 if (isHTMLOListElement(*clonedChild)) { |
| 194 Node* listChildNode = i > 1 ? ancestors[i - 2].get() : startNode; | 194 Node* listChildNode = i > 1 ? ancestors[i - 2].get() : startNode; |
| 195 // The first child of the cloned list might not be a list item eleme
nt, | 195 // The first child of the cloned list might not be a list item eleme
nt, |
| 196 // find the first one so that we know where to start numbering. | 196 // find the first one so that we know where to start numbering. |
| 197 while (listChildNode && !isHTMLLIElement(*listChildNode)) | 197 while (listChildNode && !isHTMLLIElement(*listChildNode)) |
| 198 listChildNode = listChildNode->nextSibling(); | 198 listChildNode = listChildNode->nextSibling(); |
| 199 if (isListItem(listChildNode)) | 199 if (isListItem(listChildNode)) |
| 200 setNodeAttribute(clonedChild, startAttr, AtomicString::number(to
LayoutListItem(listChildNode->layoutObject())->value())); | 200 setNodeAttribute(clonedChild, startAttr, AtomicString::number(to
LayoutListItem(listChildNode->layoutObject())->value())); |
| 201 } | 201 } |
| 202 | 202 |
| 203 appendNode(clonedChild.get(), clonedAncestor.get(), editingState); | 203 appendNode(clonedChild.get(), clonedAncestor.get(), editingState); |
| 204 if (editingState->isAborted()) | 204 if (editingState->isAborted()) |
| 205 return; | 205 return; |
| 206 clonedAncestor = clonedChild; | 206 clonedAncestor = clonedChild; |
| 207 } | 207 } |
| 208 | 208 |
| 209 moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor, editingState)
; | 209 moveRemainingSiblingsToNewParent(startNode, 0, clonedAncestor, editingState)
; |
| 210 if (editingState->isAborted()) | 210 if (editingState->isAborted()) |
| 211 return; | 211 return; |
| 212 | 212 |
| 213 if (!ancestors.isEmpty()) { | 213 if (!ancestors.isEmpty()) { |
| 214 // Split the tree up the ancestor chain until the topBlockquote | 214 // Split the tree up the ancestor chain until the topBlockquote |
| 215 // Throughout this loop, clonedParent is the clone of ancestor's parent. | 215 // Throughout this loop, clonedParent is the clone of ancestor's parent. |
| 216 // This is so we can clone ancestor's siblings and place the clones | 216 // This is so we can clone ancestor's siblings and place the clones |
| 217 // into the clone corresponding to the ancestor's parent. | 217 // into the clone corresponding to the ancestor's parent. |
| 218 RefPtrWillBeRawPtr<Element> ancestor = nullptr; | 218 RawPtr<Element> ancestor = nullptr; |
| 219 RefPtrWillBeRawPtr<Element> clonedParent = nullptr; | 219 RawPtr<Element> clonedParent = nullptr; |
| 220 for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parent
Element(); | 220 for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parent
Element(); |
| 221 ancestor && ancestor != topBlockquote; | 221 ancestor && ancestor != topBlockquote; |
| 222 ancestor = ancestor->parentElement(), clonedParent = clonedParent->p
arentElement()) { | 222 ancestor = ancestor->parentElement(), clonedParent = clonedParent->p
arentElement()) { |
| 223 moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedP
arent, editingState); | 223 moveRemainingSiblingsToNewParent(ancestor->nextSibling(), 0, clonedP
arent, editingState); |
| 224 if (editingState->isAborted()) | 224 if (editingState->isAborted()) |
| 225 return; | 225 return; |
| 226 } | 226 } |
| 227 | 227 |
| 228 // If the startNode's original parent is now empty, remove it | 228 // If the startNode's original parent is now empty, remove it |
| 229 Element* originalParent = ancestors.first().get(); | 229 Element* originalParent = ancestors.first().get(); |
| 230 if (!originalParent->hasChildren()) { | 230 if (!originalParent->hasChildren()) { |
| 231 removeNode(originalParent, editingState); | 231 removeNode(originalParent, editingState); |
| 232 if (editingState->isAborted()) | 232 if (editingState->isAborted()) |
| 233 return; | 233 return; |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 | 236 |
| 237 // Make sure the cloned block quote renders. | 237 // Make sure the cloned block quote renders. |
| 238 addBlockPlaceholderIfNeeded(clonedBlockquote.get(), editingState); | 238 addBlockPlaceholderIfNeeded(clonedBlockquote.get(), editingState); |
| 239 if (editingState->isAborted()) | 239 if (editingState->isAborted()) |
| 240 return; | 240 return; |
| 241 | 241 |
| 242 // Put the selection right before the break. | 242 // Put the selection right before the break. |
| 243 setEndingSelection(VisibleSelection(positionBeforeNode(breakElement.get()),
TextAffinity::Downstream, endingSelection().isDirectional())); | 243 setEndingSelection(VisibleSelection(positionBeforeNode(breakElement.get()),
TextAffinity::Downstream, endingSelection().isDirectional())); |
| 244 rebalanceWhitespace(); | 244 rebalanceWhitespace(); |
| 245 } | 245 } |
| 246 | 246 |
| 247 } // namespace blink | 247 } // namespace blink |
| OLD | NEW |