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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } | 97 } |
98 | 98 |
99 bool needsLayoutTreeUpdate(const Position& position) { | 99 bool needsLayoutTreeUpdate(const Position& position) { |
100 return needsLayoutTreeUpdateAlgorithm<Position>(position); | 100 return needsLayoutTreeUpdateAlgorithm<Position>(position); |
101 } | 101 } |
102 | 102 |
103 bool needsLayoutTreeUpdate(const PositionInFlatTree& position) { | 103 bool needsLayoutTreeUpdate(const PositionInFlatTree& position) { |
104 return needsLayoutTreeUpdateAlgorithm<PositionInFlatTree>(position); | 104 return needsLayoutTreeUpdateAlgorithm<PositionInFlatTree>(position); |
105 } | 105 } |
106 | 106 |
107 // Atomic means that the node has no children, or has children which are ignored
for the | 107 // Atomic means that the node has no children, or has children which are ignored |
108 // purposes of editing. | 108 // for the purposes of editing. |
109 bool isAtomicNode(const Node* node) { | 109 bool isAtomicNode(const Node* node) { |
110 return node && (!node->hasChildren() || editingIgnoresContent(node)); | 110 return node && (!node->hasChildren() || editingIgnoresContent(node)); |
111 } | 111 } |
112 | 112 |
113 template <typename Traversal> | 113 template <typename Traversal> |
114 static int comparePositions(Node* containerA, | 114 static int comparePositions(Node* containerA, |
115 int offsetA, | 115 int offsetA, |
116 Node* containerB, | 116 Node* containerB, |
117 int offsetB, | 117 int offsetB, |
118 bool* disconnected) { | 118 bool* disconnected) { |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 ? PositionTemplate<Strategy>::inParentAfterNode( | 587 ? PositionTemplate<Strategy>::inParentAfterNode( |
588 *editablePosition.anchorNode()) | 588 *editablePosition.anchorNode()) |
589 : nextVisuallyDistinctCandidate(editablePosition); | 589 : nextVisuallyDistinctCandidate(editablePosition); |
590 } | 590 } |
591 | 591 |
592 if (editablePosition.anchorNode() && | 592 if (editablePosition.anchorNode() && |
593 editablePosition.anchorNode() != &highestRoot && | 593 editablePosition.anchorNode() != &highestRoot && |
594 !editablePosition.anchorNode()->isDescendantOf(&highestRoot)) | 594 !editablePosition.anchorNode()->isDescendantOf(&highestRoot)) |
595 return PositionTemplate<Strategy>(); | 595 return PositionTemplate<Strategy>(); |
596 | 596 |
597 // If |editablePosition| has the non-editable child skipped, get the next sibl
ing position. | 597 // If |editablePosition| has the non-editable child skipped, get the next |
598 // If not, we can't get the next paragraph in InsertListCommand::doApply's whi
le loop. | 598 // sibling position. If not, we can't get the next paragraph in |
599 // See http://crbug.com/571420 | 599 // InsertListCommand::doApply's while loop. See http://crbug.com/571420 |
600 if (nonEditableNode && | 600 if (nonEditableNode && |
601 nonEditableNode->isDescendantOf(editablePosition.anchorNode())) | 601 nonEditableNode->isDescendantOf(editablePosition.anchorNode())) |
602 editablePosition = nextVisuallyDistinctCandidate(editablePosition); | 602 editablePosition = nextVisuallyDistinctCandidate(editablePosition); |
603 return editablePosition; | 603 return editablePosition; |
604 } | 604 } |
605 | 605 |
606 Position firstEditablePositionAfterPositionInRoot(const Position& position, | 606 Position firstEditablePositionAfterPositionInRoot(const Position& position, |
607 Node& highestRoot) { | 607 Node& highestRoot) { |
608 return firstEditablePositionAfterPositionInRootAlgorithm<EditingStrategy>( | 608 return firstEditablePositionAfterPositionInRootAlgorithm<EditingStrategy>( |
609 position, highestRoot); | 609 position, highestRoot); |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 EditingBoundaryCrossingRule rule) { | 1253 EditingBoundaryCrossingRule rule) { |
1254 // TODO(yosin) support CanSkipCrossEditingBoundary | 1254 // TODO(yosin) support CanSkipCrossEditingBoundary |
1255 DCHECK(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary) | 1255 DCHECK(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary) |
1256 << rule; | 1256 << rule; |
1257 if (p.isNull()) | 1257 if (p.isNull()) |
1258 return nullptr; | 1258 return nullptr; |
1259 | 1259 |
1260 ContainerNode* const root = | 1260 ContainerNode* const root = |
1261 rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : nullptr; | 1261 rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : nullptr; |
1262 for (Node* n = p.anchorNode(); n; n = Strategy::parent(*n)) { | 1262 for (Node* n = p.anchorNode(); n; n = Strategy::parent(*n)) { |
1263 // Don't return a non-editable node if the input position was editable, sinc
e | 1263 // Don't return a non-editable node if the input position was editable, |
1264 // the callers from editing will no doubt want to perform editing inside the
returned node. | 1264 // since the callers from editing will no doubt want to perform editing |
| 1265 // inside the returned node. |
1265 if (root && !hasEditableStyle(*n)) | 1266 if (root && !hasEditableStyle(*n)) |
1266 continue; | 1267 continue; |
1267 if (nodeIsOfType(n)) | 1268 if (nodeIsOfType(n)) |
1268 return n; | 1269 return n; |
1269 if (n == root) | 1270 if (n == root) |
1270 return nullptr; | 1271 return nullptr; |
1271 } | 1272 } |
1272 | 1273 |
1273 return nullptr; | 1274 return nullptr; |
1274 } | 1275 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 if (runner == root) | 1364 if (runner == root) |
1364 return 0; | 1365 return 0; |
1365 } | 1366 } |
1366 | 1367 |
1367 return 0; | 1368 return 0; |
1368 } | 1369 } |
1369 | 1370 |
1370 Node* enclosingListChild(Node* node) { | 1371 Node* enclosingListChild(Node* node) { |
1371 if (!node) | 1372 if (!node) |
1372 return 0; | 1373 return 0; |
1373 // Check for a list item element, or for a node whose parent is a list element
. Such a node | 1374 // Check for a list item element, or for a node whose parent is a list |
1374 // will appear visually as a list item (but without a list marker) | 1375 // element. Such a node will appear visually as a list item (but without a |
| 1376 // list marker) |
1375 ContainerNode* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); | 1377 ContainerNode* root = highestEditableRoot(firstPositionInOrBeforeNode(node)); |
1376 | 1378 |
1377 // FIXME: This function is inappropriately named if it starts with node instea
d of node->parentNode() | 1379 // FIXME: This function is inappropriately named if it starts with node |
| 1380 // instead of node->parentNode() |
1378 for (Node* n = node; n && n->parentNode(); n = n->parentNode()) { | 1381 for (Node* n = node; n && n->parentNode(); n = n->parentNode()) { |
1379 if (isHTMLLIElement(*n) || | 1382 if (isHTMLLIElement(*n) || |
1380 (isHTMLListElement(n->parentNode()) && n != root)) | 1383 (isHTMLListElement(n->parentNode()) && n != root)) |
1381 return n; | 1384 return n; |
1382 if (n == root || isTableCell(n)) | 1385 if (n == root || isTableCell(n)) |
1383 return 0; | 1386 return 0; |
1384 } | 1387 } |
1385 | 1388 |
1386 return 0; | 1389 return 0; |
1387 } | 1390 } |
1388 | 1391 |
1389 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagrap
h | 1392 // FIXME: This method should not need to call |
| 1393 // isStartOfParagraph/isEndOfParagraph |
1390 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) { | 1394 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos) { |
1391 DCHECK(visiblePos.isValid()); | 1395 DCHECK(visiblePos.isValid()); |
1392 | 1396 |
1393 // Check that position is on a line by itself inside a list item | 1397 // Check that position is on a line by itself inside a list item |
1394 Node* listChildNode = | 1398 Node* listChildNode = |
1395 enclosingListChild(visiblePos.deepEquivalent().anchorNode()); | 1399 enclosingListChild(visiblePos.deepEquivalent().anchorNode()); |
1396 if (!listChildNode || !isStartOfParagraph(visiblePos) || | 1400 if (!listChildNode || !isStartOfParagraph(visiblePos) || |
1397 !isEndOfParagraph(visiblePos)) | 1401 !isEndOfParagraph(visiblePos)) |
1398 return 0; | 1402 return 0; |
1399 | 1403 |
(...skipping 16 matching lines...) Expand all Loading... |
1416 | 1420 |
1417 while (HTMLElement* nextList = enclosingList(list)) { | 1421 while (HTMLElement* nextList = enclosingList(list)) { |
1418 if (nextList == rootList) | 1422 if (nextList == rootList) |
1419 break; | 1423 break; |
1420 list = nextList; | 1424 list = nextList; |
1421 } | 1425 } |
1422 | 1426 |
1423 return list; | 1427 return list; |
1424 } | 1428 } |
1425 | 1429 |
1426 // Determines whether two positions are visibly next to each other (first then s
econd) | 1430 // Determines whether two positions are visibly next to each other (first then |
1427 // while ignoring whitespaces and unrendered nodes | 1431 // second) while ignoring whitespaces and unrendered nodes |
1428 static bool isVisiblyAdjacent(const Position& first, const Position& second) { | 1432 static bool isVisiblyAdjacent(const Position& first, const Position& second) { |
1429 return createVisiblePositionDeprecated(first).deepEquivalent() == | 1433 return createVisiblePositionDeprecated(first).deepEquivalent() == |
1430 createVisiblePositionDeprecated(mostBackwardCaretPosition(second)) | 1434 createVisiblePositionDeprecated(mostBackwardCaretPosition(second)) |
1431 .deepEquivalent(); | 1435 .deepEquivalent(); |
1432 } | 1436 } |
1433 | 1437 |
1434 bool canMergeLists(Element* firstList, Element* secondList) { | 1438 bool canMergeLists(Element* firstList, Element* secondList) { |
1435 if (!firstList || !secondList || !firstList->isHTMLElement() || | 1439 if (!firstList || !secondList || !firstList->isHTMLElement() || |
1436 !secondList->isHTMLElement()) | 1440 !secondList->isHTMLElement()) |
1437 return false; | 1441 return false; |
(...skipping 21 matching lines...) Expand all Loading... |
1459 | 1463 |
1460 bool isTableCell(const Node* node) { | 1464 bool isTableCell(const Node* node) { |
1461 DCHECK(node); | 1465 DCHECK(node); |
1462 LayoutObject* r = node->layoutObject(); | 1466 LayoutObject* r = node->layoutObject(); |
1463 return r ? r->isTableCell() : isHTMLTableCellElement(*node); | 1467 return r ? r->isTableCell() : isHTMLTableCellElement(*node); |
1464 } | 1468 } |
1465 | 1469 |
1466 bool isEmptyTableCell(const Node* node) { | 1470 bool isEmptyTableCell(const Node* node) { |
1467 // Returns true IFF the passed in node is one of: | 1471 // Returns true IFF the passed in node is one of: |
1468 // .) a table cell with no children, | 1472 // .) a table cell with no children, |
1469 // .) a table cell with a single BR child, and which has no other child layo
utObject, including :before and :after layoutObject | 1473 // .) a table cell with a single BR child, and which has no other child |
| 1474 // layoutObject, including :before and :after layoutObject |
1470 // .) the BR child of such a table cell | 1475 // .) the BR child of such a table cell |
1471 | 1476 |
1472 // Find rendered node | 1477 // Find rendered node |
1473 while (node && !node->layoutObject()) | 1478 while (node && !node->layoutObject()) |
1474 node = node->parentNode(); | 1479 node = node->parentNode(); |
1475 if (!node) | 1480 if (!node) |
1476 return false; | 1481 return false; |
1477 | 1482 |
1478 // Make sure the rendered node is a table cell or <br>. | 1483 // Make sure the rendered node is a table cell or <br>. |
1479 // If it's a <br>, then the parent node has to be a table cell. | 1484 // If it's a <br>, then the parent node has to be a table cell. |
1480 LayoutObject* layoutObject = node->layoutObject(); | 1485 LayoutObject* layoutObject = node->layoutObject(); |
1481 if (layoutObject->isBR()) { | 1486 if (layoutObject->isBR()) { |
1482 layoutObject = layoutObject->parent(); | 1487 layoutObject = layoutObject->parent(); |
1483 if (!layoutObject) | 1488 if (!layoutObject) |
1484 return false; | 1489 return false; |
1485 } | 1490 } |
1486 if (!layoutObject->isTableCell()) | 1491 if (!layoutObject->isTableCell()) |
1487 return false; | 1492 return false; |
1488 | 1493 |
1489 // Check that the table cell contains no child layoutObjects except for perhap
s a single <br>. | 1494 // Check that the table cell contains no child layoutObjects except for |
| 1495 // perhaps a single <br>. |
1490 LayoutObject* childLayoutObject = | 1496 LayoutObject* childLayoutObject = |
1491 toLayoutTableCell(layoutObject)->firstChild(); | 1497 toLayoutTableCell(layoutObject)->firstChild(); |
1492 if (!childLayoutObject) | 1498 if (!childLayoutObject) |
1493 return true; | 1499 return true; |
1494 if (!childLayoutObject->isBR()) | 1500 if (!childLayoutObject->isBR()) |
1495 return false; | 1501 return false; |
1496 return !childLayoutObject->nextSibling(); | 1502 return !childLayoutObject->nextSibling(); |
1497 } | 1503 } |
1498 | 1504 |
1499 HTMLElement* createDefaultParagraphElement(Document& document) { | 1505 HTMLElement* createDefaultParagraphElement(Document& document) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1558 } | 1564 } |
1559 | 1565 |
1560 bool isNodeRendered(const Node& node) { | 1566 bool isNodeRendered(const Node& node) { |
1561 LayoutObject* layoutObject = node.layoutObject(); | 1567 LayoutObject* layoutObject = node.layoutObject(); |
1562 if (!layoutObject) | 1568 if (!layoutObject) |
1563 return false; | 1569 return false; |
1564 | 1570 |
1565 return layoutObject->style()->visibility() == EVisibility::Visible; | 1571 return layoutObject->style()->visibility() == EVisibility::Visible; |
1566 } | 1572 } |
1567 | 1573 |
1568 // return first preceding DOM position rendered at a different location, or "thi
s" | 1574 // return first preceding DOM position rendered at a different location, or |
| 1575 // "this" |
1569 static Position previousCharacterPosition(const Position& position, | 1576 static Position previousCharacterPosition(const Position& position, |
1570 TextAffinity affinity) { | 1577 TextAffinity affinity) { |
1571 if (position.isNull()) | 1578 if (position.isNull()) |
1572 return Position(); | 1579 return Position(); |
1573 | 1580 |
1574 Element* fromRootEditableElement = | 1581 Element* fromRootEditableElement = |
1575 rootEditableElement(*position.anchorNode()); | 1582 rootEditableElement(*position.anchorNode()); |
1576 | 1583 |
1577 bool atStartOfLine = | 1584 bool atStartOfLine = |
1578 isStartOfLine(createVisiblePositionDeprecated(position, affinity)); | 1585 isStartOfLine(createVisiblePositionDeprecated(position, affinity)); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 | 1767 |
1761 // Modifies selections that have an end point at the edge of a table | 1768 // Modifies selections that have an end point at the edge of a table |
1762 // that contains the other endpoint so that they don't confuse | 1769 // that contains the other endpoint so that they don't confuse |
1763 // code that iterates over selected paragraphs. | 1770 // code that iterates over selected paragraphs. |
1764 VisibleSelection selectionForParagraphIteration( | 1771 VisibleSelection selectionForParagraphIteration( |
1765 const VisibleSelection& original) { | 1772 const VisibleSelection& original) { |
1766 VisibleSelection newSelection(original); | 1773 VisibleSelection newSelection(original); |
1767 VisiblePosition startOfSelection(newSelection.visibleStart()); | 1774 VisiblePosition startOfSelection(newSelection.visibleStart()); |
1768 VisiblePosition endOfSelection(newSelection.visibleEnd()); | 1775 VisiblePosition endOfSelection(newSelection.visibleEnd()); |
1769 | 1776 |
1770 // If the end of the selection to modify is just after a table, and | 1777 // If the end of the selection to modify is just after a table, and if the |
1771 // if the start of the selection is inside that table, then the last paragraph | 1778 // start of the selection is inside that table, then the last paragraph that |
1772 // that we'll want modify is the last one inside the table, not the table itse
lf | 1779 // we'll want modify is the last one inside the table, not the table itself (a |
1773 // (a table is itself a paragraph). | 1780 // table is itself a paragraph). |
1774 if (Element* table = tableElementJustBefore(endOfSelection)) { | 1781 if (Element* table = tableElementJustBefore(endOfSelection)) { |
1775 if (startOfSelection.deepEquivalent().anchorNode()->isDescendantOf(table)) | 1782 if (startOfSelection.deepEquivalent().anchorNode()->isDescendantOf(table)) |
1776 newSelection = createVisibleSelection( | 1783 newSelection = createVisibleSelection( |
1777 startOfSelection, | 1784 startOfSelection, |
1778 previousPositionOf(endOfSelection, CannotCrossEditingBoundary)); | 1785 previousPositionOf(endOfSelection, CannotCrossEditingBoundary)); |
1779 } | 1786 } |
1780 | 1787 |
1781 // If the start of the selection to modify is just before a table, | 1788 // If the start of the selection to modify is just before a table, and if the |
1782 // and if the end of the selection is inside that table, then the first paragr
aph | 1789 // end of the selection is inside that table, then the first paragraph we'll |
1783 // we'll want to modify is the first one inside the table, not the paragraph | 1790 // want to modify is the first one inside the table, not the paragraph |
1784 // containing the table itself. | 1791 // containing the table itself. |
1785 if (Element* table = tableElementJustAfter(startOfSelection)) { | 1792 if (Element* table = tableElementJustAfter(startOfSelection)) { |
1786 if (endOfSelection.deepEquivalent().anchorNode()->isDescendantOf(table)) | 1793 if (endOfSelection.deepEquivalent().anchorNode()->isDescendantOf(table)) |
1787 newSelection = createVisibleSelection( | 1794 newSelection = createVisibleSelection( |
1788 nextPositionOf(startOfSelection, CannotCrossEditingBoundary), | 1795 nextPositionOf(startOfSelection, CannotCrossEditingBoundary), |
1789 endOfSelection); | 1796 endOfSelection); |
1790 } | 1797 } |
1791 | 1798 |
1792 return newSelection; | 1799 return newSelection; |
1793 } | 1800 } |
1794 | 1801 |
1795 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators
to convert between | 1802 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators |
1796 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEm
itsCharactersBetweenAllVisiblePositions | 1803 // to convert between VisiblePositions and indices. But TextIterator iteration |
1797 // does not exactly match VisiblePosition iteration, so using them to preserve a
selection during an editing | 1804 // using TextIteratorEmitsCharactersBetweenAllVisiblePositions does not exactly |
1798 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllV
isiblePositions mode needs to be fixed, | 1805 // match VisiblePosition iteration, so using them to preserve a selection during |
1799 // or these functions need to be changed to iterate using actual VisiblePosition
s. | 1806 // an editing opertion is unreliable. TextIterator's |
1800 // FIXME: Deploy these functions everywhere that TextIterators are used to conve
rt between VisiblePositions and indices. | 1807 // TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed, |
| 1808 // or these functions need to be changed to iterate using actual |
| 1809 // VisiblePositions. |
| 1810 // FIXME: Deploy these functions everywhere that TextIterators are used to |
| 1811 // convert between VisiblePositions and indices. |
1801 int indexForVisiblePosition(const VisiblePosition& visiblePosition, | 1812 int indexForVisiblePosition(const VisiblePosition& visiblePosition, |
1802 ContainerNode*& scope) { | 1813 ContainerNode*& scope) { |
1803 if (visiblePosition.isNull()) | 1814 if (visiblePosition.isNull()) |
1804 return 0; | 1815 return 0; |
1805 | 1816 |
1806 Position p(visiblePosition.deepEquivalent()); | 1817 Position p(visiblePosition.deepEquivalent()); |
1807 Document& document = *p.document(); | 1818 Document& document = *p.document(); |
1808 DCHECK(!document.needsLayoutTreeUpdate()); | 1819 DCHECK(!document.needsLayoutTreeUpdate()); |
1809 | 1820 |
1810 ShadowRoot* shadowRoot = p.anchorNode()->containingShadowRoot(); | 1821 ShadowRoot* shadowRoot = p.anchorNode()->containingShadowRoot(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 | 1883 |
1873 EphemeralRange range = PlainTextRange(index).createRangeForSelection(*scope); | 1884 EphemeralRange range = PlainTextRange(index).createRangeForSelection(*scope); |
1874 // Check for an invalid index. Certain editing operations invalidate indices | 1885 // Check for an invalid index. Certain editing operations invalidate indices |
1875 // because of problems with | 1886 // because of problems with |
1876 // TextIteratorEmitsCharactersBetweenAllVisiblePositions. | 1887 // TextIteratorEmitsCharactersBetweenAllVisiblePositions. |
1877 if (range.isNull()) | 1888 if (range.isNull()) |
1878 return VisiblePosition(); | 1889 return VisiblePosition(); |
1879 return createVisiblePosition(range.startPosition()); | 1890 return createVisiblePosition(range.startPosition()); |
1880 } | 1891 } |
1881 | 1892 |
1882 // Determines whether a node is inside a range or visibly starts and ends at the
boundaries of the range. | 1893 // Determines whether a node is inside a range or visibly starts and ends at the |
1883 // Call this function to determine whether a node is visibly fit inside selected
Range | 1894 // boundaries of the range. Call this function to determine whether a node is |
| 1895 // visibly fit inside selectedRange |
1884 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) { | 1896 bool isNodeVisiblyContainedWithin(Node& node, const Range& selectedRange) { |
1885 if (selectedRange.isNodeFullyContained(node)) | 1897 if (selectedRange.isNodeFullyContained(node)) |
1886 return true; | 1898 return true; |
1887 | 1899 |
1888 bool startIsVisuallySame = | 1900 bool startIsVisuallySame = |
1889 visiblePositionBeforeNode(node).deepEquivalent() == | 1901 visiblePositionBeforeNode(node).deepEquivalent() == |
1890 createVisiblePositionDeprecated(selectedRange.startPosition()) | 1902 createVisiblePositionDeprecated(selectedRange.startPosition()) |
1891 .deepEquivalent(); | 1903 .deepEquivalent(); |
1892 if (startIsVisuallySame && | 1904 if (startIsVisuallySame && |
1893 comparePositions(Position::inParentAfterNode(node), | 1905 comparePositions(Position::inParentAfterNode(node), |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 | 1958 |
1947 bool isBlockFlowElement(const Node& node) { | 1959 bool isBlockFlowElement(const Node& node) { |
1948 LayoutObject* layoutObject = node.layoutObject(); | 1960 LayoutObject* layoutObject = node.layoutObject(); |
1949 return node.isElementNode() && layoutObject && | 1961 return node.isElementNode() && layoutObject && |
1950 layoutObject->isLayoutBlockFlow(); | 1962 layoutObject->isLayoutBlockFlow(); |
1951 } | 1963 } |
1952 | 1964 |
1953 Position adjustedSelectionStartForStyleComputation( | 1965 Position adjustedSelectionStartForStyleComputation( |
1954 const VisibleSelection& selection) { | 1966 const VisibleSelection& selection) { |
1955 // This function is used by range style computations to avoid bugs like: | 1967 // This function is used by range style computations to avoid bugs like: |
1956 // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a sele
ction starting from end of line once | 1968 // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a |
1957 // It is important to skip certain irrelevant content at the start of the sele
ction, so we do not wind up | 1969 // selection starting from end of line once |
1958 // with a spurious "mixed" style. | 1970 // It is important to skip certain irrelevant content at the start of the |
| 1971 // selection, so we do not wind up with a spurious "mixed" style. |
1959 | 1972 |
1960 VisiblePosition visiblePosition = createVisiblePosition(selection.start()); | 1973 VisiblePosition visiblePosition = createVisiblePosition(selection.start()); |
1961 if (visiblePosition.isNull()) | 1974 if (visiblePosition.isNull()) |
1962 return Position(); | 1975 return Position(); |
1963 | 1976 |
1964 // if the selection is a caret, just return the position, since the style | 1977 // if the selection is a caret, just return the position, since the style |
1965 // behind us is relevant | 1978 // behind us is relevant |
1966 if (selection.isCaret()) | 1979 if (selection.isCaret()) |
1967 return visiblePosition.deepEquivalent(); | 1980 return visiblePosition.deepEquivalent(); |
1968 | 1981 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2058 return InputType::DeleteWordBackward; | 2071 return InputType::DeleteWordBackward; |
2059 if (granularity == LineBoundary) | 2072 if (granularity == LineBoundary) |
2060 return InputType::DeleteLineBackward; | 2073 return InputType::DeleteLineBackward; |
2061 return InputType::DeleteContentBackward; | 2074 return InputType::DeleteContentBackward; |
2062 default: | 2075 default: |
2063 return InputType::None; | 2076 return InputType::None; |
2064 } | 2077 } |
2065 } | 2078 } |
2066 | 2079 |
2067 } // namespace blink | 2080 } // namespace blink |
OLD | NEW |