| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty
le updateStyle) | 154 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty
le updateStyle) |
| 155 { | 155 { |
| 156 Node* node = p.parentAnchoredEquivalent().anchorNode(); | 156 Node* node = p.parentAnchoredEquivalent().anchorNode(); |
| 157 if (!node) | 157 if (!node) |
| 158 return false; | 158 return false; |
| 159 if (updateStyle == UpdateStyle) | 159 if (updateStyle == UpdateStyle) |
| 160 node->document().updateLayoutIgnorePendingStylesheets(); | 160 node->document().updateLayoutIgnorePendingStylesheets(); |
| 161 else | 161 else |
| 162 ASSERT(updateStyle == DoNotUpdateStyle); | 162 ASSERT(updateStyle == DoNotUpdateStyle); |
| 163 | 163 |
| 164 if (isRenderedTableElement(node)) | 164 if (isRenderedHTMLTableElement(node)) |
| 165 node = node->parentNode(); | 165 node = node->parentNode(); |
| 166 | 166 |
| 167 return node->hasEditableStyle(editableType); | 167 return node->hasEditableStyle(editableType); |
| 168 } | 168 } |
| 169 | 169 |
| 170 bool isAtUnsplittableElement(const Position& pos) | 170 bool isAtUnsplittableElement(const Position& pos) |
| 171 { | 171 { |
| 172 Node* node = pos.deprecatedNode(); | 172 Node* node = pos.deprecatedNode(); |
| 173 return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(
pos, &isTableCell)); | 173 return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(
pos, &isTableCell)); |
| 174 } | 174 } |
| 175 | 175 |
| 176 | 176 |
| 177 bool isRichlyEditablePosition(const Position& p, EditableType editableType) | 177 bool isRichlyEditablePosition(const Position& p, EditableType editableType) |
| 178 { | 178 { |
| 179 Node* node = p.deprecatedNode(); | 179 Node* node = p.deprecatedNode(); |
| 180 if (!node) | 180 if (!node) |
| 181 return false; | 181 return false; |
| 182 | 182 |
| 183 if (isRenderedTableElement(node)) | 183 if (isRenderedHTMLTableElement(node)) |
| 184 node = node->parentNode(); | 184 node = node->parentNode(); |
| 185 | 185 |
| 186 return node->rendererIsRichlyEditable(editableType); | 186 return node->rendererIsRichlyEditable(editableType); |
| 187 } | 187 } |
| 188 | 188 |
| 189 Element* editableRootForPosition(const Position& p, EditableType editableType) | 189 Element* editableRootForPosition(const Position& p, EditableType editableType) |
| 190 { | 190 { |
| 191 Node* node = p.containerNode(); | 191 Node* node = p.containerNode(); |
| 192 if (!node) | 192 if (!node) |
| 193 return 0; | 193 return 0; |
| 194 | 194 |
| 195 if (isRenderedTableElement(node)) | 195 if (isRenderedHTMLTableElement(node)) |
| 196 node = node->parentNode(); | 196 node = node->parentNode(); |
| 197 | 197 |
| 198 return node->rootEditableElement(editableType); | 198 return node->rootEditableElement(editableType); |
| 199 } | 199 } |
| 200 | 200 |
| 201 // Finds the enclosing element until which the tree can be split. | 201 // Finds the enclosing element until which the tree can be split. |
| 202 // When a user hits ENTER, he/she won't expect this element to be split into two
. | 202 // When a user hits ENTER, he/she won't expect this element to be split into two
. |
| 203 // You may pass it as the second argument of splitTreeToNode. | 203 // You may pass it as the second argument of splitTreeToNode. |
| 204 Element* unsplittableElementForPosition(const Position& p) | 204 Element* unsplittableElementForPosition(const Position& p) |
| 205 { | 205 { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 } | 450 } |
| 451 | 451 |
| 452 static HTMLElement* firstInSpecialElement(const Position& pos) | 452 static HTMLElement* firstInSpecialElement(const Position& pos) |
| 453 { | 453 { |
| 454 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); | 454 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); |
| 455 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd
itableElement; n = n->parentNode()) { | 455 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd
itableElement; n = n->parentNode()) { |
| 456 if (isSpecialHTMLElement(n)) { | 456 if (isSpecialHTMLElement(n)) { |
| 457 HTMLElement* specialElement = toHTMLElement(n); | 457 HTMLElement* specialElement = toHTMLElement(n); |
| 458 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); | 458 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); |
| 459 VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBe
foreNode(specialElement), DOWNSTREAM); | 459 VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBe
foreNode(specialElement), DOWNSTREAM); |
| 460 if (isRenderedTable(specialElement) && vPos == firstInElement.next()
) | 460 if (isRenderedTableElement(specialElement) && vPos == firstInElement
.next()) |
| 461 return specialElement; | 461 return specialElement; |
| 462 if (vPos == firstInElement) | 462 if (vPos == firstInElement) |
| 463 return specialElement; | 463 return specialElement; |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 return 0; | 466 return 0; |
| 467 } | 467 } |
| 468 | 468 |
| 469 static HTMLElement* lastInSpecialElement(const Position& pos) | 469 static HTMLElement* lastInSpecialElement(const Position& pos) |
| 470 { | 470 { |
| 471 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); | 471 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); |
| 472 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd
itableElement; n = n->parentNode()) { | 472 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd
itableElement; n = n->parentNode()) { |
| 473 if (isSpecialHTMLElement(n)) { | 473 if (isSpecialHTMLElement(n)) { |
| 474 HTMLElement* specialElement = toHTMLElement(n); | 474 HTMLElement* specialElement = toHTMLElement(n); |
| 475 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); | 475 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); |
| 476 VisiblePosition lastInElement = VisiblePosition(lastPositionInOrAfte
rNode(specialElement), DOWNSTREAM); | 476 VisiblePosition lastInElement = VisiblePosition(lastPositionInOrAfte
rNode(specialElement), DOWNSTREAM); |
| 477 if (isRenderedTable(specialElement) && vPos == lastInElement.previou
s()) | 477 if (isRenderedTableElement(specialElement) && vPos == lastInElement.
previous()) |
| 478 return specialElement; | 478 return specialElement; |
| 479 if (vPos == lastInElement) | 479 if (vPos == lastInElement) |
| 480 return specialElement; | 480 return specialElement; |
| 481 } | 481 } |
| 482 } | 482 } |
| 483 return 0; | 483 return 0; |
| 484 } | 484 } |
| 485 | 485 |
| 486 Position positionBeforeContainingSpecialElement(const Position& pos, HTMLElement
** containingSpecialElement) | 486 Position positionBeforeContainingSpecialElement(const Position& pos, HTMLElement
** containingSpecialElement) |
| 487 { | 487 { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 502 if (!n) | 502 if (!n) |
| 503 return pos; | 503 return pos; |
| 504 Position result = positionInParentAfterNode(*n); | 504 Position result = positionInParentAfterNode(*n); |
| 505 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) | 505 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos
.deprecatedNode()->rootEditableElement()) |
| 506 return pos; | 506 return pos; |
| 507 if (containingSpecialElement) | 507 if (containingSpecialElement) |
| 508 *containingSpecialElement = n; | 508 *containingSpecialElement = n; |
| 509 return result; | 509 return result; |
| 510 } | 510 } |
| 511 | 511 |
| 512 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) | 512 Element* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) |
| 513 { | 513 { |
| 514 Position upstream(visiblePosition.deepEquivalent().upstream()); | 514 Position upstream(visiblePosition.deepEquivalent().upstream()); |
| 515 if (isRenderedTable(upstream.deprecatedNode()) && upstream.atLastEditingPosi
tionForNode()) | 515 if (isRenderedTableElement(upstream.deprecatedNode()) && upstream.atLastEdit
ingPositionForNode()) |
| 516 return upstream.deprecatedNode(); | 516 return toElement(upstream.deprecatedNode()); |
| 517 | 517 |
| 518 return 0; | 518 return 0; |
| 519 } | 519 } |
| 520 | 520 |
| 521 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) | 521 Element* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) |
| 522 { | 522 { |
| 523 Position downstream(visiblePosition.deepEquivalent().downstream()); | 523 Position downstream(visiblePosition.deepEquivalent().downstream()); |
| 524 if (isRenderedTable(downstream.deprecatedNode()) && downstream.atFirstEditin
gPositionForNode()) | 524 if (isRenderedTableElement(downstream.deprecatedNode()) && downstream.atFirs
tEditingPositionForNode()) |
| 525 return downstream.deprecatedNode(); | 525 return toElement(downstream.deprecatedNode()); |
| 526 | 526 |
| 527 return 0; | 527 return 0; |
| 528 } | 528 } |
| 529 | 529 |
| 530 // Returns the visible position at the beginning of a node | 530 // Returns the visible position at the beginning of a node |
| 531 VisiblePosition visiblePositionBeforeNode(Node& node) | 531 VisiblePosition visiblePositionBeforeNode(Node& node) |
| 532 { | 532 { |
| 533 if (node.hasChildren()) | 533 if (node.hasChildren()) |
| 534 return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM); | 534 return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM); |
| 535 ASSERT(node.parentNode()); | 535 ASSERT(node.parentNode()); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 743 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) | 743 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) |
| 744 return false; | 744 return false; |
| 745 | 745 |
| 746 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) | 746 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) |
| 747 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l
ists are editable | 747 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l
ists are editable |
| 748 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries | 748 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries |
| 749 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent
BeforeNode(*secondList)); | 749 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent
BeforeNode(*secondList)); |
| 750 // Make sure there is no visible content between this li and the previous li
st | 750 // Make sure there is no visible content between this li and the previous li
st |
| 751 } | 751 } |
| 752 | 752 |
| 753 bool isRenderedHTMLTableElement(const Node* node) |
| 754 { |
| 755 return isHTMLTableElement(*node) && node->renderer(); |
| 756 } |
| 757 |
| 753 bool isRenderedTableElement(const Node* node) | 758 bool isRenderedTableElement(const Node* node) |
| 754 { | 759 { |
| 755 return isHTMLTableElement(*node) && node->renderer(); | |
| 756 } | |
| 757 | |
| 758 bool isRenderedTable(const Node* node) | |
| 759 { | |
| 760 if (!node || !node->isElementNode()) | 760 if (!node || !node->isElementNode()) |
| 761 return false; | 761 return false; |
| 762 | 762 |
| 763 RenderObject* renderer = node->renderer(); | 763 RenderObject* renderer = node->renderer(); |
| 764 return (renderer && renderer->isTable()); | 764 return (renderer && renderer->isTable()); |
| 765 } | 765 } |
| 766 | 766 |
| 767 bool isTableCell(const Node* node) | 767 bool isTableCell(const Node* node) |
| 768 { | 768 { |
| 769 ASSERT(node); | 769 ASSERT(node); |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original
) | 1074 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original
) |
| 1075 { | 1075 { |
| 1076 VisibleSelection newSelection(original); | 1076 VisibleSelection newSelection(original); |
| 1077 VisiblePosition startOfSelection(newSelection.visibleStart()); | 1077 VisiblePosition startOfSelection(newSelection.visibleStart()); |
| 1078 VisiblePosition endOfSelection(newSelection.visibleEnd()); | 1078 VisiblePosition endOfSelection(newSelection.visibleEnd()); |
| 1079 | 1079 |
| 1080 // If the end of the selection to modify is just after a table, and | 1080 // If the end of the selection to modify is just after a table, and |
| 1081 // if the start of the selection is inside that table, then the last paragra
ph | 1081 // if the start of the selection is inside that table, then the last paragra
ph |
| 1082 // that we'll want modify is the last one inside the table, not the table it
self | 1082 // that we'll want modify is the last one inside the table, not the table it
self |
| 1083 // (a table is itself a paragraph). | 1083 // (a table is itself a paragraph). |
| 1084 if (Node* table = isFirstPositionAfterTable(endOfSelection)) | 1084 if (Element* table = isFirstPositionAfterTable(endOfSelection)) |
| 1085 if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(t
able)) | 1085 if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(t
able)) |
| 1086 newSelection = VisibleSelection(startOfSelection, endOfSelection.pre
vious(CannotCrossEditingBoundary)); | 1086 newSelection = VisibleSelection(startOfSelection, endOfSelection.pre
vious(CannotCrossEditingBoundary)); |
| 1087 | 1087 |
| 1088 // If the start of the selection to modify is just before a table, | 1088 // If the start of the selection to modify is just before a table, |
| 1089 // and if the end of the selection is inside that table, then the first para
graph | 1089 // and if the end of the selection is inside that table, then the first para
graph |
| 1090 // we'll want to modify is the first one inside the table, not the paragraph | 1090 // we'll want to modify is the first one inside the table, not the paragraph |
| 1091 // containing the table itself. | 1091 // containing the table itself. |
| 1092 if (Node* table = isLastPositionBeforeTable(startOfSelection)) | 1092 if (Element* table = isLastPositionBeforeTable(startOfSelection)) |
| 1093 if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(tab
le)) | 1093 if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(tab
le)) |
| 1094 newSelection = VisibleSelection(startOfSelection.next(CannotCrossEdi
tingBoundary), endOfSelection); | 1094 newSelection = VisibleSelection(startOfSelection.next(CannotCrossEdi
tingBoundary), endOfSelection); |
| 1095 | 1095 |
| 1096 return newSelection; | 1096 return newSelection; |
| 1097 } | 1097 } |
| 1098 | 1098 |
| 1099 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators
to convert between | 1099 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators
to convert between |
| 1100 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEm
itsCharactersBetweenAllVisiblePositions | 1100 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEm
itsCharactersBetweenAllVisiblePositions |
| 1101 // does not exactly match VisiblePosition iteration, so using them to preserve a
selection during an editing | 1101 // does not exactly match VisiblePosition iteration, so using them to preserve a
selection during an editing |
| 1102 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllV
isiblePositions mode needs to be fixed, | 1102 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllV
isiblePositions mode needs to be fixed, |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1224 // if the selection starts just before a paragraph break, skip over it | 1224 // if the selection starts just before a paragraph break, skip over it |
| 1225 if (isEndOfParagraph(visiblePosition)) | 1225 if (isEndOfParagraph(visiblePosition)) |
| 1226 return visiblePosition.next().deepEquivalent().downstream(); | 1226 return visiblePosition.next().deepEquivalent().downstream(); |
| 1227 | 1227 |
| 1228 // otherwise, make sure to be at the start of the first selected node, | 1228 // otherwise, make sure to be at the start of the first selected node, |
| 1229 // instead of possibly at the end of the last node before the selection | 1229 // instead of possibly at the end of the last node before the selection |
| 1230 return visiblePosition.deepEquivalent().downstream(); | 1230 return visiblePosition.deepEquivalent().downstream(); |
| 1231 } | 1231 } |
| 1232 | 1232 |
| 1233 } // namespace blink | 1233 } // namespace blink |
| OLD | NEW |