OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
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 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1138 ASSERT(frame().document()); | 1138 ASSERT(frame().document()); |
1139 ApplyStyleCommand::create(*frame().document(), blockStyle.get(), editing Action)->apply(); | 1139 ApplyStyleCommand::create(*frame().document(), blockStyle.get(), editing Action)->apply(); |
1140 } | 1140 } |
1141 | 1141 |
1142 // Set the remaining style as the typing style. | 1142 // Set the remaining style as the typing style. |
1143 frame().selection().setTypingStyle(typingStyle); | 1143 frame().selection().setTypingStyle(typingStyle); |
1144 } | 1144 } |
1145 | 1145 |
1146 bool Editor::findString(const String& target, FindOptions options) | 1146 bool Editor::findString(const String& target, FindOptions options) |
1147 { | 1147 { |
1148 VisibleSelection selection = frame().selection().selection(); | 1148 const VisibleSelection& selection = frame().selection().selection(); |
1149 const EphemeralRange& resultRange = findRangeOfString( | |
1150 target, | |
1151 EphemeralRange(selection.start(), selection.end()), | |
1152 static_cast<FindOptions>(options | FindAPICall)); | |
1149 | 1153 |
1150 // TODO(yosin) We should make |findRangeOfString()| to return | 1154 if (resultRange.isCollapsed()) |
1151 // |EphemeralRange| rather than|Range| object. | |
1152 RefPtrWillBeRawPtr<Range> resultRange = findRangeOfString(target, EphemeralR ange(selection.start(), selection.end()), static_cast<FindOptions>(options | Fin dAPICall)); | |
1153 | |
1154 if (!resultRange) | |
1155 return false; | 1155 return false; |
1156 | 1156 |
1157 frame().selection().setSelection(VisibleSelection(EphemeralRange(resultRange .get()))); | 1157 frame().selection().setSelection(VisibleSelection(resultRange)); |
1158 frame().selection().revealSelection(); | 1158 frame().selection().revealSelection(); |
1159 return true; | 1159 return true; |
1160 } | 1160 } |
1161 | 1161 |
1162 template <typename Strategy> | 1162 template <typename Strategy> |
1163 static PassRefPtrWillBeRawPtr<Range> findStringAndScrollToVisibleAlgorithm(Edito r& editor, const String& target, const EphemeralRangeTemplate<Strategy>& previou sMatch, FindOptions options) | 1163 static EphemeralRangeTemplate<Strategy> findStringAndScrollToVisibleAlgorithm(Ed itor& editor, const String& target, const EphemeralRangeTemplate<Strategy>& prev iousMatch, FindOptions options) |
1164 { | 1164 { |
1165 RefPtrWillBeRawPtr<Range> nextMatch = editor.findRangeOfString(target, previ ousMatch, options); | 1165 const EphemeralRangeTemplate<Strategy>& nextMatch = editor.findRangeOfString (target, previousMatch, options); |
1166 if (!nextMatch) | 1166 if (nextMatch.isCollapsed()) |
1167 return nullptr; | 1167 return EphemeralRangeTemplate<Strategy>(); |
1168 | 1168 |
1169 nextMatch->firstNode()->layoutObject()->scrollRectToVisible(LayoutRect(nextM atch->boundingBox()), | 1169 if (auto* layoutObject = nextMatch.startPosition().nodeAsRangeFirstNode()->l ayoutObject()) { |
1170 ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeed ed, UserScroll); | 1170 layoutObject->scrollRectToVisible( |
1171 LayoutRect(nextMatch.textBoundingBox()), | |
1172 ScrollAlignment::alignCenterIfNeeded, | |
1173 ScrollAlignment::alignCenterIfNeeded, | |
1174 UserScroll); | |
1175 } | |
1171 | 1176 |
1172 return nextMatch.release(); | 1177 return nextMatch; |
1173 } | 1178 } |
1174 | 1179 |
1175 PassRefPtrWillBeRawPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* range, FindOptions options) | 1180 EphemeralRange Editor::findStringAndScrollToVisible(const String& target, const EphemeralRange& range, FindOptions options) |
1176 { | 1181 { |
1177 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) | 1182 return findStringAndScrollToVisibleAlgorithm(*this, target, range, options); |
1178 return findStringAndScrollToVisibleAlgorithm<EditingInComposedTreeStrate gy>(*this, target, EphemeralRangeInComposedTree(range), options); | |
1179 return findStringAndScrollToVisibleAlgorithm<EditingStrategy>(*this, target, EphemeralRange(range), options); | |
1180 } | 1183 } |
1181 | 1184 |
1182 // TODO(yosin) We should return |EphemeralRange| rather than |Range|. We use | 1185 EphemeralRangeInComposedTree Editor::findStringAndScrollToVisible(const String& target, const EphemeralRangeInComposedTree& range, FindOptions options) |
1183 // |Range| object for checking whether start and end position crossing shadow | 1186 { |
1184 // boundaries, however we can do it without |Range| object. | 1187 ASSERT(RuntimeEnabledFeatures::selectionForComposedTreeEnabled()); |
1188 return findStringAndScrollToVisibleAlgorithm(*this, target, range, options); | |
1189 } | |
1190 | |
1191 // This function checks whether start and end position of the |range| | |
1192 // crossing shadow boundaries. | |
1193 // It should be equivalent to !Range::create(ephemeralRange)->collapsed(). | |
1185 template <typename Strategy> | 1194 template <typename Strategy> |
1186 static PassRefPtrWillBeRawPtr<Range> findStringBetweenPositions(const String& ta rget, const EphemeralRangeTemplate<Strategy>& referenceRange, FindOptions option s) | 1195 static bool rangeBoundariesAreValid(const EphemeralRangeTemplate<Strategy>& rang e) |
yosin_UTC9
2015/11/04 07:11:06
This function doesn't check shadow boundary crossi
| |
1196 { | |
1197 const Node* endRootContainer = range.endPosition().computeContainerNode(); | |
yosin_UTC9
2015/11/04 07:11:06
When start is null position, end must be null posi
| |
1198 const Node* startRootContainer = range.startPosition().computeContainerNode( ); | |
1199 if (!startRootContainer || !endRootContainer) | |
1200 return false; | |
1201 | |
1202 ASSERT(Strategy::commonAncestor(*startRootContainer, *endRootContainer)); | |
1203 return range.startPosition().compareTo(range.endPosition()) < 0; | |
1204 } | |
1205 | |
1206 template <typename Strategy> | |
1207 static EphemeralRangeTemplate<Strategy> findStringBetweenPositions(const String& target, const EphemeralRangeTemplate<Strategy>& referenceRange, FindOptions opt ions) | |
1187 { | 1208 { |
1188 EphemeralRangeTemplate<Strategy> searchRange(referenceRange); | 1209 EphemeralRangeTemplate<Strategy> searchRange(referenceRange); |
1189 | 1210 |
1190 bool forward = !(options & Backwards); | 1211 bool forward = !(options & Backwards); |
1191 | 1212 |
1192 while (true) { | 1213 while (true) { |
1193 EphemeralRangeTemplate<Strategy> resultRange = findPlainText(searchRange , target, options); | 1214 const EphemeralRangeTemplate<Strategy>& resultRange = findPlainText(sear chRange, target, options); |
1194 if (resultRange.isCollapsed()) | 1215 if (resultRange.isCollapsed()) |
1195 return nullptr; | 1216 return EphemeralRangeTemplate<Strategy>(); |
1196 | 1217 |
1197 RefPtrWillBeRawPtr<Range> rangeObject = Range::create(resultRange.docume nt(), toPositionInDOMTree(resultRange.startPosition()), toPositionInDOMTree(resu ltRange.endPosition())); | 1218 if (rangeBoundariesAreValid(resultRange)) |
yosin_UTC9
2015/11/04 07:11:06
Just return found range even if it is crossing sha
| |
1198 if (!rangeObject->collapsed()) | 1219 return resultRange; |
1199 return rangeObject.release(); | |
1200 | 1220 |
1201 // Found text spans over multiple TreeScopes. Since it's impossible to | 1221 // Found text spans over multiple TreeScopes. Since it's impossible to |
1202 // return such section as a Range, we skip this match and seek for the | 1222 // return such section as a Range, we skip this match and seek for the |
1203 // next occurrence. | 1223 // next occurrence. |
1204 // TODO(yosin) Handle this case. | 1224 // TODO(yosin) Handle this case. |
1205 if (forward) { | 1225 if (forward) { |
1206 // TODO(yosin) We should use |PositionMoveType::Character| | 1226 // TODO(yosin) We should use |PositionMoveType::Character| |
1207 // for |nextPositionOf()|. | 1227 // for |nextPositionOf()|. |
1208 searchRange = EphemeralRangeTemplate<Strategy>(nextPositionOf(result Range.startPosition(), PositionMoveType::CodePoint), searchRange.endPosition()); | 1228 searchRange = EphemeralRangeTemplate<Strategy>(nextPositionOf(result Range.startPosition(), PositionMoveType::CodePoint), searchRange.endPosition()); |
1209 } else { | 1229 } else { |
1210 // TODO(yosin) We should use |PositionMoveType::Character| | 1230 // TODO(yosin) We should use |PositionMoveType::Character| |
1211 // for |previousPositionOf()|. | 1231 // for |previousPositionOf()|. |
1212 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), previousPositionOf(resultRange.endPosition(), PositionMoveType::CodePoin t)); | 1232 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), previousPositionOf(resultRange.endPosition(), PositionMoveType::CodePoin t)); |
1213 } | 1233 } |
1214 } | 1234 } |
1215 | 1235 |
1216 ASSERT_NOT_REACHED(); | 1236 ASSERT_NOT_REACHED(); |
1217 return nullptr; | 1237 return EphemeralRangeTemplate<Strategy>(); |
1218 } | 1238 } |
1219 | 1239 |
1220 template <typename Strategy> | 1240 template <typename Strategy> |
1221 static PassRefPtrWillBeRawPtr<Range> findRangeOfStringAlgorithm(Document& docume nt, const String& target, const EphemeralRangeTemplate<Strategy>& referenceRange , FindOptions options) | 1241 static EphemeralRangeTemplate<Strategy> findRangeOfStringAlgorithm(Document& doc ument, const String& target, const EphemeralRangeTemplate<Strategy>& referenceRa nge, FindOptions options) |
1222 { | 1242 { |
1223 if (target.isEmpty()) | 1243 if (target.isEmpty()) |
1224 return nullptr; | 1244 return EphemeralRangeTemplate<Strategy>(); |
1225 | 1245 |
1226 // Start from an edge of the reference range. Which edge is used depends on | 1246 // Start from an edge of the reference range. Which edge is used depends on |
1227 // whether we're searching forward or backward, and whether startInSelection | 1247 // whether we're searching forward or backward, and whether startInSelection |
1228 // is set. | 1248 // is set. |
1229 EphemeralRangeTemplate<Strategy> documentRange = EphemeralRangeTemplate<Stra tegy>::rangeOfContents(document); | 1249 EphemeralRangeTemplate<Strategy> documentRange = EphemeralRangeTemplate<Stra tegy>::rangeOfContents(document); |
1230 EphemeralRangeTemplate<Strategy> searchRange(documentRange); | 1250 EphemeralRangeTemplate<Strategy> searchRange(documentRange); |
1231 | 1251 |
1232 bool forward = !(options & Backwards); | 1252 bool forward = !(options & Backwards); |
1233 bool startInReferenceRange = false; | 1253 bool startInReferenceRange = false; |
1234 if (referenceRange.isNotNull()) { | 1254 if (referenceRange.isNotNull()) { |
1235 startInReferenceRange = options & StartInSelection; | 1255 startInReferenceRange = options & StartInSelection; |
1236 if (forward && startInReferenceRange) | 1256 if (forward && startInReferenceRange) |
1237 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.startP osition(), documentRange.endPosition()); | 1257 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.startP osition(), documentRange.endPosition()); |
1238 else if (forward) | 1258 else if (forward) |
1239 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.endPos ition(), documentRange.endPosition()); | 1259 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.endPos ition(), documentRange.endPosition()); |
1240 else if (startInReferenceRange) | 1260 else if (startInReferenceRange) |
1241 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.endPosition()); | 1261 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.endPosition()); |
1242 else | 1262 else |
1243 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.startPosition()); | 1263 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.startPosition()); |
1244 } | 1264 } |
1245 | 1265 |
1246 RefPtrWillBeRawPtr<Range> resultRange = findStringBetweenPositions(target, s earchRange, options); | 1266 EphemeralRangeTemplate<Strategy> resultRange = findStringBetweenPositions(ta rget, searchRange, options); |
1247 | 1267 |
1248 // If we started in the reference range and the found range exactly matches | 1268 // If we started in the reference range and the found range exactly matches |
1249 // the reference range, find again. Build a selection with the found range | 1269 // the reference range, find again. Build a selection with the found range |
1250 // to remove collapsed whitespace. Compare ranges instead of selection | 1270 // to remove collapsed whitespace. Compare ranges instead of selection |
1251 // objects to ignore the way that the current selection was made. | 1271 // objects to ignore the way that the current selection was made. |
1252 if (resultRange && startInReferenceRange && normalizeRange(EphemeralRangeTem plate<Strategy>(resultRange.get())) == referenceRange) { | 1272 if (!resultRange.isCollapsed() && startInReferenceRange && normalizeRange(re sultRange) == referenceRange) { |
1253 if (forward) | 1273 if (forward) |
1254 searchRange = EphemeralRangeTemplate<Strategy>(fromPositionInDOMTree <Strategy>(resultRange->endPosition()), searchRange.endPosition()); | 1274 searchRange = EphemeralRangeTemplate<Strategy>(resultRange.endPositi on(), searchRange.endPosition()); |
1255 else | 1275 else |
1256 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), fromPositionInDOMTree<Strategy>(resultRange->startPosition())); | 1276 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), resultRange.startPosition()); |
1257 resultRange = findStringBetweenPositions(target, searchRange, options); | 1277 resultRange = findStringBetweenPositions(target, searchRange, options); |
1258 } | 1278 } |
1259 | 1279 |
1260 if (!resultRange && options & WrapAround) | 1280 if (resultRange.isCollapsed() && options & WrapAround) |
1261 return findStringBetweenPositions(target, documentRange, options); | 1281 return findStringBetweenPositions(target, documentRange, options); |
1262 | 1282 |
1263 return resultRange.release(); | 1283 return resultRange; |
1264 } | 1284 } |
1265 | 1285 |
1266 PassRefPtrWillBeRawPtr<Range> Editor::findRangeOfString(const String& target, co nst EphemeralRange& reference, FindOptions options) | 1286 EphemeralRange Editor::findRangeOfString(const String& target, const EphemeralRa nge& reference, FindOptions options) |
1267 { | 1287 { |
1268 return findRangeOfStringAlgorithm<EditingStrategy>(*frame().document(), targ et, reference, options); | 1288 return findRangeOfStringAlgorithm<EditingStrategy>(*frame().document(), targ et, reference, options); |
1269 } | 1289 } |
1270 | 1290 |
1271 PassRefPtrWillBeRawPtr<Range> Editor::findRangeOfString(const String& target, co nst EphemeralRangeInComposedTree& reference, FindOptions options) | 1291 EphemeralRangeInComposedTree Editor::findRangeOfString(const String& target, con st EphemeralRangeInComposedTree& reference, FindOptions options) |
1272 { | 1292 { |
1273 return findRangeOfStringAlgorithm<EditingInComposedTreeStrategy>(*frame().do cument(), target, reference, options); | 1293 return findRangeOfStringAlgorithm<EditingInComposedTreeStrategy>(*frame().do cument(), target, reference, options); |
1274 } | 1294 } |
1275 | 1295 |
1276 void Editor::setMarkedTextMatchesAreHighlighted(bool flag) | 1296 void Editor::setMarkedTextMatchesAreHighlighted(bool flag) |
1277 { | 1297 { |
1278 if (flag == m_areMarkedTextMatchesHighlighted) | 1298 if (flag == m_areMarkedTextMatchesHighlighted) |
1279 return; | 1299 return; |
1280 | 1300 |
1281 m_areMarkedTextMatchesHighlighted = flag; | 1301 m_areMarkedTextMatchesHighlighted = flag; |
(...skipping 19 matching lines...) Expand all Loading... | |
1301 } | 1321 } |
1302 | 1322 |
1303 DEFINE_TRACE(Editor) | 1323 DEFINE_TRACE(Editor) |
1304 { | 1324 { |
1305 visitor->trace(m_frame); | 1325 visitor->trace(m_frame); |
1306 visitor->trace(m_lastEditCommand); | 1326 visitor->trace(m_lastEditCommand); |
1307 visitor->trace(m_mark); | 1327 visitor->trace(m_mark); |
1308 } | 1328 } |
1309 | 1329 |
1310 } // namespace blink | 1330 } // namespace blink |
OLD | NEW |