LayoutTests/ChangeLog

 12010-12-13 Benjamin Kalman <kalman@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Moving or selecting backwards by words jumps to start of contenteditable region if contenteditable=false span is encountered
 6 https://bugs.webkit.org/show_bug.cgi?id=51001
 7
 8 * editing/selection/extend-backward-by-word-over-non-editable-expected.txt: Added.
 9 * editing/selection/extend-backward-by-word-over-non-editable.html: Added.
 10
1112010-12-13 Dan Bernstein <mitz@apple.com>
212
313 Updated Leopard-specific results after r73993.

LayoutTests/editing/selection/extend-backward-by-word-over-non-editable-expected.txt

 1Tests that extending backwards over a non-contenteditable word only extends over that word
 2| "foo bar <#selection-focus>"
 3| <span>
 4| contenteditable="false"
 5| "baz"
 6| "<#selection-anchor> qux quux"

LayoutTests/editing/selection/extend-backward-by-word-over-non-editable.html

 1<!DOCTYPE html>
 2<div contenteditable>foo bar <span contenteditable=false>baz</span> qux quux</div>
 3
 4<script src="../../resources/dump-as-markup.js"></script>
 5<script>
 6 textContainer = document.getElementsByTagName("div")[0];
 7
 8 // Place cursor after "baz".
 9 getSelection().setBaseAndExtent(textContainer.childNodes[2], 0);
 10 // Extend selection backwards by a word; "baz" should be selected.
 11 getSelection().modify("extend", "backward", "word");
 12
 13 Markup.description("Tests that extending backwards over a non-contenteditable word only extends over that word");
 14 Markup.dump(textContainer);
 15</script>

WebCore/ChangeLog

 12010-12-13 Benjamin Kalman <kalman@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Moving or selecting backwards by words jumps to start of contenteditable region if contenteditable=false span is encountered
 6 https://bugs.webkit.org/show_bug.cgi?id=51001
 7
 8 Test: editing/selection/extend-backward-by-word-over-non-editable.html
 9
 10 * editing/TextIterator.cpp: For TextIteratorEndsAtEditingBoundary (now
 11 TextIteratorEndsWhenAscendsAcrossEditingBoundary), only stop text iteration if the editing
 12 boundary change occurs when ascending in the dom.
 13 (WebCore::TextIterator::TextIterator):
 14 (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
 15 (WebCore::SimplifiedBackwardsTextIterator::ascendsAcrossEditingBoundary):
 16 (WebCore::SimplifiedBackwardsTextIterator::setCurrentNode):
 17 * editing/TextIterator.h: Rename TextIteratorEndsAtEditingBoundary to
 18 TextIteratorEndsWhenAscendsAcrossEditingBoundary to reflect what it does now.
 19 * editing/visible_units.cpp:
 20 (WebCore::previousBoundary):
 21
1222010-12-13 Mike Lawther <mikelawther@chromium.org>
223
324 Reviewed by Daniel Bates.

WebCore/editing/TextIterator.cpp

@@TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior)
290290 , m_ignoresStyleVisibility(behavior & TextIteratorIgnoresStyleVisibility)
291291{
292292 // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609
293  ASSERT(behavior != TextIteratorEndsAtEditingBoundary);
 293 ASSERT(behavior != TextIteratorEndsWhenAscendsAcrossEditingBoundary);
294294
295295 if (!r)
296296 return;

@@SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r,
10511051 , m_node(0)
10521052 , m_positionNode(0)
10531053{
1054  ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary);
 1054 ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsWhenAscendsAcrossEditingBoundary);
10551055
10561056 if (!r)
10571057 return;

@@void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta
12391239 m_lastCharacter = c;
12401240}
12411241
1242 bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const
 1242bool SimplifiedBackwardsTextIterator::ascendsAcrossEditingBoundary(Node* node) const
12431243{
1244  return m_node && m_node->isContentEditable() != node->isContentEditable();
 1244 return m_node && m_node->isContentEditable() != node->isContentEditable() && m_node->parentElement() == node;
12451245}
12461246
12471247bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node)
12481248{
12491249 if (!node)
12501250 return false;
1251  if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node))
 1251 if (m_behavior == TextIteratorEndsWhenAscendsAcrossEditingBoundary && ascendsAcrossEditingBoundary(node))
12521252 return false;
12531253 m_node = node;
12541254 return true;

WebCore/editing/TextIterator.h

@@enum TextIteratorBehavior {
4141 TextIteratorEmitsCharactersBetweenAllVisiblePositions = 1 << 0,
4242 TextIteratorEntersTextControls = 1 << 1,
4343 TextIteratorEmitsTextsWithoutTranscoding = 1 << 2,
44  TextIteratorEndsAtEditingBoundary = 1 << 3,
 44 TextIteratorEndsWhenAscendsAcrossEditingBoundary = 1 << 3,
4545 TextIteratorIgnoresStyleVisibility = 1 << 4
4646};
47 
 47
4848// FIXME: Can't really answer this question correctly without knowing the white-space mode.
4949// FIXME: Move this somewhere else in the editing directory. It doesn't belong here.
5050inline bool isCollapsibleWhitespace(UChar c)

@@private:
205205 bool handleReplacedElement();
206206 bool handleNonTextNode();
207207 void emitCharacter(UChar, Node*, int startOffset, int endOffset);
208  bool crossesEditingBoundary(Node*) const;
 208 bool ascendsAcrossEditingBoundary(Node*) const;
209209 bool setCurrentNode(Node*);
210210 void clearCurrentNode();
211211

WebCore/editing/visible_units.cpp

@@static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
8989 if (ec)
9090 return VisiblePosition();
9191
92  SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsAtEditingBoundary);
 92 SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsWhenAscendsAcrossEditingBoundary);
9393 unsigned next = 0;
9494 bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
9595 bool needMoreContext = false;

@@static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
124124 pos = Position(node, next);
125125 else {
126126 // Use the character iterator to translate the next value into a DOM position.
127  BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
 127 BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsWhenAscendsAcrossEditingBoundary);
128128 charIt.advance(string.size() - suffixLength - next);
129129 pos = charIt.range()->endPosition();
130130 }