OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 } | 249 } |
250 | 250 |
251 template <typename Strategy> | 251 template <typename Strategy> |
252 static EphemeralRangeTemplate<Strategy> normalizeRangeAlgorithm(const EphemeralR
angeTemplate<Strategy>& range) | 252 static EphemeralRangeTemplate<Strategy> normalizeRangeAlgorithm(const EphemeralR
angeTemplate<Strategy>& range) |
253 { | 253 { |
254 ASSERT(range.isNotNull()); | 254 ASSERT(range.isNotNull()); |
255 range.document().updateLayoutIgnorePendingStylesheets(); | 255 range.document().updateLayoutIgnorePendingStylesheets(); |
256 | 256 |
257 // TODO(yosin) We should not call |parentAnchoredEquivalent()|, it is | 257 // TODO(yosin) We should not call |parentAnchoredEquivalent()|, it is |
258 // redundant. | 258 // redundant. |
259 const PositionAlgorithm<Strategy> normalizedStart = range.startPosition().do
wnstream().parentAnchoredEquivalent(); | 259 const PositionAlgorithm<Strategy> normalizedStart = mostForwardCaretPosition
(range.startPosition()).parentAnchoredEquivalent(); |
260 const PositionAlgorithm<Strategy> normalizedEnd = range.endPosition().upstre
am().parentAnchoredEquivalent(); | 260 const PositionAlgorithm<Strategy> normalizedEnd = mostBackwardCaretPosition(
range.endPosition()).parentAnchoredEquivalent(); |
261 // The order of the positions of |start| and |end| can be swapped after | 261 // The order of the positions of |start| and |end| can be swapped after |
262 // upstream/downstream. e.g. editing/pasteboard/copy-display-none.html | 262 // upstream/downstream. e.g. editing/pasteboard/copy-display-none.html |
263 if (normalizedStart.compareTo(normalizedEnd) > 0) | 263 if (normalizedStart.compareTo(normalizedEnd) > 0) |
264 return EphemeralRangeTemplate<Strategy>(normalizedEnd, normalizedStart); | 264 return EphemeralRangeTemplate<Strategy>(normalizedEnd, normalizedStart); |
265 return EphemeralRangeTemplate<Strategy>(normalizedStart, normalizedEnd); | 265 return EphemeralRangeTemplate<Strategy>(normalizedStart, normalizedEnd); |
266 } | 266 } |
267 | 267 |
268 EphemeralRange VisibleSelection::normalizeRange(const EphemeralRange& range) | 268 EphemeralRange VisibleSelection::normalizeRange(const EphemeralRange& range) |
269 { | 269 { |
270 return normalizeRangeAlgorithm<EditingStrategy>(range); | 270 return normalizeRangeAlgorithm<EditingStrategy>(range); |
(...skipping 16 matching lines...) Expand all Loading... |
287 m_start.document()->updateLayout(); | 287 m_start.document()->updateLayout(); |
288 | 288 |
289 // Check again, because updating layout can clear the selection. | 289 // Check again, because updating layout can clear the selection. |
290 if (isNone()) | 290 if (isNone()) |
291 return EphemeralRange(); | 291 return EphemeralRange(); |
292 | 292 |
293 if (isCaret()) { | 293 if (isCaret()) { |
294 // If the selection is a caret, move the range start upstream. This | 294 // If the selection is a caret, move the range start upstream. This |
295 // helps us match the conventions of text editors tested, which make | 295 // helps us match the conventions of text editors tested, which make |
296 // style determinations based on the character before the caret, if any. | 296 // style determinations based on the character before the caret, if any. |
297 const Position start = m_start.upstream().parentAnchoredEquivalent(); | 297 const Position start = mostBackwardCaretPosition(m_start).parentAnchored
Equivalent(); |
298 return EphemeralRange(start, start); | 298 return EphemeralRange(start, start); |
299 } | 299 } |
300 // If the selection is a range, select the minimum range that encompasses | 300 // If the selection is a range, select the minimum range that encompasses |
301 // the selection. Again, this is to match the conventions of text editors | 301 // the selection. Again, this is to match the conventions of text editors |
302 // tested, which make style determinations based on the first character of | 302 // tested, which make style determinations based on the first character of |
303 // the selection. For instance, this operation helps to make sure that the | 303 // the selection. For instance, this operation helps to make sure that the |
304 // "X" selected below is the only thing selected. The range should not be | 304 // "X" selected below is the only thing selected. The range should not be |
305 // allowed to "leak" out to the end of the previous text node, or to the | 305 // allowed to "leak" out to the end of the previous text node, or to the |
306 // beginning of the next text node, each of which has a different style. | 306 // beginning of the next text node, each of which has a different style. |
307 // | 307 // |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 m_end = m_baseIsFirst ? m_extent : m_base; | 574 m_end = m_baseIsFirst ? m_extent : m_base; |
575 resetPositionsInComposedTree(); | 575 resetPositionsInComposedTree(); |
576 } | 576 } |
577 | 577 |
578 SelectionType VisibleSelection::selectionType(const Position& start, const Posit
ion& end) | 578 SelectionType VisibleSelection::selectionType(const Position& start, const Posit
ion& end) |
579 { | 579 { |
580 if (start.isNull()) { | 580 if (start.isNull()) { |
581 ASSERT(end.isNull()); | 581 ASSERT(end.isNull()); |
582 return NoSelection; | 582 return NoSelection; |
583 } | 583 } |
584 if (start == end || start.upstream() == end.upstream()) | 584 if (start == end || mostBackwardCaretPosition(start) == mostBackwardCaretPos
ition(end)) |
585 return CaretSelection; | 585 return CaretSelection; |
586 return RangeSelection; | 586 return RangeSelection; |
587 } | 587 } |
588 | 588 |
589 SelectionType VisibleSelection::selectionType(const PositionInComposedTree& star
t, const PositionInComposedTree& end) | 589 SelectionType VisibleSelection::selectionType(const PositionInComposedTree& star
t, const PositionInComposedTree& end) |
590 { | 590 { |
591 if (start.isNull()) { | 591 if (start.isNull()) { |
592 ASSERT(end.isNull()); | 592 ASSERT(end.isNull()); |
593 return NoSelection; | 593 return NoSelection; |
594 } | 594 } |
595 if (start == end || start.upstream() == end.upstream()) | 595 if (start == end || mostBackwardCaretPosition(start) == mostBackwardCaretPos
ition(end)) |
596 return CaretSelection; | 596 return CaretSelection; |
597 return RangeSelection; | 597 return RangeSelection; |
598 } | 598 } |
599 | 599 |
600 void VisibleSelection::updateSelectionType() | 600 void VisibleSelection::updateSelectionType() |
601 { | 601 { |
602 m_selectionType = selectionType(m_start, m_end); | 602 m_selectionType = selectionType(m_start, m_end); |
603 | 603 |
604 // Affinity only makes sense for a caret | 604 // Affinity only makes sense for a caret |
605 if (m_selectionType != CaretSelection) | 605 if (m_selectionType != CaretSelection) |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 | 692 |
693 if (selectionType() == RangeSelection) { | 693 if (selectionType() == RangeSelection) { |
694 // "Constrain" the selection to be the smallest equivalent range of node
s. | 694 // "Constrain" the selection to be the smallest equivalent range of node
s. |
695 // This is a somewhat arbitrary choice, but experience shows that it is | 695 // This is a somewhat arbitrary choice, but experience shows that it is |
696 // useful to make to make the selection "canonical" (if only for | 696 // useful to make to make the selection "canonical" (if only for |
697 // purposes of comparing selections). This is an ideal point of the code | 697 // purposes of comparing selections). This is an ideal point of the code |
698 // to do this operation, since all selection changes that result in a RA
NGE | 698 // to do this operation, since all selection changes that result in a RA
NGE |
699 // come through here before anyone uses it. | 699 // come through here before anyone uses it. |
700 // FIXME: Canonicalizing is good, but haven't we already done it (when w
e | 700 // FIXME: Canonicalizing is good, but haven't we already done it (when w
e |
701 // set these two positions to VisiblePosition deepEquivalent()s above)? | 701 // set these two positions to VisiblePosition deepEquivalent()s above)? |
702 m_start = m_start.downstream(); | 702 m_start = mostForwardCaretPosition(m_start); |
703 m_end = m_end.upstream(); | 703 m_end = mostBackwardCaretPosition(m_end); |
704 | 704 |
705 // Even by downstreaming, |m_start| can be moved to the upper place from | 705 // Even by downstreaming, |m_start| can be moved to the upper place from |
706 // the original position, same as |m_end|. | 706 // the original position, same as |m_end|. |
707 // e.g.) editing/shadow/select-contenteditable-shadowhost.html | 707 // e.g.) editing/shadow/select-contenteditable-shadowhost.html |
708 m_startInComposedTree = m_startInComposedTree.downstream(); | 708 m_startInComposedTree = mostForwardCaretPosition(m_startInComposedTree); |
709 m_endInComposedTree = m_endInComposedTree.upstream(); | 709 m_endInComposedTree = mostBackwardCaretPosition(m_endInComposedTree); |
710 adjustStartAndEndInComposedTree(); | 710 adjustStartAndEndInComposedTree(); |
711 | 711 |
712 if (isCrossingSelectionBoundary(m_startInComposedTree, m_endInComposedTr
ee)) | 712 if (isCrossingSelectionBoundary(m_startInComposedTree, m_endInComposedTr
ee)) |
713 resetPositionsInComposedTree(); | 713 resetPositionsInComposedTree(); |
714 | 714 |
715 // FIXME: Position::downstream() or Position::upStream() might violate e
diting boundaries | 715 // FIXME: Position::downstream() or Position::upStream() might violate e
diting boundaries |
716 // if an anchor node has a Shadow DOM. So we adjust selection to avoid c
rossing editing | 716 // if an anchor node has a Shadow DOM. So we adjust selection to avoid c
rossing editing |
717 // boundaries again. See https://bugs.webkit.org/show_bug.cgi?id=87463 | 717 // boundaries again. See https://bugs.webkit.org/show_bug.cgi?id=87463 |
718 origExtent = m_extent; | 718 origExtent = m_extent; |
719 origEnd = m_end; | 719 origEnd = m_end; |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 sel.showTreeForThis(); | 1252 sel.showTreeForThis(); |
1253 } | 1253 } |
1254 | 1254 |
1255 void showTree(const blink::VisibleSelection* sel) | 1255 void showTree(const blink::VisibleSelection* sel) |
1256 { | 1256 { |
1257 if (sel) | 1257 if (sel) |
1258 sel->showTreeForThis(); | 1258 sel->showTreeForThis(); |
1259 } | 1259 } |
1260 | 1260 |
1261 #endif | 1261 #endif |
OLD | NEW |