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 |