| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2010 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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 switchListType = true; | 231 switchListType = true; |
| 232 } | 232 } |
| 233 | 233 |
| 234 // If the list is of the desired type, and we are not removing the list, | 234 // If the list is of the desired type, and we are not removing the list, |
| 235 // then exit early. | 235 // then exit early. |
| 236 if (!switchListType && forceCreateList) | 236 if (!switchListType && forceCreateList) |
| 237 return true; | 237 return true; |
| 238 | 238 |
| 239 // If the entire list is selected, then convert the whole list. | 239 // If the entire list is selected, then convert the whole list. |
| 240 if (switchListType && isNodeVisiblyContainedWithin(*listElement, current
Selection)) { | 240 if (switchListType && isNodeVisiblyContainedWithin(*listElement, current
Selection)) { |
| 241 bool rangeStartIsInList = visiblePositionBeforeNode(*listElement).de
epEquivalent() == VisiblePosition(currentSelection.startPosition()).deepEquivale
nt(); | 241 bool rangeStartIsInList = visiblePositionBeforeNode(*listElement).de
epEquivalent() == createVisiblePosition(currentSelection.startPosition()).deepEq
uivalent(); |
| 242 bool rangeEndIsInList = visiblePositionAfterNode(*listElement).deepE
quivalent() == VisiblePosition(currentSelection.endPosition()).deepEquivalent(); | 242 bool rangeEndIsInList = visiblePositionAfterNode(*listElement).deepE
quivalent() == createVisiblePosition(currentSelection.endPosition()).deepEquival
ent(); |
| 243 | 243 |
| 244 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document
(), listTag); | 244 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document
(), listTag); |
| 245 insertNodeBefore(newList, listElement); | 245 insertNodeBefore(newList, listElement); |
| 246 | 246 |
| 247 Node* firstChildInList = enclosingListChild(VisiblePosition(firstPos
itionInNode(listElement.get())).deepEquivalent().anchorNode(), listElement.get()
); | 247 Node* firstChildInList = enclosingListChild(createVisiblePosition(fi
rstPositionInNode(listElement.get())).deepEquivalent().anchorNode(), listElement
.get()); |
| 248 Element* outerBlock = firstChildInList && isBlockFlowElement(*firstC
hildInList) ? toElement(firstChildInList) : listElement.get(); | 248 Element* outerBlock = firstChildInList && isBlockFlowElement(*firstC
hildInList) ? toElement(firstChildInList) : listElement.get(); |
| 249 | 249 |
| 250 moveParagraphWithClones(VisiblePosition(firstPositionInNode(listElem
ent.get())), VisiblePosition(lastPositionInNode(listElement.get())), newList.get
(), outerBlock); | 250 moveParagraphWithClones(createVisiblePosition(firstPositionInNode(li
stElement.get())), createVisiblePosition(lastPositionInNode(listElement.get())),
newList.get(), outerBlock); |
| 251 | 251 |
| 252 // Manually remove listNode because moveParagraphWithClones sometime
s leaves it behind in the document. | 252 // Manually remove listNode because moveParagraphWithClones sometime
s leaves it behind in the document. |
| 253 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it
em-with-nested-lists.html. | 253 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it
em-with-nested-lists.html. |
| 254 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe
lection. | 254 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe
lection. |
| 255 if (listElement && listElement->inDocument()) | 255 if (listElement && listElement->inDocument()) |
| 256 removeNode(listElement); | 256 removeNode(listElement); |
| 257 | 257 |
| 258 newList = mergeWithNeighboringLists(newList); | 258 newList = mergeWithNeighboringLists(newList); |
| 259 | 259 |
| 260 // Restore the start and the end of current selection if they starte
d inside listNode | 260 // Restore the start and the end of current selection if they starte
d inside listNode |
| 261 // because moveParagraphWithClones could have removed them. | 261 // because moveParagraphWithClones could have removed them. |
| 262 if (rangeStartIsInList && newList) | 262 if (rangeStartIsInList && newList) |
| 263 currentSelection.setStart(newList, 0, IGNORE_EXCEPTION); | 263 currentSelection.setStart(newList, 0, IGNORE_EXCEPTION); |
| 264 if (rangeEndIsInList && newList) | 264 if (rangeEndIsInList && newList) |
| 265 currentSelection.setEnd(newList, lastOffsetInNode(newList.get())
, IGNORE_EXCEPTION); | 265 currentSelection.setEnd(newList, lastOffsetInNode(newList.get())
, IGNORE_EXCEPTION); |
| 266 | 266 |
| 267 setEndingSelection(VisiblePosition(firstPositionInNode(newList.get()
))); | 267 setEndingSelection(createVisiblePosition(firstPositionInNode(newList
.get()))); |
| 268 | 268 |
| 269 return true; | 269 return true; |
| 270 } | 270 } |
| 271 | 271 |
| 272 unlistifyParagraph(endingSelection().visibleStart(), listElement.get(),
listChildNode); | 272 unlistifyParagraph(endingSelection().visibleStart(), listElement.get(),
listChildNode); |
| 273 } | 273 } |
| 274 | 274 |
| 275 if (!listChildNode || switchListType || forceCreateList) | 275 if (!listChildNode || switchListType || forceCreateList) |
| 276 m_listElement = listifyParagraph(endingSelection().visibleStart(), listT
ag); | 276 m_listElement = listifyParagraph(endingSelection().visibleStart(), listT
ag); |
| 277 | 277 |
| 278 return true; | 278 return true; |
| 279 } | 279 } |
| 280 | 280 |
| 281 void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart,
HTMLElement* listElement, Node* listChildNode) | 281 void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart,
HTMLElement* listElement, Node* listChildNode) |
| 282 { | 282 { |
| 283 Node* nextListChild; | 283 Node* nextListChild; |
| 284 Node* previousListChild; | 284 Node* previousListChild; |
| 285 VisiblePosition start; | 285 VisiblePosition start; |
| 286 VisiblePosition end; | 286 VisiblePosition end; |
| 287 ASSERT(listChildNode); | 287 ASSERT(listChildNode); |
| 288 if (isHTMLLIElement(*listChildNode)) { | 288 if (isHTMLLIElement(*listChildNode)) { |
| 289 start = VisiblePosition(firstPositionInNode(listChildNode)); | 289 start = createVisiblePosition(firstPositionInNode(listChildNode)); |
| 290 end = VisiblePosition(lastPositionInNode(listChildNode)); | 290 end = createVisiblePosition(lastPositionInNode(listChildNode)); |
| 291 nextListChild = listChildNode->nextSibling(); | 291 nextListChild = listChildNode->nextSibling(); |
| 292 previousListChild = listChildNode->previousSibling(); | 292 previousListChild = listChildNode->previousSibling(); |
| 293 } else { | 293 } else { |
| 294 // A paragraph is visually a list item minus a list marker. The paragra
ph will be moved. | 294 // A paragraph is visually a list item minus a list marker. The paragra
ph will be moved. |
| 295 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary); | 295 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary); |
| 296 end = endOfParagraph(start, CanSkipOverEditingBoundary); | 296 end = endOfParagraph(start, CanSkipOverEditingBoundary); |
| 297 nextListChild = enclosingListChild(nextPositionOf(end).deepEquivalent().
anchorNode(), listElement); | 297 nextListChild = enclosingListChild(nextPositionOf(end).deepEquivalent().
anchorNode(), listElement); |
| 298 ASSERT(nextListChild != listChildNode); | 298 ASSERT(nextListChild != listChildNode); |
| 299 previousListChild = enclosingListChild(previousPositionOf(start).deepEqu
ivalent().anchorNode(), listElement); | 299 previousListChild = enclosingListChild(previousPositionOf(start).deepEqu
ivalent().anchorNode(), listElement); |
| 300 ASSERT(previousListChild != listChildNode); | 300 ASSERT(previousListChild != listChildNode); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 325 // in listNode that comes before listChildNode, as listChildNode could h
ave ancestors | 325 // in listNode that comes before listChildNode, as listChildNode could h
ave ancestors |
| 326 // between it and listNode. So, we split up to listNode before inserting
the placeholder | 326 // between it and listNode. So, we split up to listNode before inserting
the placeholder |
| 327 // where we're about to move listChildNode to. | 327 // where we're about to move listChildNode to. |
| 328 if (listChildNode->parentNode() != listElement) | 328 if (listChildNode->parentNode() != listElement) |
| 329 splitElement(listElement, splitTreeToNode(listChildNode, listElement
).get()); | 329 splitElement(listElement, splitTreeToNode(listChildNode, listElement
).get()); |
| 330 insertNodeBefore(elementToInsert, listElement); | 330 insertNodeBefore(elementToInsert, listElement); |
| 331 } else { | 331 } else { |
| 332 insertNodeAfter(elementToInsert, listElement); | 332 insertNodeAfter(elementToInsert, listElement); |
| 333 } | 333 } |
| 334 | 334 |
| 335 VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placehol
der.get())); | 335 VisiblePosition insertionPoint = createVisiblePosition(positionBeforeNode(pl
aceholder.get())); |
| 336 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /*
preserveStyle */ true, listChildNode); | 336 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /*
preserveStyle */ true, listChildNode); |
| 337 } | 337 } |
| 338 | 338 |
| 339 static HTMLElement* adjacentEnclosingList(const VisiblePosition& pos, const Visi
blePosition& adjacentPos, const HTMLQualifiedName& listTag) | 339 static HTMLElement* adjacentEnclosingList(const VisiblePosition& pos, const Visi
blePosition& adjacentPos, const HTMLQualifiedName& listTag) |
| 340 { | 340 { |
| 341 HTMLElement* listElement = outermostEnclosingList(adjacentPos.deepEquivalent
().anchorNode()); | 341 HTMLElement* listElement = outermostEnclosingList(adjacentPos.deepEquivalent
().anchorNode()); |
| 342 | 342 |
| 343 if (!listElement) | 343 if (!listElement) |
| 344 return 0; | 344 return 0; |
| 345 | 345 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 } else { | 379 } else { |
| 380 // Create the list. | 380 // Create the list. |
| 381 listElement = createHTMLElement(document(), listTag); | 381 listElement = createHTMLElement(document(), listTag); |
| 382 appendNode(listItemElement, listElement); | 382 appendNode(listItemElement, listElement); |
| 383 | 383 |
| 384 if (start.deepEquivalent() == end.deepEquivalent() && isEnclosingBlock(s
tart.deepEquivalent().anchorNode())) { | 384 if (start.deepEquivalent() == end.deepEquivalent() && isEnclosingBlock(s
tart.deepEquivalent().anchorNode())) { |
| 385 // Inserting the list into an empty paragraph that isn't held open | 385 // Inserting the list into an empty paragraph that isn't held open |
| 386 // by a br or a '\n', will invalidate start and end. Insert | 386 // by a br or a '\n', will invalidate start and end. Insert |
| 387 // a placeholder and then recompute start and end. | 387 // a placeholder and then recompute start and end. |
| 388 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = insertBlockPlacehold
er(start.deepEquivalent()); | 388 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = insertBlockPlacehold
er(start.deepEquivalent()); |
| 389 start = VisiblePosition(positionBeforeNode(placeholder.get())); | 389 start = createVisiblePosition(positionBeforeNode(placeholder.get()))
; |
| 390 end = start; | 390 end = start; |
| 391 } | 391 } |
| 392 | 392 |
| 393 // Insert the list at a position visually equivalent to start of the | 393 // Insert the list at a position visually equivalent to start of the |
| 394 // paragraph that is being moved into the list. | 394 // paragraph that is being moved into the list. |
| 395 // Try to avoid inserting it somewhere where it will be surrounded by | 395 // Try to avoid inserting it somewhere where it will be surrounded by |
| 396 // inline ancestors of start, since it is easier for editing to produce | 396 // inline ancestors of start, since it is easier for editing to produce |
| 397 // clean markup when inline elements are pushed down as far as possible. | 397 // clean markup when inline elements are pushed down as far as possible. |
| 398 Position insertionPos(mostBackwardCaretPosition(start.deepEquivalent()))
; | 398 Position insertionPos(mostBackwardCaretPosition(start.deepEquivalent()))
; |
| 399 // Also avoid the containing list item. | 399 // Also avoid the containing list item. |
| 400 Node* listChild = enclosingListChild(insertionPos.anchorNode()); | 400 Node* listChild = enclosingListChild(insertionPos.anchorNode()); |
| 401 if (isHTMLLIElement(listChild)) | 401 if (isHTMLLIElement(listChild)) |
| 402 insertionPos = positionInParentBeforeNode(*listChild); | 402 insertionPos = positionInParentBeforeNode(*listChild); |
| 403 | 403 |
| 404 insertNodeAt(listElement, insertionPos); | 404 insertNodeAt(listElement, insertionPos); |
| 405 | 405 |
| 406 // We inserted the list at the start of the content we're about to move | 406 // We inserted the list at the start of the content we're about to move |
| 407 // Update the start of content, so we don't try to move the list into it
self. bug 19066 | 407 // Update the start of content, so we don't try to move the list into it
self. bug 19066 |
| 408 // Layout is necessary since start's node's inline layoutObjects may hav
e been destroyed by the insertion | 408 // Layout is necessary since start's node's inline layoutObjects may hav
e been destroyed by the insertion |
| 409 // The end of the content may have changed after the insertion and layou
t so update it as well. | 409 // The end of the content may have changed after the insertion and layou
t so update it as well. |
| 410 if (insertionPos == start.deepEquivalent()) | 410 if (insertionPos == start.deepEquivalent()) |
| 411 start = originalStart; | 411 start = originalStart; |
| 412 } | 412 } |
| 413 | 413 |
| 414 // Inserting list element and list item list may change start of pargraph | 414 // Inserting list element and list item list may change start of pargraph |
| 415 // to move. We calculate start of paragraph again. | 415 // to move. We calculate start of paragraph again. |
| 416 document().updateLayoutIgnorePendingStylesheets(); | 416 document().updateLayoutIgnorePendingStylesheets(); |
| 417 start = startOfParagraph(start, CanSkipOverEditingBoundary); | 417 start = startOfParagraph(start, CanSkipOverEditingBoundary); |
| 418 end = endOfParagraph(start, CanSkipOverEditingBoundary); | 418 end = endOfParagraph(start, CanSkipOverEditingBoundary); |
| 419 moveParagraph(start, end, VisiblePosition(positionBeforeNode(placeholder.get
())), true); | 419 moveParagraph(start, end, createVisiblePosition(positionBeforeNode(placehold
er.get())), true); |
| 420 | 420 |
| 421 if (listElement) | 421 if (listElement) |
| 422 return mergeWithNeighboringLists(listElement); | 422 return mergeWithNeighboringLists(listElement); |
| 423 | 423 |
| 424 if (canMergeLists(previousList, nextList)) | 424 if (canMergeLists(previousList, nextList)) |
| 425 mergeIdenticalElements(previousList, nextList); | 425 mergeIdenticalElements(previousList, nextList); |
| 426 | 426 |
| 427 return listElement; | 427 return listElement; |
| 428 } | 428 } |
| 429 | 429 |
| 430 DEFINE_TRACE(InsertListCommand) | 430 DEFINE_TRACE(InsertListCommand) |
| 431 { | 431 { |
| 432 visitor->trace(m_listElement); | 432 visitor->trace(m_listElement); |
| 433 CompositeEditCommand::trace(visitor); | 433 CompositeEditCommand::trace(visitor); |
| 434 } | 434 } |
| 435 | 435 |
| 436 } | 436 } |
| OLD | NEW |