Bug 401990 - [Backport][Edit] "Copy Current from Right to Left" doesn't
work when triggered after Undo
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
index 77dd1a5..1c5a06d 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2013 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -427,6 +427,7 @@
 	private DocumentMerger fMerger;
 	/** The current diff */
 	private Diff fCurrentDiff;
+	private Diff fSavedDiff;
 
 	// Bug 259362 - Update diffs after undo
 	private boolean copyOperationInProgress = false;
@@ -2944,7 +2945,7 @@
 	 */
 	private void documentChanged(DocumentEvent e, boolean dirty) {
 		
-		IDocument doc= e.getDocument();
+		final IDocument doc= e.getDocument();
 		
 		if (doc == fLeft.getSourceViewer().getDocument()) {
 			setLeftDirty(dirty);
@@ -2953,8 +2954,64 @@
 		}
 		if (!isLeftDirty() && !isRightDirty()) {
 			fRedoDiff = false;
+			final Diff oldDiff = getLastDiff();
+			new UIJob(CompareMessages.DocumentMerger_0) {
+				public IStatus runInUIThread(IProgressMonitor monitor) {
+					if (!getControl().isDisposed()) {
+						doDiff();
+						if (!getControl().isDisposed()) {
+							Diff newDiff = findNewDiff(oldDiff);
+							if (newDiff != null) {
+								updateStatus(newDiff);
+								setCurrentDiff(newDiff, true);
+							}
+							invalidateLines();
+							updateLines(doc);
+						}
+					}
+					return Status.OK_STATUS;
+				}
+			}.schedule();
+		} else {
+			updateLines(doc);
 		}
-		updateLines(doc);
+	}
+	
+	
+	private void saveDiff() {
+			fSavedDiff = fCurrentDiff;
+	}
+
+	private Diff getLastDiff() {
+		if (fCurrentDiff != null) {
+			return fCurrentDiff;
+		}
+		return fSavedDiff;
+	}
+	
+	
+	private Diff findNewDiff(Diff oldDiff) {
+		if (oldDiff == null)
+			return null;
+		Diff newDiff = findNewDiff(oldDiff, LEFT_CONTRIBUTOR);
+		if (newDiff == null) {
+			newDiff = findNewDiff(oldDiff, RIGHT_CONTRIBUTOR);
+		}
+		return newDiff;
+	}
+
+	private Diff findNewDiff(Diff oldDiff, char type) {
+		int offset = oldDiff.getPosition(type).offset;
+		int length = oldDiff.getPosition(type).length;
+
+		// DocumentMerger.findDiff method doesn't really work well with 0-length
+		// diffs
+		if (length == 0) {
+			if (offset > 0)
+				offset--;
+			length = 1;
+		}
+		return fMerger.findDiff(type, offset, offset + length);
 	}
 	
 	/*
@@ -3269,7 +3326,7 @@
 		fAncestor.resetLineBackground();
 		fLeft.resetLineBackground();
 		fRight.resetLineBackground();
-		
+		saveDiff();
 		fCurrentDiff= null;
 		try {
 			fMerger.doDiff();
@@ -4427,9 +4484,11 @@
 			}
 			
 			// now switch diffs
+			saveDiff();
 			fCurrentDiff= d;
 			revealDiff(d, d.isToken());
 		} else {
+			saveDiff();
 			fCurrentDiff= d;
 		}
 
@@ -4680,7 +4739,7 @@
 	 */
 	private boolean copy(Diff diff, boolean leftToRight) {
 		
-		if (diff != null && !diff.isResolved()) {
+		if (diff != null) {
 			if (!validateChange(!leftToRight))
 				return false;
 			if (leftToRight) {
@@ -5008,6 +5067,7 @@
 
 	private void resetDiffs() {
 		// clear stuff
+		saveDiff();
 		fCurrentDiff= null;
 		fMerger.reset();
 		resetPositions(fLeft.getSourceViewer().getDocument());
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
index 81a28fe..90d840b 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -1245,7 +1245,7 @@
 	 */
 	public boolean copy(Diff diff, boolean leftToRight) {
 		
-		if (diff != null && !diff.isResolved()) {
+		if (diff != null) {
 			Position fromPos= null;
 			Position toPos= null;
 			IDocument fromDoc= null;