| 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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 | 359 |
| 360 // |nextVisuallyDistinctCandidate| is similar to |nextCandidate| except | 360 // |nextVisuallyDistinctCandidate| is similar to |nextCandidate| except |
| 361 // for returning position which |downstream()| not equal to initial position's | 361 // for returning position which |downstream()| not equal to initial position's |
| 362 // |downstream()|. | 362 // |downstream()|. |
| 363 Position nextVisuallyDistinctCandidate(const Position& position) | 363 Position nextVisuallyDistinctCandidate(const Position& position) |
| 364 { | 364 { |
| 365 if (position.isNull()) | 365 if (position.isNull()) |
| 366 return Position(); | 366 return Position(); |
| 367 | 367 |
| 368 PositionIterator p(position); | 368 PositionIterator p(position); |
| 369 Position downstreamStart = position.downstream(); | 369 Position downstreamStart = mostForwardCaretPosition(position); |
| 370 | 370 |
| 371 p.increment(); | 371 p.increment(); |
| 372 while (!p.atEnd()) { | 372 while (!p.atEnd()) { |
| 373 Position candidate = p.computePosition(); | 373 Position candidate = p.computePosition(); |
| 374 if (isVisuallyEquivalentCandidate(candidate) && candidate.downstream() !
= downstreamStart) | 374 if (isVisuallyEquivalentCandidate(candidate) && mostForwardCaretPosition
(candidate) != downstreamStart) |
| 375 return candidate; | 375 return candidate; |
| 376 | 376 |
| 377 p.increment(); | 377 p.increment(); |
| 378 } | 378 } |
| 379 | 379 |
| 380 return Position(); | 380 return Position(); |
| 381 } | 381 } |
| 382 | 382 |
| 383 template <typename Strategy> | 383 template <typename Strategy> |
| 384 PositionAlgorithm<Strategy> previousCandidateAlgorithm(const PositionAlgorithm<S
trategy>& position) | 384 PositionAlgorithm<Strategy> previousCandidateAlgorithm(const PositionAlgorithm<S
trategy>& position) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 410 // |previousVisuallyDistinctCandidate| is similar to |previousCandidate| except | 410 // |previousVisuallyDistinctCandidate| is similar to |previousCandidate| except |
| 411 // for returning position which |downstream()| not equal to initial position's | 411 // for returning position which |downstream()| not equal to initial position's |
| 412 // |downstream()|. | 412 // |downstream()|. |
| 413 template <typename Strategy> | 413 template <typename Strategy> |
| 414 PositionAlgorithm<Strategy> previousVisuallyDistinctCandidateAlgorithm(const Pos
itionAlgorithm<Strategy>& position) | 414 PositionAlgorithm<Strategy> previousVisuallyDistinctCandidateAlgorithm(const Pos
itionAlgorithm<Strategy>& position) |
| 415 { | 415 { |
| 416 if (position.isNull()) | 416 if (position.isNull()) |
| 417 return PositionAlgorithm<Strategy>(); | 417 return PositionAlgorithm<Strategy>(); |
| 418 | 418 |
| 419 PositionIteratorAlgorithm<Strategy> p(position); | 419 PositionIteratorAlgorithm<Strategy> p(position); |
| 420 PositionAlgorithm<Strategy> downstreamStart = position.downstream(); | 420 PositionAlgorithm<Strategy> downstreamStart = mostForwardCaretPosition(posit
ion); |
| 421 | 421 |
| 422 p.decrement(); | 422 p.decrement(); |
| 423 while (!p.atStart()) { | 423 while (!p.atStart()) { |
| 424 PositionAlgorithm<Strategy> candidate = p.computePosition(); | 424 PositionAlgorithm<Strategy> candidate = p.computePosition(); |
| 425 if (isVisuallyEquivalentCandidate(candidate) && candidate.downstream() !
= downstreamStart) | 425 if (isVisuallyEquivalentCandidate(candidate) && mostForwardCaretPosition
(candidate) != downstreamStart) |
| 426 return candidate; | 426 return candidate; |
| 427 | 427 |
| 428 p.decrement(); | 428 p.decrement(); |
| 429 } | 429 } |
| 430 | 430 |
| 431 return PositionAlgorithm<Strategy>(); | 431 return PositionAlgorithm<Strategy>(); |
| 432 } | 432 } |
| 433 | 433 |
| 434 Position previousVisuallyDistinctCandidate(const Position& position) | 434 Position previousVisuallyDistinctCandidate(const Position& position) |
| 435 { | 435 { |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 Position result = positionInParentAfterNode(*n); | 697 Position result = positionInParentAfterNode(*n); |
| 698 if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anc
horNode()->rootEditableElement()) | 698 if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anc
horNode()->rootEditableElement()) |
| 699 return pos; | 699 return pos; |
| 700 if (containingSpecialElement) | 700 if (containingSpecialElement) |
| 701 *containingSpecialElement = n; | 701 *containingSpecialElement = n; |
| 702 return result; | 702 return result; |
| 703 } | 703 } |
| 704 | 704 |
| 705 Element* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) | 705 Element* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) |
| 706 { | 706 { |
| 707 Position upstream(visiblePosition.deepEquivalent().upstream()); | 707 Position upstream(mostBackwardCaretPosition(visiblePosition.deepEquivalent()
)); |
| 708 if (isRenderedTableElement(upstream.anchorNode()) && upstream.atLastEditingP
ositionForNode()) | 708 if (isRenderedTableElement(upstream.anchorNode()) && upstream.atLastEditingP
ositionForNode()) |
| 709 return toElement(upstream.anchorNode()); | 709 return toElement(upstream.anchorNode()); |
| 710 | 710 |
| 711 return 0; | 711 return 0; |
| 712 } | 712 } |
| 713 | 713 |
| 714 Element* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) | 714 Element* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) |
| 715 { | 715 { |
| 716 Position downstream(visiblePosition.deepEquivalent().downstream()); | 716 Position downstream(mostForwardCaretPosition(visiblePosition.deepEquivalent(
))); |
| 717 if (isRenderedTableElement(downstream.anchorNode()) && downstream.atFirstEdi
tingPositionForNode()) | 717 if (isRenderedTableElement(downstream.anchorNode()) && downstream.atFirstEdi
tingPositionForNode()) |
| 718 return toElement(downstream.anchorNode()); | 718 return toElement(downstream.anchorNode()); |
| 719 | 719 |
| 720 return 0; | 720 return 0; |
| 721 } | 721 } |
| 722 | 722 |
| 723 static Node* previousNodeConsideringAtomicNodes(const Node& start) | 723 static Node* previousNodeConsideringAtomicNodes(const Node& start) |
| 724 { | 724 { |
| 725 if (start.previousSibling()) { | 725 if (start.previousSibling()) { |
| 726 Node* node = start.previousSibling(); | 726 Node* node = start.previousSibling(); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 list = nextList; | 973 list = nextList; |
| 974 } | 974 } |
| 975 | 975 |
| 976 return list; | 976 return list; |
| 977 } | 977 } |
| 978 | 978 |
| 979 // Determines whether two positions are visibly next to each other (first then s
econd) | 979 // Determines whether two positions are visibly next to each other (first then s
econd) |
| 980 // while ignoring whitespaces and unrendered nodes | 980 // while ignoring whitespaces and unrendered nodes |
| 981 static bool isVisiblyAdjacent(const Position& first, const Position& second) | 981 static bool isVisiblyAdjacent(const Position& first, const Position& second) |
| 982 { | 982 { |
| 983 return VisiblePosition(first).deepEquivalent() == VisiblePosition(second.ups
tream()).deepEquivalent(); | 983 return VisiblePosition(first).deepEquivalent() == VisiblePosition(mostBackwa
rdCaretPosition(second)).deepEquivalent(); |
| 984 } | 984 } |
| 985 | 985 |
| 986 bool canMergeLists(Element* firstList, Element* secondList) | 986 bool canMergeLists(Element* firstList, Element* secondList) |
| 987 { | 987 { |
| 988 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) | 988 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList-
>isHTMLElement()) |
| 989 return false; | 989 return false; |
| 990 | 990 |
| 991 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) | 991 return firstList->hasTagName(secondList->tagQName()) // make sure the list t
ypes match (ol vs. ul) |
| 992 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l
ists are editable | 992 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l
ists are editable |
| 993 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries | 993 && firstList->rootEditableElement() == secondList->rootEditableElement() //
don't cross editing boundaries |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 return position; | 1174 return position; |
| 1175 } | 1175 } |
| 1176 | 1176 |
| 1177 // This assumes that it starts in editable content. | 1177 // This assumes that it starts in editable content. |
| 1178 Position leadingWhitespacePosition(const Position& position, TextAffinity affini
ty, WhitespacePositionOption option) | 1178 Position leadingWhitespacePosition(const Position& position, TextAffinity affini
ty, WhitespacePositionOption option) |
| 1179 { | 1179 { |
| 1180 ASSERT(isEditablePosition(position, ContentIsEditable, DoNotUpdateStyle)); | 1180 ASSERT(isEditablePosition(position, ContentIsEditable, DoNotUpdateStyle)); |
| 1181 if (position.isNull()) | 1181 if (position.isNull()) |
| 1182 return Position(); | 1182 return Position(); |
| 1183 | 1183 |
| 1184 if (isHTMLBRElement(*position.upstream().anchorNode())) | 1184 if (isHTMLBRElement(*mostBackwardCaretPosition(position).anchorNode())) |
| 1185 return Position(); | 1185 return Position(); |
| 1186 | 1186 |
| 1187 Position prev = previousCharacterPosition(position, affinity); | 1187 Position prev = previousCharacterPosition(position, affinity); |
| 1188 if (prev != position && inSameContainingBlockFlowElement(prev.anchorNode(),
position.anchorNode()) && prev.anchorNode()->isTextNode()) { | 1188 if (prev != position && inSameContainingBlockFlowElement(prev.anchorNode(),
position.anchorNode()) && prev.anchorNode()->isTextNode()) { |
| 1189 String string = toText(prev.anchorNode())->data(); | 1189 String string = toText(prev.anchorNode())->data(); |
| 1190 UChar previousCharacter = string[prev.computeOffsetInContainerNode()]; | 1190 UChar previousCharacter = string[prev.computeOffsetInContainerNode()]; |
| 1191 bool isSpace = option == ConsiderNonCollapsibleWhitespace ? (isSpaceOrNe
wline(previousCharacter) || previousCharacter == noBreakSpaceCharacter) : isColl
apsibleWhitespace(previousCharacter); | 1191 bool isSpace = option == ConsiderNonCollapsibleWhitespace ? (isSpaceOrNe
wline(previousCharacter) || previousCharacter == noBreakSpaceCharacter) : isColl
apsibleWhitespace(previousCharacter); |
| 1192 if (isSpace && isEditablePosition(prev)) | 1192 if (isSpace && isEditablePosition(prev)) |
| 1193 return prev; | 1193 return prev; |
| 1194 } | 1194 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 return r ? r->caretMinOffset() : 0; | 1268 return r ? r->caretMinOffset() : 0; |
| 1269 } | 1269 } |
| 1270 | 1270 |
| 1271 int caretMaxOffset(const Node* n) | 1271 int caretMaxOffset(const Node* n) |
| 1272 { | 1272 { |
| 1273 return EditingStrategy::caretMaxOffset(*n); | 1273 return EditingStrategy::caretMaxOffset(*n); |
| 1274 } | 1274 } |
| 1275 | 1275 |
| 1276 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition) | 1276 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition) |
| 1277 { | 1277 { |
| 1278 return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream
()); | 1278 return lineBreakExistsAtPosition(mostForwardCaretPosition(visiblePosition.de
epEquivalent())); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 bool lineBreakExistsAtPosition(const Position& position) | 1281 bool lineBreakExistsAtPosition(const Position& position) |
| 1282 { | 1282 { |
| 1283 if (position.isNull()) | 1283 if (position.isNull()) |
| 1284 return false; | 1284 return false; |
| 1285 | 1285 |
| 1286 if (isHTMLBRElement(*position.anchorNode()) && position.atFirstEditingPositi
onForNode()) | 1286 if (isHTMLBRElement(*position.anchorNode()) && position.atFirstEditingPositi
onForNode()) |
| 1287 return true; | 1287 return true; |
| 1288 | 1288 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1440 if (visiblePosition.isNull()) | 1440 if (visiblePosition.isNull()) |
| 1441 return Position(); | 1441 return Position(); |
| 1442 | 1442 |
| 1443 // if the selection is a caret, just return the position, since the style | 1443 // if the selection is a caret, just return the position, since the style |
| 1444 // behind us is relevant | 1444 // behind us is relevant |
| 1445 if (selection.isCaret()) | 1445 if (selection.isCaret()) |
| 1446 return visiblePosition.deepEquivalent(); | 1446 return visiblePosition.deepEquivalent(); |
| 1447 | 1447 |
| 1448 // if the selection starts just before a paragraph break, skip over it | 1448 // if the selection starts just before a paragraph break, skip over it |
| 1449 if (isEndOfParagraph(visiblePosition)) | 1449 if (isEndOfParagraph(visiblePosition)) |
| 1450 return visiblePosition.next().deepEquivalent().downstream(); | 1450 return mostForwardCaretPosition(visiblePosition.next().deepEquivalent())
; |
| 1451 | 1451 |
| 1452 // otherwise, make sure to be at the start of the first selected node, | 1452 // otherwise, make sure to be at the start of the first selected node, |
| 1453 // instead of possibly at the end of the last node before the selection | 1453 // instead of possibly at the end of the last node before the selection |
| 1454 return visiblePosition.deepEquivalent().downstream(); | 1454 return mostForwardCaretPosition(visiblePosition.deepEquivalent()); |
| 1455 } | 1455 } |
| 1456 | 1456 |
| 1457 } // namespace blink | 1457 } // namespace blink |
| OLD | NEW |