Bug 329457 [compatibility] Editors do not get reused
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/EditorReference.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/EditorReference.java
index f5b3578..368a208 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/EditorReference.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/EditorReference.java
@@ -236,16 +236,6 @@
 	/*
 	 * (non-Javadoc)
 	 * 
-	 * @see org.eclipse.ui.IEditorReference#isPinned()
-	 */
-	public boolean isPinned() {
-		// FIXME compat implement pinning
-		return false;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
 	 * @see org.eclipse.ui.IEditorReference#getEditorInput()
 	 */
 	public IEditorInput getEditorInput() throws PartInitException {
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
index a24f782..1de70d7 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java
@@ -130,6 +130,8 @@
 import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
 import org.eclipse.ui.internal.registry.UIExtensionTracker;
 import org.eclipse.ui.internal.registry.ViewDescriptor;
+import org.eclipse.ui.internal.tweaklets.TabBehaviour;
+import org.eclipse.ui.internal.tweaklets.Tweaklets;
 import org.eclipse.ui.internal.util.Util;
 import org.eclipse.ui.model.IWorkbenchAdapter;
 import org.eclipse.ui.part.IShowInSource;
@@ -2019,40 +2021,63 @@
 		List<EditorReference> references = getCurrentEditorReferences();
 		return references.toArray(new IEditorReference[references.size()]);
 	}
+	
+	public IEditorReference[] getSortedEditors() {
+		IWorkbenchPartReference[] parts = getSortedParts(true, false);
+		IEditorReference[] editors = new IEditorReference[parts.length];
+		System.arraycopy(parts, 0, editors, 0, parts.length);
+		return editors;
+	}
 
 	public IWorkbenchPartReference[] getSortedParts() {
+		return getSortedParts(true, true);
+	}
+
+	private IWorkbenchPartReference[] getSortedParts(boolean editors, boolean views) {
+		if (!editors && !views) {
+			return new IWorkbenchPartReference[0];
+		}
+
 		List<IWorkbenchPartReference> sortedReferences = new ArrayList<IWorkbenchPartReference>();
 		IViewReference[] viewReferences = getViewReferences();
 		List<EditorReference> editorReferences = getCurrentEditorReferences();
 
 		activationLoop: for (MPart part : activationList) {
+			if (views) {
+				for (IViewReference ref : viewReferences) {
+					if (((ViewReference) ref).getModel() == part) {
+						sortedReferences.add(ref);
+						continue activationLoop;
+					}
+				}
+			}
+
+			if (editors) {
+				for (EditorReference ref : editorReferences) {
+					if (ref.getModel() == part) {
+						sortedReferences.add(ref);
+						break;
+					}
+				}
+			}
+		}
+
+		if (views) {
 			for (IViewReference ref : viewReferences) {
-				if (((ViewReference) ref).getModel() == part) {
+				if (!sortedReferences.contains(ref)) {
 					sortedReferences.add(ref);
-					continue activationLoop;
 				}
 			}
+		}
 
+		if (editors) {
 			for (EditorReference ref : editorReferences) {
-				if (ref.getModel() == part) {
+				if (!sortedReferences.contains(ref)) {
 					sortedReferences.add(ref);
-					break;
 				}
 			}
 		}
 
-		for (IViewReference ref : viewReferences) {
-			if (!sortedReferences.contains(ref)) {
-				sortedReferences.add(ref);
-			}
-		}
-
-		for (EditorReference ref : editorReferences) {
-			if (!sortedReferences.contains(ref)) {
-				sortedReferences.add(ref);
-			}
-		}
-
 		return sortedReferences.toArray(new IWorkbenchPartReference[sortedReferences.size()]);
 	}
 
@@ -2669,6 +2694,31 @@
 
 			recordEditor(input, descriptor);
 			return editor;
+		} else if (descriptor.isInternal()) {
+			// look for an editor to reuse
+			EditorReference reusableEditorRef = (EditorReference) ((TabBehaviour) Tweaklets
+					.get(TabBehaviour.KEY)).findReusableEditor(this);
+			if (reusableEditorRef != null) {
+				IEditorPart reusableEditor = reusableEditorRef.getEditor(false);
+				if (editorId.equals(reusableEditorRef.getId())
+						&& reusableEditor instanceof IReusableEditor) {
+					// reusable editors that share the same id are okay
+					recordEditor(input, descriptor);
+					reuseEditor((IReusableEditor) reusableEditor, input);
+
+					MPart editor = reusableEditorRef.getModel();
+					partService.showPart(editor, PartState.VISIBLE);
+					if (activate) {
+						partService.activate(editor);
+					} else {
+						updateActiveEditorSources(editor);
+					}
+					return reusableEditor;
+				}
+				// should have saved already if necessary, close this editor, a
+				// new one will be opened
+				closeEditor(reusableEditorRef, false);
+			}
 		} else if (descriptor.isOpenExternal()) {
 			openExternalEditor(descriptor, input);
 			// no editor parts for external editors, return null
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/tweaklets/TabBehaviourMRU.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/tweaklets/TabBehaviourMRU.java
index 0897ddb..13bf68a 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/tweaklets/TabBehaviourMRU.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/tweaklets/TabBehaviourMRU.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2009 IBM Corporation and others.
+ * Copyright (c) 2007, 2011 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
@@ -11,9 +11,18 @@
 
 package org.eclipse.ui.internal.tweaklets;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
 import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IEditorReference;
 import org.eclipse.ui.internal.IPreferenceConstants;
+import org.eclipse.ui.internal.WorkbenchMessages;
 import org.eclipse.ui.internal.WorkbenchPage;
 import org.eclipse.ui.internal.WorkbenchPlugin;
 import org.eclipse.ui.internal.e4.compatibility.E4Util;
@@ -35,7 +44,90 @@
 		if (!reuse) {
 			return null;
 		}
-		return null;
+
+		IEditorReference editors[] = page.getSortedEditors();
+		int length = editors.length;
+		if (length < page.getEditorReuseThreshold()) {
+			return null;
+		} else if (length > page.getEditorReuseThreshold()) {
+			List<IEditorReference> refs = new ArrayList<IEditorReference>();
+			List<IEditorReference> keep = new ArrayList<IEditorReference>(Arrays.asList(editors));
+			int extra = length - page.getEditorReuseThreshold();
+			// look for extra editors that should be closed
+			for (int i = 0; i < editors.length; i++) {
+				if (extra == 0) {
+					break;
+				}
+
+				if (editors[i].isPinned() || editors[i].isDirty()) {
+					continue;
+				}
+
+				refs.add(editors[i]);
+				extra--;
+			}
+
+			for (IEditorReference ref : refs) {
+				page.closeEditor(ref, false);
+				keep.remove(ref);
+			}
+
+			editors = keep.toArray(new IEditorReference[keep.size()]);
+		}
+
+		IEditorReference dirtyEditor = null;
+
+		// find an editor to reuse, go in reverse due to activation order
+		for (int i = editors.length - 1; i > -1; i--) {
+			IEditorReference editor = editors[i];
+			if (editor.isPinned()) {
+				// skip pinned editors
+				continue;
+			}
+			if (editor.isDirty()) {
+				// record dirty editors
+				if (dirtyEditor == null) {
+					dirtyEditor = editor;
+				}
+				continue;
+			}
+			// an editor is neither pinned nor dirty, use this one
+			return editor;
+		}
+		// can't find anything, return null
+		if (dirtyEditor == null) {
+			return null;
+		}
+
+		/* fix for 11122 */
+		boolean reuseDirty = WorkbenchPlugin.getDefault().getPreferenceStore()
+				.getBoolean(IPreferenceConstants.REUSE_DIRTY_EDITORS);
+		if (!reuseDirty) {
+			return null;
+		}
+
+		MessageDialog dialog = new MessageDialog(
+				page.getWorkbenchWindow().getShell(),
+				WorkbenchMessages.EditorManager_reuseEditorDialogTitle,
+				null, // accept the default window icon
+				NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, dirtyEditor.getName()),
+				MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL,
+						IDialogConstants.NO_LABEL,
+						WorkbenchMessages.EditorManager_openNewEditorLabel }, 0) {
+			protected int getShellStyle() {
+				return super.getShellStyle() | SWT.SHEET;
+			}
+		};
+		int result = dialog.open();
+		if (result == 0) { // YES
+			IEditorPart editor = dirtyEditor.getEditor(true);
+			if (!page.saveEditor(editor, false)) {
+				return null;
+			}
+		} else if ((result == 2) || (result == -1)) {
+			return null;
+		}
+		return dirtyEditor;
 	}
 
 	public IEditorReference reuseInternalEditor(WorkbenchPage page,