OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
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 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 } | 596 } |
597 if (!m_textBox && m_remainingTextBox) { | 597 if (!m_textBox && m_remainingTextBox) { |
598 m_textBox = m_remainingTextBox; | 598 m_textBox = m_remainingTextBox; |
599 m_remainingTextBox = 0; | 599 m_remainingTextBox = 0; |
600 m_firstLetterText = 0; | 600 m_firstLetterText = 0; |
601 m_offset = 0; | 601 m_offset = 0; |
602 handleTextBox(); | 602 handleTextBox(); |
603 } | 603 } |
604 } | 604 } |
605 | 605 |
| 606 static inline RenderText* firstRenderTextInFirstLetter(RenderObject* firstLetter
) |
| 607 { |
| 608 if (!firstLetter) |
| 609 return 0; |
| 610 |
| 611 // FIXME: Should this check descendent objects? |
| 612 for (RenderObject* current = firstLetter->firstChild(); current; current = c
urrent->nextSibling()) { |
| 613 if (current->isText()) |
| 614 return toRenderText(current); |
| 615 } |
| 616 return 0; |
| 617 } |
| 618 |
606 void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) | 619 void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) |
607 { | 620 { |
608 if (renderer->firstLetter()) { | 621 if (renderer->firstLetter()) { |
609 RenderObject* r = renderer->firstLetter(); | 622 RenderObject* r = renderer->firstLetter(); |
610 if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) | 623 if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility) |
611 return; | 624 return; |
612 for (RenderObject *currChild = r->firstChild(); currChild; currChild->ne
xtSibling()) { | 625 if (RenderText* firstLetter = firstRenderTextInFirstLetter(r)) { |
613 if (currChild->isText()) { | 626 m_handledFirstLetter = true; |
614 RenderText* firstLetter = toRenderText(currChild); | 627 m_remainingTextBox = m_textBox; |
615 m_handledFirstLetter = true; | 628 m_textBox = firstLetter->firstTextBox(); |
616 m_remainingTextBox = m_textBox; | 629 m_firstLetterText = firstLetter; |
617 m_textBox = firstLetter->firstTextBox(); | |
618 m_firstLetterText = firstLetter; | |
619 return; | |
620 } | |
621 } | 630 } |
622 } | 631 } |
623 m_handledFirstLetter = true; | 632 m_handledFirstLetter = true; |
624 } | 633 } |
625 | 634 |
626 bool TextIterator::handleReplacedElement() | 635 bool TextIterator::handleReplacedElement() |
627 { | 636 { |
628 if (m_fullyClippedStack.top()) | 637 if (m_fullyClippedStack.top()) |
629 return false; | 638 return false; |
630 | 639 |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 return node; | 1045 return node; |
1037 | 1046 |
1038 return node->childNode(textRange->startOffset()); | 1047 return node->childNode(textRange->startOffset()); |
1039 } | 1048 } |
1040 | 1049 |
1041 // -------- | 1050 // -------- |
1042 | 1051 |
1043 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() | 1052 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() |
1044 : m_behavior(TextIteratorDefaultBehavior) | 1053 : m_behavior(TextIteratorDefaultBehavior) |
1045 , m_node(0) | 1054 , m_node(0) |
| 1055 , m_offset(0) |
| 1056 , m_handledNode(false) |
| 1057 , m_handledChildren(false) |
| 1058 , m_startNode(0) |
| 1059 , m_startOffset(0) |
| 1060 , m_endNode(0) |
| 1061 , m_endOffset(0) |
1046 , m_positionNode(0) | 1062 , m_positionNode(0) |
| 1063 , m_positionStartOffset(0) |
| 1064 , m_positionEndOffset(0) |
| 1065 , m_textCharacters(0) |
| 1066 , m_textLength(0) |
| 1067 , m_lastTextNode(0) |
| 1068 , m_lastCharacter(0) |
| 1069 , m_singleCharacterBuffer(0) |
| 1070 , m_havePassedStartNode(false) |
| 1071 , m_shouldHandleFirstLetter(false) |
1047 { | 1072 { |
1048 } | 1073 } |
1049 | 1074 |
1050 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r,
TextIteratorBehavior behavior) | 1075 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r,
TextIteratorBehavior behavior) |
1051 : m_behavior(behavior) | 1076 : m_behavior(behavior) |
1052 , m_node(0) | 1077 , m_node(0) |
| 1078 , m_offset(0) |
| 1079 , m_handledNode(false) |
| 1080 , m_handledChildren(false) |
| 1081 , m_startNode(0) |
| 1082 , m_startOffset(0) |
| 1083 , m_endNode(0) |
| 1084 , m_endOffset(0) |
1053 , m_positionNode(0) | 1085 , m_positionNode(0) |
| 1086 , m_positionStartOffset(0) |
| 1087 , m_positionEndOffset(0) |
| 1088 , m_textCharacters(0) |
| 1089 , m_textLength(0) |
| 1090 , m_lastTextNode(0) |
| 1091 , m_lastCharacter(0) |
| 1092 , m_singleCharacterBuffer(0) |
| 1093 , m_havePassedStartNode(false) |
| 1094 , m_shouldHandleFirstLetter(false) |
1054 { | 1095 { |
1055 ASSERT(m_behavior == TextIteratorDefaultBehavior); | 1096 ASSERT(m_behavior == TextIteratorDefaultBehavior); |
1056 | 1097 |
1057 if (!r) | 1098 if (!r) |
1058 return; | 1099 return; |
1059 | 1100 |
1060 Node* startNode = r->startContainer(); | 1101 Node* startNode = r->startContainer(); |
1061 if (!startNode) | 1102 if (!startNode) |
1062 return; | 1103 return; |
1063 Node* endNode = r->endContainer(); | 1104 Node* endNode = r->endContainer(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 | 1212 |
1172 if (m_positionNode) | 1213 if (m_positionNode) |
1173 return; | 1214 return; |
1174 } | 1215 } |
1175 } | 1216 } |
1176 | 1217 |
1177 bool SimplifiedBackwardsTextIterator::handleTextNode() | 1218 bool SimplifiedBackwardsTextIterator::handleTextNode() |
1178 { | 1219 { |
1179 m_lastTextNode = m_node; | 1220 m_lastTextNode = m_node; |
1180 | 1221 |
1181 RenderText* renderer = toRenderText(m_node->renderer()); | 1222 int startOffset; |
1182 String str = renderer->text(); | 1223 int offsetInNode; |
| 1224 RenderText* renderer = handleFirstLetter(startOffset, offsetInNode); |
| 1225 if (!renderer) |
| 1226 return true; |
1183 | 1227 |
1184 if (!renderer->firstTextBox() && str.length() > 0) | 1228 String text = renderer->text(); |
| 1229 if (!renderer->firstTextBox() && text.length() > 0) |
1185 return true; | 1230 return true; |
1186 | 1231 |
1187 m_positionEndOffset = m_offset; | 1232 m_positionEndOffset = m_offset; |
1188 | 1233 m_offset = startOffset + offsetInNode; |
1189 m_offset = (m_node == m_startNode) ? m_startOffset : 0; | |
1190 m_positionNode = m_node; | 1234 m_positionNode = m_node; |
1191 m_positionStartOffset = m_offset; | 1235 m_positionStartOffset = m_offset; |
| 1236 |
| 1237 ASSERT(0 <= m_positionStartOffset - offsetInNode && m_positionStartOffset -
offsetInNode <= static_cast<int>(text.length())); |
| 1238 ASSERT(1 <= m_positionEndOffset - offsetInNode && m_positionEndOffset - offs
etInNode <= static_cast<int>(text.length())); |
| 1239 ASSERT(m_positionStartOffset <= m_positionEndOffset); |
| 1240 |
1192 m_textLength = m_positionEndOffset - m_positionStartOffset; | 1241 m_textLength = m_positionEndOffset - m_positionStartOffset; |
1193 m_textCharacters = str.characters() + m_positionStartOffset; | 1242 m_textCharacters = text.characters() + (m_positionStartOffset - offsetInNode
); |
| 1243 ASSERT(m_textCharacters >= text.characters()); |
| 1244 ASSERT(m_textCharacters + m_textLength <= text.characters() + static_cast<in
t>(text.length())); |
1194 | 1245 |
1195 m_lastCharacter = str[m_positionEndOffset - 1]; | 1246 m_lastCharacter = text[m_positionEndOffset - 1]; |
1196 | 1247 |
1197 return true; | 1248 return !m_shouldHandleFirstLetter; |
| 1249 } |
| 1250 |
| 1251 RenderText* SimplifiedBackwardsTextIterator::handleFirstLetter(int& startOffset,
int& offsetInNode) |
| 1252 { |
| 1253 RenderText* renderer = toRenderText(m_node->renderer()); |
| 1254 startOffset = (m_node == m_startNode) ? m_startOffset : 0; |
| 1255 |
| 1256 if (!renderer->isTextFragment()) { |
| 1257 offsetInNode = 0; |
| 1258 return renderer; |
| 1259 } |
| 1260 |
| 1261 RenderTextFragment* fragment = toRenderTextFragment(renderer); |
| 1262 int offsetAfterFirstLetter = fragment->start(); |
| 1263 if (startOffset >= offsetAfterFirstLetter) { |
| 1264 ASSERT(!m_shouldHandleFirstLetter); |
| 1265 offsetInNode = offsetAfterFirstLetter; |
| 1266 return renderer; |
| 1267 } |
| 1268 |
| 1269 if (!m_shouldHandleFirstLetter && offsetAfterFirstLetter < m_offset) { |
| 1270 m_shouldHandleFirstLetter = true; |
| 1271 offsetInNode = offsetAfterFirstLetter; |
| 1272 return renderer; |
| 1273 } |
| 1274 |
| 1275 m_shouldHandleFirstLetter = false; |
| 1276 offsetInNode = 0; |
| 1277 return firstRenderTextInFirstLetter(fragment->firstLetter()); |
1198 } | 1278 } |
1199 | 1279 |
1200 bool SimplifiedBackwardsTextIterator::handleReplacedElement() | 1280 bool SimplifiedBackwardsTextIterator::handleReplacedElement() |
1201 { | 1281 { |
1202 unsigned index = m_node->nodeIndex(); | 1282 unsigned index = m_node->nodeIndex(); |
1203 // We want replaced elements to behave like punctuation for boundary | 1283 // We want replaced elements to behave like punctuation for boundary |
1204 // finding, and to simply take up space for the selection preservation | 1284 // finding, and to simply take up space for the selection preservation |
1205 // code in moveParagraphs, so we use a comma. Unconditionally emit | 1285 // code in moveParagraphs, so we use a comma. Unconditionally emit |
1206 // here because this iterator is only used for boundary finding. | 1286 // here because this iterator is only used for boundary finding. |
1207 emitCharacter(',', m_node->parentNode(), index, index + 1); | 1287 emitCharacter(',', m_node->parentNode(), index, index + 1); |
(...skipping 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2583 if (!matchLength) | 2663 if (!matchLength) |
2584 return collapsedToBoundary(range, !(options & Backwards)); | 2664 return collapsedToBoundary(range, !(options & Backwards)); |
2585 } | 2665 } |
2586 | 2666 |
2587 // Then, find the document position of the start and the end of the text. | 2667 // Then, find the document position of the start and the end of the text. |
2588 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls
); | 2668 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls
); |
2589 return characterSubrange(computeRangeIterator, matchStart, matchLength); | 2669 return characterSubrange(computeRangeIterator, matchStart, matchLength); |
2590 } | 2670 } |
2591 | 2671 |
2592 } | 2672 } |
OLD | NEW |