<!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>[169500] trunk/Source</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/169500">169500</a></dd>
<dt>Author</dt> <dd>enrica@apple.com</dd>
<dt>Date</dt> <dd>2014-05-30 17:12:53 -0700 (Fri, 30 May 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION (WebKit2): space space to insert period doesn't work in web forms.
https://bugs.webkit.org/show_bug.cgi?id=133413
&lt;rdar://problem/16948333&gt;

Reviewed by Benjamin Poulain.


Source/WebCore: 
Adding utility functions and their exports.

* WebCore.exp.in:
* editing/TextIterator.cpp:
(WebCore::plainTextReplacingNoBreakSpace):
* editing/TextIterator.h:
* editing/VisibleUnits.cpp:
(WebCore::charactersAroundPosition):
(WebCore::characterBeforePosition): Deleted.
* editing/VisibleUnits.h:

Source/WebKit2: 
iOS TextInput needs to know about content surrounding the
current position while editing. Since we don't want to
query this information synchronously when asked, we cache it
as part of the EditorState. EditorState now contains a vector of
three characters representing the content after, before and two
position before the caret position.
The patch also replaces all calls to plainText with plainTextReplacingNoBreakSpace
to work well with iOS text input.

* Shared/EditorState.cpp:
(WebKit::EditorState::encode):
(WebKit::EditorState::decode):
* Shared/EditorState.h:
(WebKit::EditorState::EditorState):
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _characterInRelationToCaretSelection:]):
(+[WKAutocorrectionContext autocorrectionContextWithData:markedText:selectedText:afterText:selectedRangeInMarkedText:]):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::editorState):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestDictationContext):
(WebKit::WebPage::replaceSelectedText):
(WebKit::WebPage::replaceDictatedText):
(WebKit::WebPage::requestAutocorrectionData):
(WebKit::WebPage::syncApplyAutocorrection):
(WebKit::computeAutocorrectionContext):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorcpp">trunk/Source/WebCore/editing/TextIterator.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorh">trunk/Source/WebCore/editing/TextIterator.h</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitscpp">trunk/Source/WebCore/editing/VisibleUnits.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingVisibleUnitsh">trunk/Source/WebCore/editing/VisibleUnits.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedEditorStatecpp">trunk/Source/WebKit2/Shared/EditorState.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedEditorStateh">trunk/Source/WebKit2/Shared/EditorState.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/ChangeLog        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2014-05-30  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        REGRESSION (WebKit2): space space to insert period doesn't work in web forms.
+        https://bugs.webkit.org/show_bug.cgi?id=133413
+        &lt;rdar://problem/16948333&gt;
+
+        Reviewed by Benjamin Poulain.
+
+        Adding utility functions and their exports.
+
+        * WebCore.exp.in:
+        * editing/TextIterator.cpp:
+        (WebCore::plainTextReplacingNoBreakSpace):
+        * editing/TextIterator.h:
+        * editing/VisibleUnits.cpp:
+        (WebCore::charactersAroundPosition):
+        (WebCore::characterBeforePosition): Deleted.
+        * editing/VisibleUnits.h:
+
</ins><span class="cx"> 2014-05-30  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Cleanup temporary setting of image interpolation quality in GraphicsContext::drawImage*
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -2609,7 +2609,7 @@
</span><span class="cx"> __ZN7WebCore22startOfEditableContentERKNS_15VisiblePositionE
</span><span class="cx"> __ZN7WebCore23applicationIsMobileMailEv
</span><span class="cx"> __ZN7WebCore23atBoundaryOfGranularityERKNS_15VisiblePositionENS_15TextGranularityENS_18SelectionDirectionE
</span><del>-__ZN7WebCore23characterBeforePositionERKNS_15VisiblePositionE
</del><ins>+__ZN7WebCore24charactersAroundPositionERKNS_15VisiblePositionERiS3_S3_
</ins><span class="cx"> __ZN7WebCore24DocumentMarkerController14markersInRangeEPNS_5RangeENS_14DocumentMarker11MarkerTypesE
</span><span class="cx"> __ZN7WebCore24FloatingPointEnvironment21enableDenormalSupportEv
</span><span class="cx"> __ZN7WebCore24FloatingPointEnvironment25saveMainThreadEnvironmentEv
</span><span class="lines">@@ -2631,6 +2631,7 @@
</span><span class="cx"> __ZN7WebCore27withinTextUnitOfGranularityERKNS_15VisiblePositionENS_15TextGranularityENS_18SelectionDirectionE
</span><span class="cx"> __ZN7WebCore30closestWordBoundaryForPositionERKNS_15VisiblePositionE
</span><span class="cx"> __ZN7WebCore30enclosingTextUnitOfGranularityERKNS_15VisiblePositionENS_15TextGranularityENS_18SelectionDirectionE
</span><ins>+__ZN7WebCore30plainTextReplacingNoBreakSpaceEPKNS_5RangeEtb
</ins><span class="cx"> __ZN7WebCore31NonSharedCharacterBreakIteratorC1EN3WTF10StringViewE
</span><span class="cx"> __ZN7WebCore31NonSharedCharacterBreakIteratorD1Ev
</span><span class="cx"> __ZN7WebCore31applicationIsDaijisenDictionaryEv
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.cpp (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.cpp        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/editing/TextIterator.cpp        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -2513,6 +2513,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String plainTextReplacingNoBreakSpace(const Range* range, TextIteratorBehavior defaultBehavior, bool isDisplayString)
+{
+    return plainText(range, defaultBehavior, isDisplayString).replace(noBreakSpace, ' ');
+}
+
</ins><span class="cx"> static PassRefPtr&lt;Range&gt; collapsedToBoundary(const Range&amp; range, bool forward)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;Range&gt; result = range.cloneRange(ASSERT_NO_EXCEPTION);
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.h (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.h        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/editing/TextIterator.h        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> class RenderTextFragment;
</span><span class="cx"> 
</span><span class="cx"> String plainText(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</span><ins>+String plainTextReplacingNoBreakSpace(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</ins><span class="cx"> PassRefPtr&lt;Range&gt; findPlainText(const Range&amp;, const String&amp;, FindOptions);
</span><span class="cx"> 
</span><span class="cx"> // FIXME: Move this somewhere else in the editing directory. It doesn't belong here.
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.cpp (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.cpp        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/editing/VisibleUnits.cpp        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -1812,25 +1812,40 @@
</span><span class="cx"> 
</span><span class="cx">     return (thisIsStart ? -distance : distance);
</span><span class="cx"> }
</span><del>-    
-UChar32 characterBeforePosition(const VisiblePosition&amp; position)
</del><ins>+
+void charactersAroundPosition(const VisiblePosition&amp; position, UChar32&amp; oneAfter, UChar32&amp; oneBefore, UChar32&amp; twoBefore)
</ins><span class="cx"> {
</span><ins>+    Vector&lt;UChar32&gt; characters(3);
+
</ins><span class="cx">     if (position.isNull() || isStartOfDocument(position))
</span><del>-        return 0;
</del><ins>+        return;
+
+    VisiblePosition startPosition = position;
+    VisiblePosition endPosition = position;
+
+    VisiblePosition nextPosition = nextCharacterBoundaryInDirection(position, DirectionForward);
+    if (nextPosition.isNotNull())
+        endPosition = nextPosition;
+
</ins><span class="cx">     VisiblePosition previousPosition = nextCharacterBoundaryInDirection(position, DirectionBackward);
</span><del>-    if (previousPosition.isNull())
-        return 0;
-    String characterString = plainText(Range::create(position.deepEquivalent().anchorNode()-&gt;document(), previousPosition, position).get(), TextIteratorDefaultBehavior, true);
-    if (characterString.isEmpty())
-        return 0;
-    
-    if (characterString.length() == 2) {
-        UTF32Char lead = characterString[0];
-        UTF32Char trail = characterString[1];
-        if (U16_IS_LEAD(lead) &amp;&amp; U16_IS_TRAIL(trail))
-            return U16_GET_SUPPLEMENTARY(lead, trail);
</del><ins>+    if (previousPosition.isNotNull()) {
+        startPosition = previousPosition;
+        previousPosition = nextCharacterBoundaryInDirection(previousPosition, DirectionBackward);
+        if (previousPosition.isNotNull())
+            startPosition = previousPosition;
</ins><span class="cx">     }
</span><del>-    return characterString[0] != noBreakSpace ? characterString[0] : ' ';
</del><ins>+
+    if (startPosition != endPosition) {
+        String characterString = plainText(Range::create(position.deepEquivalent().anchorNode()-&gt;document(), startPosition, endPosition).get()).replace(noBreakSpace, ' ');
+        for (int i = characterString.length() - 1, index = 0; i &gt;= 0; --i) {
+            if (!index &amp;&amp; nextPosition.isNull())
+                index++;
+            characters[index++] = characterString[i];
+        }
+    }
+    oneAfter = characters[0];
+    oneBefore = characters[1];
+    twoBefore = characters[2];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;Range&gt; wordRangeFromPosition(const VisiblePosition&amp; position)
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingVisibleUnitsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/VisibleUnits.h (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/VisibleUnits.h        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebCore/editing/VisibleUnits.h        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx"> int distanceBetweenPositions(const VisiblePosition&amp;, const VisiblePosition&amp;);
</span><span class="cx"> PassRefPtr&lt;Range&gt; wordRangeFromPosition(const VisiblePosition&amp; position);
</span><span class="cx"> VisiblePosition closestWordBoundaryForPosition(const VisiblePosition&amp; position);
</span><del>-UChar32 characterBeforePosition(const VisiblePosition&amp;);
</del><ins>+void charactersAroundPosition(const VisiblePosition&amp;, UChar32&amp; oneAfter, UChar32&amp; oneBefore, UChar32&amp; twoBefore);
</ins><span class="cx"> #endif
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/ChangeLog        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2014-05-30  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        REGRESSION (WebKit2): space space to insert period doesn't work in web forms.
+        https://bugs.webkit.org/show_bug.cgi?id=133413
+        &lt;rdar://problem/16948333&gt;
+
+        Reviewed by Benjamin Poulain.
+
+        iOS TextInput needs to know about content surrounding the
+        current position while editing. Since we don't want to
+        query this information synchronously when asked, we cache it
+        as part of the EditorState. EditorState now contains a vector of
+        three characters representing the content after, before and two
+        position before the caret position.
+        The patch also replaces all calls to plainText with plainTextReplacingNoBreakSpace
+        to work well with iOS text input.
+
+        * Shared/EditorState.cpp:
+        (WebKit::EditorState::encode):
+        (WebKit::EditorState::decode):
+        * Shared/EditorState.h:
+        (WebKit::EditorState::EditorState):
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _characterInRelationToCaretSelection:]):
+        (+[WKAutocorrectionContext autocorrectionContextWithData:markedText:selectedText:afterText:selectedRangeInMarkedText:]):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::editorState):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::requestDictationContext):
+        (WebKit::WebPage::replaceSelectedText):
+        (WebKit::WebPage::replaceDictatedText):
+        (WebKit::WebPage::requestAutocorrectionData):
+        (WebKit::WebPage::syncApplyAutocorrection):
+        (WebKit::computeAutocorrectionContext):
+
</ins><span class="cx"> 2014-05-30  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fixed the build by adding back a declaration I deleted by accident :(.
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedEditorStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/EditorState.cpp (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/EditorState.cpp        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/Shared/EditorState.cpp        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -48,7 +48,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     encoder &lt;&lt; isReplaceAllowed;
</span><ins>+    encoder &lt;&lt; characterAfterSelection;
</ins><span class="cx">     encoder &lt;&lt; characterBeforeSelection;
</span><ins>+    encoder &lt;&lt; twoCharacterBeforeSelection;
</ins><span class="cx">     encoder &lt;&lt; caretRectAtStart;
</span><span class="cx">     encoder &lt;&lt; caretRectAtEnd;
</span><span class="cx">     encoder &lt;&lt; selectionRects;
</span><span class="lines">@@ -93,8 +95,12 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     if (!decoder.decode(result.isReplaceAllowed))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(result.characterAfterSelection))
+        return false;
</ins><span class="cx">     if (!decoder.decode(result.characterBeforeSelection))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(result.twoCharacterBeforeSelection))
+        return false;
</ins><span class="cx">     if (!decoder.decode(result.caretRectAtStart))
</span><span class="cx">         return false;
</span><span class="cx">     if (!decoder.decode(result.caretRectAtEnd))
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedEditorStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/EditorState.h (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/EditorState.h        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/Shared/EditorState.h        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -48,7 +48,9 @@
</span><span class="cx">         , hasComposition(false)
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         , isReplaceAllowed(false)
</span><ins>+        , characterAfterSelection(0)
</ins><span class="cx">         , characterBeforeSelection(0)
</span><ins>+        , twoCharacterBeforeSelection(0)
</ins><span class="cx">         , selectedTextLength(0)
</span><span class="cx"> #endif
</span><span class="cx">     {
</span><span class="lines">@@ -66,7 +68,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     bool isReplaceAllowed;
</span><ins>+    UChar32 characterAfterSelection;
</ins><span class="cx">     UChar32 characterBeforeSelection;
</span><ins>+    UChar32 twoCharacterBeforeSelection;
</ins><span class="cx">     WebCore::IntRect caretRectAtStart;
</span><span class="cx">     WebCore::IntRect caretRectAtEnd;
</span><span class="cx">     Vector&lt;WebCore::SelectionRect&gt; selectionRects;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -1486,6 +1486,20 @@
</span><span class="cx">     return _page-&gt;editorState().characterBeforeSelection;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (UTF32Char)_characterInRelationToCaretSelection:(int)amount
+{
+    switch (amount) {
+    case 0:
+        return _page-&gt;editorState().characterAfterSelection;
+    case -1:
+        return _page-&gt;editorState().characterBeforeSelection;
+    case -2:
+        return _page-&gt;editorState().twoCharacterBeforeSelection;
+    default:
+        return 0;
+    }
+}
+
</ins><span class="cx"> - (CGRect)textFirstRect
</span><span class="cx"> {
</span><span class="cx">     return (_page-&gt;editorState().hasComposition) ? _page-&gt;editorState().firstMarkedRect : _autocorrectionData.textFirstRect;
</span><span class="lines">@@ -2471,14 +2485,16 @@
</span><span class="cx"> {
</span><span class="cx">     WKAutocorrectionContext *context = [[WKAutocorrectionContext alloc] init];
</span><span class="cx"> 
</span><ins>+    const UChar noBreakSpace = 0x00A0;
+
</ins><span class="cx">     if ([beforeText length])
</span><del>-        context.contextBeforeSelection = [beforeText copy];
</del><ins>+        context.contextBeforeSelection = [[beforeText _stringByReplacingCharacter:(unichar)noBreakSpace withCharacter:' '] copy];
</ins><span class="cx">     if ([selectedText length])
</span><del>-        context.selectedText = [selectedText copy];
</del><ins>+        context.selectedText = [[selectedText _stringByReplacingCharacter:(unichar)noBreakSpace withCharacter:' '] copy];
</ins><span class="cx">     if ([markedText length])
</span><del>-        context.markedText = [markedText copy];
</del><ins>+        context.markedText = [[markedText _stringByReplacingCharacter:(unichar)noBreakSpace withCharacter:' '] copy];
</ins><span class="cx">     if ([afterText length])
</span><del>-        context.contextAfterSelection = [afterText copy];
</del><ins>+        context.contextAfterSelection = [[afterText _stringByReplacingCharacter:(unichar)noBreakSpace withCharacter:' '] copy];
</ins><span class="cx">     context.rangeInMarkedText = range;
</span><span class="cx">     return [context autorelease];
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -704,7 +704,7 @@
</span><span class="cx">             result.lastMarkedRect = compositionRects.last().rect();
</span><span class="cx">         else
</span><span class="cx">             result.lastMarkedRect = result.firstMarkedRect;
</span><del>-        result.markedText = plainText(compositionRange.get());
</del><ins>+        result.markedText = plainTextReplacingNoBreakSpace(compositionRange.get());
</ins><span class="cx">     }
</span><span class="cx">     FrameView* view = frame.view();
</span><span class="cx">     if (selection.isCaret()) {
</span><span class="lines">@@ -712,15 +712,15 @@
</span><span class="cx">         result.caretRectAtEnd = result.caretRectAtStart;
</span><span class="cx">         // FIXME: The following check should take into account writing direction.
</span><span class="cx">         result.isReplaceAllowed = result.isContentEditable &amp;&amp; atBoundaryOfGranularity(selection.start(), WordGranularity, DirectionForward);
</span><del>-        result.wordAtSelection = plainText(wordRangeFromPosition(selection.start()).get());
-        result.characterBeforeSelection = characterBeforePosition(selection.start());
</del><ins>+        result.wordAtSelection = plainTextReplacingNoBreakSpace(wordRangeFromPosition(selection.start()).get());
+        charactersAroundPosition(selection.start(), result.characterAfterSelection, result.characterBeforeSelection, result.twoCharacterBeforeSelection);
</ins><span class="cx">     } else if (selection.isRange()) {
</span><span class="cx">         result.caretRectAtStart = view-&gt;contentsToRootView(VisiblePosition(selection.start()).absoluteCaretBounds());
</span><span class="cx">         result.caretRectAtEnd = view-&gt;contentsToRootView(VisiblePosition(selection.end()).absoluteCaretBounds());
</span><span class="cx">         RefPtr&lt;Range&gt; selectedRange = selection.toNormalizedRange();
</span><span class="cx">         selectedRange-&gt;collectSelectionRects(result.selectionRects);
</span><span class="cx">         convertSelectionRectsToRootView(view, result.selectionRects);
</span><del>-        String selectedText = plainText(selectedRange.get(), TextIteratorDefaultBehavior, true);
</del><ins>+        String selectedText = plainTextReplacingNoBreakSpace(selectedRange.get(), TextIteratorDefaultBehavior, true);
</ins><span class="cx">         // FIXME: We should disallow replace when the string contains only CJ characters.
</span><span class="cx">         result.isReplaceAllowed = result.isContentEditable &amp;&amp; !result.isInPasswordField &amp;&amp; !selectedText.containsOnlyWhitespace();
</span><span class="cx">         result.selectedTextLength = selectedText.length();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (169499 => 169500)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-05-30 23:10:46 UTC (rev 169499)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-05-31 00:12:53 UTC (rev 169500)
</span><span class="lines">@@ -1377,7 +1377,7 @@
</span><span class="cx"> 
</span><span class="cx">     String selectedText;
</span><span class="cx">     if (frame.selection().isRange())
</span><del>-        selectedText = plainText(frame.selection().selection().toNormalizedRange().get());
</del><ins>+        selectedText = plainTextReplacingNoBreakSpace(frame.selection().selection().toNormalizedRange().get());
</ins><span class="cx"> 
</span><span class="cx">     String contextBefore;
</span><span class="cx">     if (startPosition != startOfEditableContent(startPosition)) {
</span><span class="lines">@@ -1390,7 +1390,7 @@
</span><span class="cx">             lastPosition = currentPosition;
</span><span class="cx">         }
</span><span class="cx">         if (lastPosition.isNotNull() &amp;&amp; lastPosition != startPosition)
</span><del>-            contextBefore = plainText(Range::create(*frame.document(), lastPosition, startPosition).get());
</del><ins>+            contextBefore = plainTextReplacingNoBreakSpace(Range::create(*frame.document(), lastPosition, startPosition).get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     String contextAfter;
</span><span class="lines">@@ -1404,7 +1404,7 @@
</span><span class="cx">             lastPosition = currentPosition;
</span><span class="cx">         }
</span><span class="cx">         if (lastPosition.isNotNull() &amp;&amp; lastPosition != endPosition)
</span><del>-            contextAfter = plainText(Range::create(*frame.document(), endPosition, lastPosition).get());
</del><ins>+            contextAfter = plainTextReplacingNoBreakSpace(Range::create(*frame.document(), endPosition, lastPosition).get());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     send(Messages::WebPageProxy::DictationContextCallback(selectedText, contextBefore, contextAfter, callbackID));
</span><span class="lines">@@ -1414,7 +1414,7 @@
</span><span class="cx"> {
</span><span class="cx">     Frame&amp; frame = m_page-&gt;focusController().focusedOrMainFrame();
</span><span class="cx">     RefPtr&lt;Range&gt; wordRange = frame.selection().isCaret() ? wordRangeFromPosition(frame.selection().selection().start()) : frame.selection().toNormalizedRange();
</span><del>-    if (plainText(wordRange.get()) != oldText)
</del><ins>+    if (plainTextReplacingNoBreakSpace(wordRange.get()) != oldText)
</ins><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     frame.editor().setIgnoreCompositionSelectionChange(true);
</span><span class="lines">@@ -1440,7 +1440,7 @@
</span><span class="cx">         position = startOfDocument(static_cast&lt;Node*&gt;(frame.document()-&gt;documentElement()));
</span><span class="cx">     RefPtr&lt;Range&gt; range = Range::create(*frame.document(), position, frame.selection().selection().start());
</span><span class="cx"> 
</span><del>-    if (plainText(range.get()) != oldText)
</del><ins>+    if (plainTextReplacingNoBreakSpace(range.get()) != oldText)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // We don't want to notify the client that the selection has changed until we are done inserting the new text.
</span><span class="lines">@@ -1459,7 +1459,7 @@
</span><span class="cx">     Vector&lt;SelectionRect&gt; selectionRects;
</span><span class="cx"> 
</span><span class="cx">     range = wordRangeFromPosition(position);
</span><del>-    String textForRange = plainText(range.get());
</del><ins>+    String textForRange = plainTextReplacingNoBreakSpace(range.get());
</ins><span class="cx">     const unsigned maxSearchAttempts = 5;
</span><span class="cx">     for (size_t i = 0;  i &lt; maxSearchAttempts &amp;&amp; textForRange != textForAutocorrection; ++i)
</span><span class="cx">     {
</span><span class="lines">@@ -1467,7 +1467,7 @@
</span><span class="cx">         if (position.isNull() || position == range-&gt;startPosition())
</span><span class="cx">             break;
</span><span class="cx">         range = Range::create(*frame.document(), wordRangeFromPosition(position)-&gt;startPosition(), range-&gt;endPosition());
</span><del>-        textForRange = plainText(range.get());
</del><ins>+        textForRange = plainTextReplacingNoBreakSpace(range.get());
</ins><span class="cx">     }
</span><span class="cx">     if (textForRange == textForAutocorrection)
</span><span class="cx">         range-&gt;collectSelectionRects(selectionRects);
</span><span class="lines">@@ -1507,7 +1507,7 @@
</span><span class="cx">     VisiblePosition position = frame.selection().selection().start();
</span><span class="cx">     
</span><span class="cx">     range = wordRangeFromPosition(position);
</span><del>-    String textForRange = plainText(range.get());
</del><ins>+    String textForRange = plainTextReplacingNoBreakSpace(range.get());
</ins><span class="cx">     if (textForRange != originalText) {
</span><span class="cx">         for (size_t i = 0; i &lt; originalText.length(); ++i)
</span><span class="cx">             position = position.previous();
</span><span class="lines">@@ -1515,7 +1515,7 @@
</span><span class="cx">             position = startOfDocument(static_cast&lt;Node*&gt;(frame.document()-&gt;documentElement()));
</span><span class="cx">         range = Range::create(*frame.document(), position, frame.selection().selection().start());
</span><span class="cx">         if (range)
</span><del>-            textForRange = (range) ? plainText(range.get()) : emptyString();
</del><ins>+            textForRange = (range) ? plainTextReplacingNoBreakSpace(range.get()) : emptyString();
</ins><span class="cx">         unsigned loopCount = 0;
</span><span class="cx">         const unsigned maxPositionsAttempts = 10;
</span><span class="cx">         while (textForRange.length() &amp;&amp; textForRange.length() &gt; originalText.length() &amp;&amp; loopCount &lt; maxPositionsAttempts) {
</span><span class="lines">@@ -1524,7 +1524,7 @@
</span><span class="cx">                 range = NULL;
</span><span class="cx">             else
</span><span class="cx">                 range = Range::create(*frame.document(), position, frame.selection().selection().start());
</span><del>-            textForRange = (range) ? plainText(range.get()) : emptyString();
</del><ins>+            textForRange = (range) ? plainTextReplacingNoBreakSpace(range.get()) : emptyString();
</ins><span class="cx">             loopCount++;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -1553,17 +1553,17 @@
</span><span class="cx">     const unsigned maxContextLength = 30;
</span><span class="cx"> 
</span><span class="cx">     if (frame.selection().isRange())
</span><del>-        selectedText = plainText(frame.selection().selection().toNormalizedRange().get());
</del><ins>+        selectedText = plainTextReplacingNoBreakSpace(frame.selection().selection().toNormalizedRange().get());
</ins><span class="cx"> 
</span><span class="cx">     if (frame.editor().hasComposition()) {
</span><span class="cx">         range = Range::create(*frame.document(), frame.editor().compositionRange()-&gt;startPosition(), startPosition);
</span><span class="cx">         String markedTextBefore;
</span><span class="cx">         if (range)
</span><del>-            markedTextBefore = plainText(range.get());
</del><ins>+            markedTextBefore = plainTextReplacingNoBreakSpace(range.get());
</ins><span class="cx">         range = Range::create(*frame.document(), endPosition, frame.editor().compositionRange()-&gt;endPosition());
</span><span class="cx">         String markedTextAfter;
</span><span class="cx">         if (range)
</span><del>-            markedTextAfter = plainText(range.get());
</del><ins>+            markedTextAfter = plainTextReplacingNoBreakSpace(range.get());
</ins><span class="cx">         markedText = markedTextBefore + selectedText + markedTextAfter;
</span><span class="cx">         if (!markedText.isEmpty()) {
</span><span class="cx">             location = markedTextBefore.length();
</span><span class="lines">@@ -1580,14 +1580,14 @@
</span><span class="cx">                 previousPosition = startOfWord(positionOfNextBoundaryOfGranularity(currentPosition, WordGranularity, DirectionBackward));
</span><span class="cx">                 if (previousPosition.isNull())
</span><span class="cx">                     break;
</span><del>-                String currentWord = plainText(Range::create(*frame.document(), previousPosition, currentPosition).get());
</del><ins>+                String currentWord = plainTextReplacingNoBreakSpace(Range::create(*frame.document(), previousPosition, currentPosition).get());
</ins><span class="cx">                 totalContextLength += currentWord.length();
</span><span class="cx">                 if (totalContextLength &gt;= maxContextLength)
</span><span class="cx">                     break;
</span><span class="cx">                 currentPosition = previousPosition;
</span><span class="cx">             }
</span><span class="cx">             if (currentPosition.isNotNull() &amp;&amp; currentPosition != startPosition) {
</span><del>-                contextBefore = plainText(Range::create(*frame.document(), currentPosition, startPosition).get());
</del><ins>+                contextBefore = plainTextReplacingNoBreakSpace(Range::create(*frame.document(), currentPosition, startPosition).get());
</ins><span class="cx">                 if (atBoundaryOfGranularity(currentPosition, ParagraphGranularity, DirectionBackward))
</span><span class="cx">                     contextBefore = ASCIILiteral(&quot;\n &quot;) + contextBefore;
</span><span class="cx">             }
</span><span class="lines">@@ -1598,7 +1598,7 @@
</span><span class="cx">             if (!atBoundaryOfGranularity(endPosition, WordGranularity, DirectionForward) &amp;&amp; withinTextUnitOfGranularity(endPosition, WordGranularity, DirectionForward))
</span><span class="cx">                 nextPosition = positionOfNextBoundaryOfGranularity(endPosition, WordGranularity, DirectionForward);
</span><span class="cx">             if (nextPosition.isNotNull())
</span><del>-                contextAfter = plainText(Range::create(*frame.document(), endPosition, nextPosition).get());
</del><ins>+                contextAfter = plainTextReplacingNoBreakSpace(Range::create(*frame.document(), endPosition, nextPosition).get());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>