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 |