| 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 |