OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r ights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r ights reserved. |
3 * Copyright (C) 2005 Alexey Proskuryakov. | 3 * Copyright (C) 2005 Alexey Proskuryakov. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 | 740 |
741 static bool shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) | 741 static bool shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) |
742 { | 742 { |
743 RenderObject* renderer = node->renderer(); | 743 RenderObject* renderer = node->renderer(); |
744 | 744 |
745 if (renderer ? !renderer->isBR() : !node->hasTagName(brTag)) | 745 if (renderer ? !renderer->isBR() : !node->hasTagName(brTag)) |
746 return false; | 746 return false; |
747 return emitsOriginalText || !(node->isInShadowTree() && node->shadowHost()-> hasTagName(inputTag)); | 747 return emitsOriginalText || !(node->isInShadowTree() && node->shadowHost()-> hasTagName(inputTag)); |
748 } | 748 } |
749 | 749 |
750 static bool shouldEmitNewlinesBeforeAndAfterNode(Node* node) | 750 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) |
751 { | 751 { |
752 // Block flow (versus inline flow) is represented by having | 752 // Block flow (versus inline flow) is represented by having |
753 // a newline both before and after the element. | 753 // a newline both before and after the element. |
754 RenderObject* r = node->renderer(); | 754 RenderObject* r = node.renderer(); |
755 if (!r) { | 755 if (!r) { |
756 return (node->hasTagName(blockquoteTag) | 756 return (node.hasTagName(blockquoteTag) |
757 || node->hasTagName(ddTag) | 757 || node.hasTagName(ddTag) |
758 || node->hasTagName(divTag) | 758 || node.hasTagName(divTag) |
759 || node->hasTagName(dlTag) | 759 || node.hasTagName(dlTag) |
760 || node->hasTagName(dtTag) | 760 || node.hasTagName(dtTag) |
761 || node->hasTagName(h1Tag) | 761 || node.hasTagName(h1Tag) |
762 || node->hasTagName(h2Tag) | 762 || node.hasTagName(h2Tag) |
763 || node->hasTagName(h3Tag) | 763 || node.hasTagName(h3Tag) |
764 || node->hasTagName(h4Tag) | 764 || node.hasTagName(h4Tag) |
765 || node->hasTagName(h5Tag) | 765 || node.hasTagName(h5Tag) |
766 || node->hasTagName(h6Tag) | 766 || node.hasTagName(h6Tag) |
767 || node->hasTagName(hrTag) | 767 || node.hasTagName(hrTag) |
768 || node->hasTagName(liTag) | 768 || node.hasTagName(liTag) |
769 || node->hasTagName(listingTag) | 769 || node.hasTagName(listingTag) |
770 || node->hasTagName(olTag) | 770 || node.hasTagName(olTag) |
771 || node->hasTagName(pTag) | 771 || node.hasTagName(pTag) |
772 || node->hasTagName(preTag) | 772 || node.hasTagName(preTag) |
773 || node->hasTagName(trTag) | 773 || node.hasTagName(trTag) |
774 || node->hasTagName(ulTag)); | 774 || node.hasTagName(ulTag)); |
775 } | 775 } |
776 | 776 |
777 // Need to make an exception for table cells, because they are blocks, but w e | 777 // Need to make an exception for table cells, because they are blocks, but w e |
778 // want them tab-delimited rather than having newlines before and after. | 778 // want them tab-delimited rather than having newlines before and after. |
779 if (isTableCell(node)) | 779 if (isTableCell(&node)) |
780 return false; | 780 return false; |
781 | 781 |
782 // Need to make an exception for table row elements, because they are neithe r | 782 // Need to make an exception for table row elements, because they are neithe r |
783 // "inline" or "RenderBlock", but we want newlines for them. | 783 // "inline" or "RenderBlock", but we want newlines for them. |
784 if (r->isTableRow()) { | 784 if (r->isTableRow()) { |
785 RenderTable* t = toRenderTableRow(r)->table(); | 785 RenderTable* t = toRenderTableRow(r)->table(); |
786 if (t && !t->isInline()) | 786 if (t && !t->isInline()) |
787 return true; | 787 return true; |
788 } | 788 } |
789 | 789 |
790 return !r->isInline() && r->isRenderBlock() | 790 return !r->isInline() && r->isRenderBlock() |
791 && !r->isFloatingOrOutOfFlowPositioned() && !r->isBody() && !r->isRubyTe xt(); | 791 && !r->isFloatingOrOutOfFlowPositioned() && !r->isBody() && !r->isRubyTe xt(); |
792 } | 792 } |
793 | 793 |
794 static bool shouldEmitNewlineAfterNode(Node* node) | 794 static bool shouldEmitNewlineAfterNode(Node& node) |
795 { | 795 { |
796 // FIXME: It should be better but slower to create a VisiblePosition here. | 796 // FIXME: It should be better but slower to create a VisiblePosition here. |
797 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) | 797 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) |
798 return false; | 798 return false; |
799 // Check if this is the very last renderer in the document. | 799 // Check if this is the very last renderer in the document. |
800 // If so, then we should not emit a newline. | 800 // If so, then we should not emit a newline. |
801 while ((node = NodeTraversal::nextSkippingChildren(node))) { | 801 Node* next = &node; |
802 if (node->renderer()) | 802 while ((next = NodeTraversal::nextSkippingChildren(*next))) { |
adamk
2013/11/12 21:07:43
Nit: can you remove the extra parentheses while yo
Inactive
2013/11/12 21:19:16
I would but I cannot :)
../../third_party/WebKit/
adamk
2013/11/12 22:21:36
Sigh. Oh well, lgtm anyway
| |
803 if (next->renderer()) | |
803 return true; | 804 return true; |
804 } | 805 } |
805 return false; | 806 return false; |
806 } | 807 } |
807 | 808 |
808 static bool shouldEmitNewlineBeforeNode(Node* node) | 809 static bool shouldEmitNewlineBeforeNode(Node& node) |
809 { | 810 { |
810 return shouldEmitNewlinesBeforeAndAfterNode(node); | 811 return shouldEmitNewlinesBeforeAndAfterNode(node); |
811 } | 812 } |
812 | 813 |
813 static bool shouldEmitExtraNewlineForNode(Node* node) | 814 static bool shouldEmitExtraNewlineForNode(Node* node) |
814 { | 815 { |
815 // When there is a significant collapsed bottom margin, emit an extra | 816 // When there is a significant collapsed bottom margin, emit an extra |
816 // newline for a more realistic result. We end up getting the right | 817 // newline for a more realistic result. We end up getting the right |
817 // result even without margin collapsing. For example: <div><p>text</p></div > | 818 // result even without margin collapsing. For example: <div><p>text</p></div > |
818 // will work right even if both the <div> and the <p> have bottom margins. | 819 // will work right even if both the <div> and the <p> have bottom margins. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
929 { | 930 { |
930 // Emit a character to show the positioning of m_node. | 931 // Emit a character to show the positioning of m_node. |
931 | 932 |
932 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe ro() can | 933 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe ro() can |
933 // create VisiblePositions, which is expensive. So, we perform the inexpensi ve checks | 934 // create VisiblePositions, which is expensive. So, we perform the inexpensi ve checks |
934 // on m_node to see if it necessitates emitting a character first and will e arly return | 935 // on m_node to see if it necessitates emitting a character first and will e arly return |
935 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. | 936 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
936 if (shouldEmitTabBeforeNode(m_node)) { | 937 if (shouldEmitTabBeforeNode(m_node)) { |
937 if (shouldRepresentNodeOffsetZero()) | 938 if (shouldRepresentNodeOffsetZero()) |
938 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); | 939 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); |
939 } else if (shouldEmitNewlineBeforeNode(m_node)) { | 940 } else if (shouldEmitNewlineBeforeNode(*m_node)) { |
940 if (shouldRepresentNodeOffsetZero()) | 941 if (shouldRepresentNodeOffsetZero()) |
941 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); | 942 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); |
942 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { | 943 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { |
943 if (shouldRepresentNodeOffsetZero()) | 944 if (shouldRepresentNodeOffsetZero()) |
944 emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); | 945 emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); |
945 } | 946 } |
946 } | 947 } |
947 | 948 |
948 bool TextIterator::handleNonTextNode() | 949 bool TextIterator::handleNonTextNode() |
949 { | 950 { |
(...skipping 17 matching lines...) Expand all Loading... | |
967 return; | 968 return; |
968 | 969 |
969 // Emit with a position *inside* m_node, after m_node's contents, in | 970 // Emit with a position *inside* m_node, after m_node's contents, in |
970 // case it is a block, because the run should start where the | 971 // case it is a block, because the run should start where the |
971 // emitted character is positioned visually. | 972 // emitted character is positioned visually. |
972 Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; | 973 Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; |
973 // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making | 974 // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making |
974 // the logic in _web_attributedStringFromRange match. We'll get that for fre e when we switch to use | 975 // the logic in _web_attributedStringFromRange match. We'll get that for fre e when we switch to use |
975 // TextIterator in _web_attributedStringFromRange. | 976 // TextIterator in _web_attributedStringFromRange. |
976 // See <rdar://problem/5428427> for an example of how this mismatch will cau se problems. | 977 // See <rdar://problem/5428427> for an example of how this mismatch will cau se problems. |
977 if (m_lastTextNode && shouldEmitNewlineAfterNode(m_node)) { | 978 if (m_lastTextNode && shouldEmitNewlineAfterNode(*m_node)) { |
978 // use extra newline to represent margin bottom, as needed | 979 // use extra newline to represent margin bottom, as needed |
979 bool addNewline = shouldEmitExtraNewlineForNode(m_node); | 980 bool addNewline = shouldEmitExtraNewlineForNode(m_node); |
980 | 981 |
981 // FIXME: We need to emit a '\n' as we leave an empty block(s) that | 982 // FIXME: We need to emit a '\n' as we leave an empty block(s) that |
982 // contain a VisiblePosition when doing selection preservation. | 983 // contain a VisiblePosition when doing selection preservation. |
983 if (m_lastCharacter != '\n') { | 984 if (m_lastCharacter != '\n') { |
984 // insert a newline with a position following this block's contents. | 985 // insert a newline with a position following this block's contents. |
985 emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); | 986 emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); |
986 // remember whether to later add a newline for the current node | 987 // remember whether to later add a newline for the current node |
987 ASSERT(!m_needsAnotherNewline); | 988 ASSERT(!m_needsAnotherNewline); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1306 // code in moveParagraphs, so we use a comma. Unconditionally emit | 1307 // code in moveParagraphs, so we use a comma. Unconditionally emit |
1307 // here because this iterator is only used for boundary finding. | 1308 // here because this iterator is only used for boundary finding. |
1308 emitCharacter(',', m_node->parentNode(), index, index + 1); | 1309 emitCharacter(',', m_node->parentNode(), index, index + 1); |
1309 return true; | 1310 return true; |
1310 } | 1311 } |
1311 | 1312 |
1312 bool SimplifiedBackwardsTextIterator::handleNonTextNode() | 1313 bool SimplifiedBackwardsTextIterator::handleNonTextNode() |
1313 { | 1314 { |
1314 // We can use a linefeed in place of a tab because this simple iterator is o nly used to | 1315 // We can use a linefeed in place of a tab because this simple iterator is o nly used to |
1315 // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. | 1316 // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. |
1316 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neAfterNode(m_node) || shouldEmitTabBeforeNode(m_node)) { | 1317 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neAfterNode(*m_node) || shouldEmitTabBeforeNode(m_node)) { |
1317 unsigned index = m_node->nodeIndex(); | 1318 unsigned index = m_node->nodeIndex(); |
1318 // The start of this emitted range is wrong. Ensuring correctness would require | 1319 // The start of this emitted range is wrong. Ensuring correctness would require |
1319 // VisiblePositions and so would be slow. previousBoundary expects this. | 1320 // VisiblePositions and so would be slow. previousBoundary expects this. |
1320 emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); | 1321 emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); |
1321 } | 1322 } |
1322 return true; | 1323 return true; |
1323 } | 1324 } |
1324 | 1325 |
1325 void SimplifiedBackwardsTextIterator::exitNode() | 1326 void SimplifiedBackwardsTextIterator::exitNode() |
1326 { | 1327 { |
1327 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neBeforeNode(m_node) || shouldEmitTabBeforeNode(m_node)) { | 1328 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neBeforeNode(*m_node) || shouldEmitTabBeforeNode(m_node)) { |
1328 // The start of this emitted range is wrong. Ensuring correctness would require | 1329 // The start of this emitted range is wrong. Ensuring correctness would require |
1329 // VisiblePositions and so would be slow. previousBoundary expects this. | 1330 // VisiblePositions and so would be slow. previousBoundary expects this. |
1330 emitCharacter('\n', m_node, 0, 0); | 1331 emitCharacter('\n', m_node, 0, 0); |
1331 } | 1332 } |
1332 } | 1333 } |
1333 | 1334 |
1334 void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta rtOffset, int endOffset) | 1335 void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta rtOffset, int endOffset) |
1335 { | 1336 { |
1336 m_singleCharacterBuffer = c; | 1337 m_singleCharacterBuffer = c; |
1337 m_positionNode = node; | 1338 m_positionNode = node; |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2325 if (!matchLength) | 2326 if (!matchLength) |
2326 return collapsedToBoundary(range, !(options & Backwards)); | 2327 return collapsedToBoundary(range, !(options & Backwards)); |
2327 } | 2328 } |
2328 | 2329 |
2329 // Then, find the document position of the start and the end of the text. | 2330 // Then, find the document position of the start and the end of the text. |
2330 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls ); | 2331 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls ); |
2331 return characterSubrange(computeRangeIterator, matchStart, matchLength); | 2332 return characterSubrange(computeRangeIterator, matchStart, matchLength); |
2332 } | 2333 } |
2333 | 2334 |
2334 } | 2335 } |
OLD | NEW |