Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2009 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 continue; | 74 continue; |
| 75 if (!node->hasEditableStyle()) | 75 if (!node->hasEditableStyle()) |
| 76 continue; | 76 continue; |
| 77 if ((layoutObject->isBox() && toLayoutBox(layoutObject)->inlineBoxWrappe r()) || (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox())) | 77 if ((layoutObject->isBox() && toLayoutBox(layoutObject)->inlineBoxWrappe r()) || (layoutObject->isText() && toLayoutText(layoutObject)->firstTextBox())) |
| 78 return node; | 78 return node; |
| 79 } | 79 } |
| 80 return 0; | 80 return 0; |
| 81 } | 81 } |
| 82 | 82 |
| 83 template <typename Strategy> | 83 template <typename Strategy> |
| 84 const TreeScope* PositionAlgorithm<Strategy>::commonAncestorTreeScope(const Posi tionType& a, const PositionType& b) | 84 const TreeScope* PositionAlgorithm<Strategy>::commonAncestorTreeScope(const Posi tionAlgorithm<Strategy>& a, const PositionAlgorithm<Strategy>& b) |
| 85 { | 85 { |
| 86 if (!a.containerNode() || !b.containerNode()) | 86 if (!a.containerNode() || !b.containerNode()) |
| 87 return nullptr; | 87 return nullptr; |
| 88 return a.containerNode()->treeScope().commonAncestorTreeScope(b.containerNod e()->treeScope()); | 88 return a.containerNode()->treeScope().commonAncestorTreeScope(b.containerNod e()->treeScope()); |
| 89 } | 89 } |
| 90 | 90 |
| 91 template <typename Strategy> | 91 template <typename Strategy> |
| 92 PositionAlgorithm<Strategy>::PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anch orNode, LegacyEditingOffset offset) | 92 PositionAlgorithm<Strategy>::PositionAlgorithm(PassRefPtrWillBeRawPtr<Node> anch orNode, LegacyEditingOffset offset) |
| 93 : m_anchorNode(anchorNode) | 93 : m_anchorNode(anchorNode) |
| 94 , m_offset(offset.value()) | 94 , m_offset(offset.value()) |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 int PositionAlgorithm<Strategy>::offsetForPositionAfterAnchor() const | 223 int PositionAlgorithm<Strategy>::offsetForPositionAfterAnchor() const |
| 224 { | 224 { |
| 225 ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAf terChildren); | 225 ASSERT(m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsAf terChildren); |
| 226 ASSERT(!m_isLegacyEditingPosition); | 226 ASSERT(!m_isLegacyEditingPosition); |
| 227 return Strategy::lastOffsetForEditing(m_anchorNode.get()); | 227 return Strategy::lastOffsetForEditing(m_anchorNode.get()); |
| 228 } | 228 } |
| 229 | 229 |
| 230 // Neighbor-anchored positions are invalid DOM positions, so they need to be | 230 // Neighbor-anchored positions are invalid DOM positions, so they need to be |
| 231 // fixed up before handing them off to the Range object. | 231 // fixed up before handing them off to the Range object. |
| 232 template <typename Strategy> | 232 template <typename Strategy> |
| 233 typename Strategy::PositionType PositionAlgorithm<Strategy>::parentAnchoredEquiv alent() const | 233 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::parentAnchored Equivalent() const |
|
yosin_UTC9
2015/06/26 08:39:24
We don't need to have |typename|.
Apply this comme
yoichio
2015/06/29 06:00:33
Done.
| |
| 234 { | 234 { |
| 235 if (!m_anchorNode) | 235 if (!m_anchorNode) |
| 236 return PositionType(); | 236 return PositionAlgorithm<Strategy>(); |
| 237 | 237 |
| 238 // FIXME: This should only be necessary for legacy positions, but is also ne eded for positions before and after Tables | 238 // FIXME: This should only be necessary for legacy positions, but is also ne eded for positions before and after Tables |
| 239 if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) { | 239 if (m_offset <= 0 && (m_anchorType != PositionIsAfterAnchor && m_anchorType != PositionIsAfterChildren)) { |
| 240 if (Strategy::parent(*m_anchorNode) && (Strategy::editingIgnoresContent( m_anchorNode.get()) || isRenderedHTMLTableElement(m_anchorNode.get()))) | 240 if (Strategy::parent(*m_anchorNode) && (Strategy::editingIgnoresContent( m_anchorNode.get()) || isRenderedHTMLTableElement(m_anchorNode.get()))) |
| 241 return inParentBeforeNode(*m_anchorNode); | 241 return inParentBeforeNode(*m_anchorNode); |
| 242 return PositionType(m_anchorNode.get(), 0, PositionIsOffsetInAnchor); | 242 return PositionAlgorithm<Strategy>(m_anchorNode.get(), 0, PositionIsOffs etInAnchor); |
| 243 } | 243 } |
| 244 if (!m_anchorNode->offsetInCharacters() | 244 if (!m_anchorNode->offsetInCharacters() |
| 245 && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsA fterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->countChildren() ) | 245 && (m_anchorType == PositionIsAfterAnchor || m_anchorType == PositionIsA fterChildren || static_cast<unsigned>(m_offset) == m_anchorNode->countChildren() ) |
| 246 && (Strategy::editingIgnoresContent(m_anchorNode.get()) || isRenderedHTM LTableElement(m_anchorNode.get())) | 246 && (Strategy::editingIgnoresContent(m_anchorNode.get()) || isRenderedHTM LTableElement(m_anchorNode.get())) |
| 247 && containerNode()) { | 247 && containerNode()) { |
| 248 return inParentAfterNode(*m_anchorNode); | 248 return inParentAfterNode(*m_anchorNode); |
| 249 } | 249 } |
| 250 | 250 |
| 251 return PositionType(containerNode(), computeOffsetInContainerNode(), Positio nIsOffsetInAnchor); | 251 return PositionAlgorithm<Strategy>(containerNode(), computeOffsetInContainer Node(), PositionIsOffsetInAnchor); |
| 252 } | 252 } |
| 253 | 253 |
| 254 template <typename Strategy> | 254 template <typename Strategy> |
| 255 typename Strategy::PositionType PositionAlgorithm<Strategy>::toOffsetInAnchor() const | 255 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::toOffsetInAnch or() const |
| 256 { | 256 { |
| 257 if (isNull()) | 257 if (isNull()) |
| 258 return PositionType(); | 258 return PositionAlgorithm<Strategy>(); |
| 259 | 259 |
| 260 return PositionType(containerNode(), computeOffsetInContainerNode(), Positio nIsOffsetInAnchor); | 260 return PositionAlgorithm<Strategy>(containerNode(), computeOffsetInContainer Node(), PositionIsOffsetInAnchor); |
| 261 } | 261 } |
| 262 | 262 |
| 263 template <typename Strategy> | 263 template <typename Strategy> |
| 264 Node* PositionAlgorithm<Strategy>::computeNodeBeforePosition() const | 264 Node* PositionAlgorithm<Strategy>::computeNodeBeforePosition() const |
| 265 { | 265 { |
| 266 if (!m_anchorNode) | 266 if (!m_anchorNode) |
| 267 return 0; | 267 return 0; |
| 268 switch (anchorType()) { | 268 switch (anchorType()) { |
| 269 case PositionIsBeforeChildren: | 269 case PositionIsBeforeChildren: |
| 270 return 0; | 270 return 0; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 if (m_anchorType != PositionIsOffsetInAnchor) | 339 if (m_anchorType != PositionIsOffsetInAnchor) |
| 340 return toOffsetInAnchor().nodeAsRangePastLastNode(); | 340 return toOffsetInAnchor().nodeAsRangePastLastNode(); |
| 341 if (m_anchorNode->offsetInCharacters()) | 341 if (m_anchorNode->offsetInCharacters()) |
| 342 return Strategy::nextSkippingChildren(*m_anchorNode); | 342 return Strategy::nextSkippingChildren(*m_anchorNode); |
| 343 if (Node* child = Strategy::childAt(*m_anchorNode, m_offset)) | 343 if (Node* child = Strategy::childAt(*m_anchorNode, m_offset)) |
| 344 return child; | 344 return child; |
| 345 return Strategy::nextSkippingChildren(*m_anchorNode); | 345 return Strategy::nextSkippingChildren(*m_anchorNode); |
| 346 } | 346 } |
| 347 | 347 |
| 348 template <typename Strategy> | 348 template <typename Strategy> |
| 349 Node* PositionAlgorithm<Strategy>::commonAncestorContainer(const PositionType& o ther) const | 349 Node* PositionAlgorithm<Strategy>::commonAncestorContainer(const PositionAlgorit hm<Strategy>& other) const |
| 350 { | 350 { |
| 351 return Strategy::commonAncestor(*containerNode(), *other.containerNode()); | 351 return Strategy::commonAncestor(*containerNode(), *other.containerNode()); |
| 352 } | 352 } |
| 353 | 353 |
| 354 template <typename Strategy> | 354 template <typename Strategy> |
| 355 typename PositionAlgorithm<Strategy>::AnchorType PositionAlgorithm<Strategy>::an chorTypeForLegacyEditingPosition(Node* anchorNode, int offset) | 355 typename PositionAlgorithm<Strategy>::AnchorType PositionAlgorithm<Strategy>::an chorTypeForLegacyEditingPosition(Node* anchorNode, int offset) |
| 356 { | 356 { |
| 357 if (anchorNode && Strategy::editingIgnoresContent(anchorNode)) { | 357 if (anchorNode && Strategy::editingIgnoresContent(anchorNode)) { |
| 358 if (offset == 0) | 358 if (offset == 0) |
| 359 return PositionIsBeforeAnchor; | 359 return PositionIsBeforeAnchor; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 388 ASSERT(positionB.isNotNull()); | 388 ASSERT(positionB.isNotNull()); |
| 389 | 389 |
| 390 Node* containerA = positionA.containerNode(); | 390 Node* containerA = positionA.containerNode(); |
| 391 Node* containerB = positionB.containerNode(); | 391 Node* containerB = positionB.containerNode(); |
| 392 int offsetA = positionA.computeOffsetInContainerNode(); | 392 int offsetA = positionA.computeOffsetInContainerNode(); |
| 393 int offsetB = positionB.computeOffsetInContainerNode(); | 393 int offsetB = positionB.computeOffsetInContainerNode(); |
| 394 return EditingInComposedTreeStrategy::comparePositions(containerA, offsetA, containerB, offsetB); | 394 return EditingInComposedTreeStrategy::comparePositions(containerA, offsetA, containerB, offsetB); |
| 395 } | 395 } |
| 396 | 396 |
| 397 template <typename Strategy> | 397 template <typename Strategy> |
| 398 int PositionAlgorithm<Strategy>::compareTo(const PositionType& other) const | 398 int PositionAlgorithm<Strategy>::compareTo(const PositionAlgorithm<Strategy>& ot her) const |
| 399 { | 399 { |
| 400 return comparePositions(*this, other); | 400 return comparePositions(*this, other); |
| 401 } | 401 } |
| 402 | 402 |
| 403 template <typename Strategy> | 403 template <typename Strategy> |
| 404 typename Strategy::PositionType PositionAlgorithm<Strategy>::previous(PositionMo veType moveType) const | 404 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::previous(Posit ionMoveType moveType) const |
| 405 { | 405 { |
| 406 Node* node = deprecatedNode(); | 406 Node* node = deprecatedNode(); |
| 407 if (!node) | 407 if (!node) |
| 408 return PositionType(*this); | 408 return PositionAlgorithm<Strategy>(*this); |
| 409 | 409 |
| 410 int offset = deprecatedEditingOffset(); | 410 int offset = deprecatedEditingOffset(); |
| 411 // FIXME: Negative offsets shouldn't be allowed. We should catch this earlie r. | 411 // FIXME: Negative offsets shouldn't be allowed. We should catch this earlie r. |
| 412 ASSERT(offset >= 0); | 412 ASSERT(offset >= 0); |
| 413 | 413 |
| 414 if (offset > 0) { | 414 if (offset > 0) { |
| 415 if (Node* child = Strategy::childAt(*node, offset - 1)) | 415 if (Node* child = Strategy::childAt(*node, offset - 1)) |
| 416 return lastPositionInOrAfterNode(child); | 416 return lastPositionInOrAfterNode(child); |
| 417 | 417 |
| 418 // There are two reasons child might be 0: | 418 // There are two reasons child might be 0: |
| 419 // 1) The node is node like a text node that is not an element, and th erefore has no children. | 419 // 1) The node is node like a text node that is not an element, and th erefore has no children. |
| 420 // Going backward one character at a time is correct. | 420 // Going backward one character at a time is correct. |
| 421 // 2) The old offset was a bogus offset like (<br>, 1), and there is n o child. | 421 // 2) The old offset was a bogus offset like (<br>, 1), and there is n o child. |
| 422 // Going from 1 to 0 is correct. | 422 // Going from 1 to 0 is correct. |
| 423 switch (moveType) { | 423 switch (moveType) { |
| 424 case CodePoint: | 424 case CodePoint: |
| 425 return createLegacyEditingPosition(node, offset - 1); | 425 return createLegacyEditingPosition(node, offset - 1); |
| 426 case Character: | 426 case Character: |
| 427 return createLegacyEditingPosition(node, uncheckedPreviousOffset(nod e, offset)); | 427 return createLegacyEditingPosition(node, uncheckedPreviousOffset(nod e, offset)); |
| 428 case BackwardDeletion: | 428 case BackwardDeletion: |
| 429 return createLegacyEditingPosition(node, uncheckedPreviousOffsetForB ackwardDeletion(node, offset)); | 429 return createLegacyEditingPosition(node, uncheckedPreviousOffsetForB ackwardDeletion(node, offset)); |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 | 432 |
| 433 if (ContainerNode* parent = Strategy::parent(*node)) | 433 if (ContainerNode* parent = Strategy::parent(*node)) |
| 434 return createLegacyEditingPosition(parent, node->nodeIndex()); | 434 return createLegacyEditingPosition(parent, node->nodeIndex()); |
| 435 return PositionType(*this); | 435 return PositionAlgorithm<Strategy>(*this); |
| 436 } | 436 } |
| 437 | 437 |
| 438 template <typename Strategy> | 438 template <typename Strategy> |
| 439 typename Strategy::PositionType PositionAlgorithm<Strategy>::next(PositionMoveTy pe moveType) const | 439 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::next(PositionM oveType moveType) const |
| 440 { | 440 { |
| 441 ASSERT(moveType != BackwardDeletion); | 441 ASSERT(moveType != BackwardDeletion); |
| 442 | 442 |
| 443 Node* node = deprecatedNode(); | 443 Node* node = deprecatedNode(); |
| 444 if (!node) | 444 if (!node) |
| 445 return PositionType(*this); | 445 return PositionAlgorithm<Strategy>(*this); |
| 446 | 446 |
| 447 int offset = deprecatedEditingOffset(); | 447 int offset = deprecatedEditingOffset(); |
| 448 // FIXME: Negative offsets shouldn't be allowed. We should catch this earlie r. | 448 // FIXME: Negative offsets shouldn't be allowed. We should catch this earlie r. |
| 449 ASSERT(offset >= 0); | 449 ASSERT(offset >= 0); |
| 450 | 450 |
| 451 if (Node* child = Strategy::childAt(*node, offset)) | 451 if (Node* child = Strategy::childAt(*node, offset)) |
| 452 return firstPositionInOrBeforeNode(child); | 452 return firstPositionInOrBeforeNode(child); |
| 453 | 453 |
| 454 if (!Strategy::hasChildren(*node) && offset < lastOffsetForEditing(node)) { | 454 if (!Strategy::hasChildren(*node) && offset < lastOffsetForEditing(node)) { |
| 455 // There are two reasons child might be 0: | 455 // There are two reasons child might be 0: |
| 456 // 1) The node is node like a text node that is not an element, and th erefore has no children. | 456 // 1) The node is node like a text node that is not an element, and th erefore has no children. |
| 457 // Going forward one character at a time is correct. | 457 // Going forward one character at a time is correct. |
| 458 // 2) The new offset is a bogus offset like (<br>, 1), and there is no child. | 458 // 2) The new offset is a bogus offset like (<br>, 1), and there is no child. |
| 459 // Going from 0 to 1 is correct. | 459 // Going from 0 to 1 is correct. |
| 460 return createLegacyEditingPosition(node, (moveType == Character) ? unche ckedNextOffset(node, offset) : offset + 1); | 460 return createLegacyEditingPosition(node, (moveType == Character) ? unche ckedNextOffset(node, offset) : offset + 1); |
| 461 } | 461 } |
| 462 | 462 |
| 463 if (ContainerNode* parent = Strategy::parent(*node)) | 463 if (ContainerNode* parent = Strategy::parent(*node)) |
| 464 return createLegacyEditingPosition(parent, node->nodeIndex() + 1); | 464 return createLegacyEditingPosition(parent, node->nodeIndex() + 1); |
| 465 return PositionType(*this); | 465 return PositionAlgorithm<Strategy>(*this); |
| 466 } | 466 } |
| 467 | 467 |
| 468 template <typename Strategy> | 468 template <typename Strategy> |
| 469 int PositionAlgorithm<Strategy>::uncheckedPreviousOffset(const Node* n, int curr ent) | 469 int PositionAlgorithm<Strategy>::uncheckedPreviousOffset(const Node* n, int curr ent) |
| 470 { | 470 { |
| 471 return n->layoutObject() ? n->layoutObject()->previousOffset(current) : curr ent - 1; | 471 return n->layoutObject() ? n->layoutObject()->previousOffset(current) : curr ent - 1; |
| 472 } | 472 } |
| 473 | 473 |
| 474 template <typename Strategy> | 474 template <typename Strategy> |
| 475 int PositionAlgorithm<Strategy>::uncheckedPreviousOffsetForBackwardDeletion(cons t Node* n, int current) | 475 int PositionAlgorithm<Strategy>::uncheckedPreviousOffsetForBackwardDeletion(cons t Node* n, int current) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 // A position is considered at editing boundary if one of the following is true: | 517 // A position is considered at editing boundary if one of the following is true: |
| 518 // 1. It is the first position in the node and the next visually equivalent posi tion | 518 // 1. It is the first position in the node and the next visually equivalent posi tion |
| 519 // is non editable. | 519 // is non editable. |
| 520 // 2. It is the last position in the node and the previous visually equivalent p osition | 520 // 2. It is the last position in the node and the previous visually equivalent p osition |
| 521 // is non editable. | 521 // is non editable. |
| 522 // 3. It is an editable position and both the next and previous visually equival ent | 522 // 3. It is an editable position and both the next and previous visually equival ent |
| 523 // positions are both non editable. | 523 // positions are both non editable. |
| 524 template <typename Strategy> | 524 template <typename Strategy> |
| 525 bool PositionAlgorithm<Strategy>::atEditingBoundary() const | 525 bool PositionAlgorithm<Strategy>::atEditingBoundary() const |
| 526 { | 526 { |
| 527 PositionType nextPosition = downstream(CanCrossEditingBoundary); | 527 PositionAlgorithm<Strategy> nextPosition = downstream(CanCrossEditingBoundar y); |
| 528 if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosi tion.deprecatedNode()->hasEditableStyle()) | 528 if (atFirstEditingPositionForNode() && nextPosition.isNotNull() && !nextPosi tion.deprecatedNode()->hasEditableStyle()) |
| 529 return true; | 529 return true; |
| 530 | 530 |
| 531 PositionType prevPosition = upstream(CanCrossEditingBoundary); | 531 PositionAlgorithm<Strategy> prevPosition = upstream(CanCrossEditingBoundary) ; |
| 532 if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosit ion.deprecatedNode()->hasEditableStyle()) | 532 if (atLastEditingPositionForNode() && prevPosition.isNotNull() && !prevPosit ion.deprecatedNode()->hasEditableStyle()) |
| 533 return true; | 533 return true; |
| 534 | 534 |
| 535 return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditab leStyle() | 535 return nextPosition.isNotNull() && !nextPosition.deprecatedNode()->hasEditab leStyle() |
| 536 && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditab leStyle(); | 536 && prevPosition.isNotNull() && !prevPosition.deprecatedNode()->hasEditab leStyle(); |
| 537 } | 537 } |
| 538 | 538 |
| 539 template <typename Strategy> | 539 template <typename Strategy> |
| 540 static ContainerNode* nonShadowBoundaryParentNode(Node* node) | 540 static ContainerNode* nonShadowBoundaryParentNode(Node* node) |
| 541 { | 541 { |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 return pos.atStartOfNode(); | 650 return pos.atStartOfNode(); |
| 651 } | 651 } |
| 652 | 652 |
| 653 // This function and downstream() are used for moving back and forth between vis ually equivalent candidates. | 653 // This function and downstream() are used for moving back and forth between vis ually equivalent candidates. |
| 654 // For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates | 654 // For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates |
| 655 // that map to the VisiblePosition between 'b' and the space. This function wil l return the left candidate | 655 // that map to the VisiblePosition between 'b' and the space. This function wil l return the left candidate |
| 656 // and downstream() will return the right one. | 656 // and downstream() will return the right one. |
| 657 // Also, upstream() will return [boundary, 0] for any of the positions from [bou ndary, 0] to the first candidate | 657 // Also, upstream() will return [boundary, 0] for any of the positions from [bou ndary, 0] to the first candidate |
| 658 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true. | 658 // in boundary, where endsOfNodeAreVisuallyDistinctPositions(boundary) is true. |
| 659 template <typename Strategy> | 659 template <typename Strategy> |
| 660 typename Strategy::PositionType PositionAlgorithm<Strategy>::upstream(EditingBou ndaryCrossingRule rule) const | 660 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::upstream(Editi ngBoundaryCrossingRule rule) const |
| 661 { | 661 { |
| 662 Node* startNode = deprecatedNode(); | 662 Node* startNode = deprecatedNode(); |
| 663 if (!startNode) | 663 if (!startNode) |
| 664 return PositionType(); | 664 return PositionAlgorithm<Strategy>(); |
| 665 | 665 |
| 666 // iterate backward from there, looking for a qualified position | 666 // iterate backward from there, looking for a qualified position |
| 667 Node* boundary = enclosingVisualBoundary<Strategy>(startNode); | 667 Node* boundary = enclosingVisualBoundary<Strategy>(startNode); |
| 668 // FIXME: PositionIterator should respect Before and After positions. | 668 // FIXME: PositionIterator should respect Before and After positions. |
| 669 typename Strategy::PositionIteratorType lastVisible(m_anchorType == Position IsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m _anchorNode.get())) : PositionType(*this)); | 669 typename Strategy::PositionIteratorType lastVisible(m_anchorType == Position IsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m _anchorNode.get())) : PositionAlgorithm<Strategy>(*this)); |
| 670 typename Strategy::PositionIteratorType currentPos = lastVisible; | 670 typename Strategy::PositionIteratorType currentPos = lastVisible; |
| 671 bool startEditable = startNode->hasEditableStyle(); | 671 bool startEditable = startNode->hasEditableStyle(); |
| 672 Node* lastNode = startNode; | 672 Node* lastNode = startNode; |
| 673 bool boundaryCrossed = false; | 673 bool boundaryCrossed = false; |
| 674 for (; !currentPos.atStart(); currentPos.decrement()) { | 674 for (; !currentPos.atStart(); currentPos.decrement()) { |
| 675 Node* currentNode = currentPos.node(); | 675 Node* currentNode = currentPos.node(); |
| 676 // Don't check for an editability change if we haven't moved to a differ ent node, | 676 // Don't check for an editability change if we haven't moved to a differ ent node, |
| 677 // to avoid the expense of computing hasEditableStyle(). | 677 // to avoid the expense of computing hasEditableStyle(). |
| 678 if (currentNode != lastNode) { | 678 if (currentNode != lastNode) { |
| 679 // Don't change editability. | 679 // Don't change editability. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 772 } | 772 } |
| 773 | 773 |
| 774 // This function and upstream() are used for moving back and forth between visua lly equivalent candidates. | 774 // This function and upstream() are used for moving back and forth between visua lly equivalent candidates. |
| 775 // For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates | 775 // For example, for the text node "foo bar" where whitespace is collapsible, there are two candidates |
| 776 // that map to the VisiblePosition between 'b' and the space. This function wil l return the right candidate | 776 // that map to the VisiblePosition between 'b' and the space. This function wil l return the right candidate |
| 777 // and upstream() will return the left one. | 777 // and upstream() will return the left one. |
| 778 // Also, downstream() will return the last position in the last atomic node in b oundary for all of the positions | 778 // Also, downstream() will return the last position in the last atomic node in b oundary for all of the positions |
| 779 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPosi tions(boundary). | 779 // in boundary after the last candidate, where endsOfNodeAreVisuallyDistinctPosi tions(boundary). |
| 780 // FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264 | 780 // FIXME: This function should never be called when the line box tree is dirty. See https://bugs.webkit.org/show_bug.cgi?id=97264 |
| 781 template <typename Strategy> | 781 template <typename Strategy> |
| 782 typename Strategy::PositionType PositionAlgorithm<Strategy>::downstream(EditingB oundaryCrossingRule rule) const | 782 typename PositionAlgorithm<Strategy> PositionAlgorithm<Strategy>::downstream(Edi tingBoundaryCrossingRule rule) const |
| 783 { | 783 { |
| 784 Node* startNode = deprecatedNode(); | 784 Node* startNode = deprecatedNode(); |
| 785 if (!startNode) | 785 if (!startNode) |
| 786 return PositionType(); | 786 return PositionAlgorithm<Strategy>(); |
| 787 | 787 |
| 788 // iterate forward from there, looking for a qualified position | 788 // iterate forward from there, looking for a qualified position |
| 789 Node* boundary = enclosingVisualBoundary<Strategy>(startNode); | 789 Node* boundary = enclosingVisualBoundary<Strategy>(startNode); |
| 790 // FIXME: PositionIterator should respect Before and After positions. | 790 // FIXME: PositionIterator should respect Before and After positions. |
| 791 typename Strategy::PositionIteratorType lastVisible(m_anchorType == Position IsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m _anchorNode.get())) : PositionType(*this)); | 791 typename Strategy::PositionIteratorType lastVisible(m_anchorType == Position IsAfterAnchor ? createLegacyEditingPosition(m_anchorNode.get(), caretMaxOffset(m _anchorNode.get())) : PositionAlgorithm<Strategy>(*this)); |
| 792 typename Strategy::PositionIteratorType currentPos = lastVisible; | 792 typename Strategy::PositionIteratorType currentPos = lastVisible; |
| 793 bool startEditable = startNode->hasEditableStyle(); | 793 bool startEditable = startNode->hasEditableStyle(); |
| 794 Node* lastNode = startNode; | 794 Node* lastNode = startNode; |
| 795 bool boundaryCrossed = false; | 795 bool boundaryCrossed = false; |
| 796 for (; !currentPos.atEnd(); currentPos.increment()) { | 796 for (; !currentPos.atEnd(); currentPos.increment()) { |
| 797 Node* currentNode = currentPos.node(); | 797 Node* currentNode = currentPos.node(); |
| 798 // Don't check for an editability change if we haven't moved to a differ ent node, | 798 // Don't check for an editability change if we haven't moved to a differ ent node, |
| 799 // to avoid the expense of computing hasEditableStyle(). | 799 // to avoid the expense of computing hasEditableStyle(). |
| 800 if (currentNode != lastNode) { | 800 if (currentNode != lastNode) { |
| 801 // Don't change editability. | 801 // Don't change editability. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1043 return false; | 1043 return false; |
| 1044 } | 1044 } |
| 1045 if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast <int>(box->start() + box->len())) | 1045 if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast <int>(box->start() + box->len())) |
| 1046 return true; | 1046 return true; |
| 1047 } | 1047 } |
| 1048 | 1048 |
| 1049 return false; | 1049 return false; |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 template <typename Strategy> | 1052 template <typename Strategy> |
| 1053 bool PositionAlgorithm<Strategy>::rendersInDifferentPosition(const PositionType &pos) const | 1053 bool PositionAlgorithm<Strategy>::rendersInDifferentPosition(const PositionAlgor ithm<Strategy> &pos) const |
| 1054 { | 1054 { |
| 1055 if (isNull() || pos.isNull()) | 1055 if (isNull() || pos.isNull()) |
| 1056 return false; | 1056 return false; |
| 1057 | 1057 |
| 1058 LayoutObject* layoutObject = deprecatedNode()->layoutObject(); | 1058 LayoutObject* layoutObject = deprecatedNode()->layoutObject(); |
| 1059 if (!layoutObject) | 1059 if (!layoutObject) |
| 1060 return false; | 1060 return false; |
| 1061 | 1061 |
| 1062 LayoutObject* posLayoutObject = pos.deprecatedNode()->layoutObject(); | 1062 LayoutObject* posLayoutObject = pos.deprecatedNode()->layoutObject(); |
| 1063 if (!posLayoutObject) | 1063 if (!posLayoutObject) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 minOffset = caretMinOffset; | 1171 minOffset = caretMinOffset; |
| 1172 } | 1172 } |
| 1173 } | 1173 } |
| 1174 if (match) | 1174 if (match) |
| 1175 return match; | 1175 return match; |
| 1176 } | 1176 } |
| 1177 } | 1177 } |
| 1178 return 0; | 1178 return 0; |
| 1179 } | 1179 } |
| 1180 | 1180 |
| 1181 template <typename PositionType> | 1181 template <typename Strategy> |
| 1182 PositionType downstreamIgnoringEditingBoundaries(PositionType position) | 1182 PositionAlgorithm<Strategy> downstreamIgnoringEditingBoundaries(PositionAlgorith m<Strategy> position) |
| 1183 { | 1183 { |
| 1184 PositionType lastPosition; | 1184 PositionAlgorithm<Strategy> lastPosition; |
| 1185 while (position != lastPosition) { | 1185 while (position != lastPosition) { |
| 1186 lastPosition = position; | 1186 lastPosition = position; |
| 1187 position = position.downstream(CanCrossEditingBoundary); | 1187 position = position.downstream(CanCrossEditingBoundary); |
| 1188 } | 1188 } |
| 1189 return position; | 1189 return position; |
| 1190 } | 1190 } |
| 1191 | 1191 |
| 1192 template <typename PositionType> | 1192 template <typename Strategy> |
| 1193 PositionType upstreamIgnoringEditingBoundaries(PositionType position) | 1193 PositionAlgorithm<Strategy> upstreamIgnoringEditingBoundaries(PositionAlgorithm< Strategy> position) |
| 1194 { | 1194 { |
| 1195 PositionType lastPosition; | 1195 PositionAlgorithm<Strategy> lastPosition; |
| 1196 while (position != lastPosition) { | 1196 while (position != lastPosition) { |
| 1197 lastPosition = position; | 1197 lastPosition = position; |
| 1198 position = position.upstream(CanCrossEditingBoundary); | 1198 position = position.upstream(CanCrossEditingBoundary); |
| 1199 } | 1199 } |
| 1200 return position; | 1200 return position; |
| 1201 } | 1201 } |
| 1202 | 1202 |
| 1203 template <typename Strategy> | 1203 template <typename Strategy> |
| 1204 void PositionAlgorithm<Strategy>::getInlineBoxAndOffset(EAffinity affinity, Text Direction primaryDirection, InlineBox*& inlineBox, int& caretOffset) const | 1204 void PositionAlgorithm<Strategy>::getInlineBoxAndOffset(EAffinity affinity, Text Direction primaryDirection, InlineBox*& inlineBox, int& caretOffset) const |
| 1205 { | 1205 { |
| 1206 caretOffset = deprecatedEditingOffset(); | 1206 caretOffset = deprecatedEditingOffset(); |
| 1207 LayoutObject* layoutObject = deprecatedNode()->layoutObject(); | 1207 LayoutObject* layoutObject = deprecatedNode()->layoutObject(); |
| 1208 | 1208 |
| 1209 if (!layoutObject->isText()) { | 1209 if (!layoutObject->isText()) { |
| 1210 inlineBox = 0; | 1210 inlineBox = 0; |
| 1211 if (canHaveChildrenForEditing(deprecatedNode()) && layoutObject->isLayou tBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { | 1211 if (canHaveChildrenForEditing(deprecatedNode()) && layoutObject->isLayou tBlockFlow() && hasRenderedNonAnonymousDescendantsWithHeight(layoutObject)) { |
| 1212 // Try a visually equivalent position with possibly opposite editabi lity. This helps in case |this| is in | 1212 // Try a visually equivalent position with possibly opposite editabi lity. This helps in case |this| is in |
| 1213 // an editable block but surrounded by non-editable positions. It ac ts to negate the logic at the beginning | 1213 // an editable block but surrounded by non-editable positions. It ac ts to negate the logic at the beginning |
| 1214 // of LayoutObject::createVisiblePosition(). | 1214 // of LayoutObject::createVisiblePosition(). |
| 1215 PositionType thisPosition = PositionType(*this); | 1215 PositionAlgorithm<Strategy> thisPosition = PositionAlgorithm<Strateg y>(*this); |
| 1216 PositionType equivalent = downstreamIgnoringEditingBoundaries<typena me Strategy::PositionType>(thisPosition); | 1216 PositionAlgorithm<Strategy> equivalent = downstreamIgnoringEditingBo undaries(thisPosition); |
| 1217 if (equivalent == thisPosition) { | 1217 if (equivalent == thisPosition) { |
| 1218 equivalent = upstreamIgnoringEditingBoundaries(thisPosition); | 1218 equivalent = upstreamIgnoringEditingBoundaries(thisPosition); |
| 1219 if (equivalent == thisPosition || downstreamIgnoringEditingBound aries<typename Strategy::PositionType>(equivalent) == thisPosition) | 1219 if (equivalent == thisPosition || downstreamIgnoringEditingBound aries(equivalent) == thisPosition) |
| 1220 return; | 1220 return; |
| 1221 } | 1221 } |
| 1222 | 1222 |
| 1223 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB ox, caretOffset); | 1223 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB ox, caretOffset); |
| 1224 return; | 1224 return; |
| 1225 } | 1225 } |
| 1226 if (layoutObject->isBox()) { | 1226 if (layoutObject->isBox()) { |
| 1227 inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper(); | 1227 inlineBox = toLayoutBox(layoutObject)->inlineBoxWrapper(); |
| 1228 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care tOffset < inlineBox->caretMaxOffset())) | 1228 if (!inlineBox || (caretOffset > inlineBox->caretMinOffset() && care tOffset < inlineBox->caretMaxOffset())) |
| 1229 return; | 1229 return; |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 | 1545 |
| 1546 void showTree(const blink::Position* pos) | 1546 void showTree(const blink::Position* pos) |
| 1547 { | 1547 { |
| 1548 if (pos) | 1548 if (pos) |
| 1549 pos->showTreeForThis(); | 1549 pos->showTreeForThis(); |
| 1550 else | 1550 else |
| 1551 fprintf(stderr, "Cannot showTree for (nil)\n"); | 1551 fprintf(stderr, "Cannot showTree for (nil)\n"); |
| 1552 } | 1552 } |
| 1553 | 1553 |
| 1554 #endif | 1554 #endif |
| OLD | NEW |