<!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>[195037] releases/WebKitGTK/webkit-2.10</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/195037">195037</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-01-14 04:14:19 -0800 (Thu, 14 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/192641">r192641</a> - REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/8780">r8780</a>): Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend
https://bugs.webkit.org/show_bug.cgi?id=151300

Reviewed by Darin Adler.

Source/WebCore:

Over 11 years ago, someone was in a big hurry to fix a bunch
of emacs keybindings bugs, and accidentally regressed the kill ring
behavior for backwards-delete-word. It should prepend to the beginning.

This patch fixes the regression and cleans up the kill ring-related
code in Editor and commands. It also adds some tests to cover the
regressed code a bit better.

Tests: editing/pasteboard/emacs-killring-alternating-append-prepend.html
       editing/pasteboard/emacs-killring-backward-delete-prepend.html

* editing/Editor.cpp:

    Use more explicit names for insertion mode parameters and member variables.

(WebCore::Editor::deleteWithDirection):
(WebCore::Editor::performDelete):
(WebCore::Editor::addRangeToKillRing):
(WebCore::Editor::addTextToKillRing):

    Only one call site for now, but another will be added in a dependent fix.

(WebCore::Editor::addToKillRing): Deleted.
* editing/Editor.h:
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::TypingCommand):
(WebCore::TypingCommand::deleteKeyPressed):
(WebCore::TypingCommand::forwardDeleteKeyPressed):
(WebCore::TypingCommand::doApply):
* editing/TypingCommand.h:
* platform/mac/KillRingMac.mm:
(WebCore::KillRing::append):
(WebCore::KillRing::prepend):

    It turns out that the native API implicitly clears the kill sequence when
    alternating between prepend and append operations. Its behavior does not match
    what Sublime Text or Emacs do in this case. Clear the previous operation flag
    to prevent this behavior from happening.

LayoutTests:

* editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt: Added.
* editing/pasteboard/emacs-killring-alternating-append-prepend.html: Added.
* editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt: Added.
* editing/pasteboard/emacs-killring-backward-delete-prepend.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestsChangeLog">releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreeditingEditorcpp">releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreeditingEditorh">releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreeditingTypingCommandcpp">releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreeditingTypingCommandh">releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.h</a></li>
<li><a href="#releasesWebKitGTKwebkit210SourceWebCoreplatformmacKillRingMacmm">releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/mac/KillRingMac.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringalternatingappendprependexpectedtxt">releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringalternatingappendprependhtml">releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend.html</a></li>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringbackwarddeleteprependexpectedtxt">releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt</a></li>
<li><a href="#releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringbackwarddeleteprependhtml">releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit210LayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/ChangeLog        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2015-11-19  Brian Burg  &lt;bburg@apple.com&gt;
+
+        REGRESSION(r8780): Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend
+        https://bugs.webkit.org/show_bug.cgi?id=151300
+
+        Reviewed by Darin Adler.
+
+        * editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt: Added.
+        * editing/pasteboard/emacs-killring-alternating-append-prepend.html: Added.
+        * editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt: Added.
+        * editing/pasteboard/emacs-killring-backward-delete-prepend.html: Added.
+
</ins><span class="cx"> 2015-11-18  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WK1] Crash loading Blink layout test fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringalternatingappendprependexpectedtxt"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt (0 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend-expected.txt        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+Test for bug 151300: Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend.
+
+one two three
+Expected result: one two three
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringalternatingappendprependhtml"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend.html (0 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend.html                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-alternating-append-prepend.html        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+&lt;p&gt;Test for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=151300&quot;&gt;bug 151300&lt;/a&gt;:
+Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend.&lt;/p&gt;
+
+&lt;div contenteditable id=ce&gt;
+one two three
+&lt;/div&gt;
+
+&lt;div&gt;
+Expected result:
+one two three
+&lt;/div&gt;
+
+&lt;script&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    document.getElementById(&quot;ce&quot;).focus();
+    testRunner.execCommand(&quot;MoveWordForward&quot;);
+    testRunner.execCommand(&quot;MoveWordForward&quot;);
+    testRunner.execCommand(&quot;DeleteWordBackward&quot;);
+    testRunner.execCommand(&quot;DeleteWordBackward&quot;);
+    testRunner.execCommand(&quot;DeleteWordForward&quot;);
+    testRunner.execCommand(&quot;Yank&quot;);
+} else
+    document.write(&quot;This test only runs in automatic mode&quot;);
+&lt;/script&gt;
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringbackwarddeleteprependexpectedtxt"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt (0 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend-expected.txt        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -0,0 +1,6 @@
</span><ins>+Test for bug 151300: Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend.
+
+This test checks that backwards delete-by-word prepends to the kill ring.
+
+one two three
+Expected result: one two three
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210LayoutTestseditingpasteboardemacskillringbackwarddeleteprependhtml"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend.html (0 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend.html                                (rev 0)
+++ releases/WebKitGTK/webkit-2.10/LayoutTests/editing/pasteboard/emacs-killring-backward-delete-prepend.html        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+&lt;p&gt;Test for &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=151300&quot;&gt;bug 151300&lt;/a&gt;:
+Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend.&lt;/p&gt;
+&lt;p&gt;This test checks that backwards delete-by-word prepends to the kill ring.&lt;/p&gt;
+
+&lt;div contenteditable id=ce&gt;
+one two three
+&lt;/div&gt;
+
+&lt;div&gt;
+Expected result:
+one two three
+&lt;/div&gt;
+
+&lt;script&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    document.getElementById(&quot;ce&quot;).focus();
+    testRunner.execCommand(&quot;MoveToEndOfLine&quot;);
+    testRunner.execCommand(&quot;DeleteWordBackward&quot;);
+    testRunner.execCommand(&quot;DeleteWordBackward&quot;);
+    testRunner.execCommand(&quot;DeleteWordBackward&quot;);
+    testRunner.execCommand(&quot;Yank&quot;);
+} else
+    document.write(&quot;This test only runs in automatic mode&quot;);
+&lt;/script&gt;
</ins></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2015-11-19  Brian Burg  &lt;bburg@apple.com&gt;
+
+        REGRESSION(r8780): Backwards delete by word incorrectly appends deleted text to kill ring, should be prepend
+        https://bugs.webkit.org/show_bug.cgi?id=151300
+
+        Reviewed by Darin Adler.
+
+        Over 11 years ago, someone was in a big hurry to fix a bunch
+        of emacs keybindings bugs, and accidentally regressed the kill ring
+        behavior for backwards-delete-word. It should prepend to the beginning.
+
+        This patch fixes the regression and cleans up the kill ring-related
+        code in Editor and commands. It also adds some tests to cover the
+        regressed code a bit better.
+
+        Tests: editing/pasteboard/emacs-killring-alternating-append-prepend.html
+               editing/pasteboard/emacs-killring-backward-delete-prepend.html
+
+        * editing/Editor.cpp:
+
+            Use more explicit names for insertion mode parameters and member variables.
+
+        (WebCore::Editor::deleteWithDirection):
+        (WebCore::Editor::performDelete):
+        (WebCore::Editor::addRangeToKillRing):
+        (WebCore::Editor::addTextToKillRing):
+
+            Only one call site for now, but another will be added in a dependent fix.
+
+        (WebCore::Editor::addToKillRing): Deleted.
+        * editing/Editor.h:
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::TypingCommand):
+        (WebCore::TypingCommand::deleteKeyPressed):
+        (WebCore::TypingCommand::forwardDeleteKeyPressed):
+        (WebCore::TypingCommand::doApply):
+        * editing/TypingCommand.h:
+        * platform/mac/KillRingMac.mm:
+        (WebCore::KillRing::append):
+        (WebCore::KillRing::prepend):
+
+            It turns out that the native API implicitly clears the kill sequence when
+            alternating between prepend and append operations. Its behavior does not match
+            what Sublime Text or Emacs do in this case. Clear the previous operation flag
+            to prevent this behavior from happening.
+
</ins><span class="cx"> 2015-11-18  Jiewen Tan  &lt;jiewen_tan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WK1] Crash loading Blink layout test fast/dom/Window/property-access-on-cached-window-after-frame-removed.html
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.cpp (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.cpp        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.cpp        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -331,7 +331,7 @@
</span><span class="cx">     return client() &amp;&amp; client()-&gt;isSelectTrailingWhitespaceEnabled();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool killRing, bool isTypingAction)
</del><ins>+bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool shouldAddToKillRing, bool isTypingAction)
</ins><span class="cx"> {
</span><span class="cx">     if (!canEdit())
</span><span class="cx">         return false;
</span><span class="lines">@@ -341,8 +341,8 @@
</span><span class="cx">             TypingCommand::deleteKeyPressed(document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
</span><span class="cx">             revealSelectionAfterEditingOperation();
</span><span class="cx">         } else {
</span><del>-            if (killRing)
-                addToKillRing(selectedRange().get(), false);
</del><ins>+            if (shouldAddToKillRing)
+                addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
</ins><span class="cx">             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
</span><span class="cx">             // Implicitly calls revealSelectionAfterEditingOperation().
</span><span class="cx">         }
</span><span class="lines">@@ -350,8 +350,8 @@
</span><span class="cx">         TypingCommand::Options options = 0;
</span><span class="cx">         if (canSmartCopyOrDelete())
</span><span class="cx">             options |= TypingCommand::SmartDelete;
</span><del>-        if (killRing)
-            options |= TypingCommand::KillRing;
</del><ins>+        if (shouldAddToKillRing)
+            options |= TypingCommand::AddsToKillRing;
</ins><span class="cx">         switch (direction) {
</span><span class="cx">         case DirectionForward:
</span><span class="cx">         case DirectionRight:
</span><span class="lines">@@ -368,7 +368,7 @@
</span><span class="cx">     // FIXME: We should to move this down into deleteKeyPressed.
</span><span class="cx">     // clear the &quot;start new kill ring sequence&quot; setting, because it was set to true
</span><span class="cx">     // when the selection was updated by deleting the range
</span><del>-    if (killRing)
</del><ins>+    if (shouldAddToKillRing)
</ins><span class="cx">         setStartNewKillRingSequence(false);
</span><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="lines">@@ -1096,7 +1096,6 @@
</span><span class="cx"> Editor::Editor(Frame&amp; frame)
</span><span class="cx">     : m_frame(frame)
</span><span class="cx">     , m_ignoreCompositionSelectionChange(false)
</span><del>-    , m_shouldStartNewKillRingSequence(false)
</del><span class="cx">     // This is off by default, since most editors want this behavior (this matches IE but not FF).
</span><span class="cx">     , m_shouldStyleWithCSS(false)
</span><span class="cx">     , m_killRing(std::make_unique&lt;KillRing&gt;())
</span><span class="lines">@@ -1335,7 +1334,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    addToKillRing(selectedRange().get(), false);
</del><ins>+    addRangeToKillRing(*selectedRange().get(), KillRingInsertionMode::AppendText);
</ins><span class="cx">     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
</span><span class="cx"> 
</span><span class="cx">     // clear the &quot;start new kill ring sequence&quot; setting, because it was set to true
</span><span class="lines">@@ -2851,17 +2850,29 @@
</span><span class="cx">     replaceSelectionWithText(transposed, false, false, EditActionInsert);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Editor::addToKillRing(Range* range, bool prepend)
</del><ins>+void Editor::addRangeToKillRing(const Range&amp; range, KillRingInsertionMode mode)
</ins><span class="cx"> {
</span><ins>+    addTextToKillRing(plainText(&amp;range), mode);
+}
+
+void Editor::addTextToKillRing(const String&amp; text, KillRingInsertionMode mode)
+{
</ins><span class="cx">     if (m_shouldStartNewKillRingSequence)
</span><span class="cx">         killRing().startNewSequence();
</span><span class="cx"> 
</span><del>-    String text = plainText(range);
-    if (prepend)
</del><ins>+    m_shouldStartNewKillRingSequence = false;
+
+    // If the kill was from a backwards motion, prepend to the kill ring.
+    // This will ensure that alternating forward and backward kills will
+    // build up the original string in the kill ring without permuting it.
+    switch (mode) {
+    case KillRingInsertionMode::PrependText:
</ins><span class="cx">         killRing().prepend(text);
</span><del>-    else
</del><ins>+        break;
+    case KillRingInsertionMode::AppendText:
</ins><span class="cx">         killRing().append(text);
</span><del>-    m_shouldStartNewKillRingSequence = false;
</del><ins>+        break;
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Editor::startAlternativeTextUITimer()
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreeditingEditorh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.h (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.h        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/Editor.h        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -315,8 +315,6 @@
</span><span class="cx">     WEBCORE_EXPORT void setIgnoreCompositionSelectionChange(bool, RevealSelection shouldRevealExistingSelection = RevealSelection::Yes);
</span><span class="cx">     bool ignoreCompositionSelectionChange() const { return m_ignoreCompositionSelectionChange; }
</span><span class="cx"> 
</span><del>-    void setStartNewKillRingSequence(bool);
-
</del><span class="cx">     WEBCORE_EXPORT PassRefPtr&lt;Range&gt; rangeForPoint(const IntPoint&amp; windowPoint);
</span><span class="cx"> 
</span><span class="cx">     void clear();
</span><span class="lines">@@ -338,7 +336,10 @@
</span><span class="cx">     WEBCORE_EXPORT void setDictationPhrasesAsChildOfElement(const Vector&lt;Vector&lt;String&gt;&gt;&amp; dictationPhrases, RetainPtr&lt;id&gt; metadata, Element&amp;);
</span><span class="cx"> #endif
</span><span class="cx">     
</span><del>-    void addToKillRing(Range*, bool prepend);
</del><ins>+    enum class KillRingInsertionMode { PrependText, AppendText };
+    void addRangeToKillRing(const Range&amp;, KillRingInsertionMode);
+    void addTextToKillRing(const String&amp;, KillRingInsertionMode);
+    void setStartNewKillRingSequence(bool);
</ins><span class="cx"> 
</span><span class="cx">     void startAlternativeTextUITimer();
</span><span class="cx">     // If user confirmed a correction in the correction panel, correction has non-zero length, otherwise it means that user has dismissed the panel.
</span><span class="lines">@@ -501,7 +502,7 @@
</span><span class="cx">     unsigned m_compositionEnd;
</span><span class="cx">     Vector&lt;CompositionUnderline&gt; m_customCompositionUnderlines;
</span><span class="cx">     bool m_ignoreCompositionSelectionChange;
</span><del>-    bool m_shouldStartNewKillRingSequence;
</del><ins>+    bool m_shouldStartNewKillRingSequence {false};
</ins><span class="cx">     bool m_shouldStyleWithCSS;
</span><span class="cx">     const std::unique_ptr&lt;KillRing&gt; m_killRing;
</span><span class="cx">     const std::unique_ptr&lt;SpellChecker&gt; m_spellChecker;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreeditingTypingCommandcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.cpp (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.cpp        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.cpp        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx">     , m_smartDelete(options &amp; SmartDelete)
</span><span class="cx">     , m_granularity(granularity)
</span><span class="cx">     , m_compositionType(compositionType)
</span><del>-    , m_killRing(options &amp; KillRing)
</del><ins>+    , m_shouldAddToKillRing(options &amp; AddsToKillRing)
</ins><span class="cx">     , m_openedByBackwardDelete(false)
</span><span class="cx">     , m_shouldRetainAutocorrectionIndicator(options &amp; RetainAutocorrectionIndicator)
</span><span class="cx">     , m_shouldPreventSpellChecking(options &amp; PreventSpellChecking)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx">         if (RefPtr&lt;TypingCommand&gt; lastTypingCommand = lastTypingCommandIfStillOpenForTyping(document.frame())) {
</span><span class="cx">             updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), document.frame());
</span><span class="cx">             lastTypingCommand-&gt;setShouldPreventSpellChecking(options &amp; PreventSpellChecking);
</span><del>-            lastTypingCommand-&gt;deleteKeyPressed(granularity, options &amp; KillRing);
</del><ins>+            lastTypingCommand-&gt;deleteKeyPressed(granularity, options &amp; AddsToKillRing);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -130,7 +130,7 @@
</span><span class="cx">         if (RefPtr&lt;TypingCommand&gt; lastTypingCommand = lastTypingCommandIfStillOpenForTyping(frame)) {
</span><span class="cx">             updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand.get(), frame);
</span><span class="cx">             lastTypingCommand-&gt;setShouldPreventSpellChecking(options &amp; PreventSpellChecking);
</span><del>-            lastTypingCommand-&gt;forwardDeleteKeyPressed(granularity, options &amp; KillRing);
</del><ins>+            lastTypingCommand-&gt;forwardDeleteKeyPressed(granularity, options &amp; AddsToKillRing);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -263,10 +263,10 @@
</span><span class="cx">         deleteSelection(m_smartDelete);
</span><span class="cx">         return;
</span><span class="cx">     case DeleteKey:
</span><del>-        deleteKeyPressed(m_granularity, m_killRing);
</del><ins>+        deleteKeyPressed(m_granularity, m_shouldAddToKillRing);
</ins><span class="cx">         return;
</span><span class="cx">     case ForwardDeleteKey:
</span><del>-        forwardDeleteKeyPressed(m_granularity, m_killRing);
</del><ins>+        forwardDeleteKeyPressed(m_granularity, m_shouldAddToKillRing);
</ins><span class="cx">         return;
</span><span class="cx">     case InsertLineBreak:
</span><span class="cx">         insertLineBreak();
</span><span class="lines">@@ -433,7 +433,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool killRing)
</del><ins>+void TypingCommand::deleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing)
</ins><span class="cx"> {
</span><span class="cx">     Frame&amp; frame = this-&gt;frame();
</span><span class="cx"> 
</span><span class="lines">@@ -458,7 +458,7 @@
</span><span class="cx">         FrameSelection selection;
</span><span class="cx">         selection.setSelection(endingSelection());
</span><span class="cx">         selection.modify(FrameSelection::AlterationExtend, DirectionBackward, granularity);
</span><del>-        if (killRing &amp;&amp; selection.isCaret() &amp;&amp; granularity != CharacterGranularity)
</del><ins>+        if (shouldAddToKillRing &amp;&amp; selection.isCaret() &amp;&amp; granularity != CharacterGranularity)
</ins><span class="cx">             selection.modify(FrameSelection::AlterationExtend, DirectionBackward, CharacterGranularity);
</span><span class="cx"> 
</span><span class="cx">         if (endingSelection().visibleStart().previous(CannotCrossEditingBoundary).isNull()) {
</span><span class="lines">@@ -530,8 +530,8 @@
</span><span class="cx">     if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (killRing)
-        frame.editor().addToKillRing(selectionToDelete.toNormalizedRange().get(), false);
</del><ins>+    if (shouldAddToKillRing)
+        frame.editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange().get(), Editor::KillRingInsertionMode::PrependText);
</ins><span class="cx">     // Make undo select everything that has been deleted, unless an undo will undo more than just this deletion.
</span><span class="cx">     // FIXME: This behaves like TextEdit except for the case where you open with text insertion and then delete
</span><span class="cx">     // more text than you insert.  In that case all of the text that was around originally should be selected.
</span><span class="lines">@@ -542,7 +542,7 @@
</span><span class="cx">     typingAddedToOpenCommand(DeleteKey);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool killRing)
</del><ins>+void TypingCommand::forwardDeleteKeyPressed(TextGranularity granularity, bool shouldAddToKillRing)
</ins><span class="cx"> {
</span><span class="cx">     Frame&amp; frame = this-&gt;frame();
</span><span class="cx"> 
</span><span class="lines">@@ -565,7 +565,7 @@
</span><span class="cx">         FrameSelection selection;
</span><span class="cx">         selection.setSelection(endingSelection());
</span><span class="cx">         selection.modify(FrameSelection::AlterationExtend, DirectionForward, granularity);
</span><del>-        if (killRing &amp;&amp; selection.isCaret() &amp;&amp; granularity != CharacterGranularity)
</del><ins>+        if (shouldAddToKillRing &amp;&amp; selection.isCaret() &amp;&amp; granularity != CharacterGranularity)
</ins><span class="cx">             selection.modify(FrameSelection::AlterationExtend, DirectionForward, CharacterGranularity);
</span><span class="cx"> 
</span><span class="cx">         Position downstreamEnd = endingSelection().end().downstream();
</span><span class="lines">@@ -628,8 +628,8 @@
</span><span class="cx">     if (selectionToDelete.isCaret() || !frame.selection().shouldDeleteSelection(selectionToDelete))
</span><span class="cx">         return;
</span><span class="cx">         
</span><del>-    if (killRing)
-        frame.editor().addToKillRing(selectionToDelete.toNormalizedRange().get(), false);
</del><ins>+    if (shouldAddToKillRing)
+        frame.editor().addRangeToKillRing(*selectionToDelete.toNormalizedRange().get(), Editor::KillRingInsertionMode::AppendText);
</ins><span class="cx">     // make undo select what was deleted
</span><span class="cx">     setStartingSelection(selectionAfterUndo);
</span><span class="cx">     CompositeEditCommand::deleteSelection(selectionToDelete, m_smartDelete);
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreeditingTypingCommandh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.h (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.h        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/editing/TypingCommand.h        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> 
</span><span class="cx">     enum Option {
</span><span class="cx">         SelectInsertedText = 1 &lt;&lt; 0,
</span><del>-        KillRing = 1 &lt;&lt; 1,
</del><ins>+        AddsToKillRing = 1 &lt;&lt; 1,
</ins><span class="cx">         RetainAutocorrectionIndicator = 1 &lt;&lt; 2,
</span><span class="cx">         PreventSpellChecking = 1 &lt;&lt; 3,
</span><span class="cx">         SmartDelete = 1 &lt;&lt; 4
</span><span class="lines">@@ -75,8 +75,8 @@
</span><span class="cx">     void insertLineBreak();
</span><span class="cx">     void insertParagraphSeparatorInQuotedContent();
</span><span class="cx">     void insertParagraphSeparator();
</span><del>-    void deleteKeyPressed(TextGranularity, bool killRing);
-    void forwardDeleteKeyPressed(TextGranularity, bool killRing);
</del><ins>+    void deleteKeyPressed(TextGranularity, bool shouldAddToKillRing);
+    void forwardDeleteKeyPressed(TextGranularity, bool shouldAddToKillRing);
</ins><span class="cx">     void deleteSelection(bool smartDelete);
</span><span class="cx">     void setCompositionType(TextCompositionType type) { m_compositionType = type; }
</span><span class="cx"> 
</span><span class="lines">@@ -131,7 +131,7 @@
</span><span class="cx">     bool m_smartDelete;
</span><span class="cx">     TextGranularity m_granularity;
</span><span class="cx">     TextCompositionType m_compositionType;
</span><del>-    bool m_killRing;
</del><ins>+    bool m_shouldAddToKillRing;
</ins><span class="cx">     bool m_preservesTypingStyle;
</span><span class="cx">     
</span><span class="cx">     // Undoing a series of backward deletes will restore a selection around all of the
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit210SourceWebCoreplatformmacKillRingMacmm"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/mac/KillRingMac.mm (195036 => 195037)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/mac/KillRingMac.mm        2016-01-14 12:08:05 UTC (rev 195036)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/mac/KillRingMac.mm        2016-01-14 12:14:19 UTC (rev 195037)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> NSString *_NSYankFromKillRing();
</span><span class="cx"> void _NSNewKillRingSequence();
</span><span class="cx"> void _NSSetKillRingToYankedState();
</span><ins>+void _NSResetKillRingOperationFlag();
</ins><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -53,12 +54,16 @@
</span><span class="cx"> void KillRing::append(const String&amp; string)
</span><span class="cx"> {
</span><span class="cx">     initializeKillRingIfNeeded();
</span><ins>+    // Necessary to prevent an implicit new sequence if the previous command was NSPrependToKillRing.
+    _NSResetKillRingOperationFlag();
</ins><span class="cx">     _NSAppendToKillRing(string);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void KillRing::prepend(const String&amp; string)
</span><span class="cx"> {
</span><span class="cx">     initializeKillRingIfNeeded();
</span><ins>+    // Necessary to prevent an implicit new sequence if the previous command was NSAppendToKillRing.
+    _NSResetKillRingOperationFlag();
</ins><span class="cx">     _NSPrependToKillRing(string);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>