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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "wtf/unicode/CharacterNames.h" | 47 #include "wtf/unicode/CharacterNames.h" |
48 #include <stdio.h> | 48 #include <stdio.h> |
49 | 49 |
50 namespace blink { | 50 namespace blink { |
51 | 51 |
52 using namespace HTMLNames; | 52 using namespace HTMLNames; |
53 | 53 |
54 static Node* nextRenderedEditable(Node* node) | 54 static Node* nextRenderedEditable(Node* node) |
55 { | 55 { |
56 for (node = node->nextLeafNode(); node; node = node->nextLeafNode()) { | 56 for (node = node->nextLeafNode(); node; node = node->nextLeafNode()) { |
57 RenderObject* renderer = node->renderer(); | 57 LayoutObject* renderer = node->renderer(); |
58 if (!renderer) | 58 if (!renderer) |
59 continue; | 59 continue; |
60 if (!node->hasEditableStyle()) | 60 if (!node->hasEditableStyle()) |
61 continue; | 61 continue; |
62 if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) ||
(renderer->isText() && toRenderText(renderer)->firstTextBox())) | 62 if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) ||
(renderer->isText() && toRenderText(renderer)->firstTextBox())) |
63 return node; | 63 return node; |
64 } | 64 } |
65 return 0; | 65 return 0; |
66 } | 66 } |
67 | 67 |
68 static Node* previousRenderedEditable(Node* node) | 68 static Node* previousRenderedEditable(Node* node) |
69 { | 69 { |
70 for (node = node->previousLeafNode(); node; node = node->previousLeafNode())
{ | 70 for (node = node->previousLeafNode(); node; node = node->previousLeafNode())
{ |
71 RenderObject* renderer = node->renderer(); | 71 LayoutObject* renderer = node->renderer(); |
72 if (!renderer) | 72 if (!renderer) |
73 continue; | 73 continue; |
74 if (!node->hasEditableStyle()) | 74 if (!node->hasEditableStyle()) |
75 continue; | 75 continue; |
76 if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) ||
(renderer->isText() && toRenderText(renderer)->firstTextBox())) | 76 if ((renderer->isBox() && toRenderBox(renderer)->inlineBoxWrapper()) ||
(renderer->isText() && toRenderText(renderer)->firstTextBox())) |
77 return node; | 77 return node; |
78 } | 78 } |
79 return 0; | 79 return 0; |
80 } | 80 } |
81 | 81 |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 } | 563 } |
564 lastNode = currentNode; | 564 lastNode = currentNode; |
565 } | 565 } |
566 | 566 |
567 // If we've moved to a position that is visually distinct, return the la
st saved position. There | 567 // If we've moved to a position that is visually distinct, return the la
st saved position. There |
568 // is code below that terminates early if we're *about* to move to a vis
ually distinct position. | 568 // is code below that terminates early if we're *about* to move to a vis
ually distinct position. |
569 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode !
= boundary) | 569 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode !
= boundary) |
570 return lastVisible; | 570 return lastVisible; |
571 | 571 |
572 // skip position in unrendered or invisible node | 572 // skip position in unrendered or invisible node |
573 RenderObject* renderer = currentNode->renderer(); | 573 LayoutObject* renderer = currentNode->renderer(); |
574 if (!renderer || renderer->style()->visibility() != VISIBLE) | 574 if (!renderer || renderer->style()->visibility() != VISIBLE) |
575 continue; | 575 continue; |
576 | 576 |
577 if (rule == CanCrossEditingBoundary && boundaryCrossed) { | 577 if (rule == CanCrossEditingBoundary && boundaryCrossed) { |
578 lastVisible = currentPos; | 578 lastVisible = currentPos; |
579 break; | 579 break; |
580 } | 580 } |
581 | 581 |
582 // track last visible streamer position | 582 // track last visible streamer position |
583 if (isStreamer(currentPos)) | 583 if (isStreamer(currentPos)) |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 // Do not move to a visually distinct position. | 696 // Do not move to a visually distinct position. |
697 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode !
= boundary) | 697 if (endsOfNodeAreVisuallyDistinctPositions(currentNode) && currentNode !
= boundary) |
698 return lastVisible; | 698 return lastVisible; |
699 // Do not move past a visually disinct position. | 699 // Do not move past a visually disinct position. |
700 // Note: The first position after the last in a node whose ends are visu
ally distinct | 700 // Note: The first position after the last in a node whose ends are visu
ally distinct |
701 // positions will be [boundary->parentNode(), originalBlock->nodeIndex()
+ 1]. | 701 // positions will be [boundary->parentNode(), originalBlock->nodeIndex()
+ 1]. |
702 if (boundary && boundary->parentNode() == currentNode) | 702 if (boundary && boundary->parentNode() == currentNode) |
703 return lastVisible; | 703 return lastVisible; |
704 | 704 |
705 // skip position in unrendered or invisible node | 705 // skip position in unrendered or invisible node |
706 RenderObject* renderer = currentNode->renderer(); | 706 LayoutObject* renderer = currentNode->renderer(); |
707 if (!renderer || renderer->style()->visibility() != VISIBLE) | 707 if (!renderer || renderer->style()->visibility() != VISIBLE) |
708 continue; | 708 continue; |
709 | 709 |
710 if (rule == CanCrossEditingBoundary && boundaryCrossed) { | 710 if (rule == CanCrossEditingBoundary && boundaryCrossed) { |
711 lastVisible = currentPos; | 711 lastVisible = currentPos; |
712 break; | 712 break; |
713 } | 713 } |
714 | 714 |
715 // track last visible streamer position | 715 // track last visible streamer position |
716 if (isStreamer(currentPos)) | 716 if (isStreamer(currentPos)) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 | 767 |
768 if (continuesOnNextLine) | 768 if (continuesOnNextLine) |
769 return currentPos; | 769 return currentPos; |
770 } | 770 } |
771 } | 771 } |
772 } | 772 } |
773 | 773 |
774 return lastVisible; | 774 return lastVisible; |
775 } | 775 } |
776 | 776 |
777 static int boundingBoxLogicalHeight(RenderObject *o, const IntRect &rect) | 777 static int boundingBoxLogicalHeight(LayoutObject *o, const IntRect &rect) |
778 { | 778 { |
779 return o->style()->isHorizontalWritingMode() ? rect.height() : rect.width(); | 779 return o->style()->isHorizontalWritingMode() ? rect.height() : rect.width(); |
780 } | 780 } |
781 | 781 |
782 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* render
er) | 782 bool Position::hasRenderedNonAnonymousDescendantsWithHeight(LayoutObject* render
er) |
783 { | 783 { |
784 RenderObject* stop = renderer->nextInPreOrderAfterChildren(); | 784 LayoutObject* stop = renderer->nextInPreOrderAfterChildren(); |
785 for (RenderObject *o = renderer->slowFirstChild(); o && o != stop; o = o->ne
xtInPreOrder()) | 785 for (LayoutObject *o = renderer->slowFirstChild(); o && o != stop; o = o->ne
xtInPreOrder()) |
786 if (o->nonPseudoNode()) { | 786 if (o->nonPseudoNode()) { |
787 if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->lin
esBoundingBox())) | 787 if ((o->isText() && boundingBoxLogicalHeight(o, toRenderText(o)->lin
esBoundingBox())) |
788 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight()) | 788 || (o->isBox() && toRenderBox(o)->pixelSnappedLogicalHeight()) |
789 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogica
lHeight(o, toRenderInline(o)->linesBoundingBox()))) | 789 || (o->isRenderInline() && isEmptyInline(o) && boundingBoxLogica
lHeight(o, toRenderInline(o)->linesBoundingBox()))) |
790 return true; | 790 return true; |
791 } | 791 } |
792 return false; | 792 return false; |
793 } | 793 } |
794 | 794 |
795 bool Position::nodeIsUserSelectNone(Node* node) | 795 bool Position::nodeIsUserSelectNone(Node* node) |
(...skipping 26 matching lines...) Expand all Loading... |
822 parent = candidateRoot->parentNode(); | 822 parent = candidateRoot->parentNode(); |
823 } | 823 } |
824 return candidateRoot; | 824 return candidateRoot; |
825 } | 825 } |
826 | 826 |
827 bool Position::isCandidate() const | 827 bool Position::isCandidate() const |
828 { | 828 { |
829 if (isNull()) | 829 if (isNull()) |
830 return false; | 830 return false; |
831 | 831 |
832 RenderObject* renderer = deprecatedNode()->renderer(); | 832 LayoutObject* renderer = deprecatedNode()->renderer(); |
833 if (!renderer) | 833 if (!renderer) |
834 return false; | 834 return false; |
835 | 835 |
836 if (renderer->style()->visibility() != VISIBLE) | 836 if (renderer->style()->visibility() != VISIBLE) |
837 return false; | 837 return false; |
838 | 838 |
839 if (renderer->isBR()) | 839 if (renderer->isBR()) |
840 // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor
, but for now we still need to support legacy positions. | 840 // FIXME: The condition should be m_anchorType == PositionIsBeforeAnchor
, but for now we still need to support legacy positions. |
841 return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUser
SelectNone(deprecatedNode()->parentNode()); | 841 return !m_offset && m_anchorType != PositionIsAfterAnchor && !nodeIsUser
SelectNone(deprecatedNode()->parentNode()); |
842 | 842 |
(...skipping 25 matching lines...) Expand all Loading... |
868 } | 868 } |
869 | 869 |
870 return false; | 870 return false; |
871 } | 871 } |
872 | 872 |
873 bool Position::inRenderedText() const | 873 bool Position::inRenderedText() const |
874 { | 874 { |
875 if (isNull() || !deprecatedNode()->isTextNode()) | 875 if (isNull() || !deprecatedNode()->isTextNode()) |
876 return false; | 876 return false; |
877 | 877 |
878 RenderObject* renderer = deprecatedNode()->renderer(); | 878 LayoutObject* renderer = deprecatedNode()->renderer(); |
879 if (!renderer) | 879 if (!renderer) |
880 return false; | 880 return false; |
881 | 881 |
882 RenderText *textRenderer = toRenderText(renderer); | 882 RenderText *textRenderer = toRenderText(renderer); |
883 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next
TextBox()) { | 883 for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->next
TextBox()) { |
884 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains
ReversedText()) { | 884 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains
ReversedText()) { |
885 // The offset we're looking for is before this node | 885 // The offset we're looking for is before this node |
886 // this means the offset must be in content that is | 886 // this means the offset must be in content that is |
887 // not rendered. Return false. | 887 // not rendered. Return false. |
888 return false; | 888 return false; |
889 } | 889 } |
890 if (box->containsCaretOffset(m_offset)) | 890 if (box->containsCaretOffset(m_offset)) |
891 // Return false for offsets inside composed characters. | 891 // Return false for offsets inside composed characters. |
892 return m_offset == 0 || m_offset == textRenderer->nextOffset(textRen
derer->previousOffset(m_offset)); | 892 return m_offset == 0 || m_offset == textRenderer->nextOffset(textRen
derer->previousOffset(m_offset)); |
893 } | 893 } |
894 | 894 |
895 return false; | 895 return false; |
896 } | 896 } |
897 | 897 |
898 bool Position::isRenderedCharacter() const | 898 bool Position::isRenderedCharacter() const |
899 { | 899 { |
900 if (isNull() || !deprecatedNode()->isTextNode()) | 900 if (isNull() || !deprecatedNode()->isTextNode()) |
901 return false; | 901 return false; |
902 | 902 |
903 RenderObject* renderer = deprecatedNode()->renderer(); | 903 LayoutObject* renderer = deprecatedNode()->renderer(); |
904 if (!renderer) | 904 if (!renderer) |
905 return false; | 905 return false; |
906 | 906 |
907 RenderText* textRenderer = toRenderText(renderer); | 907 RenderText* textRenderer = toRenderText(renderer); |
908 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->next
TextBox()) { | 908 for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->next
TextBox()) { |
909 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains
ReversedText()) { | 909 if (m_offset < static_cast<int>(box->start()) && !textRenderer->contains
ReversedText()) { |
910 // The offset we're looking for is before this node | 910 // The offset we're looking for is before this node |
911 // this means the offset must be in content that is | 911 // this means the offset must be in content that is |
912 // not rendered. Return false. | 912 // not rendered. Return false. |
913 return false; | 913 return false; |
914 } | 914 } |
915 if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast
<int>(box->start() + box->len())) | 915 if (m_offset >= static_cast<int>(box->start()) && m_offset < static_cast
<int>(box->start() + box->len())) |
916 return true; | 916 return true; |
917 } | 917 } |
918 | 918 |
919 return false; | 919 return false; |
920 } | 920 } |
921 | 921 |
922 bool Position::rendersInDifferentPosition(const Position &pos) const | 922 bool Position::rendersInDifferentPosition(const Position &pos) const |
923 { | 923 { |
924 if (isNull() || pos.isNull()) | 924 if (isNull() || pos.isNull()) |
925 return false; | 925 return false; |
926 | 926 |
927 RenderObject* renderer = deprecatedNode()->renderer(); | 927 LayoutObject* renderer = deprecatedNode()->renderer(); |
928 if (!renderer) | 928 if (!renderer) |
929 return false; | 929 return false; |
930 | 930 |
931 RenderObject* posRenderer = pos.deprecatedNode()->renderer(); | 931 LayoutObject* posRenderer = pos.deprecatedNode()->renderer(); |
932 if (!posRenderer) | 932 if (!posRenderer) |
933 return false; | 933 return false; |
934 | 934 |
935 if (renderer->style()->visibility() != VISIBLE || | 935 if (renderer->style()->visibility() != VISIBLE || |
936 posRenderer->style()->visibility() != VISIBLE) | 936 posRenderer->style()->visibility() != VISIBLE) |
937 return false; | 937 return false; |
938 | 938 |
939 if (deprecatedNode() == pos.deprecatedNode()) { | 939 if (deprecatedNode() == pos.deprecatedNode()) { |
940 if (isHTMLBRElement(*deprecatedNode())) | 940 if (isHTMLBRElement(*deprecatedNode())) |
941 return false; | 941 return false; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 } | 1003 } |
1004 | 1004 |
1005 return true; | 1005 return true; |
1006 } | 1006 } |
1007 | 1007 |
1008 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox,
int& caretOffset) const | 1008 void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox,
int& caretOffset) const |
1009 { | 1009 { |
1010 getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset); | 1010 getInlineBoxAndOffset(affinity, primaryDirection(), inlineBox, caretOffset); |
1011 } | 1011 } |
1012 | 1012 |
1013 static bool isNonTextLeafChild(RenderObject* object) | 1013 static bool isNonTextLeafChild(LayoutObject* object) |
1014 { | 1014 { |
1015 if (object->slowFirstChild()) | 1015 if (object->slowFirstChild()) |
1016 return false; | 1016 return false; |
1017 if (object->isText()) | 1017 if (object->isText()) |
1018 return false; | 1018 return false; |
1019 return true; | 1019 return true; |
1020 } | 1020 } |
1021 | 1021 |
1022 static InlineTextBox* searchAheadForBetterMatch(RenderObject* renderer) | 1022 static InlineTextBox* searchAheadForBetterMatch(LayoutObject* renderer) |
1023 { | 1023 { |
1024 RenderBlock* container = renderer->containingBlock(); | 1024 RenderBlock* container = renderer->containingBlock(); |
1025 for (RenderObject* next = renderer->nextInPreOrder(container); next; next =
next->nextInPreOrder(container)) { | 1025 for (LayoutObject* next = renderer->nextInPreOrder(container); next; next =
next->nextInPreOrder(container)) { |
1026 if (next->isRenderBlock()) | 1026 if (next->isRenderBlock()) |
1027 return 0; | 1027 return 0; |
1028 if (next->isBR()) | 1028 if (next->isBR()) |
1029 return 0; | 1029 return 0; |
1030 if (isNonTextLeafChild(next)) | 1030 if (isNonTextLeafChild(next)) |
1031 return 0; | 1031 return 0; |
1032 if (next->isText()) { | 1032 if (next->isText()) { |
1033 InlineTextBox* match = 0; | 1033 InlineTextBox* match = 0; |
1034 int minOffset = INT_MAX; | 1034 int minOffset = INT_MAX; |
1035 for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; b
ox = box->nextTextBox()) { | 1035 for (InlineTextBox* box = toRenderText(next)->firstTextBox(); box; b
ox = box->nextTextBox()) { |
(...skipping 26 matching lines...) Expand all Loading... |
1062 while (position != lastPosition) { | 1062 while (position != lastPosition) { |
1063 lastPosition = position; | 1063 lastPosition = position; |
1064 position = position.upstream(CanCrossEditingBoundary); | 1064 position = position.upstream(CanCrossEditingBoundary); |
1065 } | 1065 } |
1066 return position; | 1066 return position; |
1067 } | 1067 } |
1068 | 1068 |
1069 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi
rection, InlineBox*& inlineBox, int& caretOffset) const | 1069 void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDi
rection, InlineBox*& inlineBox, int& caretOffset) const |
1070 { | 1070 { |
1071 caretOffset = deprecatedEditingOffset(); | 1071 caretOffset = deprecatedEditingOffset(); |
1072 RenderObject* renderer = deprecatedNode()->renderer(); | 1072 LayoutObject* renderer = deprecatedNode()->renderer(); |
1073 | 1073 |
1074 if (!renderer->isText()) { | 1074 if (!renderer->isText()) { |
1075 inlineBox = 0; | 1075 inlineBox = 0; |
1076 if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isRenderBlo
ckFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { | 1076 if (canHaveChildrenForEditing(deprecatedNode()) && renderer->isRenderBlo
ckFlow() && hasRenderedNonAnonymousDescendantsWithHeight(renderer)) { |
1077 // Try a visually equivalent position with possibly opposite editabi
lity. This helps in case |this| is in | 1077 // Try a visually equivalent position with possibly opposite editabi
lity. This helps in case |this| is in |
1078 // an editable block but surrounded by non-editable positions. It ac
ts to negate the logic at the beginning | 1078 // an editable block but surrounded by non-editable positions. It ac
ts to negate the logic at the beginning |
1079 // of RenderObject::createVisiblePosition(). | 1079 // of LayoutObject::createVisiblePosition(). |
1080 Position equivalent = downstreamIgnoringEditingBoundaries(*this); | 1080 Position equivalent = downstreamIgnoringEditingBoundaries(*this); |
1081 if (equivalent == *this) { | 1081 if (equivalent == *this) { |
1082 equivalent = upstreamIgnoringEditingBoundaries(*this); | 1082 equivalent = upstreamIgnoringEditingBoundaries(*this); |
1083 if (equivalent == *this || downstreamIgnoringEditingBoundaries(e
quivalent) == *this) | 1083 if (equivalent == *this || downstreamIgnoringEditingBoundaries(e
quivalent) == *this) |
1084 return; | 1084 return; |
1085 } | 1085 } |
1086 | 1086 |
1087 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB
ox, caretOffset); | 1087 equivalent.getInlineBoxAndOffset(UPSTREAM, primaryDirection, inlineB
ox, caretOffset); |
1088 return; | 1088 return; |
1089 } | 1089 } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1218 inlineBox = tertiaryBox; | 1218 inlineBox = tertiaryBox; |
1219 } | 1219 } |
1220 caretOffset = inlineBox->caretRightmostOffset(); | 1220 caretOffset = inlineBox->caretRightmostOffset(); |
1221 } | 1221 } |
1222 } | 1222 } |
1223 } | 1223 } |
1224 | 1224 |
1225 TextDirection Position::primaryDirection() const | 1225 TextDirection Position::primaryDirection() const |
1226 { | 1226 { |
1227 TextDirection primaryDirection = LTR; | 1227 TextDirection primaryDirection = LTR; |
1228 for (const RenderObject* r = m_anchorNode->renderer(); r; r = r->parent()) { | 1228 for (const LayoutObject* r = m_anchorNode->renderer(); r; r = r->parent()) { |
1229 if (r->isRenderBlockFlow()) { | 1229 if (r->isRenderBlockFlow()) { |
1230 primaryDirection = r->style()->direction(); | 1230 primaryDirection = r->style()->direction(); |
1231 break; | 1231 break; |
1232 } | 1232 } |
1233 } | 1233 } |
1234 | 1234 |
1235 return primaryDirection; | 1235 return primaryDirection; |
1236 } | 1236 } |
1237 | 1237 |
1238 void Position::trace(Visitor* visitor) | 1238 void Position::trace(Visitor* visitor) |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1313 pos.showTreeForThis(); | 1313 pos.showTreeForThis(); |
1314 } | 1314 } |
1315 | 1315 |
1316 void showTree(const blink::Position* pos) | 1316 void showTree(const blink::Position* pos) |
1317 { | 1317 { |
1318 if (pos) | 1318 if (pos) |
1319 pos->showTreeForThis(); | 1319 pos->showTreeForThis(); |
1320 } | 1320 } |
1321 | 1321 |
1322 #endif | 1322 #endif |
OLD | NEW |