| 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 11 matching lines...) Expand all Loading... |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/editing/Position.h" | 27 #include "core/editing/Position.h" |
| 28 | 28 |
| 29 #include "core/dom/shadow/ElementShadow.h" | 29 #include "core/dom/shadow/ElementShadow.h" |
| 30 #include "core/editing/EditingUtilities.h" | 30 #include "core/editing/EditingUtilities.h" |
| 31 #include "core/editing/TextAffinity.h" | 31 #include "core/editing/TextAffinity.h" |
| 32 #include "core/editing/VisibleUnits.h" | |
| 33 #include "core/layout/LayoutObject.h" | |
| 34 #include "wtf/text/CString.h" | 32 #include "wtf/text/CString.h" |
| 35 #include <stdio.h> | 33 #include <stdio.h> |
| 36 | 34 |
| 37 namespace blink { | 35 namespace blink { |
| 38 | 36 |
| 39 #if ENABLE(ASSERT) | 37 #if ENABLE(ASSERT) |
| 40 static bool canBeAnchorNode(Node* node) | 38 static bool canBeAnchorNode(Node* node) |
| 41 { | 39 { |
| 42 if (!node || node->isFirstLetterPseudoElement()) | 40 if (!node || node->isFirstLetterPseudoElement()) |
| 43 return true; | 41 return true; |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 int offsetB = positionB.computeOffsetInContainerNode(); | 290 int offsetB = positionB.computeOffsetInContainerNode(); |
| 293 return comparePositionsInComposedTree(containerA, offsetA, containerB, offse
tB); | 291 return comparePositionsInComposedTree(containerA, offsetA, containerB, offse
tB); |
| 294 } | 292 } |
| 295 | 293 |
| 296 template <typename Strategy> | 294 template <typename Strategy> |
| 297 int PositionAlgorithm<Strategy>::compareTo(const PositionAlgorithm<Strategy>& ot
her) const | 295 int PositionAlgorithm<Strategy>::compareTo(const PositionAlgorithm<Strategy>& ot
her) const |
| 298 { | 296 { |
| 299 return comparePositions(*this, other); | 297 return comparePositions(*this, other); |
| 300 } | 298 } |
| 301 | 299 |
| 302 // TODO(yosin) We should move |uncheckedPreviousOffsetForBackwardDeletion()| | |
| 303 // to "EditingUtilities.cpp" with |previousPositionOf()|. | |
| 304 // TODO(yosin) To avoid forward declaration, we should move implementation of | |
| 305 // |uncheckedPreviousOffsetForBackwardDeletion()| here. | |
| 306 static int uncheckedPreviousOffsetForBackwardDeletion(const Node*, int current); | |
| 307 | |
| 308 template <typename Strategy> | |
| 309 PositionAlgorithm<Strategy> previousPositionOfAlgorithm(const PositionAlgorithm<
Strategy>& position, PositionMoveType moveType) | |
| 310 { | |
| 311 Node* const node = position.anchorNode(); | |
| 312 if (!node) | |
| 313 return position; | |
| 314 | |
| 315 const int offset = position.computeEditingOffset(); | |
| 316 | |
| 317 if (offset > 0) { | |
| 318 if (editingIgnoresContent(node)) | |
| 319 return PositionAlgorithm<Strategy>::beforeNode(node); | |
| 320 if (Node* child = Strategy::childAt(*node, offset - 1)) | |
| 321 return PositionAlgorithm<Strategy>::lastPositionInOrAfterNode(child)
; | |
| 322 | |
| 323 // There are two reasons child might be 0: | |
| 324 // 1) The node is node like a text node that is not an element, and | |
| 325 // therefore has no children. Going backward one character at a | |
| 326 // time is correct. | |
| 327 // 2) The old offset was a bogus offset like (<br>, 1), and there is | |
| 328 // no child. Going from 1 to 0 is correct. | |
| 329 switch (moveType) { | |
| 330 case PositionMoveType::CodePoint: | |
| 331 return PositionAlgorithm<Strategy>(node, offset - 1); | |
| 332 case PositionMoveType::Character: | |
| 333 return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffset(nod
e, offset)); | |
| 334 case PositionMoveType::BackwardDeletion: | |
| 335 return PositionAlgorithm<Strategy>(node, uncheckedPreviousOffsetForB
ackwardDeletion(node, offset)); | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 if (ContainerNode* parent = Strategy::parent(*node)) { | |
| 340 if (editingIgnoresContent(parent)) | |
| 341 return PositionAlgorithm<Strategy>::beforeNode(parent); | |
| 342 // TODO(yosin) We should use |Strategy::index(Node&)| instead of | |
| 343 // |Node::nodeIndex()|. | |
| 344 return PositionAlgorithm<Strategy>(parent, node->nodeIndex()); | |
| 345 } | |
| 346 return position; | |
| 347 } | |
| 348 | |
| 349 Position previousPositionOf(const Position& position, PositionMoveType moveType) | |
| 350 { | |
| 351 return previousPositionOfAlgorithm<EditingStrategy>(position, moveType); | |
| 352 } | |
| 353 | |
| 354 PositionInComposedTree previousPositionOf(const PositionInComposedTree& position
, PositionMoveType moveType) | |
| 355 { | |
| 356 return previousPositionOfAlgorithm<EditingInComposedTreeStrategy>(position,
moveType); | |
| 357 } | |
| 358 | |
| 359 template <typename Strategy> | |
| 360 PositionAlgorithm<Strategy> nextPositionOfAlgorithm(const PositionAlgorithm<Stra
tegy>& position, PositionMoveType moveType) | |
| 361 { | |
| 362 ASSERT(moveType != PositionMoveType::BackwardDeletion); | |
| 363 | |
| 364 Node* node = position.anchorNode(); | |
| 365 if (!node) | |
| 366 return position; | |
| 367 | |
| 368 const int offset = position.computeEditingOffset(); | |
| 369 | |
| 370 if (Node* child = Strategy::childAt(*node, offset)) | |
| 371 return PositionAlgorithm<Strategy>::firstPositionInOrBeforeNode(child); | |
| 372 | |
| 373 // TODO(yosin) We should use |Strategy::lastOffsetForEditing()| instead of | |
| 374 // DOM tree version. | |
| 375 if (!Strategy::hasChildren(*node) && offset < EditingStrategy::lastOffsetFor
Editing(node)) { | |
| 376 // There are two reasons child might be 0: | |
| 377 // 1) The node is node like a text node that is not an element, and | |
| 378 // therefore has no children. Going forward one character at a time | |
| 379 // is correct. | |
| 380 // 2) The new offset is a bogus offset like (<br>, 1), and there is no | |
| 381 // child. Going from 0 to 1 is correct. | |
| 382 return PositionAlgorithm<Strategy>::editingPositionOf(node, (moveType ==
PositionMoveType::Character) ? uncheckedNextOffset(node, offset) : offset + 1); | |
| 383 } | |
| 384 | |
| 385 if (ContainerNode* parent = Strategy::parent(*node)) | |
| 386 return PositionAlgorithm<Strategy>::editingPositionOf(parent, Strategy::
index(*node) + 1); | |
| 387 return position; | |
| 388 } | |
| 389 | |
| 390 Position nextPositionOf(const Position& position, PositionMoveType moveType) | |
| 391 { | |
| 392 return nextPositionOfAlgorithm<EditingStrategy>(position, moveType); | |
| 393 } | |
| 394 | |
| 395 PositionInComposedTree nextPositionOf(const PositionInComposedTree& position, Po
sitionMoveType moveType) | |
| 396 { | |
| 397 return nextPositionOfAlgorithm<EditingInComposedTreeStrategy>(position, move
Type); | |
| 398 } | |
| 399 | |
| 400 int uncheckedPreviousOffset(const Node* n, int current) | |
| 401 { | |
| 402 return n->layoutObject() ? n->layoutObject()->previousOffset(current) : curr
ent - 1; | |
| 403 } | |
| 404 | |
| 405 static int uncheckedPreviousOffsetForBackwardDeletion(const Node* n, int current
) | |
| 406 { | |
| 407 return n->layoutObject() ? n->layoutObject()->previousOffsetForBackwardDelet
ion(current) : current - 1; | |
| 408 } | |
| 409 | |
| 410 int uncheckedNextOffset(const Node* n, int current) | |
| 411 { | |
| 412 return n->layoutObject() ? n->layoutObject()->nextOffset(current) : current
+ 1; | |
| 413 } | |
| 414 | |
| 415 template <typename Strategy> | 300 template <typename Strategy> |
| 416 bool PositionAlgorithm<Strategy>::atFirstEditingPositionForNode() const | 301 bool PositionAlgorithm<Strategy>::atFirstEditingPositionForNode() const |
| 417 { | 302 { |
| 418 if (isNull()) | 303 if (isNull()) |
| 419 return true; | 304 return true; |
| 420 // FIXME: Position before anchor shouldn't be considered as at the first edi
ting position for node | 305 // FIXME: Position before anchor shouldn't be considered as at the first edi
ting position for node |
| 421 // since that position resides outside of the node. | 306 // since that position resides outside of the node. |
| 422 switch (m_anchorType) { | 307 switch (m_anchorType) { |
| 423 case PositionAnchorType::OffsetInAnchor: | 308 case PositionAnchorType::OffsetInAnchor: |
| 424 return m_offset == 0; | 309 return m_offset == 0; |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 | 527 |
| 643 void showTree(const blink::Position* pos) | 528 void showTree(const blink::Position* pos) |
| 644 { | 529 { |
| 645 if (pos) | 530 if (pos) |
| 646 pos->showTreeForThis(); | 531 pos->showTreeForThis(); |
| 647 else | 532 else |
| 648 fprintf(stderr, "Cannot showTree for (nil)\n"); | 533 fprintf(stderr, "Cannot showTree for (nil)\n"); |
| 649 } | 534 } |
| 650 | 535 |
| 651 #endif | 536 #endif |
| OLD | NEW |