1GDIHZA: ITPUI:ALL - Compare shouldn't be enabled for more than 3 inputs
diff --git a/bundles/org.eclipse.compare/compare/changes.html b/bundles/org.eclipse.compare/compare/changes.html
index 92af81a..262bbe5 100644
--- a/bundles/org.eclipse.compare/compare/changes.html
+++ b/bundles/org.eclipse.compare/compare/changes.html
@@ -32,12 +32,15 @@
 Problem reports fixed</h2>

 1GCC8BV: ITPUI:ALL - Need icons for Compare<br>

 1GD9XVG: ITPJUI:WIN2000 - Release: no busy cursor during diff computation<br>

-1GCWH49: ITPVCM:WINNT - UI: If nothing to release, should not say "Compare failed"

+1GCWH49: ITPVCM:WINNT - UI: If nothing to release, should not say "Compare failed"<br>

+1GDIF8U: ITPUI:ALL - Compare of file with folder results in empty compare editor<br>

+1GDIHZA: ITPUI:ALL - Compare shouldn't be enabled for more than 3 inputs<br>

 

 <h2>

 Problem reports closed</h2>

 1G60D5W: ITPUI:ALL - Compare should not be enabled if two items not selected<br>

 1G5YG2R: ITPUI:ALL - Navigator->Popup->Compare should be disabled if there is only one item selected.<br>

+1GCQKGD: ITPVCM:WINNT - Viewer should close after release/catchup<br>

 

 <h1>

 <hr WIDTH="100%"></h1>

diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
index 4193d9a..cd48754 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
@@ -15,18 +15,16 @@
 

 public class CompareAction implements IActionDelegate {

 

-	private ISelection fSelection;

+	private ResourceCompareInput fInput;

 

 	public void run(IAction action) {

-		CompareUI.openCompareEditor(new ResourceCompareInput(new CompareConfiguration(), fSelection));

+		if (fInput != null)

+			CompareUI.openCompareEditor(fInput);

 	}

 

-	public void selectionChanged(IAction a, ISelection s) {

-		fSelection= s;

-		// the following check is disabled because it results in a confusing UI:

-		// action might be enabled if plugin is not loaded but

-		// it gets disabled after plugin has been loaded...

-		//Object[] selection= StructuredSelection.toArray(s);

-		//((Action)a).setEnabled(selection.length == 2);

+	public void selectionChanged(IAction action, ISelection selection) {

+		if (fInput == null)

+			fInput= new ResourceCompareInput(new CompareConfiguration());

+		action.setEnabled(fInput.setSelection(selection));

 	}

 }

diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
index 6c6e073..7aadc3c 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
@@ -19,7 +19,16 @@
  */

 class ResourceCompareInput extends CompareEditorInput {

 	

-	private ISelection fSelection;

+	private static final boolean NORMALIZE_CASE= true;

+	

+	private boolean fThreeWay= false;

+	private IStructureComparator fAncestor;

+	private IStructureComparator fLeft;

+	private IStructureComparator fRight;

+	private IResource fAncestorResource;

+	private IResource fLeftResource;

+	private IResource fRightResource;

+	

 	

 	private class MyDiffNode extends DiffNode {

 		public MyDiffNode(IDiffContainer parent, int description, ITypedElement ancestor, ITypedElement left, ITypedElement right) {

@@ -34,82 +43,64 @@
 	/**

 	 * Creates an compare editor input for the given selection.

 	 */

-	ResourceCompareInput(CompareConfiguration config, ISelection selection) {

+	ResourceCompareInput(CompareConfiguration config) {

 		super(config);

-		fSelection= selection;

 	}

 		

 	/**

-	 * Performs a two-way or three-way diff on the current selection.

+	 * Returns true if compare can be executed for the given selection.

 	 */

-	public Object prepareInput(IProgressMonitor pm) {

-		

-		try {

-			pm.beginTask("Comparing:", IProgressMonitor.UNKNOWN);

-													

-			IResource[] selection= Utilities.getResources(fSelection);

-					

-			if (selection.length < 2 || selection.length > 3) {

-				setMessage("Selection must contain two or three resources");

-				return null;

-			}

-			

-			boolean threeWay= selection.length == 3;

-			

-			IResource lr= selection[0];

-			IResource rr= selection[1];

-			if (threeWay) {

-				lr= selection[1];		

-				rr= selection[2];

-			}

-			

-			IStructureComparator ancestor= null;

-			IStructureComparator left= getStructure(lr);

-			IStructureComparator right= getStructure(rr);

-						

-			if (right == null || left == null) {

-				setMessage("Selected resources must be of same type");

-				return null;

-			}

-	

-			CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();

+	boolean setSelection(ISelection s) {

 

-			String leftLabel= lr.getName();

-			cc.setLeftLabel(leftLabel);

-			cc.setLeftImage(CompareUIPlugin.getImage(lr));

-			

-			String rightLabel= rr.getName();

-			cc.setRightLabel(rightLabel);

-			cc.setRightImage(CompareUIPlugin.getImage(rr));

-			

-			StringBuffer title= new StringBuffer();

-			title.append("Compare (");

-			if (threeWay) {

-				IResource ar= selection[0];

-				ancestor= getStructure(ar);

-				String ancestorLabel= ar.getName();

-				cc.setAncestorLabel(ancestorLabel);

-				cc.setAncestorImage(CompareUIPlugin.getImage(ar));

-				title.append(ancestorLabel);

-				title.append("-");

-			}

-			title.append(leftLabel);

-			title.append("-");

-			title.append(rightLabel);

-			title.append(")");

-			setTitle(title.toString());

-			

-			Differencer d= new Differencer() {

-				protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {

-					return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);

-				}

-			};

-			

-			return d.findDifferences(threeWay, pm, null, ancestor, left, right);

+		IResource[] selection= Utilities.getResources(s);

+		if (selection.length < 2 || selection.length > 3)

+			return false;

+

+		fThreeWay= selection.length == 3;

 		

-		} finally {

-			pm.done();

+		fLeftResource= selection[0];

+		fRightResource= selection[1];

+		if (fThreeWay) {

+			fLeftResource= selection[1];		

+			fRightResource= selection[2];

 		}

+		

+		fAncestor= null;

+		fLeft= getStructure(fLeftResource);

+		fRight= getStructure(fRightResource);

+					

+		if (incomparable(fLeft, fRight))

+			return false;

+

+		if (fThreeWay) {

+			fAncestorResource= selection[0];

+			fAncestor= getStructure(fAncestorResource);

+			

+			if (incomparable(fAncestor, fRight))

+				return false;

+		}

+

+		return true;

+	}

+	

+	/**

+	 * Returns true if the given arguments cannot be compared.

+	 */

+	private boolean incomparable(IStructureComparator c1, IStructureComparator c2) {

+		if (c1 == null || c2 == null)

+			return true;

+		return isLeaf(c1) != isLeaf(c2);

+	}

+	

+	/**

+	 * Returns true if the given arguments is a leaf.

+	 */

+	private boolean isLeaf(IStructureComparator c) {

+		if (c instanceof ITypedElement) {

+			ITypedElement te= (ITypedElement) c;

+			return !ITypedElement.FOLDER_TYPE.equals(te.getType());

+		}

+		return false;

 	}

 	

 	/**

@@ -126,23 +117,58 @@
 			ResourceNode rn= new ResourceNode(input);

 			IFile file= (IFile) input;

 			String type= normalizeCase(file.getFileExtension());

-			if ("JAR".equals(type) || "ZIP".equals(type)) {	// FIXME

-				

+			if ("JAR".equals(type) || "ZIP".equals(type))

 				return new ZipStructureCreator().getStructure(rn);

-				

-//				IStructureCreatorDescriptor scd= CompareUIPlugin.getStructureCreator(type);

-//				if (scd != null) {

-//					IStructureCreator sc= scd.createStructureCreator();

-//					if (sc != null)

-//						return sc.getStructure(rn);

-//				}

-			}

 			return rn;

 		}

 		return null;

 	}

 	

-	private static final boolean NORMALIZE_CASE= true;

+	/**

+	 * Performs a two-way or three-way diff on the current selection.

+	 */

+	public Object prepareInput(IProgressMonitor pm) {

+				

+		CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();

+	

+		String leftLabel= fLeftResource.getName();

+		cc.setLeftLabel(leftLabel);

+		cc.setLeftImage(CompareUIPlugin.getImage(fLeftResource));

+		

+		String rightLabel= fRightResource.getName();

+		cc.setRightLabel(rightLabel);

+		cc.setRightImage(CompareUIPlugin.getImage(fRightResource));

+		

+		StringBuffer title= new StringBuffer();

+		title.append("Compare (");

+		if (fThreeWay) {			

+			String ancestorLabel= fAncestorResource.getName();

+			cc.setAncestorLabel(ancestorLabel);

+			cc.setAncestorImage(CompareUIPlugin.getImage(fAncestorResource));

+			title.append(ancestorLabel);

+			title.append("-");

+		}

+		title.append(leftLabel);

+		title.append("-");

+		title.append(rightLabel);

+		title.append(")");

+		setTitle(title.toString());

+			

+		try {													

+			pm.beginTask("Comparing:", IProgressMonitor.UNKNOWN);

+

+			Differencer d= new Differencer() {

+				protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {

+					return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);

+				}

+			};

+			

+			return d.findDifferences(fThreeWay, pm, null, fAncestor, fLeft, fRight);

+		

+		} finally {

+			pm.done();

+		}

+	}

 	

 	private static String normalizeCase(String s) {

 		if (NORMALIZE_CASE && s != null)

diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/changes.html b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/changes.html
index 92af81a..262bbe5 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/changes.html
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/changes.html
@@ -32,12 +32,15 @@
 Problem reports fixed</h2>

 1GCC8BV: ITPUI:ALL - Need icons for Compare<br>

 1GD9XVG: ITPJUI:WIN2000 - Release: no busy cursor during diff computation<br>

-1GCWH49: ITPVCM:WINNT - UI: If nothing to release, should not say "Compare failed"

+1GCWH49: ITPVCM:WINNT - UI: If nothing to release, should not say "Compare failed"<br>

+1GDIF8U: ITPUI:ALL - Compare of file with folder results in empty compare editor<br>

+1GDIHZA: ITPUI:ALL - Compare shouldn't be enabled for more than 3 inputs<br>

 

 <h2>

 Problem reports closed</h2>

 1G60D5W: ITPUI:ALL - Compare should not be enabled if two items not selected<br>

 1G5YG2R: ITPUI:ALL - Navigator->Popup->Compare should be disabled if there is only one item selected.<br>

+1GCQKGD: ITPVCM:WINNT - Viewer should close after release/catchup<br>

 

 <h1>

 <hr WIDTH="100%"></h1>

diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
index 4193d9a..cd48754 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
@@ -15,18 +15,16 @@
 

 public class CompareAction implements IActionDelegate {

 

-	private ISelection fSelection;

+	private ResourceCompareInput fInput;

 

 	public void run(IAction action) {

-		CompareUI.openCompareEditor(new ResourceCompareInput(new CompareConfiguration(), fSelection));

+		if (fInput != null)

+			CompareUI.openCompareEditor(fInput);

 	}

 

-	public void selectionChanged(IAction a, ISelection s) {

-		fSelection= s;

-		// the following check is disabled because it results in a confusing UI:

-		// action might be enabled if plugin is not loaded but

-		// it gets disabled after plugin has been loaded...

-		//Object[] selection= StructuredSelection.toArray(s);

-		//((Action)a).setEnabled(selection.length == 2);

+	public void selectionChanged(IAction action, ISelection selection) {

+		if (fInput == null)

+			fInput= new ResourceCompareInput(new CompareConfiguration());

+		action.setEnabled(fInput.setSelection(selection));

 	}

 }

diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
index 6c6e073..7aadc3c 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
@@ -19,7 +19,16 @@
  */

 class ResourceCompareInput extends CompareEditorInput {

 	

-	private ISelection fSelection;

+	private static final boolean NORMALIZE_CASE= true;

+	

+	private boolean fThreeWay= false;

+	private IStructureComparator fAncestor;

+	private IStructureComparator fLeft;

+	private IStructureComparator fRight;

+	private IResource fAncestorResource;

+	private IResource fLeftResource;

+	private IResource fRightResource;

+	

 	

 	private class MyDiffNode extends DiffNode {

 		public MyDiffNode(IDiffContainer parent, int description, ITypedElement ancestor, ITypedElement left, ITypedElement right) {

@@ -34,82 +43,64 @@
 	/**

 	 * Creates an compare editor input for the given selection.

 	 */

-	ResourceCompareInput(CompareConfiguration config, ISelection selection) {

+	ResourceCompareInput(CompareConfiguration config) {

 		super(config);

-		fSelection= selection;

 	}

 		

 	/**

-	 * Performs a two-way or three-way diff on the current selection.

+	 * Returns true if compare can be executed for the given selection.

 	 */

-	public Object prepareInput(IProgressMonitor pm) {

-		

-		try {

-			pm.beginTask("Comparing:", IProgressMonitor.UNKNOWN);

-													

-			IResource[] selection= Utilities.getResources(fSelection);

-					

-			if (selection.length < 2 || selection.length > 3) {

-				setMessage("Selection must contain two or three resources");

-				return null;

-			}

-			

-			boolean threeWay= selection.length == 3;

-			

-			IResource lr= selection[0];

-			IResource rr= selection[1];

-			if (threeWay) {

-				lr= selection[1];		

-				rr= selection[2];

-			}

-			

-			IStructureComparator ancestor= null;

-			IStructureComparator left= getStructure(lr);

-			IStructureComparator right= getStructure(rr);

-						

-			if (right == null || left == null) {

-				setMessage("Selected resources must be of same type");

-				return null;

-			}

-	

-			CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();

+	boolean setSelection(ISelection s) {

 

-			String leftLabel= lr.getName();

-			cc.setLeftLabel(leftLabel);

-			cc.setLeftImage(CompareUIPlugin.getImage(lr));

-			

-			String rightLabel= rr.getName();

-			cc.setRightLabel(rightLabel);

-			cc.setRightImage(CompareUIPlugin.getImage(rr));

-			

-			StringBuffer title= new StringBuffer();

-			title.append("Compare (");

-			if (threeWay) {

-				IResource ar= selection[0];

-				ancestor= getStructure(ar);

-				String ancestorLabel= ar.getName();

-				cc.setAncestorLabel(ancestorLabel);

-				cc.setAncestorImage(CompareUIPlugin.getImage(ar));

-				title.append(ancestorLabel);

-				title.append("-");

-			}

-			title.append(leftLabel);

-			title.append("-");

-			title.append(rightLabel);

-			title.append(")");

-			setTitle(title.toString());

-			

-			Differencer d= new Differencer() {

-				protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {

-					return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);

-				}

-			};

-			

-			return d.findDifferences(threeWay, pm, null, ancestor, left, right);

+		IResource[] selection= Utilities.getResources(s);

+		if (selection.length < 2 || selection.length > 3)

+			return false;

+

+		fThreeWay= selection.length == 3;

 		

-		} finally {

-			pm.done();

+		fLeftResource= selection[0];

+		fRightResource= selection[1];

+		if (fThreeWay) {

+			fLeftResource= selection[1];		

+			fRightResource= selection[2];

 		}

+		

+		fAncestor= null;

+		fLeft= getStructure(fLeftResource);

+		fRight= getStructure(fRightResource);

+					

+		if (incomparable(fLeft, fRight))

+			return false;

+

+		if (fThreeWay) {

+			fAncestorResource= selection[0];

+			fAncestor= getStructure(fAncestorResource);

+			

+			if (incomparable(fAncestor, fRight))

+				return false;

+		}

+

+		return true;

+	}

+	

+	/**

+	 * Returns true if the given arguments cannot be compared.

+	 */

+	private boolean incomparable(IStructureComparator c1, IStructureComparator c2) {

+		if (c1 == null || c2 == null)

+			return true;

+		return isLeaf(c1) != isLeaf(c2);

+	}

+	

+	/**

+	 * Returns true if the given arguments is a leaf.

+	 */

+	private boolean isLeaf(IStructureComparator c) {

+		if (c instanceof ITypedElement) {

+			ITypedElement te= (ITypedElement) c;

+			return !ITypedElement.FOLDER_TYPE.equals(te.getType());

+		}

+		return false;

 	}

 	

 	/**

@@ -126,23 +117,58 @@
 			ResourceNode rn= new ResourceNode(input);

 			IFile file= (IFile) input;

 			String type= normalizeCase(file.getFileExtension());

-			if ("JAR".equals(type) || "ZIP".equals(type)) {	// FIXME

-				

+			if ("JAR".equals(type) || "ZIP".equals(type))

 				return new ZipStructureCreator().getStructure(rn);

-				

-//				IStructureCreatorDescriptor scd= CompareUIPlugin.getStructureCreator(type);

-//				if (scd != null) {

-//					IStructureCreator sc= scd.createStructureCreator();

-//					if (sc != null)

-//						return sc.getStructure(rn);

-//				}

-			}

 			return rn;

 		}

 		return null;

 	}

 	

-	private static final boolean NORMALIZE_CASE= true;

+	/**

+	 * Performs a two-way or three-way diff on the current selection.

+	 */

+	public Object prepareInput(IProgressMonitor pm) {

+				

+		CompareConfiguration cc= (CompareConfiguration) getCompareConfiguration();

+	

+		String leftLabel= fLeftResource.getName();

+		cc.setLeftLabel(leftLabel);

+		cc.setLeftImage(CompareUIPlugin.getImage(fLeftResource));

+		

+		String rightLabel= fRightResource.getName();

+		cc.setRightLabel(rightLabel);

+		cc.setRightImage(CompareUIPlugin.getImage(fRightResource));

+		

+		StringBuffer title= new StringBuffer();

+		title.append("Compare (");

+		if (fThreeWay) {			

+			String ancestorLabel= fAncestorResource.getName();

+			cc.setAncestorLabel(ancestorLabel);

+			cc.setAncestorImage(CompareUIPlugin.getImage(fAncestorResource));

+			title.append(ancestorLabel);

+			title.append("-");

+		}

+		title.append(leftLabel);

+		title.append("-");

+		title.append(rightLabel);

+		title.append(")");

+		setTitle(title.toString());

+			

+		try {													

+			pm.beginTask("Comparing:", IProgressMonitor.UNKNOWN);

+

+			Differencer d= new Differencer() {

+				protected Object visit(Object parent, int description, Object ancestor, Object left, Object right) {

+					return new MyDiffNode((IDiffContainer) parent, description, (ITypedElement)ancestor, (ITypedElement)left, (ITypedElement)right);

+				}

+			};

+			

+			return d.findDifferences(fThreeWay, pm, null, fAncestor, fLeft, fRight);

+		

+		} finally {

+			pm.done();

+		}

+	}

 	

 	private static String normalizeCase(String s) {

 		if (NORMALIZE_CASE && s != null)