<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[171996] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/171996">171996</a></dd>
<dt>Author</dt> <dd>cfleizach@apple.com</dd>
<dt>Date</dt> <dd>2014-08-04 10:32:21 -0700 (Mon, 04 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>AX: AXSelectTextWithCriteriaParameterizedAttribute incorrectly selects the beginning letters of a word
https://bugs.webkit.org/show_bug.cgi?id=135547

Reviewed by Mario Sanchez Prada.

Source/WebCore:
Allow text search to specify that it wants to match end of words as well as start of words.
This allows select text criteria to match on whole words only.

Test: platform/mac/accessibility/select-text-should-match-whole-words.html

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::rangeOfStringClosestToRangeInDirection):
* editing/FindOptions.h:
* editing/TextIterator.cpp:
(WebCore::SearchBuffer::isWordEndMatch):
(WebCore::SearchBuffer::search):

LayoutTests:
* platform/mac/accessibility/select-text-should-match-whole-words-expected.txt: Added.
* platform/mac/accessibility/select-text-should-match-whole-words.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreaccessibilityAccessibilityObjectcpp">trunk/Source/WebCore/accessibility/AccessibilityObject.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingFindOptionsh">trunk/Source/WebCore/editing/FindOptions.h</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorcpp">trunk/Source/WebCore/editing/TextIterator.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsplatformmacaccessibilityselecttextshouldmatchwholewordsexpectedtxt">trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacaccessibilityselecttextshouldmatchwholewordshtml">trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (171995 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-08-04 17:26:42 UTC (rev 171995)
+++ trunk/LayoutTests/ChangeLog        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -1,5 +1,15 @@
</span><span class="cx"> 2014-08-04  Chris Fleizach  &lt;cfleizach@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        AX: AXSelectTextWithCriteriaParameterizedAttribute incorrectly selects the beginning letters of a word
+        https://bugs.webkit.org/show_bug.cgi?id=135547
+
+        Reviewed by Mario Sanchez Prada.
+
+        * platform/mac/accessibility/select-text-should-match-whole-words-expected.txt: Added.
+        * platform/mac/accessibility/select-text-should-match-whole-words.html: Added.
+
+2014-08-04  Chris Fleizach  &lt;cfleizach@apple.com&gt;
+
</ins><span class="cx">         AX: The Dictation command &quot;Replace &lt;phrase&gt; with &lt;phrase&gt;&quot; always capitalizes the replacement string
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=135557
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacaccessibilityselecttextshouldmatchwholewordsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words-expected.txt (0 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words-expected.txt                                (rev 0)
+++ trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words-expected.txt        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+The man jumped high.
+
+This tests that selection matches whole words, rather than partial matches.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS result is ''
+PASS windowSelection.getRangeAt(0).startOffset is 0
+PASS windowSelection.getRangeAt(0).endOffset is 0
+PASS result is 'jumped'
+PASS windowSelection.getRangeAt(0).startOffset is 8
+PASS windowSelection.getRangeAt(0).endOffset is 14
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacaccessibilityselecttextshouldmatchwholewordshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words.html (0 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words.html                                (rev 0)
+++ trunk/LayoutTests/platform/mac/accessibility/select-text-should-match-whole-words.html        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;title&gt;Select Text&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+
+&lt;p contenteditable=&quot;true&quot; id=&quot;text&quot;&gt;The man jumped high.&lt;/p&gt;
+
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+
+&lt;script&gt;
+    description(&quot;This tests that selection matches whole words, rather than partial matches.&quot;);
+    
+    if (window.accessibilityController) {
+        var text = accessibilityController.accessibleElementById(&quot;text&quot;);
+        var windowSelection = window.getSelection();
+        windowSelection.removeAllRanges();
+
+        // A matching range before the selection should be selected when searching for closest match.
+        document.getElementById(&quot;text&quot;).focus();
+
+        // First find the range before the current selection.
+        var range = document.createRange();
+        range.setStart(document.getElementById(&quot;text&quot;).firstChild, 0);
+        range.setEnd(document.getElementById(&quot;text&quot;).firstChild, 0);
+        windowSelection.addRange(range);
+      
+        // Try to select a partial word, it should fail.
+        result = text.selectTextWithCriteria(&quot;AXSelectTextAmbiguityResolutionClosestToSelection&quot;, &quot;jump&quot;);
+        shouldBe(&quot;result&quot;, &quot;''&quot;);
+        shouldBe(&quot;windowSelection.getRangeAt(0).startOffset&quot;, &quot;0&quot;);
+        shouldBe(&quot;windowSelection.getRangeAt(0).endOffset&quot;, &quot;0&quot;);
+
+        // Select the whole word, it should succeed.
+        result = text.selectTextWithCriteria(&quot;AXSelectTextAmbiguityResolutionClosestToSelection&quot;, &quot;jumped&quot;);
+        shouldBe(&quot;result&quot;, &quot;'jumped'&quot;);
+        shouldBe(&quot;windowSelection.getRangeAt(0).startOffset&quot;, &quot;8&quot;);
+        shouldBe(&quot;windowSelection.getRangeAt(0).endOffset&quot;, &quot;14&quot;);
+
+    }
+&lt;/script&gt;
+
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (171995 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-04 17:26:42 UTC (rev 171995)
+++ trunk/Source/WebCore/ChangeLog        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2014-08-04  Chris Fleizach  &lt;cfleizach@apple.com&gt;
+
+        AX: AXSelectTextWithCriteriaParameterizedAttribute incorrectly selects the beginning letters of a word
+        https://bugs.webkit.org/show_bug.cgi?id=135547
+
+        Reviewed by Mario Sanchez Prada.
+
+        Allow text search to specify that it wants to match end of words as well as start of words.
+        This allows select text criteria to match on whole words only.
+
+        Test: platform/mac/accessibility/select-text-should-match-whole-words.html
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::rangeOfStringClosestToRangeInDirection):
+        * editing/FindOptions.h:
+        * editing/TextIterator.cpp:
+        (WebCore::SearchBuffer::isWordEndMatch):
+        (WebCore::SearchBuffer::search):
+
</ins><span class="cx"> 2014-08-04  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [MSE] Re-enqueing due to overlapping appended samples can cause stuttering playback
</span></span></pre></div>
<a id="trunkSourceWebCoreaccessibilityAccessibilityObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (171995 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2014-08-04 17:26:42 UTC (rev 171995)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -557,7 +557,7 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     
</span><span class="cx">     bool isBackwardSearch = searchDirection == SearchDirectionPrevious;
</span><del>-    FindOptions findOptions = AtWordStarts | CaseInsensitive | StartInSelection;
</del><ins>+    FindOptions findOptions = AtWordStarts | AtWordEnds | CaseInsensitive | StartInSelection;
</ins><span class="cx">     if (isBackwardSearch)
</span><span class="cx">         findOptions |= Backwards;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingFindOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/FindOptions.h (171995 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/FindOptions.h        2014-08-04 17:26:42 UTC (rev 171995)
+++ trunk/Source/WebCore/editing/FindOptions.h        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -37,7 +37,8 @@
</span><span class="cx">     Backwards = 1 &lt;&lt; 3,
</span><span class="cx">     WrapAround = 1 &lt;&lt; 4,
</span><span class="cx">     StartInSelection = 1 &lt;&lt; 5,
</span><del>-    DoNotRevealSelection = 1 &lt;&lt; 6
</del><ins>+    DoNotRevealSelection = 1 &lt;&lt; 6,
+    AtWordEnds = 1 &lt;&lt; 7
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef unsigned char FindOptions;
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.cpp (171995 => 171996)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.cpp        2014-08-04 17:26:42 UTC (rev 171995)
+++ trunk/Source/WebCore/editing/TextIterator.cpp        2014-08-04 17:32:21 UTC (rev 171996)
</span><span class="lines">@@ -92,6 +92,7 @@
</span><span class="cx"> private:
</span><span class="cx">     bool isBadMatch(const UChar*, size_t length) const;
</span><span class="cx">     bool isWordStartMatch(size_t start, size_t length) const;
</span><ins>+    bool isWordEndMatch(size_t start, size_t length) const;
</ins><span class="cx"> 
</span><span class="cx">     const String m_target;
</span><span class="cx">     const StringView::UpconvertedCharacters m_targetCharacters;
</span><span class="lines">@@ -2117,7 +2118,16 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span><ins>+    
+inline bool SearchBuffer::isWordEndMatch(size_t start, size_t length) const
+{
+    ASSERT(m_options &amp; AtWordEnds);
</ins><span class="cx"> 
</span><ins>+    int endWord;
+    findEndWordBoundary(StringView(m_buffer.data(), m_buffer.size()), start, &amp;endWord);
+    return static_cast&lt;size_t&gt;(endWord) == (start + length);
+}
+
</ins><span class="cx"> inline bool SearchBuffer::isWordStartMatch(size_t start, size_t length) const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_options &amp; AtWordStarts);
</span><span class="lines">@@ -2225,7 +2235,9 @@
</span><span class="cx">     ASSERT_WITH_SECURITY_IMPLICATION(matchStart + matchedLength &lt;= size);
</span><span class="cx"> 
</span><span class="cx">     // If this match is &quot;bad&quot;, move on to the next match.
</span><del>-    if (isBadMatch(m_buffer.data() + matchStart, matchedLength) || ((m_options &amp; AtWordStarts) &amp;&amp; !isWordStartMatch(matchStart, matchedLength))) {
</del><ins>+    if (isBadMatch(m_buffer.data() + matchStart, matchedLength)
+        || ((m_options &amp; AtWordStarts) &amp;&amp; !isWordStartMatch(matchStart, matchedLength))
+        || ((m_options &amp; AtWordEnds) &amp;&amp; !isWordEndMatch(matchStart, matchedLength))) {
</ins><span class="cx">         matchStart = usearch_next(searcher, &amp;status);
</span><span class="cx">         ASSERT(status == U_ZERO_ERROR);
</span><span class="cx">         goto nextMatch;
</span></span></pre>
</div>
</div>

</body>
</html>