<!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>[171016] trunk/Source/WebCore</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/171016">171016</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2014-07-11 16:54:55 -0700 (Fri, 11 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Phone numbers that span two lines are not detected.
&lt;rdar://problem/17601146&gt; and https://bugs.webkit.org/show_bug.cgi?id=134808

Reviewed by Tim Horton.

* editing/Editor.cpp:
(WebCore::Editor::scanSelectionForTelephoneNumbers): After scanning a range from the TextIterator,
    create an &quot;edge range&quot; window around the end of the TextIterator range, and scan it.
    Also make sure to not accumulate duplicate ranges that might have showed up in both the
    TextIterator range and the edge window range.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorcpp">trunk/Source/WebCore/editing/Editor.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (171015 => 171016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-07-11 23:24:24 UTC (rev 171015)
+++ trunk/Source/WebCore/ChangeLog        2014-07-11 23:54:55 UTC (rev 171016)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-07-11  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        Phone numbers that span two lines are not detected.
+        &lt;rdar://problem/17601146&gt; and https://bugs.webkit.org/show_bug.cgi?id=134808
+
+        Reviewed by Tim Horton.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::scanSelectionForTelephoneNumbers): After scanning a range from the TextIterator,
+            create an &quot;edge range&quot; window around the end of the TextIterator range, and scan it.
+            Also make sure to not accumulate duplicate ranges that might have showed up in both the
+            TextIterator range and the edge window range.
+
</ins><span class="cx"> 2014-07-11  Enrica Casucci  &lt;enrica@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement textStylingAtPosition in WK2.
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.cpp (171015 => 171016)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.cpp        2014-07-11 23:24:24 UTC (rev 171015)
+++ trunk/Source/WebCore/editing/Editor.cpp        2014-07-11 23:54:55 UTC (rev 171016)
</span><span class="lines">@@ -3369,6 +3369,7 @@
</span><span class="cx">         client()-&gt;selectedTelephoneNumberRangesChanged(markedRanges);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    RefPtr&lt;Range&gt; selectedRange = frameSelection.toNormalizedRange();
</ins><span class="cx"> 
</span><span class="cx">     // Extend the range a few characters in each direction to detect incompletely selected phone numbers.
</span><span class="cx">     static const int charactersToExtend = 15;
</span><span class="lines">@@ -3384,19 +3385,54 @@
</span><span class="cx">     extendedSelection.setExtent(extent);
</span><span class="cx">     RefPtr&lt;Range&gt; extendedRange = extendedSelection.toNormalizedRange();
</span><span class="cx"> 
</span><del>-    // FIXME: This won't work if a phone number spans multiple chunks of text from the perspective of the TextIterator
-    // (By a style change, image, line break, etc.)
-    // One idea to handle this would be a model like text search that uses a rotating window.
</del><span class="cx">     for (TextIterator textChunk(extendedRange.get()); !textChunk.atEnd(); textChunk.advance()) {
</span><del>-        // TextIterator is supposed to never returns a Range that spans multiple Nodes.
-        ASSERT(textChunk.range()-&gt;startContainer() == textChunk.range()-&gt;endContainer());
</del><ins>+        Vector&lt;RefPtr&lt;Range&gt;&gt; markedChunkRanges;
+        Vector&lt;RefPtr&lt;Range&gt;&gt; markedEdgeRanges;
</ins><span class="cx"> 
</span><del>-        scanRangeForTelephoneNumbers(*textChunk.range(), textChunk.text(), markedRanges);
</del><ins>+        // Scan the text iterator range.
+        RefPtr&lt;Range&gt; range = textChunk.range();
+        scanRangeForTelephoneNumbers(*range, textChunk.text(), markedChunkRanges);
+
+        // If this text iterator range's end position is before the end of the full range,
+        // then scan a window that is a bit before and a bit after this text iterator range.
+        RefPtr&lt;Range&gt; edgeRange;
+        if (range-&gt;endPosition() &lt; extendedRange-&gt;endPosition()) {
+            Position endPosition = range-&gt;endPosition();
+            Position startPosition = endPosition;
+            for (int i = 0; i &lt; charactersToExtend; ++i) {
+                startPosition = startPosition.previous(Character);
+                endPosition = endPosition.next(Character);
+            }
+
+            edgeRange = Range::create(range-&gt;ownerDocument(), startPosition, endPosition);
+            scanRangeForTelephoneNumbers(*edgeRange, plainText(edgeRange.get()), markedEdgeRanges);
+        }
+
+        // Add both of these sets of ranges to the full set of marked ranges, double checking to
+        // make sure we don't end up with two equivalent ranges in the full set.
+        for (auto&amp; chunkRange : markedChunkRanges) {
+            bool matchesEdgeRange = false;
+            for (auto&amp; edgeRange : markedEdgeRanges) {
+                if (areRangesEqual(chunkRange.get(), edgeRange.get())) {
+                    matchesEdgeRange = true;
+                    break;
+                }
+            }
+
+            if (!matchesEdgeRange)
+                markedRanges.append(chunkRange);
+        }
+
+        for (auto&amp; range : markedEdgeRanges)
+            markedRanges.append(range);
+
+        // If the edge range's end position is past the end position of the original range, we're done scanning.
+        if (edgeRange &amp;&amp; edgeRange-&gt;endPosition() &gt;= extendedRange-&gt;endPosition())
+            break;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Only consider ranges with a detected telephone number if they overlap with the actual selection range.
</span><span class="cx">     Vector&lt;RefPtr&lt;Range&gt;&gt; extendedMarkedRanges;
</span><del>-    RefPtr&lt;Range&gt; selectedRange = frameSelection.toNormalizedRange();
</del><span class="cx">     for (auto&amp; range : markedRanges) {
</span><span class="cx">         if (rangesOverlap(range.get(), selectedRange.get()))
</span><span class="cx">             extendedMarkedRanges.append(range);
</span></span></pre>
</div>
</div>

</body>
</html>