| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 mergeIdenticalElements(list, nextList); | 80 mergeIdenticalElements(list, nextList); |
| 81 return nextList.release(); | 81 return nextList.release(); |
| 82 } | 82 } |
| 83 return list.release(); | 83 return list.release(); |
| 84 } | 84 } |
| 85 | 85 |
| 86 bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection
, const HTMLQualifiedName& listTag) | 86 bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection
, const HTMLQualifiedName& listTag) |
| 87 { | 87 { |
| 88 VisiblePosition start = selection.visibleStart(); | 88 VisiblePosition start = selection.visibleStart(); |
| 89 | 89 |
| 90 if (!enclosingList(start.deepEquivalent().deprecatedNode())) | 90 if (!enclosingList(start.deepEquivalent().anchorNode())) |
| 91 return false; | 91 return false; |
| 92 | 92 |
| 93 VisiblePosition end = startOfParagraph(selection.visibleEnd()); | 93 VisiblePosition end = startOfParagraph(selection.visibleEnd()); |
| 94 while (start.isNotNull() && start != end) { | 94 while (start.isNotNull() && start != end) { |
| 95 HTMLElement* listElement = enclosingList(start.deepEquivalent().deprecat
edNode()); | 95 HTMLElement* listElement = enclosingList(start.deepEquivalent().anchorNo
de()); |
| 96 if (!listElement || !listElement->hasTagName(listTag)) | 96 if (!listElement || !listElement->hasTagName(listTag)) |
| 97 return false; | 97 return false; |
| 98 start = startOfNextParagraph(start); | 98 start = startOfNextParagraph(start); |
| 99 } | 99 } |
| 100 | 100 |
| 101 return true; | 101 return true; |
| 102 } | 102 } |
| 103 | 103 |
| 104 InsertListCommand::InsertListCommand(Document& document, Type type) | 104 InsertListCommand::InsertListCommand(Document& document, Type type) |
| 105 : CompositeEditCommand(document), m_type(type) | 105 : CompositeEditCommand(document), m_type(type) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 | 198 |
| 199 ASSERT(endingSelection().firstRange()); | 199 ASSERT(endingSelection().firstRange()); |
| 200 doApplyForSingleParagraph(false, listTag, *endingSelection().firstRange()); | 200 doApplyForSingleParagraph(false, listTag, *endingSelection().firstRange()); |
| 201 } | 201 } |
| 202 | 202 |
| 203 void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HT
MLQualifiedName& listTag, Range& currentSelection) | 203 void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HT
MLQualifiedName& listTag, Range& currentSelection) |
| 204 { | 204 { |
| 205 // FIXME: This will produce unexpected results for a selection that starts j
ust before a | 205 // FIXME: This will produce unexpected results for a selection that starts j
ust before a |
| 206 // table and ends inside the first cell, selectionForParagraphIteration shou
ld probably | 206 // table and ends inside the first cell, selectionForParagraphIteration shou
ld probably |
| 207 // be renamed and deployed inside setEndingSelection(). | 207 // be renamed and deployed inside setEndingSelection(). |
| 208 Node* selectionNode = endingSelection().start().deprecatedNode(); | 208 Node* selectionNode = endingSelection().start().anchorNode(); |
| 209 Node* listChildNode = enclosingListChild(selectionNode); | 209 Node* listChildNode = enclosingListChild(selectionNode); |
| 210 bool switchListType = false; | 210 bool switchListType = false; |
| 211 if (listChildNode) { | 211 if (listChildNode) { |
| 212 // Remove the list chlild. | 212 // Remove the list chlild. |
| 213 RefPtrWillBeRawPtr<HTMLElement> listElement = enclosingList(listChildNod
e); | 213 RefPtrWillBeRawPtr<HTMLElement> listElement = enclosingList(listChildNod
e); |
| 214 if (!listElement) { | 214 if (!listElement) { |
| 215 listElement = fixOrphanedListChild(listChildNode); | 215 listElement = fixOrphanedListChild(listChildNode); |
| 216 listElement = mergeWithNeighboringLists(listElement); | 216 listElement = mergeWithNeighboringLists(listElement); |
| 217 } | 217 } |
| 218 if (!listElement->hasTagName(listTag)) | 218 if (!listElement->hasTagName(listTag)) |
| 219 // listChildNode will be removed from the list and a list of type m_
type will be created. | 219 // listChildNode will be removed from the list and a list of type m_
type will be created. |
| 220 switchListType = true; | 220 switchListType = true; |
| 221 | 221 |
| 222 // If the list is of the desired type, and we are not removing the list,
then exit early. | 222 // If the list is of the desired type, and we are not removing the list,
then exit early. |
| 223 if (!switchListType && forceCreateList) | 223 if (!switchListType && forceCreateList) |
| 224 return; | 224 return; |
| 225 | 225 |
| 226 // If the entire list is selected, then convert the whole list. | 226 // If the entire list is selected, then convert the whole list. |
| 227 if (switchListType && isNodeVisiblyContainedWithin(*listElement, current
Selection)) { | 227 if (switchListType && isNodeVisiblyContainedWithin(*listElement, current
Selection)) { |
| 228 bool rangeStartIsInList = visiblePositionBeforeNode(*listElement) ==
VisiblePosition(currentSelection.startPosition()); | 228 bool rangeStartIsInList = visiblePositionBeforeNode(*listElement) ==
VisiblePosition(currentSelection.startPosition()); |
| 229 bool rangeEndIsInList = visiblePositionAfterNode(*listElement) == Vi
siblePosition(currentSelection.endPosition()); | 229 bool rangeEndIsInList = visiblePositionAfterNode(*listElement) == Vi
siblePosition(currentSelection.endPosition()); |
| 230 | 230 |
| 231 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document
(), listTag); | 231 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document
(), listTag); |
| 232 insertNodeBefore(newList, listElement); | 232 insertNodeBefore(newList, listElement); |
| 233 | 233 |
| 234 Node* firstChildInList = enclosingListChild(VisiblePosition(firstPos
itionInNode(listElement.get())).deepEquivalent().deprecatedNode(), listElement.g
et()); | 234 Node* firstChildInList = enclosingListChild(VisiblePosition(firstPos
itionInNode(listElement.get())).deepEquivalent().anchorNode(), listElement.get()
); |
| 235 Element* outerBlock = firstChildInList && isBlockFlowElement(*firstC
hildInList) ? toElement(firstChildInList) : listElement.get(); | 235 Element* outerBlock = firstChildInList && isBlockFlowElement(*firstC
hildInList) ? toElement(firstChildInList) : listElement.get(); |
| 236 | 236 |
| 237 moveParagraphWithClones(VisiblePosition(firstPositionInNode(listElem
ent.get())), VisiblePosition(lastPositionInNode(listElement.get())), newList.get
(), outerBlock); | 237 moveParagraphWithClones(VisiblePosition(firstPositionInNode(listElem
ent.get())), VisiblePosition(lastPositionInNode(listElement.get())), newList.get
(), outerBlock); |
| 238 | 238 |
| 239 // Manually remove listNode because moveParagraphWithClones sometime
s leaves it behind in the document. | 239 // Manually remove listNode because moveParagraphWithClones sometime
s leaves it behind in the document. |
| 240 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it
em-with-nested-lists.html. | 240 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it
em-with-nested-lists.html. |
| 241 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe
lection. | 241 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe
lection. |
| 242 if (listElement && listElement->inDocument()) | 242 if (listElement && listElement->inDocument()) |
| 243 removeNode(listElement); | 243 removeNode(listElement); |
| 244 | 244 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 272 ASSERT(listChildNode); | 272 ASSERT(listChildNode); |
| 273 if (isHTMLLIElement(*listChildNode)) { | 273 if (isHTMLLIElement(*listChildNode)) { |
| 274 start = VisiblePosition(firstPositionInNode(listChildNode)); | 274 start = VisiblePosition(firstPositionInNode(listChildNode)); |
| 275 end = VisiblePosition(lastPositionInNode(listChildNode)); | 275 end = VisiblePosition(lastPositionInNode(listChildNode)); |
| 276 nextListChild = listChildNode->nextSibling(); | 276 nextListChild = listChildNode->nextSibling(); |
| 277 previousListChild = listChildNode->previousSibling(); | 277 previousListChild = listChildNode->previousSibling(); |
| 278 } else { | 278 } else { |
| 279 // A paragraph is visually a list item minus a list marker. The paragra
ph will be moved. | 279 // A paragraph is visually a list item minus a list marker. The paragra
ph will be moved. |
| 280 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary); | 280 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary); |
| 281 end = endOfParagraph(start, CanSkipOverEditingBoundary); | 281 end = endOfParagraph(start, CanSkipOverEditingBoundary); |
| 282 nextListChild = enclosingListChild(end.next().deepEquivalent().deprecate
dNode(), listElement); | 282 nextListChild = enclosingListChild(end.next().deepEquivalent().anchorNod
e(), listElement); |
| 283 ASSERT(nextListChild != listChildNode); | 283 ASSERT(nextListChild != listChildNode); |
| 284 previousListChild = enclosingListChild(start.previous().deepEquivalent()
.deprecatedNode(), listElement); | 284 previousListChild = enclosingListChild(start.previous().deepEquivalent()
.anchorNode(), listElement); |
| 285 ASSERT(previousListChild != listChildNode); | 285 ASSERT(previousListChild != listChildNode); |
| 286 } | 286 } |
| 287 // When removing a list, we must always create a placeholder to act as a poi
nt of insertion | 287 // When removing a list, we must always create a placeholder to act as a poi
nt of insertion |
| 288 // for the list content being removed. | 288 // for the list content being removed. |
| 289 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document(
)); | 289 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document(
)); |
| 290 RefPtrWillBeRawPtr<HTMLElement> elementToInsert = placeholder; | 290 RefPtrWillBeRawPtr<HTMLElement> elementToInsert = placeholder; |
| 291 // If the content of the list item will be moved into another list, put it i
n a list item | 291 // If the content of the list item will be moved into another list, put it i
n a list item |
| 292 // so that we don't create an orphaned list child. | 292 // so that we don't create an orphaned list child. |
| 293 if (enclosingList(listElement)) { | 293 if (enclosingList(listElement)) { |
| 294 elementToInsert = createListItemElement(document()); | 294 elementToInsert = createListItemElement(document()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 316 } else { | 316 } else { |
| 317 insertNodeAfter(elementToInsert, listElement); | 317 insertNodeAfter(elementToInsert, listElement); |
| 318 } | 318 } |
| 319 | 319 |
| 320 VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placehol
der.get())); | 320 VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placehol
der.get())); |
| 321 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /*
preserveStyle */ true, listChildNode); | 321 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /*
preserveStyle */ true, listChildNode); |
| 322 } | 322 } |
| 323 | 323 |
| 324 static HTMLElement* adjacentEnclosingList(const VisiblePosition& pos, const Visi
blePosition& adjacentPos, const HTMLQualifiedName& listTag) | 324 static HTMLElement* adjacentEnclosingList(const VisiblePosition& pos, const Visi
blePosition& adjacentPos, const HTMLQualifiedName& listTag) |
| 325 { | 325 { |
| 326 HTMLElement* listElement = outermostEnclosingList(adjacentPos.deepEquivalent
().deprecatedNode()); | 326 HTMLElement* listElement = outermostEnclosingList(adjacentPos.deepEquivalent
().anchorNode()); |
| 327 | 327 |
| 328 if (!listElement) | 328 if (!listElement) |
| 329 return 0; | 329 return 0; |
| 330 | 330 |
| 331 Element* previousCell = enclosingTableCell(pos.deepEquivalent()); | 331 Element* previousCell = enclosingTableCell(pos.deepEquivalent()); |
| 332 Element* currentCell = enclosingTableCell(adjacentPos.deepEquivalent()); | 332 Element* currentCell = enclosingTableCell(adjacentPos.deepEquivalent()); |
| 333 | 333 |
| 334 if (!listElement->hasTagName(listTag) | 334 if (!listElement->hasTagName(listTag) |
| 335 || listElement->contains(pos.deepEquivalent().deprecatedNode()) | 335 || listElement->contains(pos.deepEquivalent().anchorNode()) |
| 336 || previousCell != currentCell | 336 || previousCell != currentCell |
| 337 || enclosingList(listElement) != enclosingList(pos.deepEquivalent().depr
ecatedNode())) | 337 || enclosingList(listElement) != enclosingList(pos.deepEquivalent().anch
orNode())) |
| 338 return 0; | 338 return 0; |
| 339 | 339 |
| 340 return listElement; | 340 return listElement; |
| 341 } | 341 } |
| 342 | 342 |
| 343 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::listifyParagraph(const Vi
siblePosition& originalStart, const HTMLQualifiedName& listTag) | 343 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::listifyParagraph(const Vi
siblePosition& originalStart, const HTMLQualifiedName& listTag) |
| 344 { | 344 { |
| 345 VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBo
undary); | 345 VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBo
undary); |
| 346 VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary); | 346 VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary); |
| 347 | 347 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 359 RefPtrWillBeRawPtr<HTMLElement> listElement = nullptr; | 359 RefPtrWillBeRawPtr<HTMLElement> listElement = nullptr; |
| 360 if (previousList) | 360 if (previousList) |
| 361 appendNode(listItemElement, previousList); | 361 appendNode(listItemElement, previousList); |
| 362 else if (nextList) | 362 else if (nextList) |
| 363 insertNodeAt(listItemElement, positionBeforeNode(nextList)); | 363 insertNodeAt(listItemElement, positionBeforeNode(nextList)); |
| 364 else { | 364 else { |
| 365 // Create the list. | 365 // Create the list. |
| 366 listElement = createHTMLElement(document(), listTag); | 366 listElement = createHTMLElement(document(), listTag); |
| 367 appendNode(listItemElement, listElement); | 367 appendNode(listItemElement, listElement); |
| 368 | 368 |
| 369 if (start == end && isBlock(start.deepEquivalent().deprecatedNode())) { | 369 if (start == end && isBlock(start.deepEquivalent().anchorNode())) { |
| 370 // Inserting the list into an empty paragraph that isn't held open | 370 // Inserting the list into an empty paragraph that isn't held open |
| 371 // by a br or a '\n', will invalidate start and end. Insert | 371 // by a br or a '\n', will invalidate start and end. Insert |
| 372 // a placeholder and then recompute start and end. | 372 // a placeholder and then recompute start and end. |
| 373 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = insertBlockPlacehold
er(start.deepEquivalent()); | 373 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = insertBlockPlacehold
er(start.deepEquivalent()); |
| 374 start = VisiblePosition(positionBeforeNode(placeholder.get())); | 374 start = VisiblePosition(positionBeforeNode(placeholder.get())); |
| 375 end = start; | 375 end = start; |
| 376 } | 376 } |
| 377 | 377 |
| 378 // Insert the list at a position visually equivalent to start of the | 378 // Insert the list at a position visually equivalent to start of the |
| 379 // paragraph that is being moved into the list. | 379 // paragraph that is being moved into the list. |
| 380 // Try to avoid inserting it somewhere where it will be surrounded by | 380 // Try to avoid inserting it somewhere where it will be surrounded by |
| 381 // inline ancestors of start, since it is easier for editing to produce | 381 // inline ancestors of start, since it is easier for editing to produce |
| 382 // clean markup when inline elements are pushed down as far as possible. | 382 // clean markup when inline elements are pushed down as far as possible. |
| 383 Position insertionPos(start.deepEquivalent().upstream()); | 383 Position insertionPos(start.deepEquivalent().upstream()); |
| 384 // Also avoid the containing list item. | 384 // Also avoid the containing list item. |
| 385 Node* listChild = enclosingListChild(insertionPos.deprecatedNode()); | 385 Node* listChild = enclosingListChild(insertionPos.anchorNode()); |
| 386 if (isHTMLLIElement(listChild)) | 386 if (isHTMLLIElement(listChild)) |
| 387 insertionPos = positionInParentBeforeNode(*listChild); | 387 insertionPos = positionInParentBeforeNode(*listChild); |
| 388 | 388 |
| 389 insertNodeAt(listElement, insertionPos); | 389 insertNodeAt(listElement, insertionPos); |
| 390 | 390 |
| 391 // We inserted the list at the start of the content we're about to move | 391 // We inserted the list at the start of the content we're about to move |
| 392 // Update the start of content, so we don't try to move the list into it
self. bug 19066 | 392 // Update the start of content, so we don't try to move the list into it
self. bug 19066 |
| 393 // Layout is necessary since start's node's inline layoutObjects may hav
e been destroyed by the insertion | 393 // Layout is necessary since start's node's inline layoutObjects may hav
e been destroyed by the insertion |
| 394 // The end of the content may have changed after the insertion and layou
t so update it as well. | 394 // The end of the content may have changed after the insertion and layou
t so update it as well. |
| 395 if (insertionPos == start.deepEquivalent()) | 395 if (insertionPos == start.deepEquivalent()) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 412 return listElement; | 412 return listElement; |
| 413 } | 413 } |
| 414 | 414 |
| 415 DEFINE_TRACE(InsertListCommand) | 415 DEFINE_TRACE(InsertListCommand) |
| 416 { | 416 { |
| 417 visitor->trace(m_listElement); | 417 visitor->trace(m_listElement); |
| 418 CompositeEditCommand::trace(visitor); | 418 CompositeEditCommand::trace(visitor); |
| 419 } | 419 } |
| 420 | 420 |
| 421 } | 421 } |
| OLD | NEW |