| 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 | 262 |
| 263 ContainerNode* highestRoot = rootEditableElementOf(position, editableType); | 263 ContainerNode* highestRoot = rootEditableElementOf(position, editableType); |
| 264 if (!highestRoot) | 264 if (!highestRoot) |
| 265 return 0; | 265 return 0; |
| 266 | 266 |
| 267 if (isHTMLBodyElement(*highestRoot)) | 267 if (isHTMLBodyElement(*highestRoot)) |
| 268 return highestRoot; | 268 return highestRoot; |
| 269 | 269 |
| 270 ContainerNode* node = highestRoot->parentNode(); | 270 ContainerNode* node = highestRoot->parentNode(); |
| 271 while (node) { | 271 while (node) { |
| 272 if (node->hasEditableStyle(editableType)) | 272 if (hasEditableStyle(*node, editableType)) |
| 273 highestRoot = node; | 273 highestRoot = node; |
| 274 if (isHTMLBodyElement(*node)) | 274 if (isHTMLBodyElement(*node)) |
| 275 break; | 275 break; |
| 276 node = node->parentNode(); | 276 node = node->parentNode(); |
| 277 } | 277 } |
| 278 | 278 |
| 279 return highestRoot; | 279 return highestRoot; |
| 280 } | 280 } |
| 281 | 281 |
| 282 ContainerNode* highestEditableRoot(const PositionInFlatTree& position, EditableT
ype editableType) | 282 ContainerNode* highestEditableRoot(const PositionInFlatTree& position, EditableT
ype editableType) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 296 // calling |isEditablePosition()| in |InStyleRecalc| is safe. | 296 // calling |isEditablePosition()| in |InStyleRecalc| is safe. |
| 297 } else { | 297 } else { |
| 298 DCHECK(!needsLayoutTreeUpdate(position)) << position; | 298 DCHECK(!needsLayoutTreeUpdate(position)) << position; |
| 299 } | 299 } |
| 300 | 300 |
| 301 if (isDisplayInsideTable(node)) | 301 if (isDisplayInsideTable(node)) |
| 302 node = node->parentNode(); | 302 node = node->parentNode(); |
| 303 | 303 |
| 304 if (node->isDocumentNode()) | 304 if (node->isDocumentNode()) |
| 305 return false; | 305 return false; |
| 306 return node->hasEditableStyle(editableType); | 306 return hasEditableStyle(*node, editableType); |
| 307 } | 307 } |
| 308 | 308 |
| 309 bool isEditablePosition(const PositionInFlatTree& p, EditableType editableType) | 309 bool isEditablePosition(const PositionInFlatTree& p, EditableType editableType) |
| 310 { | 310 { |
| 311 return isEditablePosition(toPositionInDOMTree(p), editableType); | 311 return isEditablePosition(toPositionInDOMTree(p), editableType); |
| 312 } | 312 } |
| 313 | 313 |
| 314 bool isAtUnsplittableElement(const Position& pos) | 314 bool isAtUnsplittableElement(const Position& pos) |
| 315 { | 315 { |
| 316 Node* node = pos.anchorNode(); | 316 Node* node = pos.anchorNode(); |
| 317 return (node == rootEditableElementOf(pos) || node == enclosingNodeOfType(po
s, &isTableCell)); | 317 return (node == rootEditableElementOf(pos) || node == enclosingNodeOfType(po
s, &isTableCell)); |
| 318 } | 318 } |
| 319 | 319 |
| 320 | 320 |
| 321 bool isRichlyEditablePosition(const Position& p, EditableType editableType) | 321 bool isRichlyEditablePosition(const Position& p, EditableType editableType) |
| 322 { | 322 { |
| 323 Node* node = p.anchorNode(); | 323 Node* node = p.anchorNode(); |
| 324 if (!node) | 324 if (!node) |
| 325 return false; | 325 return false; |
| 326 | 326 |
| 327 if (isDisplayInsideTable(node)) | 327 if (isDisplayInsideTable(node)) |
| 328 node = node->parentNode(); | 328 node = node->parentNode(); |
| 329 | 329 |
| 330 return node->layoutObjectIsRichlyEditable(editableType); | 330 return layoutObjectIsRichlyEditable(*node, editableType); |
| 331 } | 331 } |
| 332 | 332 |
| 333 Element* rootEditableElementOf(const Position& p, EditableType editableType) | 333 Element* rootEditableElementOf(const Position& p, EditableType editableType) |
| 334 { | 334 { |
| 335 Node* node = p.computeContainerNode(); | 335 Node* node = p.computeContainerNode(); |
| 336 if (!node) | 336 if (!node) |
| 337 return 0; | 337 return 0; |
| 338 | 338 |
| 339 if (isDisplayInsideTable(node)) | 339 if (isDisplayInsideTable(node)) |
| 340 node = node->parentNode(); | 340 node = node->parentNode(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 VisiblePositionInFlatTree firstEditableVisiblePositionAfterPositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) | 502 VisiblePositionInFlatTree firstEditableVisiblePositionAfterPositionInRoot(const
PositionInFlatTree& position, ContainerNode& highestRoot) |
| 503 { | 503 { |
| 504 return createVisiblePosition(firstEditablePositionAfterPositionInRoot(positi
on, highestRoot)); | 504 return createVisiblePosition(firstEditablePositionAfterPositionInRoot(positi
on, highestRoot)); |
| 505 } | 505 } |
| 506 | 506 |
| 507 template <typename Strategy> | 507 template <typename Strategy> |
| 508 PositionTemplate<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) | 508 PositionTemplate<Strategy> firstEditablePositionAfterPositionInRootAlgorithm(con
st PositionTemplate<Strategy>& position, Node& highestRoot) |
| 509 { | 509 { |
| 510 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; | 510 DCHECK(!needsLayoutTreeUpdate(highestRoot)) << position << ' ' << highestRoo
t; |
| 511 // position falls before highestRoot. | 511 // position falls before highestRoot. |
| 512 if (position.compareTo(PositionTemplate<Strategy>::firstPositionInNode(&high
estRoot)) == -1 && highestRoot.hasEditableStyle()) | 512 if (position.compareTo(PositionTemplate<Strategy>::firstPositionInNode(&high
estRoot)) == -1 && hasEditableStyle(highestRoot)) |
| 513 return PositionTemplate<Strategy>::firstPositionInNode(&highestRoot); | 513 return PositionTemplate<Strategy>::firstPositionInNode(&highestRoot); |
| 514 | 514 |
| 515 PositionTemplate<Strategy> editablePosition = position; | 515 PositionTemplate<Strategy> editablePosition = position; |
| 516 | 516 |
| 517 if (position.anchorNode()->treeScope() != highestRoot.treeScope()) { | 517 if (position.anchorNode()->treeScope() != highestRoot.treeScope()) { |
| 518 Node* shadowAncestor = highestRoot.treeScope().ancestorInThisScope(edita
blePosition.anchorNode()); | 518 Node* shadowAncestor = highestRoot.treeScope().ancestorInThisScope(edita
blePosition.anchorNode()); |
| 519 if (!shadowAncestor) | 519 if (!shadowAncestor) |
| 520 return PositionTemplate<Strategy>(); | 520 return PositionTemplate<Strategy>(); |
| 521 | 521 |
| 522 editablePosition = PositionTemplate<Strategy>::afterNode(shadowAncestor)
; | 522 editablePosition = PositionTemplate<Strategy>::afterNode(shadowAncestor)
; |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 } | 1095 } |
| 1096 | 1096 |
| 1097 Element* enclosingElementWithTag(const Position& p, const QualifiedName& tagName
) | 1097 Element* enclosingElementWithTag(const Position& p, const QualifiedName& tagName
) |
| 1098 { | 1098 { |
| 1099 if (p.isNull()) | 1099 if (p.isNull()) |
| 1100 return 0; | 1100 return 0; |
| 1101 | 1101 |
| 1102 ContainerNode* root = highestEditableRoot(p); | 1102 ContainerNode* root = highestEditableRoot(p); |
| 1103 Element* ancestor = p.anchorNode()->isElementNode() ? toElement(p.anchorNode
()) : p.anchorNode()->parentElement(); | 1103 Element* ancestor = p.anchorNode()->isElementNode() ? toElement(p.anchorNode
()) : p.anchorNode()->parentElement(); |
| 1104 for (; ancestor; ancestor = ancestor->parentElement()) { | 1104 for (; ancestor; ancestor = ancestor->parentElement()) { |
| 1105 if (root && !ancestor->hasEditableStyle()) | 1105 if (root && !hasEditableStyle(*ancestor)) |
| 1106 continue; | 1106 continue; |
| 1107 if (ancestor->hasTagName(tagName)) | 1107 if (ancestor->hasTagName(tagName)) |
| 1108 return ancestor; | 1108 return ancestor; |
| 1109 if (ancestor == root) | 1109 if (ancestor == root) |
| 1110 return 0; | 1110 return 0; |
| 1111 } | 1111 } |
| 1112 | 1112 |
| 1113 return 0; | 1113 return 0; |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 template <typename Strategy> | 1116 template <typename Strategy> |
| 1117 static Node* enclosingNodeOfTypeAlgorithm(const PositionTemplate<Strategy>& p, b
ool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule) | 1117 static Node* enclosingNodeOfTypeAlgorithm(const PositionTemplate<Strategy>& p, b
ool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule) |
| 1118 { | 1118 { |
| 1119 // TODO(yosin) support CanSkipCrossEditingBoundary | 1119 // TODO(yosin) support CanSkipCrossEditingBoundary |
| 1120 DCHECK(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary
) << rule; | 1120 DCHECK(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary
) << rule; |
| 1121 if (p.isNull()) | 1121 if (p.isNull()) |
| 1122 return nullptr; | 1122 return nullptr; |
| 1123 | 1123 |
| 1124 ContainerNode* const root = rule == CannotCrossEditingBoundary ? highestEdit
ableRoot(p) : nullptr; | 1124 ContainerNode* const root = rule == CannotCrossEditingBoundary ? highestEdit
ableRoot(p) : nullptr; |
| 1125 for (Node* n = p.anchorNode(); n; n = Strategy::parent(*n)) { | 1125 for (Node* n = p.anchorNode(); n; n = Strategy::parent(*n)) { |
| 1126 // Don't return a non-editable node if the input position was editable,
since | 1126 // Don't return a non-editable node if the input position was editable,
since |
| 1127 // the callers from editing will no doubt want to perform editing inside
the returned node. | 1127 // the callers from editing will no doubt want to perform editing inside
the returned node. |
| 1128 if (root && !n->hasEditableStyle()) | 1128 if (root && !hasEditableStyle(*n)) |
| 1129 continue; | 1129 continue; |
| 1130 if (nodeIsOfType(n)) | 1130 if (nodeIsOfType(n)) |
| 1131 return n; | 1131 return n; |
| 1132 if (n == root) | 1132 if (n == root) |
| 1133 return nullptr; | 1133 return nullptr; |
| 1134 } | 1134 } |
| 1135 | 1135 |
| 1136 return nullptr; | 1136 return nullptr; |
| 1137 } | 1137 } |
| 1138 | 1138 |
| 1139 Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*),
EditingBoundaryCrossingRule rule) | 1139 Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*),
EditingBoundaryCrossingRule rule) |
| 1140 { | 1140 { |
| 1141 return enclosingNodeOfTypeAlgorithm<EditingStrategy>(p, nodeIsOfType, rule); | 1141 return enclosingNodeOfTypeAlgorithm<EditingStrategy>(p, nodeIsOfType, rule); |
| 1142 } | 1142 } |
| 1143 | 1143 |
| 1144 Node* enclosingNodeOfType(const PositionInFlatTree& p, bool (*nodeIsOfType)(cons
t Node*), EditingBoundaryCrossingRule rule) | 1144 Node* enclosingNodeOfType(const PositionInFlatTree& p, bool (*nodeIsOfType)(cons
t Node*), EditingBoundaryCrossingRule rule) |
| 1145 { | 1145 { |
| 1146 return enclosingNodeOfTypeAlgorithm<EditingInFlatTreeStrategy>(p, nodeIsOfTy
pe, rule); | 1146 return enclosingNodeOfTypeAlgorithm<EditingInFlatTreeStrategy>(p, nodeIsOfTy
pe, rule); |
| 1147 } | 1147 } |
| 1148 | 1148 |
| 1149 Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const N
ode*), EditingBoundaryCrossingRule rule, Node* stayWithin) | 1149 Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const N
ode*), EditingBoundaryCrossingRule rule, Node* stayWithin) |
| 1150 { | 1150 { |
| 1151 Node* highest = nullptr; | 1151 Node* highest = nullptr; |
| 1152 ContainerNode* root = rule == CannotCrossEditingBoundary ? highestEditableRo
ot(p) : nullptr; | 1152 ContainerNode* root = rule == CannotCrossEditingBoundary ? highestEditableRo
ot(p) : nullptr; |
| 1153 for (Node* n = p.computeContainerNode(); n && n != stayWithin; n = n->parent
Node()) { | 1153 for (Node* n = p.computeContainerNode(); n && n != stayWithin; n = n->parent
Node()) { |
| 1154 if (root && !n->hasEditableStyle()) | 1154 if (root && !hasEditableStyle(*n)) |
| 1155 continue; | 1155 continue; |
| 1156 if (nodeIsOfType(n)) | 1156 if (nodeIsOfType(n)) |
| 1157 highest = n; | 1157 highest = n; |
| 1158 if (n == root) | 1158 if (n == root) |
| 1159 break; | 1159 break; |
| 1160 } | 1160 } |
| 1161 | 1161 |
| 1162 return highest; | 1162 return highest; |
| 1163 } | 1163 } |
| 1164 | 1164 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 { | 1281 { |
| 1282 return createVisiblePosition(first).deepEquivalent() == createVisiblePositio
n(mostBackwardCaretPosition(second)).deepEquivalent(); | 1282 return createVisiblePosition(first).deepEquivalent() == createVisiblePositio
n(mostBackwardCaretPosition(second)).deepEquivalent(); |
| 1283 } | 1283 } |
| 1284 | 1284 |
| 1285 bool canMergeLists(Element* firstList, Element* secondList) | 1285 bool canMergeLists(Element* firstList, Element* secondList) |
| 1286 { | 1286 { |
| 1287 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) | 1287 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) |
| 1288 return false; | 1288 return false; |
| 1289 | 1289 |
| 1290 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) | 1290 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) |
| 1291 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l
ists are editable | 1291 && hasEditableStyle(*firstList) && hasEditableStyle(*secondList) // both lis
ts are editable |
| 1292 && rootEditableElement(*firstList) == rootEditableElement(*secondList) // do
n't cross editing boundaries | 1292 && rootEditableElement(*firstList) == rootEditableElement(*secondList) // do
n't cross editing boundaries |
| 1293 && isVisiblyAdjacent(Position::inParentAfterNode(*firstList), Position::inPa
rentBeforeNode(*secondList)); | 1293 && isVisiblyAdjacent(Position::inParentAfterNode(*firstList), Position::inPa
rentBeforeNode(*secondList)); |
| 1294 // Make sure there is no visible content between this li and the previous li
st | 1294 // Make sure there is no visible content between this li and the previous li
st |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 bool isDisplayInsideTable(const Node* node) | 1297 bool isDisplayInsideTable(const Node* node) |
| 1298 { | 1298 { |
| 1299 if (!node || !node->isElementNode()) | 1299 if (!node || !node->isElementNode()) |
| 1300 return false; | 1300 return false; |
| 1301 | 1301 |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 return false; | 1723 return false; |
| 1724 | 1724 |
| 1725 const Element& firstElement = toElement(first); | 1725 const Element& firstElement = toElement(first); |
| 1726 const Element& secondElement = toElement(second); | 1726 const Element& secondElement = toElement(second); |
| 1727 if (!firstElement.hasTagName(secondElement.tagQName())) | 1727 if (!firstElement.hasTagName(secondElement.tagQName())) |
| 1728 return false; | 1728 return false; |
| 1729 | 1729 |
| 1730 if (!firstElement.hasEquivalentAttributes(&secondElement)) | 1730 if (!firstElement.hasEquivalentAttributes(&secondElement)) |
| 1731 return false; | 1731 return false; |
| 1732 | 1732 |
| 1733 return firstElement.hasEditableStyle() && secondElement.hasEditableStyle(); | 1733 return hasEditableStyle(firstElement) && hasEditableStyle(secondElement); |
| 1734 } | 1734 } |
| 1735 | 1735 |
| 1736 bool isNonTableCellHTMLBlockElement(const Node* node) | 1736 bool isNonTableCellHTMLBlockElement(const Node* node) |
| 1737 { | 1737 { |
| 1738 if (!node->isHTMLElement()) | 1738 if (!node->isHTMLElement()) |
| 1739 return false; | 1739 return false; |
| 1740 | 1740 |
| 1741 const HTMLElement& element = toHTMLElement(*node); | 1741 const HTMLElement& element = toHTMLElement(*node); |
| 1742 return element.hasTagName(listingTag) | 1742 return element.hasTagName(listingTag) |
| 1743 || element.hasTagName(olTag) | 1743 || element.hasTagName(olTag) |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 { | 1816 { |
| 1817 if (!RuntimeEnabledFeatures::inputEventEnabled()) | 1817 if (!RuntimeEnabledFeatures::inputEventEnabled()) |
| 1818 return DispatchEventResult::NotCanceled; | 1818 return DispatchEventResult::NotCanceled; |
| 1819 if (!target) | 1819 if (!target) |
| 1820 return DispatchEventResult::NotCanceled; | 1820 return DispatchEventResult::NotCanceled; |
| 1821 InputEvent* beforeInputEvent = InputEvent::createBeforeInput(inputType, data
, InputEvent::EventCancelable::IsCancelable, InputEvent::EventIsComposing::NotCo
mposing, ranges); | 1821 InputEvent* beforeInputEvent = InputEvent::createBeforeInput(inputType, data
, InputEvent::EventCancelable::IsCancelable, InputEvent::EventIsComposing::NotCo
mposing, ranges); |
| 1822 return target->dispatchEvent(beforeInputEvent); | 1822 return target->dispatchEvent(beforeInputEvent); |
| 1823 } | 1823 } |
| 1824 | 1824 |
| 1825 } // namespace blink | 1825 } // namespace blink |
| OLD | NEW |