bug 325946: [backport] Provide a way to disable capping in the comparison algorithm
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/ComparePlugin.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/ComparePlugin.java
index 4f8aa60..fb52f01 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/ComparePlugin.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/ComparePlugin.java
@@ -25,7 +25,9 @@
 
 	// The shared instance
 	private static ComparePlugin plugin;
-	
+
+	private boolean cappingDisabled;
+
 	/**
 	 * The constructor
 	 */
@@ -53,7 +55,7 @@
 
 	/**
 	 * Returns the shared instance
-	 *
+	 * 
 	 * @return the shared instance
 	 */
 	public static ComparePlugin getDefault() {
@@ -61,11 +63,19 @@
 	}
 
 	public static void log(Throwable e) {
-		log(new Status(IStatus.ERROR, PLUGIN_ID, 0, Messages.Activator_1, e)); 
+		log(new Status(IStatus.ERROR, PLUGIN_ID, 0, Messages.Activator_1, e));
 	}
-	
+
 	public static void log(IStatus status) {
 		getDefault().getLog().log(status);
 	}
 
+	public void setCappingDisabled(boolean disable) {
+		this.cappingDisabled = disable;
+	}
+
+	public boolean isCappingDisabled() {
+		return this.cappingDisabled;
+	}
+
 }
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/LCS.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/LCS.java
index 26b40dd..e458e23 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/LCS.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare.core/src/org/eclipse/compare/internal/core/LCS.java
@@ -52,7 +52,7 @@
 		}
 
 		this.max_differences = (length1 + length2 + 1) / 2; // ceil((N+M)/2)
-		if ((double) length1 * (double) length2 > TOO_LONG) {
+		if (!isCappingDisabled() && (double) length1 * (double) length2 > TOO_LONG) {
 			// limit complexity to D^POW_LIMIT for long sequences
 			this.max_differences = (int) Math.pow(this.max_differences, POW_LIMIT - 1.0);
 		}
@@ -94,6 +94,10 @@
 
 	}
 
+	private boolean isCappingDisabled() {
+		return ComparePlugin.getDefault().isCappingDisabled();
+	}
+
 	/**
 	 * The recursive helper function for Myers' LCS. Computes the LCS of
 	 * l1[bottoml1 .. topl1] and l2[bottoml2 .. topl2] fills in the appropriate
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
index 11a62da..d9d18b0 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePreferencePage.java
@@ -20,6 +20,7 @@
 import org.eclipse.compare.IEncodedStreamContentAccessor;
 import org.eclipse.compare.ITypedElement;
 import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.compare.internal.core.ComparePlugin;
 import org.eclipse.compare.structuremergeviewer.DiffNode;
 import org.eclipse.compare.structuremergeviewer.Differencer;
 import org.eclipse.jface.dialogs.Dialog;
@@ -92,6 +93,7 @@
 	public static final String USE_SINGLE_LINE= PREFIX + "UseSingleLine"; //$NON-NLS-1$
 	public static final String HIGHLIGHT_TOKEN_CHANGES= PREFIX + "HighlightTokenChanges"; //$NON-NLS-1$
 	//public static final String USE_RESOLVE_UI= PREFIX + "UseResolveUI"; //$NON-NLS-1$
+	public static final String CAPPING_DISABLED= PREFIX + "CappingDisable"; //$NON-NLS-1$
 	public static final String PATH_FILTER= PREFIX + "PathFilter"; //$NON-NLS-1$
 	public static final String ADDED_LINES_REGEX= PREFIX + "AddedLinesRegex"; //$NON-NLS-1$
 	public static final String REMOVED_LINES_REGEX= PREFIX + "RemovedLinesRegex"; //$NON-NLS-1$
@@ -122,6 +124,7 @@
 		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_SINGLE_LINE),
 		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, HIGHLIGHT_TOKEN_CHANGES),
 		//new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, USE_RESOLVE_UI),
+		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, CAPPING_DISABLED),
 		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PATH_FILTER),
 		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION),
 		new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL),
@@ -143,6 +146,7 @@
 		store.setDefault(USE_SINGLE_LINE, true);
 		store.setDefault(HIGHLIGHT_TOKEN_CHANGES, true);
 		//store.setDefault(USE_RESOLVE_UI, false);
+		store.setDefault(CAPPING_DISABLED, false);
 		store.setDefault(PATH_FILTER, ""); //$NON-NLS-1$
 		store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, ICompareUIConstants.PREF_VALUE_PROMPT);
 		store.setDefault(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, ICompareUIConstants.PREF_VALUE_LOOP);
@@ -183,8 +187,12 @@
 		fOverlayStore.setValue(ADDED_LINES_REGEX, addedLinesRegex.getText());
 		fOverlayStore.setValue(REMOVED_LINES_REGEX, removedLinesRegex.getText());
 
-		editor.store();		
+		editor.store();
 		fOverlayStore.propagate();
+
+		ComparePlugin.getDefault().setCappingDisabled(
+				getPreferenceStore().getBoolean(
+						ComparePreferencePage.CAPPING_DISABLED));
 		return true;
 	}
 	
@@ -343,6 +351,7 @@
 		addCheckBox(composite, "ComparePreferencePage.useSingleLine.label", USE_SINGLE_LINE, 0);	//$NON-NLS-1$
 		addCheckBox(composite, "ComparePreferencePage.highlightTokenChanges.label", HIGHLIGHT_TOKEN_CHANGES, 0);	//$NON-NLS-1$
 		//addCheckBox(composite, "ComparePreferencePage.useResolveUI.label", USE_RESOLVE_UI, 0);	//$NON-NLS-1$
+		addCheckBox(composite, "ComparePreferencePage.disableCapping.label", CAPPING_DISABLED, 0);	//$NON-NLS-1$
 		
 		Composite radioGroup = new Composite(composite, SWT.NULL);
 		radioGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
index b3d058c..4e32e94 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -32,6 +32,7 @@
 import org.eclipse.compare.IStreamContentAccessor;
 import org.eclipse.compare.IStreamMerger;
 import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.internal.core.ComparePlugin;
 import org.eclipse.compare.structuremergeviewer.ICompareInput;
 import org.eclipse.compare.structuremergeviewer.IStructureCreator;
 import org.eclipse.compare.structuremergeviewer.StructureDiffViewer;
@@ -256,6 +257,10 @@
 
 	public void start(BundleContext context) throws Exception {
 		super.start(context);
+
+		ComparePlugin.getDefault().setCappingDisabled(
+				getPreferenceStore().getBoolean(
+						ComparePreferencePage.CAPPING_DISABLED));
 	}
 			
 	public void stop(BundleContext context) throws Exception {
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 1dc8bb8..abbd294 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
@@ -11,17 +11,36 @@
 package org.eclipse.compare.internal.merge;
 
 import java.lang.reflect.InvocationTargetException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
 import org.eclipse.compare.CompareConfiguration;
 import org.eclipse.compare.contentmergeviewer.ITokenComparator;
-import org.eclipse.compare.internal.*;
+import org.eclipse.compare.internal.CompareContentViewerSwitchingPane;
+import org.eclipse.compare.internal.CompareMessages;
+import org.eclipse.compare.internal.ComparePreferencePage;
+import org.eclipse.compare.internal.CompareUIPlugin;
+import org.eclipse.compare.internal.DocLineComparator;
+import org.eclipse.compare.internal.MergeViewerContentProvider;
+import org.eclipse.compare.internal.Utilities;
 import org.eclipse.compare.internal.core.LCS;
-import org.eclipse.compare.rangedifferencer.*;
+import org.eclipse.compare.rangedifferencer.IRangeComparator;
+import org.eclipse.compare.rangedifferencer.RangeDifference;
+import org.eclipse.compare.rangedifferencer.RangeDifferencer;
 import org.eclipse.compare.structuremergeviewer.Differencer;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.BadPositionCategoryException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.ui.PlatformUI;
@@ -412,7 +431,7 @@
 				}
 			}*/
 		}
-			
+
 		final Object[] result= new Object[1];
 		final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
 		IRunnableWithProgress runnable= new IRunnableWithProgress() {
@@ -532,6 +551,8 @@
 
 	private boolean isCapped(DocLineComparator ancestor,
 			DocLineComparator left, DocLineComparator right) {
+		if (isCappingDisabled())
+			return false;
 		int aLength = ancestor == null? 0 : ancestor.getRangeCount();
 		int lLength = left.getRangeCount();
 		int rLength = right.getRangeCount();
@@ -648,6 +669,10 @@
 		return Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
 	}
 	
+	private boolean isCappingDisabled() {
+		return CompareUIPlugin.getDefault().getPreferenceStore().getBoolean(ComparePreferencePage.CAPPING_DISABLED);
+	}
+
 	private IDocument getDocument(char contributor) {
 		return fInput.getDocument(contributor);
 	}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.properties
index c8e2865..a5fb23f 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.properties
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/plugin.properties
@@ -130,6 +130,7 @@
 ComparePreferencePage.synchronizeScrolling.label= Synchronize &scrolling between panes in compare viewers
 ComparePreferencePage.useSingleLine.label= Connect &ranges with single line
 ComparePreferencePage.highlightTokenChanges.label=&Highlight individual changes
+ComparePreferencePage.disableCapping.label=Disable &capping when comparing large documents
 
 ComparePreferencePage.preview.label= Previe&w:
 ComparePreferencePage.ancestor.label= Common Ancestor