Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal')
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AbstractViewer.java30
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AddFromHistoryDialog.java17
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewer.java92
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewerCreator.java24
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BufferedCanvas.java86
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ChangePropertyAction.java39
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java32
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareDialog.java137
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditor.java159
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditorContributor.java44
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePluginResources.properties35
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java706
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareViewerSwitchingPane.java251
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DiffImage.java54
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DocLineComparator.java216
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IStructureCreatorDescriptor.java28
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IViewerDescriptor.java36
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IgnoreWhiteSpaceAction.java21
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageCanvas.java137
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewer.java127
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerCreator.java25
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerResources.properties55
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeSourceViewer.java218
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeViewerContentProvider.java142
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Pane.java94
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.java90
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties22
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java153
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ShowPseudoConflicts.java21
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Splitter.java69
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextMergeViewerCreator.java26
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewer.java64
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewerCreator.java27
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TokenComparator.java190
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java237
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ViewerDescriptor.java56
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ZipStructureCreator.java253
37 files changed, 4013 insertions, 0 deletions
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AbstractViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AbstractViewer.java
new file mode 100644
index 000000000..2017e31de
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AbstractViewer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.Viewer;
+
+
+abstract class AbstractViewer extends Viewer {
+
+ public void setInput(Object input) {
+ }
+
+ public Object getInput() {
+ return null;
+ }
+
+ public ISelection getSelection() {
+ return null;
+ }
+
+ public void setSelection(ISelection s, boolean reveal) {
+ }
+
+ public void refresh() {
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AddFromHistoryDialog.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AddFromHistoryDialog.java
new file mode 100644
index 000000000..eb6c44eab
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/AddFromHistoryDialog.java
@@ -0,0 +1,17 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000,2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.widgets.Shell;
+
+
+public class AddFromHistoryDialog extends Dialog {
+
+ public AddFromHistoryDialog(Shell parent) {
+ super(parent);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewer.java
new file mode 100644
index 000000000..07be03f22
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewer.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.ICompareInput;
+
+/**
+ * A simple compare viewer for binary files.
+ * Shows the position of the first non-matching byte.
+ */
+public class BinaryCompareViewer extends AbstractViewer {
+
+ private static final int EOF= -1;
+ private Text fControl;
+ private ICompareInput fInput;
+
+
+ public BinaryCompareViewer(Composite parent, CompareConfiguration cc) {
+ fControl= new Text(parent, SWT.NONE);
+ fControl.setEditable(false);
+ fControl.setData(CompareUI.COMPARE_VIEWER_TITLE, "Binary Compare");
+ }
+
+ public Control getControl() {
+ return fControl;
+ }
+
+ public void setInput(Object input) {
+ if (fControl != null && input instanceof ICompareInput) {
+ fInput= (ICompareInput) input;
+
+ InputStream left= null;
+ InputStream right= null;
+
+ try {
+ left= getStream(fInput.getLeft());
+ right= getStream(fInput.getRight());
+
+ int pos= 0;
+ while (true) {
+ int l= left.read();
+ int r= right.read();
+ if (l != r) {
+ fControl.setText("first bytes differ at position " + pos);
+ break;
+ }
+ if (l == EOF)
+ break;
+ pos++;
+ }
+ } catch (CoreException ex) {
+ fControl.setText("CoreException " + ex);
+ } catch (IOException ex) {
+ fControl.setText("IOException " + ex);
+ } finally {
+ if (left != null) {
+ try {
+ left.close();
+ } catch (IOException ex) {
+ }
+ }
+ if (right != null) {
+ try {
+ right.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ }
+ }
+
+ public Object getInput() {
+ return fInput;
+ }
+
+ private InputStream getStream(ITypedElement input) throws CoreException {
+ if (input instanceof IStreamContentAccessor)
+ return ((IStreamContentAccessor)input).getContents();
+ return new ByteArrayInputStream(new byte[0]);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewerCreator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewerCreator.java
new file mode 100644
index 000000000..503756b10
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BinaryCompareViewerCreator.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.compare.*;
+
+/**
+ * A factory object for the <code>BinaryCompareViewer</code>.
+ * This indirection is necessary because only objects with a default
+ * constructor can be created via an extension point
+ * (this precludes Viewers).
+ */
+public class BinaryCompareViewerCreator implements IViewerCreator {
+
+ public Viewer createViewer(Composite parent, CompareConfiguration mp) {
+ return new BinaryCompareViewer(parent, mp);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BufferedCanvas.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BufferedCanvas.java
new file mode 100644
index 000000000..6a073a3e7
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/BufferedCanvas.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.events.*;
+
+/**
+ * A Canvas which reduces flicker by drawing in an off screen buffer.
+ */
+public abstract class BufferedCanvas extends Canvas {
+
+ /** The drawable for double buffering */
+ private Image fBuffer;
+
+ public BufferedCanvas(Composite parent, int flags) {
+ super(parent, flags + SWT.NO_BACKGROUND);
+
+ addPaintListener(
+ new PaintListener() {
+ public void paintControl(PaintEvent event) {
+ doubleBufferPaint(event.gc);
+ }
+ }
+ );
+
+ addDisposeListener(
+ new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if (fBuffer != null) {
+ fBuffer.dispose();
+ fBuffer= null;
+ }
+ }
+ }
+ );
+ }
+
+ public void repaint() {
+ if (!isDisposed()) {
+ GC gc= new GC(this);
+ doubleBufferPaint(gc);
+ gc.dispose();
+ }
+ }
+
+ /**
+ * Double buffer drawing.
+ * @private
+ */
+ private void doubleBufferPaint(GC dest) {
+
+ Point size= getSize();
+
+ if (size.x <= 0 || size.y <= 0)
+ return;
+
+ if (fBuffer != null) {
+ Rectangle r= fBuffer.getBounds();
+ if (r.width != size.x || r.height != size.y) {
+ fBuffer.dispose();
+ fBuffer= null;
+ }
+ }
+ if (fBuffer == null)
+ fBuffer= new Image(getDisplay(), size.x, size.y);
+
+ GC gc= new GC(fBuffer);
+ try {
+ gc.setBackground(getBackground());
+ gc.fillRectangle(0, 0, size.x, size.y);
+ doPaint(gc);
+ } finally {
+ gc.dispose();
+ }
+
+ dest.drawImage(fBuffer, 0, 0);
+ }
+
+ abstract public void doPaint(GC gc);
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ChangePropertyAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ChangePropertyAction.java
new file mode 100644
index 000000000..5f54e30f7
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ChangePropertyAction.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.compare.CompareConfiguration;
+
+/**
+ * Toggles a boolean property of an <code>ICompareConfiguration</code>.
+ */
+public class ChangePropertyAction extends Action {
+
+ private CompareConfiguration fCompareConfiguration;
+ private String fPropertyKey;
+
+
+ public ChangePropertyAction(ResourceBundle bundle, CompareConfiguration cc, String rkey, String pkey) {
+ fPropertyKey= pkey;
+ Utilities.initAction(this, bundle, rkey);
+ setCompareConfiguration(cc);
+ }
+
+ public void run() {
+ boolean b= !Utilities.getBoolean(fCompareConfiguration, fPropertyKey, false);
+ setChecked(b);
+ if (fCompareConfiguration != null)
+ fCompareConfiguration.setProperty(fPropertyKey, new Boolean(b));
+ }
+
+ public void setCompareConfiguration(CompareConfiguration cc) {
+ fCompareConfiguration= cc;
+ setChecked(Utilities.getBoolean(fCompareConfiguration, fPropertyKey, false));
+ }
+}
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
new file mode 100644
index 000000000..4193d9a80
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareAction.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.CompareUI;
+
+
+public class CompareAction implements IActionDelegate {
+
+ private ISelection fSelection;
+
+ public void run(IAction action) {
+ CompareUI.openCompareEditor(new ResourceCompareInput(new CompareConfiguration(), fSelection));
+ }
+
+ 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);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareDialog.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareDialog.java
new file mode 100644
index 000000000..cb6ce6526
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareDialog.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.layout.*;
+
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+import org.eclipse.compare.CompareEditorInput;
+import org.eclipse.jface.util.IPropertyChangeListener;
+
+
+public class CompareDialog extends Dialog implements IPropertyChangeListener {
+
+ private static final String COMMIT_LABEL= "Commit";
+
+ private CompareEditorInput fCompareEditorInput;
+ private Button fCommitButton;
+
+
+ CompareDialog(Shell shell, CompareEditorInput input) {
+ super(shell);
+ setShellStyle(SWT.CLOSE | SWT.APPLICATION_MODAL | SWT.RESIZE);
+
+ Assert.isNotNull(input);
+ fCompareEditorInput= input;
+ fCompareEditorInput.addPropertyChangeListener(this);
+ }
+
+ public boolean close() {
+ if (super.close()) {
+ if (fCompareEditorInput != null)
+ fCompareEditorInput.addPropertyChangeListener(this);
+ return true;
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Dialog.
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ fCommitButton= createButton(parent, IDialogConstants.OK_ID, COMMIT_LABEL, true);
+ fCommitButton.setEnabled(false);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ if (fCommitButton != null && fCompareEditorInput != null)
+ fCommitButton.setEnabled(fCompareEditorInput.isSaveNeeded());
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Dialog.
+ */
+ protected Control createDialogArea(Composite parent) {
+
+ Control c= fCompareEditorInput.createContents(parent);
+ c.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Shell shell= c.getShell();
+ shell.setText(fCompareEditorInput.getTitle());
+ shell.setImage(fCompareEditorInput.getTitleImage());
+
+ return c;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Window.
+ */
+ protected Point getInitialSize() {
+ Point size= new Point(0, 0);
+ Shell shell= getParentShell();
+ if (shell != null) {
+ Point parentSize= shell.getSize();
+ size.x= parentSize.x-100;
+ size.y= parentSize.y-100;
+ }
+ if (size.x < 800)
+ size.x= 800;
+ if (size.y < 600)
+ size.y= 600;
+ return size;
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Window.
+ */
+ public int open() {
+
+ int rc= super.open();
+
+ if (rc == OK && fCompareEditorInput.isSaveNeeded()) {
+
+ WorkspaceModifyOperation operation= new WorkspaceModifyOperation() {
+ public void execute(IProgressMonitor pm) throws CoreException {
+ fCompareEditorInput.save(pm);
+ }
+ };
+
+ Shell shell= getParentShell();
+ ProgressMonitorDialog pmd= new ProgressMonitorDialog(shell);
+ try {
+ operation.run(pmd.getProgressMonitor());
+
+ } catch (InterruptedException x) {
+ } catch (OperationCanceledException x) {
+ } catch (InvocationTargetException x) {
+ //String title= getResourceString("Error.save.title");
+ //String msg= getResourceString("Error.save.message");
+ String title= "Save Error";
+ String msg= "Can't save ";
+ MessageDialog.openError(shell, title, msg + x.getTargetException().getMessage());
+ }
+ }
+
+ return rc;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditor.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditor.java
new file mode 100644
index 000000000..cfc6ccf6c
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditor.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.jface.util.*;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.compare.*;
+import org.eclipse.ui.part.EditorPart;
+
+
+/**
+ * A CompareEditor takes a ICompareEditorInput as input.
+ * Most functionality is delegated to the ICompareEditorInput.
+ */
+public class CompareEditor extends EditorPart implements IPropertyChangeListener {
+
+ public CompareEditor() {
+ }
+
+ /* package */ CompareConfiguration getCompareConfiguration() {
+ IEditorInput input= getEditorInput();
+ if (input instanceof CompareEditorInput)
+ return ((CompareEditorInput)input).getCompareConfiguration();
+ return null;
+ }
+
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+
+ if (!(input instanceof CompareEditorInput))
+ throw new PartInitException("Invalid Input: Must be CompareEditorInput");
+
+ CompareEditorInput cei= (CompareEditorInput) input;
+
+ setSite(site);
+ setInput(input);
+
+ setTitleImage(cei.getTitleImage());
+ setTitle(cei.getTitle());
+
+ if (input instanceof IPropertyChangeNotifier)
+ ((IPropertyChangeNotifier)input).addPropertyChangeListener(this);
+ }
+
+ /*
+ * @see IDesktopPart#createPartControl(Composite)
+ */
+ public void createPartControl(Composite parent) {
+
+ IEditorInput input= getEditorInput();
+ if (input instanceof CompareEditorInput)
+ ((CompareEditorInput) input).createContents(parent);
+ }
+
+ /*
+ * @see DesktopPart#dispose
+ */
+ public void dispose() {
+
+ IEditorInput input= getEditorInput();
+ if (input instanceof IPropertyChangeNotifier)
+ ((IPropertyChangeNotifier)input).removePropertyChangeListener(this);
+
+ super.dispose();
+ }
+
+ /*
+ * @see IDesktopPart#setFocus
+ */
+ public void setFocus() {
+ IEditorInput input= getEditorInput();
+ if (input instanceof CompareEditorInput)
+ ((CompareEditorInput)input).setFocus();
+ }
+
+ /**
+ * Returns false because the editor doesn't support "Save As...".
+ */
+ public boolean isSaveAsAllowed() {
+ return false;
+ }
+
+ public void gotoMarker(IMarker marker) {
+ }
+
+ /**
+ * Always throws an AssertionFailedException.
+ */
+ /*
+ * @see IEditorPart#doSaveAs()
+ */
+ public void doSaveAs() {
+ Assert.isTrue(false, "Save As not supported for CompareEditor");
+ }
+
+ /*
+ * @see IEditorPart#doSave()
+ */
+ public void doSave(IProgressMonitor progressMonitor) {
+
+ final IEditorInput input= getEditorInput();
+
+ WorkspaceModifyOperation operation= new WorkspaceModifyOperation() {
+ public void execute(IProgressMonitor pm) throws CoreException {
+ if (input instanceof CompareEditorInput)
+ ((CompareEditorInput)input).save(pm);
+ }
+ };
+
+ Shell shell= getSite().getWorkbenchWindow().getShell();
+
+ try {
+
+ operation.run(progressMonitor);
+
+ firePropertyChange(PROP_DIRTY);
+
+
+ } catch (InterruptedException x) {
+ } catch (OperationCanceledException x) {
+ } catch (InvocationTargetException x) {
+ //String title= getResourceString("Error.save.title");
+ //String msg= getResourceString("Error.save.message");
+ String title= "Save Error";
+ String msg= "Can't save ";
+ MessageDialog.openError(shell, title, msg + x.getTargetException().getMessage());
+ }
+ }
+
+ /*
+ * @see IEditorPart#isDirty()
+ */
+ public boolean isDirty() {
+ IEditorInput input= getEditorInput();
+ if (input instanceof CompareEditorInput)
+ return ((CompareEditorInput)input).isSaveNeeded();
+ return false;
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ if (isDirty())
+ firePropertyChange(PROP_DIRTY);
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditorContributor.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditorContributor.java
new file mode 100644
index 000000000..be21b8ab3
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareEditorContributor.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.part.EditorActionBarContributor;
+
+import org.eclipse.compare.*;
+
+
+public class CompareEditorContributor extends EditorActionBarContributor {
+
+ private IgnoreWhiteSpaceAction fIgnoreWhitespace;
+ private ShowPseudoConflicts fShowPseudoConflicts;
+
+
+ public CompareEditorContributor() {
+ ResourceBundle bundle= CompareUIPlugin.getResourceBundle();
+ fIgnoreWhitespace= new IgnoreWhiteSpaceAction(bundle, null);
+ fShowPseudoConflicts= new ShowPseudoConflicts(bundle, null);
+ }
+
+ public void contributeToToolBar(IToolBarManager tbm) {
+ tbm.add(new Separator());
+ tbm.add(fIgnoreWhitespace);
+ tbm.add(fShowPseudoConflicts);
+ }
+
+ public void setActiveEditor(IEditorPart targetEditor) {
+ if (targetEditor instanceof CompareEditor) {
+ CompareConfiguration cc= ((CompareEditor) targetEditor).getCompareConfiguration();
+ fIgnoreWhitespace.setCompareConfiguration(cc);
+ fShowPseudoConflicts.setCompareConfiguration(cc);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePluginResources.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePluginResources.properties
new file mode 100644
index 000000000..7c77fdb76
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ComparePluginResources.properties
@@ -0,0 +1,35 @@
+# =====================================
+# Licensed Materials - Property of IBM,
+# WebSphere Studio Workbench
+# (c) Copyright IBM Corp 1999-2001
+# =====================================
+# @(#)ComparePluginResources.properties
+#
+# Resource strings for Compare Plugin
+
+#####################################################
+# Actions
+#####################################################
+
+action.IgnoreWhiteSpace.label=Ignore White Space
+action.IgnoreWhiteSpace.tooltip=Ignore white space where applicable
+action.IgnoreWhiteSpace.image=ctool16/ignorews.gif
+
+action.ShowPseudoConflicts.label=Show Pseudo Conflicts
+action.ShowPseudoConflicts.tooltip=Show pseudo conflicts where applicable
+action.ShowPseudoConflicts.image=ctool16/showpseudoconflicts.gif
+
+#action.ToggleMergeDirection.label=Toggle Merge Direction
+#action.ToggleMergeDirection.tooltip=Toggle merge direction
+#action.ToggleMergeDirection.image=ctool16/toggle.gif
+
+#action.NextDiff.label=Next
+#action.NextDiff.tooltip=Show Next Difference
+#action.NextDiff.image=ctool16/next.gif
+
+#action.PrevDiff.label=Previous
+#action.PrevDiff.tooltip=Show Previous Difference
+#action.PrevDiff.image=ctool16/prev.gif
+
+
+
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
new file mode 100644
index 000000000..696dfca4c
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareUIPlugin.java
@@ -0,0 +1,706 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.util.Assert;
+
+import org.eclipse.ui.internal.SharedImages;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+import org.eclipse.ui.*;
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+/**
+ * The Compare UI plug-in defines the entry point to initiate a configurable
+ * compare operation on arbitrary resources. The result of the compare
+ * is opened into a compare editor where the details can be browsed and
+ * edited in dynamically selected structure and content viewers.
+ * <p>
+ * The Compare UI provides a registry for content and structure compare viewers,
+ * which is initialized from extensions contributed to extension points
+ * declared by this plug-in.
+ * <p>
+ * This class is the plug-in runtime class for the
+ * <code>"org.eclipse.compare"</code> plug-in.
+ * </p>
+ */
+public final class CompareUIPlugin extends AbstractUIPlugin {
+
+ private static boolean NORMALIZE_CASE= true;
+
+ private final static String CLASS_ATTRIBUTE= "class";
+ private final static String EXTENSIONS_ATTRIBUTE= "extensions";
+
+ private static final String RESOURCE_BUNDLE= "org.eclipse.compare.internal.ComparePluginResources";
+
+ private static final String PLUGIN_ID= "org.eclipse.compare";
+
+ private static final String STRUCTURE_CREATOR_EXTENSION_POINT= "structureCreators";
+ private static final String STRUCTURE_MERGEVIEWER_EXTENSION_POINT= "structureMergeViewers";
+ private static final String CONTENT_MERGEVIEWER_EXTENSION_POINT= "contentMergeViewers";
+ private static final String CONTENT_VIEWER_EXTENSION_POINT= "contentViewers";
+
+ private static final String COMPARE_EDITOR= "org.eclipse.compare.CompareEditor";
+
+ private static final String COMPARE_FAILED= "Compare failed";
+ private static final String PROBLEMS_OPENING_EDITOR= "Problems Opening Editor";
+
+ /** Maps type to icons */
+ private static Map fgImages= new Hashtable(10);
+ /** Maps type to ImageDescriptors */
+ private static Map fgImageDescriptors= new Hashtable(10);
+ /** Maps ImageDescriptors to Images */
+ private static Map fgImages2= new Hashtable(10);
+
+ private static Map fgStructureCreators= new Hashtable(10);
+ private static Map fgStructureViewerDescriptors= new Hashtable(10);
+ private static Map fgContentViewerDescriptors= new Hashtable(10);
+ private static Map fgContentMergeViewerDescriptors= new Hashtable(10);
+
+ private static List fgDisposeOnShutdownImages= new ArrayList();
+
+ private static ResourceBundle fgResourceBundle;
+
+ private static CompareUIPlugin fgComparePlugin;
+
+ /**
+ * Creates the <code>CompareUIPlugin</code> object and registers all
+ * structure creators, content merge viewers, and structure merge viewers
+ * contributed to this plug-in's extension points.
+ * <p>
+ * Note that instances of plug-in runtime classes are automatically created
+ * by the platform in the course of plug-in activation.
+ * </p>
+ *
+ * @param descriptor the plug-in descriptor
+ */
+ public CompareUIPlugin(IPluginDescriptor descriptor) {
+ super(descriptor);
+
+ fgComparePlugin= this;
+
+ registerExtensions();
+ }
+
+ /**
+ * Registers all structure creators, content merge viewers, and structure merge viewers
+ * that are found in the XML plugin files.
+ */
+ private void registerExtensions() {
+ IPluginRegistry registry= Platform.getPluginRegistry();
+
+ // collect all IStructureCreators
+ IConfigurationElement[] elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_CREATOR_EXTENSION_POINT);
+ for (int i= 0; i < elements.length; i++) {
+ final IConfigurationElement conf= elements[i];
+ String extensions= conf.getAttribute(EXTENSIONS_ATTRIBUTE);
+ registerStructureCreator(extensions,
+ new IStructureCreatorDescriptor() {
+ public IStructureCreator createStructureCreator() {
+ try {
+ return (IStructureCreator) conf.createExecutableExtension(CLASS_ATTRIBUTE);
+ } catch (CoreException ex) {
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ // collect all viewers which define the structure mergeviewer extension point
+ elements= registry.getConfigurationElementsFor(PLUGIN_ID, STRUCTURE_MERGEVIEWER_EXTENSION_POINT);
+ for (int i= 0; i < elements.length; i++) {
+ ViewerDescriptor desc= new ViewerDescriptor(elements[i]);
+ String ext= desc.getExtension();
+ if (ext != null)
+ registerStructureViewerDescriptor(desc.getExtension(), desc);
+ }
+
+ // collect all viewers which define the content mergeviewer extension point
+ elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_MERGEVIEWER_EXTENSION_POINT);
+ for (int i= 0; i < elements.length; i++) {
+ ViewerDescriptor desc= new ViewerDescriptor(elements[i]);
+ String ext= desc.getExtension();
+ if (ext != null)
+ registerContentMergeViewerDescriptor(desc.getExtension(), desc);
+ }
+
+ // collect all viewers which define the content viewer extension point
+ elements= registry.getConfigurationElementsFor(PLUGIN_ID, CONTENT_VIEWER_EXTENSION_POINT);
+ for (int i= 0; i < elements.length; i++) {
+ ViewerDescriptor desc= new ViewerDescriptor(elements[i]);
+ String ext= desc.getExtension();
+ if (ext != null)
+ registerContentViewerDescriptor(desc.getExtension(), desc);
+ }
+ }
+
+ /**
+ * Returns the singleton instance of this plug-in runtime class.
+ *
+ * @return the compare plug-in instance
+ */
+ public static CompareUIPlugin getDefault() {
+ return fgComparePlugin;
+ }
+
+ /**
+ * Returns this plug-in's resource bundle.
+ *
+ * @return the plugin's resource bundle
+ */
+ public static ResourceBundle getResourceBundle() {
+ if (fgResourceBundle == null)
+ fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
+ return fgResourceBundle;
+ }
+
+ /**
+ * Returns the active workkbench page or <code>null</code> if
+ * no active workkbench page can be determined.
+ *
+ * @return the active workkbench page or <code>null</code> if
+ * no active workkbench page can be determined
+ */
+ private static IWorkbenchPage getActivePage() {
+ CompareUIPlugin plugin= getDefault();
+ if (plugin == null)
+ return null;
+ IWorkbench workbench= plugin.getWorkbench();
+ if (workbench == null)
+ return null;
+ IWorkbenchWindow window= workbench.getActiveWorkbenchWindow();
+ if (window == null)
+ return null;
+ return window.getActivePage();
+ }
+
+ /**
+ * Returns the SWT Shell of the active workbench window or <code>null</code> if
+ * no workbench window is active.
+ *
+ * @return the SWT Shell of the active workbench window, or <code>null</code> if
+ * no workbench window is active
+ */
+ public static Shell getShell() {
+ CompareUIPlugin p= getDefault();
+ if (p == null)
+ return null;
+ IWorkbench wb= p.getWorkbench();
+ if (wb == null)
+ return null;
+ IWorkbenchWindow ww= wb.getActiveWorkbenchWindow();
+ if (ww == null)
+ return null;
+ return ww.getShell();
+ }
+
+ /**
+ * Registers the given image for being disposed when this plug-in is shutdown.
+ *
+ * @param image the image to register for disposal
+ */
+ public static void disposeOnShutdown(Image image) {
+ if (image != null)
+ fgDisposeOnShutdownImages.add(image);
+ }
+
+ /* (non-Javadoc)
+ * Method declared on Plugin.
+ * Frees all resources of the compare plug-in.
+ */
+ public void shutdown() throws CoreException {
+ super.shutdown();
+
+ if (fgDisposeOnShutdownImages != null) {
+ Iterator i= fgDisposeOnShutdownImages.iterator();
+ while (i.hasNext()) {
+ Image img= (Image) i.next();
+ if (!img.isDisposed())
+ img.dispose();
+ }
+ fgImages= null;
+ }
+ }
+
+ /**
+ * Performs the comparison described by the given input and opens a
+ * compare editor on the result.
+ *
+ * @param input the input on which to open the compare editor
+ * @see ICompareEditorInput
+ */
+ public void openCompareEditor(CompareEditorInput input) {
+
+ if (compareResultOK(input)) {
+ IWorkbenchPage activePage= getActivePage();
+ if (activePage != null) {
+ try {
+ activePage.openEditor(input, COMPARE_EDITOR);
+ } catch (PartInitException e) {
+ MessageDialog.openError(getShell(), PROBLEMS_OPENING_EDITOR, e.getMessage());
+ }
+ } else {
+ MessageDialog.openError(getShell(), PROBLEMS_OPENING_EDITOR, "Can't find active workbench page");
+ }
+ }
+ }
+
+ /**
+ * Performs the comparison described by the given input and opens a
+ * compare dialog on the result.
+ *
+ * @param input the input on which to open the compare editor
+ * @see ICompareEditorInput
+ */
+ public void openCompareDialog(final CompareEditorInput input) {
+
+ if (compareResultOK(input)) {
+ CompareDialog dialog= new CompareDialog(getShell(), input);
+ dialog.open();
+ }
+ }
+
+ /**
+ * @return <code>true</code> if compare result is OK to show, <code>false</code> otherwise
+ */
+ private boolean compareResultOK(CompareEditorInput input) {
+ final Shell shell= getShell();
+ try {
+
+ // run operation in separate thread and make it canceable
+ new ProgressMonitorDialog(shell).run(true, true, input);
+
+ String message= input.getMessage();
+ if (message != null) {
+ MessageDialog.openError(shell, COMPARE_FAILED, message);
+ return false;
+ }
+
+ if (input.getCompareResult() == null) {
+ MessageDialog.openInformation(shell, COMPARE_FAILED, "There are no differences between the selected inputs");
+ return false;
+ }
+
+ return true;
+
+ } catch (InterruptedException x) {
+ // cancelled by user
+ } catch (InvocationTargetException x) {
+ MessageDialog.openError(shell, COMPARE_FAILED, x.getTargetException().getMessage());
+ }
+ return false;
+ }
+
+ /**
+ * Registers an image for the given type.
+ */
+ private static void registerImage(String type, Image image, boolean dispose) {
+ fgImages.put(normalizeCase(type), image);
+ if (image != null && dispose) {
+ fgDisposeOnShutdownImages.add(image);
+ }
+ }
+
+ /**
+ * Registers an image descriptor for the given type.
+ *
+ * @param type the type
+ * @param descriptor the image descriptor
+ */
+ public static void registerImageDescriptor(String type, ImageDescriptor descriptor) {
+ fgImageDescriptors.put(normalizeCase(type), descriptor);
+ }
+
+ public static ImageDescriptor getImageDescriptor(String relativePath) {
+
+ URL installURL= null;
+ if (fgComparePlugin != null)
+ installURL= fgComparePlugin.getDescriptor().getInstallURL();
+
+ if (installURL != null) {
+ try {
+ URL url= new URL(installURL, "icons/basic/" + relativePath);
+ return ImageDescriptor.createFromURL(url);
+ } catch (MalformedURLException e) {
+ Assert.isTrue(false);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a shared image for the given type, or a generic image if none
+ * has been registered for the given type.
+ * <p>
+ * Note: Images returned from this method will be automitically disposed
+ * of when this plug-in shuts down. Callers must not dispose of these
+ * images themselves.
+ * </p>
+ *
+ * @param type the type
+ * @return the image
+ */
+ public static Image getImage(String type) {
+
+ type= normalizeCase(type);
+
+ boolean dispose= false;
+ Image image= null;
+ if (type != null)
+ image= (Image) fgImages.get(type);
+ if (image == null) {
+ ImageDescriptor id= (ImageDescriptor) fgImageDescriptors.get(type);
+ if (id != null) {
+ image= id.createImage();
+ dispose= true;
+ }
+
+ if (image == null) {
+ if (fgComparePlugin != null) {
+ if (ITypedElement.FOLDER_TYPE.equals(type)) {
+ image= getDefault().getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+ //image= SharedImages.getImage(ISharedImages.IMG_OBJ_FOLDER);
+ } else {
+ image= createWorkbenchImage(type);
+ dispose= true;
+ }
+ } else {
+ id= (ImageDescriptor) fgImageDescriptors.get(normalizeCase("file"));
+ image= id.createImage();
+ dispose= true;
+ }
+ }
+ if (image != null)
+ registerImage(type, image, dispose);
+ }
+ return image;
+ }
+
+ /**
+ * Returns a shared image for the given adaptable.
+ * This convenience method queries the given adaptable
+ * for its <code>IWorkbenchAdapter.getImageDescriptor</code>, which it
+ * uses to create an image if it does not already have one.
+ * <p>
+ * Note: Images returned from this method will be automitically disposed
+ * of when this plug-in shuts down. Callers must not dispose of these
+ * images themselves.
+ * </p>
+ *
+ * @param adaptable the adaptable for which to find an image
+ * @return an image
+ */
+ public static Image getImage(IAdaptable adaptable) {
+ if (adaptable != null) {
+ Object o= adaptable.getAdapter(IWorkbenchAdapter.class);
+ if (o instanceof IWorkbenchAdapter) {
+ ImageDescriptor id= ((IWorkbenchAdapter) o).getImageDescriptor(adaptable);
+ if (id != null) {
+ Image image= (Image)fgImages2.get(id);
+ if (image == null) {
+ image= id.createImage();
+ try {
+ fgImages2.put(id, image);
+ } catch (NullPointerException ex) {
+ System.out.println("NPE in CompareUIPlugin.getImage");
+ }
+ fgDisposeOnShutdownImages.add(image);
+
+ }
+ return image;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Image createWorkbenchImage(String type) {
+ IEditorRegistry er= getDefault().getWorkbench().getEditorRegistry();
+ ImageDescriptor id= er.getImageDescriptor("foo." + type);
+ return id.createImage();
+ }
+
+ /**
+ * Registers the given structure creator descriptor for one or more types.
+ *
+ * @param types one or more types separated by commas and whitespace
+ * @param descriptor the descriptor to register
+ */
+ public static void registerStructureCreator(String types, IStructureCreatorDescriptor descriptor) {
+ if (types != null) {
+ StringTokenizer tokenizer= new StringTokenizer(types, ",");
+ while (tokenizer.hasMoreElements()) {
+ String extension= tokenizer.nextToken().trim();
+ fgStructureCreators.put(normalizeCase(extension), descriptor);
+ }
+ }
+ }
+
+ /**
+ * Returns an structure creator descriptor for the given type.
+ *
+ * @param type the type for which to find a descriptor
+ * @return a descriptor for the given type, or <code>null</code> if no
+ * descriptor has been registered
+ */
+ public static IStructureCreatorDescriptor getStructureCreator(String type) {
+ return (IStructureCreatorDescriptor) fgStructureCreators.get(normalizeCase(type));
+ }
+
+ /**
+ * Registers the given structure viewer descriptor for one or more types.
+ *
+ * @param types one or more types separated by commas and whitespace
+ * @param the descriptor to register
+ */
+ public static void registerStructureViewerDescriptor(String types, IViewerDescriptor descriptor) {
+ StringTokenizer tokenizer= new StringTokenizer(types, ",");
+ while (tokenizer.hasMoreElements()) {
+ String extension= tokenizer.nextToken().trim();
+ fgStructureViewerDescriptors.put(normalizeCase(extension), descriptor);
+ }
+ }
+
+ /**
+ * Registers the given content merge viewer descriptor for one or more types.
+ *
+ * @param types one or more types separated by commas and whitespace
+ * @param descriptor the descriptor to register
+ */
+ public static void registerContentMergeViewerDescriptor(String types, IViewerDescriptor descriptor) {
+ StringTokenizer tokenizer= new StringTokenizer(types, ",");
+ while (tokenizer.hasMoreElements()) {
+ String extension= tokenizer.nextToken().trim();
+ fgContentMergeViewerDescriptors.put(normalizeCase(extension), descriptor);
+ }
+ }
+
+ /**
+ * Registers the given content viewer descriptor for one or more types.
+ *
+ * @param types one or more types separated by commas and whitespace
+ * @param descriptor the descriptor to register
+ */
+ public static void registerContentViewerDescriptor(String types, IViewerDescriptor descriptor) {
+ StringTokenizer tokenizer= new StringTokenizer(types, ",");
+ while (tokenizer.hasMoreElements()) {
+ String extension= tokenizer.nextToken().trim();
+ fgContentViewerDescriptors.put(normalizeCase(extension), descriptor);
+ }
+ }
+
+ /**
+ * Returns a structure compare viewer based on an old viewer and an input object.
+ * If the old viewer is suitable for showing the input, the old viewer
+ * is returned. Otherwise, the input's type is used to find a viewer descriptor in the registry
+ * which in turn is used to create a structure compare viewer under the given parent composite.
+ * If no viewer descriptor can be found <code>null</code> is returned.
+ *
+ * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
+ * @param input the input object for which to find a structure viewer
+ * @param parent the SWT parent composite under which the new viewer is created
+ * @param configuration a configuration which is passed to a newly created viewer
+ * @return the compare viewer which is suitable for the given input object or <code>null</code>
+ */
+ public static Viewer findStructureViewer(Viewer oldViewer, ICompareInput input, Composite parent,
+ CompareConfiguration configuration) {
+
+ if (input.getLeft() == null || input.getRight() == null) // we don't show the structure of additions or deletions
+ return null;
+
+ String type= getType(input);
+ if (type == null)
+ return null;
+
+ type= normalizeCase(type);
+
+ IViewerDescriptor vd= (IViewerDescriptor) fgStructureViewerDescriptors.get(type);
+ if (vd != null)
+ return vd.createViewer(oldViewer, parent, configuration);
+
+ IStructureCreatorDescriptor scc= getStructureCreator(type);
+ if (scc != null) {
+ IStructureCreator sc= scc.createStructureCreator();
+ if (sc != null) {
+ StructureDiffViewer sdv= new StructureDiffViewer(parent, configuration);
+ sdv.setStructureCreator(sc);
+ return sdv;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a content compare viewer based on an old viewer and an input object.
+ * If the old viewer is suitable for showing the input the old viewer
+ * is returned. Otherwise the input's type is used to find a viewer descriptor in the registry
+ * which in turn is used to create a content compare viewer under the given parent composite.
+ * If no viewer descriptor can be found <code>null</code> is returned.
+ *
+ * @param oldViewer a new viewer is only created if this old viewer cannot show the given input
+ * @param input the input object for which to find a content viewer
+ * @param parent the SWT parent composite under which the new viewer is created
+ * @param configuration a configuration which is passed to a newly created viewer
+ * @return the compare viewer which is suitable for the given input object or <code>null</code>
+ */
+ public static Viewer findContentViewer(Viewer oldViewer, Object in, Composite parent, CompareConfiguration cc) {
+
+ if (! (in instanceof ICompareInput)) {
+ String type= ITypedElement.TEXT_TYPE;
+ if (in instanceof ITypedElement) {
+ ITypedElement tin= (ITypedElement) in;
+ type= tin.getType();
+ }
+ type= normalizeCase(type);
+
+ IViewerDescriptor vd= (IViewerDescriptor) fgContentViewerDescriptors.get(type);
+ Viewer viewer= null;
+ if (vd != null) {
+ viewer= vd.createViewer(oldViewer, parent, cc);
+ if (viewer != null)
+ return viewer;
+ }
+ // fallback
+ return new TextViewer(parent);
+ }
+
+ ICompareInput input= (ICompareInput) in;
+ String type= getType(input);
+ type= normalizeCase(type);
+
+ if (ITypedElement.FOLDER_TYPE.equals(type))
+ return null;
+
+ if (type != null) {
+ IViewerDescriptor vd= (IViewerDescriptor) fgContentMergeViewerDescriptors.get(type);
+ Viewer viewer= null;
+ if (vd != null) {
+ viewer= vd.createViewer(oldViewer, parent, cc);
+ if (viewer != null)
+ return viewer;
+ }
+ }
+
+ // fallback
+ String leftType= guessType(input.getLeft());
+ String rightType= guessType(input.getRight());
+
+ if (leftType != null && rightType != null) {
+ if (ITypedElement.TEXT_TYPE.equals(leftType) && ITypedElement.TEXT_TYPE.equals(rightType))
+ type= ITypedElement.TEXT_TYPE;
+ else
+ type= "binary";
+
+ IViewerDescriptor vd= (IViewerDescriptor) fgContentMergeViewerDescriptors.get(normalizeCase(type));
+ if (vd != null)
+ return vd.createViewer(oldViewer, parent, cc);
+ }
+ return null;
+ }
+
+ /**
+ * Determines the type of the given threeway input by analyzing
+ * the types (file extension) of the individual parts.
+ * Returns null if no type can be determined.
+ */
+ private static String getType(ICompareInput input) {
+ ITypedElement ancestor= input.getAncestor();
+ ITypedElement left= input.getLeft();
+ ITypedElement right= input.getRight();
+
+ String[] types= new String[3];
+ int cnt= 0;
+
+ if (ancestor != null) {
+ String type= ancestor.getType();
+ if (type != null)
+ types[cnt++]= type;
+ }
+ if (left != null) {
+ String type= left.getType();
+ if (type != null)
+ types[cnt++]= type;
+ }
+ if (right != null) {
+ String type= right.getType();
+ if (type != null)
+ types[cnt++]= type;
+ }
+ boolean homogenous= false;
+ switch (cnt) {
+ case 1:
+ homogenous= true;
+ break;
+ case 2:
+ homogenous= types[0].equals(types[1]);
+ break;
+ case 3:
+ homogenous= types[0].equals(types[1]) && types[1].equals(types[2]);
+ break;
+ }
+ if (homogenous)
+ return types[0];
+ return null;
+ }
+
+ /**
+ * Guesses the file type of the given input.
+ * Returns ITypedElement.TEXT_TYPE if the first 1000 bytes contain only values in the range 0-127.
+ * Returns ITypedElement.UNKNOWN_TYPE if a single byte is out of this range.
+ * Returns <code>null</code> if the input isn't an <code>IStreamContentAccessor</code>.
+ */
+ private static String guessType(ITypedElement input) {
+ if (input instanceof IStreamContentAccessor) {
+ IStreamContentAccessor sca= (IStreamContentAccessor) input;
+ try {
+ InputStream is= sca.getContents();
+ if (is == null)
+ return null;
+ for (int i= 0; i < 1000; i++)
+ if (is.read() >= 128)
+ return ITypedElement.UNKNOWN_TYPE;
+ return ITypedElement.TEXT_TYPE;
+ } catch (CoreException ex) {
+ // be silent and return UNKNOWN_TYPE
+ } catch (IOException ex) {
+ // be silent and return UNKNOWN_TYPE
+ }
+ return ITypedElement.UNKNOWN_TYPE;
+ }
+ return null;
+ }
+
+ private static IViewerDescriptor getContentViewerDescriptor2(String type) {
+ return (IViewerDescriptor) fgContentMergeViewerDescriptors.get(normalizeCase(type));
+ }
+
+ private static String normalizeCase(String s) {
+ if (NORMALIZE_CASE && s != null)
+ return s.toUpperCase();
+ return s;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareViewerSwitchingPane.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareViewerSwitchingPane.java
new file mode 100644
index 000000000..62d9d55bf
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/CompareViewerSwitchingPane.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.*;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.util.ListenerList;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.ICompareInput;
+import org.eclipse.compare.contentmergeviewer.ContentMergeViewer;
+import org.eclipse.compare.structuremergeviewer.DiffTreeViewer;
+
+
+/**
+ * A custom <code>Pane</code> which supports viewer switching.
+ * <p>
+ * If a property with the name CompareUI.COMPARE_VIEWER_TITLE is set
+ * on the top level SWT control of a viewer, it is used as a title in the pane's
+ * title bar.
+ */
+public abstract class CompareViewerSwitchingPane extends Pane
+ implements ISelectionChangedListener, ISelectionProvider, IDoubleClickListener {
+
+ /**
+ * Used whenever the input is null or no viewer can be found.
+ */
+ private static class NullViewer extends AbstractViewer {
+
+ private Control fDummy;
+
+ public NullViewer(Composite parent) {
+
+ fDummy= new Tree(parent, SWT.NULL);
+
+ CompareViewerSwitchingPane.clearToolBar(parent);
+ }
+
+ public Control getControl() {
+ return fDummy;
+ }
+ }
+
+ private Viewer fViewer;
+ private Object fInput;
+ private ListenerList fSelectionListeners= new ListenerList();
+ private ListenerList fOpenListeners= new ListenerList();
+ private boolean fControlVisibility= false;
+
+ /**
+ * Creates a ViewerPane as a child of the given parent and with the
+ * specified SWT style bits.
+ */
+ public CompareViewerSwitchingPane(Composite parent, int style) {
+ this(parent, style, false);
+ }
+
+ /**
+ * Creates a ViewerPane as a child of the given parent and with the
+ * specified SWT style bits.
+ */
+ public CompareViewerSwitchingPane(Composite parent, int style, boolean visibility) {
+ super(parent, style);
+
+ fControlVisibility= visibility;
+
+ setViewer(new NullViewer(this));
+
+ addDisposeListener(
+ new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if (fViewer instanceof ISelectionProvider)
+ ((ISelectionProvider) fViewer).removeSelectionChangedListener(CompareViewerSwitchingPane.this);
+ if (fViewer instanceof StructuredViewer)
+ ((StructuredViewer) fViewer).removeDoubleClickListener(CompareViewerSwitchingPane.this);
+ fViewer= null;
+ fInput= null;
+ fSelectionListeners= null;
+ }
+ }
+ );
+ }
+
+ /**
+ * Returns the current viewer.
+ */
+ public Viewer getViewer() {
+ return fViewer;
+ }
+
+ /**
+ * Sets the current viewer.
+ */
+ private void setViewer(Viewer newViewer) {
+
+ if (newViewer == fViewer)
+ return;
+
+ boolean oldEmpty= isEmpty();
+
+ if (fViewer != null) {
+
+ if (fViewer instanceof ISelectionProvider)
+ ((ISelectionProvider) fViewer).removeSelectionChangedListener(this);
+
+ if (fViewer instanceof StructuredViewer)
+ ((StructuredViewer)fViewer).removeDoubleClickListener(this);
+
+ Control content= getContent();
+ setContent(null);
+
+ fViewer.setInput(null);
+
+ if (content != null && !content.isDisposed()) {
+ content.dispose();
+ }
+ } else
+ oldEmpty= false;
+ setContent(null);
+
+ fViewer= newViewer;
+
+ if (fViewer != null) {
+ // workaround: setContent changes the visibility of the CustomPane
+ boolean old= getVisible();
+ setContent(fViewer.getControl());
+ setVisible(old);
+ // end of workaround
+
+ boolean newEmpty= isEmpty();
+
+ if (fViewer instanceof ISelectionProvider)
+ ((ISelectionProvider) fViewer).addSelectionChangedListener(this);
+ if (fViewer instanceof StructuredViewer)
+ ((StructuredViewer)fViewer).addDoubleClickListener(this);
+
+ if (oldEmpty != newEmpty) {// relayout my container
+ Composite parent= getParent();
+ if (parent instanceof Splitter)
+ ((Splitter)parent).setVisible(this, fControlVisibility ? !newEmpty : true);
+ //else
+ // parent.layout(true);
+ }
+
+ //else if (!newEmpty)// otherwise just relayout myself
+ layout(true);
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if no viewer is installed or if the current viewer
+ * is a <code>NullViewer</code>.
+ */
+ public boolean isEmpty() {
+ return fViewer == null || fViewer instanceof NullViewer;
+ }
+
+ public void addSelectionChangedListener(ISelectionChangedListener l) {
+ fSelectionListeners.add(l);
+ }
+
+ public void removeSelectionChangedListener(ISelectionChangedListener l) {
+ fSelectionListeners.remove(l);
+ }
+
+ public void addDoubleClickListener(IDoubleClickListener l) {
+ fOpenListeners.add(l);
+ }
+
+ public void removeDoubleClickListener(IDoubleClickListener l) {
+ fOpenListeners.remove(l);
+ }
+
+ public void doubleClick(DoubleClickEvent event) {
+ Object[] listeners= fOpenListeners.getListeners();
+ for (int i= 0; i < listeners.length; i++)
+ ((IDoubleClickListener) listeners[i]).doubleClick(event);
+ }
+
+ public ISelection getSelection() {
+ if (fViewer instanceof ISelectionProvider)
+ return ((ISelectionProvider) fViewer).getSelection();
+ return null;
+ }
+
+ public void setSelection(ISelection s) {
+ if (fViewer instanceof ISelectionProvider)
+ ((ISelectionProvider) fViewer).setSelection(s);
+ }
+
+ public void selectionChanged(SelectionChangedEvent ev) {
+ Object[] listeners= fSelectionListeners.getListeners();
+ for (int i= 0; i < listeners.length; i++)
+ ((ISelectionChangedListener) listeners[i]).selectionChanged(ev);
+ }
+
+ public void setInput(Object input) {
+
+ if (fInput == input)
+ return;
+
+ fInput= input;
+
+ // viewer switching
+ Viewer newViewer= null;
+ if (input != null)
+ newViewer= getViewer(fViewer, input);
+
+ if (newViewer == null) {
+ if (fViewer instanceof NullViewer)
+ return;
+ newViewer= new NullViewer(this);
+ }
+
+ setViewer(newViewer);
+
+ // set input
+ fViewer.setInput(input);
+
+ Image image= null;
+ if (!(fViewer instanceof NullViewer) && input instanceof ICompareInput)
+ image= ((ICompareInput)input).getImage();
+ setImage(image);
+
+ String title= null;
+ if (fViewer != null) {
+ Control c= fViewer.getControl();
+ if (c != null) {
+ Object data= c.getData(CompareUI.COMPARE_VIEWER_TITLE);
+ if (data instanceof String)
+ title= (String) data;
+ }
+ }
+
+ setText(title != null ? title : "");
+ }
+
+ public Object getInput() {
+ return fInput;
+ }
+
+ abstract protected Viewer getViewer(Viewer oldViewer, Object input);
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DiffImage.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DiffImage.java
new file mode 100644
index 000000000..dce0ae6b9
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DiffImage.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.graphics.*;
+
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ * Combines an image with an overlay.
+ */
+public class DiffImage extends CompositeImageDescriptor {
+
+ static final int HEIGHT= 16;
+
+ private Image fBaseImage;
+ private ImageDescriptor fOverlayImage;
+ private int fWidth;
+
+ public DiffImage(Image base, ImageDescriptor overlay, int w) {
+ fBaseImage= base;
+ fOverlayImage= overlay;
+ fWidth= w;
+ }
+
+ protected Point getSize() {
+ return new Point(fWidth, HEIGHT);
+ }
+
+ protected void drawCompositeImage(int width, int height) {
+
+ if (fBaseImage != null) {
+ ImageData base= fBaseImage.getImageData();
+ if (base == null)
+ base= DEFAULT_IMAGE_DATA;
+ try {
+ drawImage(base, fWidth - base.width, 0);
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ // workaround for PR 1GCQKWP
+ }
+ }
+
+ if (fOverlayImage != null) {
+ ImageData dir= fOverlayImage.getImageData();
+ if (dir == null)
+ dir= DEFAULT_IMAGE_DATA;
+ drawImage(dir, 0, (HEIGHT - dir.height) / 2);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DocLineComparator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DocLineComparator.java
new file mode 100644
index 000000000..81591752b
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/DocLineComparator.java
@@ -0,0 +1,216 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWTError;
+import org.eclipse.jface.text.*;
+import org.eclipse.compare.rangedifferencer.IRangeComparator;
+import org.eclipse.compare.contentmergeviewer.ITokenComparator;
+
+/**
+ * Implements the <code>ITokenComparator</code> interface for lines in a document.
+ * A <code>DocLineComparator</code> is used as the input for the <code>RangeDifferencer</code>
+ * engine to perform a line oriented compare on documents.
+ * <p>
+ * A <code>DocLineComparator</code> doesn't know anything about line separators because
+ * its notion of lines is solely defined in the underlying <code>IDocument</code>.
+ */
+public class DocLineComparator implements IRangeComparator {
+
+ private IDocument fDocument;
+ private int fLineOffset;
+ private int fLineCount;
+ private int fLength;
+ private boolean fIgnoreWhiteSpace;
+
+ /**
+ * Creates a <code>DocLineComparator</code> for the given document range.
+ * ignoreWhiteSpace controls whether comparing lines (in method
+ * <code>rangesEqual<code>) should ignore whitespace.
+ *
+ * @param document the document from which the lines are taken
+ * @param region if non-<code>null</code> only lines within this range are taken
+ * @param ignoreWhiteSpace if <code>true</code> white space is ignored when comparing lines
+ */
+ public DocLineComparator(IDocument document, IRegion region, boolean ignoreWhiteSpace) {
+
+ fDocument= document;
+ fIgnoreWhiteSpace= ignoreWhiteSpace;
+
+ fLineOffset= 0;
+ if (region != null) {
+ fLength= region.getLength();
+ int start= region.getOffset();
+ try {
+ fLineOffset= fDocument.getLineOfOffset(start);
+ } catch (BadLocationException ex) {
+ }
+
+ if (fLength == 0)
+ fLineCount= 0;
+ else {
+ int endLine= fDocument.getNumberOfLines();
+ try {
+ endLine= fDocument.getLineOfOffset(start + fLength);
+ } catch (BadLocationException ex) {
+ }
+ fLineCount= endLine - fLineOffset + 1;
+ }
+
+ } else {
+ fLength= document.getLength();
+ fLineCount= fDocument.getNumberOfLines();
+ }
+ }
+
+ /**
+ * Returns the content of lines in the specified range as a String.
+ * This includes the line separators.
+ *
+ * @param start index of first line
+ * @param length number of lines
+ * @return the contents of the specified line range as a String
+ */
+ public String extract(int start, int length) {
+ if (fLength > 0) {
+ if (fLength == 1)
+ return extract(start);
+ int startPos= getTokenStart(start);
+ int endPos= getTokenStart(start + length);
+ try {
+ return fDocument.get(startPos, endPos - startPos);
+ } catch (BadLocationException e) {
+ System.out.println("extract("+fDocument.getLength()+"): " + startPos + " " + endPos);
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Extract a single line from the underlying document without the line separator.
+ *
+ * @param line the number of the line to extract
+ * @return the contents of the line as a String
+ */
+ public String extract(int line) {
+ line += fLineOffset;
+ if (line < fLength) {
+ try {
+ IRegion r= fDocument.getLineInformation(line);
+ return fDocument.get(r.getOffset(), r.getLength());
+ // return fDocument.getLine(line);
+ } catch(BadLocationException e) {
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Returns the number of lines in the document.
+ *
+ * @return number of lines
+ */
+ public int getRangeCount() {
+ return fLineCount;
+ }
+
+ /**
+ * Returns <code>true</code> if a line given by the first index
+ * matches a line specified by the other <code>IRangeComparator</code> and index.
+ *
+ * @param thisIndex the number of the line within this range comparator
+ * @param other the range comparator to compare this with
+ * @param otherIndex the number of the line within the other comparator
+ * @return <code>true</code> if the lines are equal
+ */
+ public boolean rangesEqual(int thisIndex, IRangeComparator other0, int otherIndex) {
+
+ if (other0 != null && other0.getClass() == getClass()) {
+ DocLineComparator other= (DocLineComparator) other0;
+
+ if (fIgnoreWhiteSpace) {
+ String s1= extract(thisIndex);
+ String s2= other.extract(otherIndex);
+ return compare(s1, s2);
+ }
+
+ int tlen= getTokenLength(thisIndex);
+ int olen= other.getTokenLength(otherIndex);
+ if (tlen == olen) {
+ String s1= extract(thisIndex);
+ String s2= other.extract(otherIndex);
+ return s1.equals(s2);
+ }
+ }
+ return false;
+ }
+
+ /* (non Javadoc)
+ * see IRangeComparator.skipRangeComparison
+ */
+ public boolean skipRangeComparison(int length, int max, IRangeComparator other) {
+ return false;
+ }
+
+ /* (non Javadoc)
+ * see ITokenComparator.getTokenStart
+ */
+ public int getTokenStart(int line) {
+ try {
+ IRegion r= fDocument.getLineInformation(fLineOffset + line);
+ return r.getOffset();
+ //return fDocument.getLineStartOffset(fLineOffset + line);
+ } catch (BadLocationException ex) {
+ return fDocument.getLength();
+ }
+ }
+
+ /* (non Javadoc)
+ * see ITokenComparator.getTokenEnd
+ */
+ public int getTokenEnd(int start, int length) {
+ return getTokenStart(start + length);
+ }
+
+ //---- private methods
+
+ private int getTokenLength(int line) {
+ if (fLength == 0)
+ return 0;
+ return getTokenStart(line + 1) - getTokenStart(line);
+ }
+
+ private boolean compare(String s1, String s2) {
+ int i1= 0;
+ int i2= 0;
+ int l1= s1.length();
+ int l2= s2.length();
+ char c1= ' ';
+ char c2= ' ';
+ while (i1 < l1 || i2 < l2) {
+ if (i1 < l1) {
+ c1= s1.charAt(i1);
+ if (Character.isWhitespace(c1)) {
+ i1++;
+ continue;
+ }
+ }
+ if (i2 < l2) {
+ c2= s2.charAt(i2);
+ if (Character.isWhitespace(c2)) {
+ i2++;
+ continue;
+ }
+ }
+ if (c1 != c2)
+ return false;
+ i1++;
+ i2++;
+ }
+ return true;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IStructureCreatorDescriptor.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IStructureCreatorDescriptor.java
new file mode 100644
index 000000000..cd866e6c1
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IStructureCreatorDescriptor.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.compare.structuremergeviewer.IStructureCreator;
+
+/**
+ * A factory object for creating <code>IStructureCreator</code>s from a descriptor.
+ * <p>
+ * It is used when registering <code>IStructureCreator</code> for types
+ * in <code>CompareUIPlugin.registerStructureCreator</code>.
+ * </p>
+ *
+ * @see IStructureCreator
+ * @see CompareUIPlugin
+ */
+public interface IStructureCreatorDescriptor {
+
+ /**
+ * Creates a new structure creator.
+ *
+ * @return a newly created structure creator
+ */
+ IStructureCreator createStructureCreator();
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IViewerDescriptor.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IViewerDescriptor.java
new file mode 100644
index 000000000..f22578149
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IViewerDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.compare.CompareConfiguration;
+
+/**
+ * A factory object for creating a <code>Viewer</code>s from a descriptor.
+ * <p>
+ * It is used when registering a viewer for a specific type
+ * in <code>CompareUIPlugin.registerContentViewerDescriptor</code> and
+ * in <code>CompareUIPlugin.registerStructureViewerDescriptor</code>.
+ *
+ * @see org.eclipse.compare.structuremergeviewer.IStructureCreator
+ * @see CompareUIPlugin
+ */
+public interface IViewerDescriptor {
+
+ /**
+ * Creates a new viewer from this descriptor under the given STW parent control.
+ * If the current viewer has the same type as a new viewer
+ * the implementation of this method is free to return the current viewer instead.
+ *
+ * @param currentViewer the current viewer which is going to be replaced with a new viewer.
+ * @param parent the SWT parent control under which the new viewer has to be created.
+ * @param config a compare configuration the new viewer might be interested in.
+ * @return a new viewer or the current viewer.
+ */
+ Viewer createViewer(Viewer currentViewer, Composite parent, CompareConfiguration config);
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IgnoreWhiteSpaceAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IgnoreWhiteSpaceAction.java
new file mode 100644
index 000000000..64aed3b09
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/IgnoreWhiteSpaceAction.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.*;
+
+/**
+ * Toggles the <code>ICompareConfiguration.IGNORE_WS</code> property of an
+ * <code>ICompareConfiguration</code>.
+ */
+public class IgnoreWhiteSpaceAction extends ChangePropertyAction {
+
+ public IgnoreWhiteSpaceAction(ResourceBundle bundle, CompareConfiguration cc) {
+ super(bundle, cc, "action.IgnoreWhiteSpace.", CompareConfiguration.IGNORE_WHITESPACE);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageCanvas.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageCanvas.java
new file mode 100644
index 000000000..2d56fc406
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageCanvas.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * A <code>Canvas</code> showing a single centered SWT <code>Image</code>.
+ * If the <code>Image</code> is larger than the <code>Canvas<code>,
+ * <code>Scrollbars</code> will appear.
+ */
+class ImageCanvas extends Canvas {
+
+ private Image fImage;
+
+ /**
+ * Create a new ImageCanvas with the given SWT stylebits.
+ * (SWT.H_SCROLL and SWT.V_SCROLL are automtically added).
+ */
+ public ImageCanvas(Composite parent, int style) {
+ super(parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
+
+ ScrollBar sb= getHorizontalBar();
+ sb.setIncrement(20);
+ sb.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event e) {
+ repaint();
+ }
+ });
+
+ sb= getVerticalBar();
+ sb.setIncrement(20);
+ sb.addListener(SWT.Selection, new Listener() {
+ public void handleEvent(Event e) {
+ repaint();
+ }
+ });
+
+ addListener(SWT.Resize, new Listener() {
+ public void handleEvent(Event e) {
+ updateScrollbars();
+ }
+ });
+
+ addListener(SWT.Paint, new Listener() {
+ public void handleEvent(Event event) {
+ paint(event.gc);
+ }
+ });
+ }
+
+ /**
+ * Set the SWT Image to use as the ImageCanvas contents.
+ */
+ public void setImage(Image img) {
+ fImage= img;
+
+ if (!isDisposed()) {
+ getHorizontalBar().setSelection(0);
+ getVerticalBar().setSelection(0);
+ updateScrollbars();
+ getParent().layout();
+ redraw();
+ }
+ }
+
+ public void repaint() {
+ if (!isDisposed()) {
+ GC gc= new GC(this);
+ paint(gc);
+ gc.dispose();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private void paint(GC gc) {
+ if (fImage != null) {
+ Rectangle bounds= fImage.getBounds();
+ Rectangle clientArea= getClientArea();
+
+ int x;
+ if (bounds.width < clientArea.width)
+ x= (clientArea.width - bounds.width) / 2;
+ else
+ x= -getHorizontalBar().getSelection();
+
+ int y;
+ if (bounds.height < clientArea.height)
+ y= (clientArea.height - bounds.height) / 2;
+ else
+ y= -getVerticalBar().getSelection();
+
+ gc.drawImage(fImage, x, y);
+ }
+ }
+
+ /**
+ * @private
+ */
+ private void updateScrollbars() {
+ Rectangle bounds= fImage != null ? fImage.getBounds() : new Rectangle(0, 0, 0, 0);
+ Point size= getSize();
+ Rectangle clientArea= getClientArea();
+
+ ScrollBar horizontal= getHorizontalBar();
+ if (bounds.width <= clientArea.width) {
+ horizontal.setVisible(false);
+ horizontal.setSelection(0);
+ } else {
+ horizontal.setPageIncrement(clientArea.width - horizontal.getIncrement());
+ int max= bounds.width + (size.x - clientArea.width);
+ horizontal.setMaximum(max);
+ horizontal.setThumb(size.x > max ? max : size.x);
+ horizontal.setVisible(true);
+ }
+
+ ScrollBar vertical= getVerticalBar();
+ if (bounds.height <= clientArea.height) {
+ vertical.setVisible(false);
+ vertical.setSelection(0);
+ } else {
+ vertical.setPageIncrement(clientArea.height - vertical.getIncrement());
+ int max= bounds.height + (size.y - clientArea.height);
+ vertical.setMaximum(max);
+ vertical.setThumb(size.y > max ? max : size.y);
+ vertical.setVisible(true);
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewer.java
new file mode 100644
index 000000000..0114a22c4
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewer.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ResourceBundle;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.contentmergeviewer.ContentMergeViewer;
+
+/**
+ */
+public class ImageMergeViewer extends ContentMergeViewer {
+
+ private static final String BUNDLE_NAME= "org.eclipse.compare.internal.ImageMergeViewerResources";
+
+ private Object fAncestorImage;
+ private Object fLeftImage;
+ private Object fRightImage;
+
+ private ImageCanvas fAncestor;
+ private ImageCanvas fLeft;
+ private ImageCanvas fRight;
+
+
+ public ImageMergeViewer(Composite parent, int styles, CompareConfiguration mp) {
+ super(styles, ResourceBundle.getBundle(BUNDLE_NAME), mp);
+ buildControl(parent);
+ getControl().setData(CompareUI.COMPARE_VIEWER_TITLE, "Image Compare");
+ }
+
+ protected void updateContent(Object ancestor, Object left, Object right) {
+
+ fAncestorImage= ancestor;
+ setInput(fAncestor, ancestor);
+
+ fLeftImage= left;
+ setInput(fLeft, left);
+
+ fRightImage= right;
+ setInput(fRight, right);
+ }
+
+ /**
+ * We can't modify the contents of either side we just return null.
+ */
+ protected byte[] getContents(boolean left) {
+ return null;
+ }
+
+ public void createControls(Composite composite) {
+ fAncestor= new ImageCanvas(composite, SWT.NONE);
+ fLeft= new ImageCanvas(composite, SWT.NONE);
+ fRight= new ImageCanvas(composite, SWT.NONE);
+ }
+
+ private static void setInput(ImageCanvas canvas, Object input) {
+ if (canvas != null) {
+
+ InputStream stream= null;
+ if (input instanceof IStreamContentAccessor) {
+ IStreamContentAccessor sca= (IStreamContentAccessor) input;
+ if (sca != null) {
+ try {
+ stream= sca.getContents();
+ } catch (CoreException ex) {
+ }
+ }
+ }
+
+ Image image= null;
+ Display display= canvas.getDisplay();
+ if (stream != null) {
+ try {
+ image= new Image(display, stream);
+ } catch (SWTException ex) {
+ }
+ }
+
+ canvas.setImage(image);
+ if (image != null) {
+ canvas.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+ } else {
+ canvas.setBackground(null);
+ }
+ }
+ }
+
+ protected void handleResizeAncestor(int x, int y, int width, int height) {
+ if (width > 0) {
+ fAncestor.setVisible(true);
+ fAncestor.setBounds(x, y, width, height);
+ } else {
+ fAncestor.setVisible(false);
+ }
+ }
+
+ protected void handleResizeLeftRight(int x, int y, int width1, int centerWidth, int width2, int height) {
+ fLeft.setBounds(x, y, width1, height);
+ fRight.setBounds(x+width1+centerWidth, y, width2, height);
+ }
+
+ protected void copy(boolean leftToRight) {
+ if (leftToRight) {
+ fRightImage= fLeftImage;
+ setInput(fRight, fRightImage);
+ setRightDirty(true);
+ } else {
+ fLeftImage= fRightImage;
+ setInput(fLeft, fLeftImage);
+ setLeftDirty(true);
+ }
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerCreator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerCreator.java
new file mode 100644
index 000000000..e57c9c99d
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerCreator.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.compare.*;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * A factory object for the <code>ImageMergeViewer</code>.
+ * This indirection is necessary because only objects with a default
+ * constructor can be created via an extension point
+ * (this precludes Viewers).
+ */
+public class ImageMergeViewerCreator implements IViewerCreator {
+
+ public Viewer createViewer(Composite parent, CompareConfiguration mp) {
+ return new ImageMergeViewer(parent, SWT.NULL, mp);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerResources.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerResources.properties
new file mode 100644
index 000000000..dcc529805
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ImageMergeViewerResources.properties
@@ -0,0 +1,55 @@
+# =====================================
+# Licensed Materials - Property of IBM,
+# WebSphere Studio Workbench
+# (c) Copyright IBM Corp 1999-2001
+# =====================================
+
+# @(#)ImageMergeViewerResources.properties
+#
+# Resource strings for ImageMergeViewer.java
+
+#####################################################
+# Images
+#####################################################
+
+#####################################################
+# Status messages
+#####################################################
+
+#####################################################
+# Dialogs
+#####################################################
+
+CantSaveProperty.title=Error while saving contents
+CantSaveProperty.message=Couldn''t save contents.\nReason: {0}
+
+ContentInaccessible.title=Error while accessing content
+ContentInaccessible.message=Content currently inaccessible.
+
+#####################################################
+# Actions
+#####################################################
+
+action.CopyLeftToRight.label=Copy Left to Right
+action.CopyLeftToRight.tooltip=Copy image from left to right
+action.CopyLeftToRight.image=ctool16/lefttoright.gif
+
+action.CopyRightToLeft.label=Copy Right to Left
+action.CopyRightToLeft.tooltip=Copy image from right to left
+action.CopyRightToLeft.image=ctool16/righttoleft.gif
+
+#action.ToggleMergeDirection.label=Toggle Merge Direction
+#action.ToggleMergeDirection.tooltip=Toggle merge direction
+#action.ToggleMergeDirection.image=ctool16/toggle.gif
+
+action.EnableAncestor.label=Enable Ancestor Pane
+action.EnableAncestor.tooltip=Controls visibility of ancestor pane
+action.EnableAncestor.image=ctool16/panes3.gif
+
+# Pop up menu
+
+#action.Save.label=Save@Ctrl+S
+#action.Save.tooltip=Save Changes
+
+
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeSourceViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeSourceViewer.java
new file mode 100644
index 000000000..ce4780b9f
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeSourceViewer.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.graphics.Color;
+
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+
+/**
+ * Extends the SEF SourceViewer with some convenience methods.
+ */
+public class MergeSourceViewer extends SourceViewer {
+
+ private IRegion fRegion;
+ private boolean fEnabled= true;
+
+
+ public MergeSourceViewer(Composite parent) {
+ super(parent, null, SWT.H_SCROLL + SWT.V_SCROLL);
+ }
+
+ public void setEnabled(boolean enabled) {
+ if (enabled != fEnabled) {
+ fEnabled= enabled;
+ StyledText c= getTextWidget();
+ if (c != null) {
+ c.setEnabled(enabled);
+ Display d= c.getDisplay();
+ c.setBackground(enabled ? d.getSystemColor(SWT.COLOR_LIST_BACKGROUND) : null);
+ }
+ }
+ }
+
+ public boolean getEnabled() {
+ return fEnabled;
+ }
+
+ public void setRegion(IRegion region) {
+ fRegion= region;
+ }
+
+ public IRegion getRegion() {
+ return fRegion;
+ }
+
+ public boolean isControlOkToUse() {
+ StyledText t= getTextWidget();
+ return t != null && !t.isDisposed();
+ }
+
+ public void setSelection(Position p) {
+ setSelectedRange(p.getOffset(), p.getLength());
+ }
+
+ public void setLineBackground(Position p, Color c) {
+ StyledText t= getTextWidget();
+ if (t != null && !t.isDisposed()) {
+ Point region= new Point(0, 0);
+ getLineRange(p, region);
+
+ region.x-= getDocumentRegionOffset();
+
+ t.setLineBackground(region.x, region.y, c);
+ }
+ }
+
+ public void resetLineBackground() {
+ StyledText t= getTextWidget();
+ if (t != null && !t.isDisposed()) {
+ int lines= getLineCount();
+ t.setLineBackground(0, lines, null);
+ }
+ }
+
+ /**
+ * Returns number of lines in document region.
+ */
+ public int getLineCount() {
+ IRegion region= getVisibleRegion();
+
+ int length= region.getLength();
+ if (length == 0)
+ return 0;
+
+ IDocument doc= getDocument();
+ int startLine= 0;
+ int endLine= 0;
+
+ int start= region.getOffset();
+ try {
+ startLine= doc.getLineOfOffset(start);
+ } catch(BadLocationException ex) {
+ }
+ try {
+ endLine= doc.getLineOfOffset(start+length);
+ } catch(BadLocationException ex) {
+ }
+
+ return endLine-startLine+1;
+ }
+
+ public int getViewportLines() {
+ StyledText te= getTextWidget();
+ Rectangle clArea= te.getClientArea();
+ if (!clArea.isEmpty())
+ return clArea.height / te.getLineHeight();
+ return 0;
+ }
+
+ public int getViewportHeight() {
+ StyledText te= getTextWidget();
+ Rectangle clArea= te.getClientArea();
+ if (!clArea.isEmpty())
+ return clArea.height;
+ return 0;
+ }
+
+ /**
+ * Returns lines
+ */
+ public int getDocumentRegionOffset() {
+ int start= getVisibleRegion().getOffset();
+ IDocument doc= getDocument();
+ if (doc != null) {
+ try {
+ return doc.getLineOfOffset(start);
+ } catch(BadLocationException ex) {
+ }
+ }
+ return 0;
+ }
+
+ public int getVerticalScrollOffset() {
+ StyledText st= getTextWidget();
+ int lineHeight= st.getLineHeight();
+ return getTopInset() - ((getDocumentRegionOffset()*lineHeight) + st.getTopPixel());
+ }
+
+ /**
+ * Returns the start line and the number of lines which correspond to the given position.
+ * Starting line number is 0 based.
+ */
+ public Point getLineRange(Position p, Point region) {
+
+ if (p == null) {
+ region.x= 0;
+ region.y= 0;
+ return region;
+ }
+
+ IDocument doc= getDocument();
+
+ int start= p.getOffset();
+ int length= p.getLength();
+
+ int startLine= 0;
+ try {
+ startLine= doc.getLineOfOffset(start);
+ } catch (BadLocationException e) {
+ }
+
+ int lineCount= 0;
+
+ if (length == 0) {
+// // if range length is 0 and if range starts a new line
+// try {
+// if (start == doc.getLineStartOffset(startLine)) {
+// lines--;
+// }
+// } catch (BadLocationException e) {
+// lines--;
+// }
+
+ } else {
+ int endLine= 0;
+ try {
+ endLine= doc.getLineOfOffset(start + length - 1); // why -1?
+ } catch (BadLocationException e) {
+ }
+ lineCount= endLine-startLine+1;
+ }
+
+ region.x= startLine;
+ region.y= lineCount;
+ return region;
+ }
+
+ /**
+ * Scroll TextPart to the given line.
+ */
+ public void vscroll(int line) {
+
+ int srcViewSize= getLineCount();
+ int srcExtentSize= getViewportLines();
+
+ if (srcViewSize > srcExtentSize) {
+ //if (pos + srcExtentSize > srcViewSize)
+ // pos= srcViewSize-srcExtentSize;
+
+ if (line < 0)
+ line= 0;
+
+ int cp= getTopIndex();
+ if (cp != line)
+ setTopIndex(line + getDocumentRegionOffset());
+ }
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeViewerContentProvider.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeViewerContentProvider.java
new file mode 100644
index 000000000..29994d804
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/MergeViewerContentProvider.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+import org.eclipse.compare.contentmergeviewer.IMergeViewerContentProvider;
+
+/**
+ * Adapts any <code>ContentMergeViewer</code> to work on an <code>ICompareInput</code>
+ * e.g. a <code>DiffNode</code>.
+ */
+public class MergeViewerContentProvider implements IMergeViewerContentProvider {
+
+ private CompareConfiguration fCompareConfiguration;
+
+ public MergeViewerContentProvider(CompareConfiguration cc) {
+ fCompareConfiguration= cc;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer v, Object o1, Object o2) {
+ }
+
+ //---- ancestor
+
+ public String getAncestorLabel(Object element) {
+ return fCompareConfiguration.getAncestorLabel(element);
+ }
+
+ public Image getAncestorImage(Object element) {
+ return fCompareConfiguration.getAncestorImage(element);
+ }
+
+ public Object getAncestorContent(Object element) {
+ if (element instanceof ICompareInput)
+ return ((ICompareInput) element).getAncestor();
+ return null;
+ }
+
+ public boolean showAncestor(Object element) {
+ if (element instanceof ICompareInput)
+ return (((ICompareInput)element).getKind() & Differencer.DIRECTION_MASK) == Differencer.CONFLICTING;
+ return false;
+ }
+
+ //---- left
+
+ public String getLeftLabel(Object element) {
+ return fCompareConfiguration.getLeftLabel(element);
+ }
+
+ public Image getLeftImage(Object element) {
+ return fCompareConfiguration.getLeftImage(element);
+ }
+
+ public Object getLeftContent(Object element) {
+ if (element instanceof ICompareInput)
+ return ((ICompareInput) element).getLeft();
+ return null;
+ }
+
+ public boolean isLeftEditable(Object element) {
+ if (element instanceof ICompareInput) {
+ Object left= ((ICompareInput) element).getLeft();
+ if (left == null) {
+ IDiffElement parent= ((IDiffElement)element).getParent();
+ if (parent instanceof ICompareInput)
+ left= ((ICompareInput) parent).getLeft();
+ }
+ if (left instanceof IEditableContent)
+ return ((IEditableContent)left).isEditable();
+ }
+ return false;
+ }
+
+ public void saveLeftContent(Object element, byte[] bytes) {
+ if (element instanceof ICompareInput) {
+ ICompareInput node= (ICompareInput) element;
+ if (bytes != null) {
+ ITypedElement left= node.getLeft();
+ if (left instanceof IEditableContent)
+ ((IEditableContent)left).setContent(bytes);
+ } else {
+ node.copy(false);
+ }
+ }
+ }
+
+ //---- right
+
+ public String getRightLabel(Object element) {
+ return fCompareConfiguration.getRightLabel(element);
+ }
+
+ public Image getRightImage(Object element) {
+ return fCompareConfiguration.getRightImage(element);
+ }
+
+ public Object getRightContent(Object element) {
+ if (element instanceof ICompareInput)
+ return ((ICompareInput) element).getRight();
+ return null;
+ }
+
+ public boolean isRightEditable(Object element) {
+ if (element instanceof ICompareInput) {
+ Object right= ((ICompareInput) element).getRight();
+ if (right == null) {
+ IDiffContainer parent= ((IDiffElement)element).getParent();
+ if (parent instanceof ICompareInput)
+ right= ((ICompareInput) parent).getRight();
+ }
+ if (right instanceof IEditableContent)
+ return ((IEditableContent)right).isEditable();
+ }
+ return false;
+ }
+
+ public void saveRightContent(Object element, byte[] bytes) {
+ if (element instanceof ICompareInput) {
+ ICompareInput node= (ICompareInput) element;
+ if (bytes != null) {
+ ITypedElement right= node.getRight();
+ if (right instanceof IEditableContent)
+ ((IEditableContent)right).setContent(bytes);
+ } else {
+ node.copy(true);
+ }
+ }
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Pane.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Pane.java
new file mode 100644
index 000000000..be0612dca
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Pane.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.ViewForm;
+
+import org.eclipse.jface.action.ToolBarManager;
+
+/**
+ * A Pane is a convenience class which installs a CustomLabel and a Toolbar (on demand).
+ * Double clicking onto the Pane's title bar maximizes the Pane
+ * to the size of an enclosing Splitter (if there is one).
+ * If more Splitters are nested maximizing walks up and maximizes to the outermost Splitter.
+ */
+public class Pane extends ViewForm {
+
+ private ToolBarManager fToolBarManager;
+
+ public Pane(Composite parent, int style) {
+ super(parent, SWT.BORDER);
+
+ marginWidth= 0;
+ marginHeight= 0;
+
+ CLabel label= new CLabel(this, SWT.NONE);
+ setTopLeft(label);
+
+ MouseAdapter ml= new MouseAdapter() {
+ public void mouseDoubleClick(MouseEvent e) {
+ Control parent= getParent();
+ if (parent instanceof Splitter)
+ ((Splitter)parent).setMaximizedControl(Pane.this);
+ }
+ };
+
+ addMouseListener(ml);
+ label.addMouseListener(ml);
+ }
+
+ public void setText(String label) {
+ CLabel cl= (CLabel) getTopLeft();
+ cl.setText(label);
+ }
+
+ public void setImage(Image image) {
+ CLabel cl= (CLabel) getTopLeft();
+ cl.setImage(image);
+ }
+
+ /**
+ * Returns a <code>ToolBarManager</code> if the given parent is a <code>ViewerPane</code>.
+ */
+ public static ToolBarManager getToolBarManager(Composite parent) {
+ if (parent instanceof Pane) {
+ Pane pane= (Pane) parent;
+ return pane.getToolBarManager();
+ }
+ return null;
+ }
+
+ /**
+ * Clear tool items in <code>ViewerPane</code>'s control bar.
+ */
+ public static void clearToolBar(Composite parent) {
+ ToolBarManager tbm= getToolBarManager(parent);
+ if (tbm != null) {
+ tbm.removeAll();
+ tbm.update(true);
+ }
+ }
+
+ //---- private stuff
+
+ private ToolBarManager getToolBarManager() {
+ if (fToolBarManager == null) {
+ ToolBar tb= new ToolBar(this, SWT.FLAT);
+ setTopCenter(tb);
+ fToolBarManager= new ToolBarManager(tb);
+ }
+ return fToolBarManager;
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.java
new file mode 100644
index 000000000..e62dee7c4
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.InputStream;
+import java.util.ResourceBundle;
+
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.compare.*;
+
+
+public class ReplaceWithEditionAction implements IActionDelegate {
+
+ private static final String ACTION_LABEL= "Replace with Edition";
+ private ISelection fSelection;
+
+
+ public void run(IAction action) {
+
+ Object[] s= Utilities.toArray(fSelection);
+
+ for (int i= 0; i < s.length; i++) {
+ Object o= s[i];
+ if (o instanceof IFile) {
+ replaceFromHistory((IFile)o);
+ continue;
+ }
+ if (o instanceof IAdaptable) {
+ IAdaptable a= (IAdaptable) o;
+ Object adapter= a.getAdapter(IResource.class);
+ if (adapter instanceof IFile)
+ replaceFromHistory((IFile)adapter);
+ continue;
+ }
+ }
+ }
+
+ public void selectionChanged(IAction a, ISelection s) {
+ fSelection= s;
+ }
+
+ void replaceFromHistory(IFile file) {
+
+ Shell parent= CompareUIPlugin.getShell();
+
+ IFileState states[]= null;
+ try {
+ states= file.getHistory(null);
+ } catch (CoreException ex) {
+ MessageDialog.openError(parent, ACTION_LABEL, ex.getMessage());
+ return;
+ }
+
+ if (states != null && states.length > 0) {
+
+ ITypedElement base= new ResourceNode(file);
+
+ ITypedElement[] editions= new ITypedElement[states.length];
+ for (int i= 0; i < states.length; i++)
+ editions[i]= new HistoryItem(base, states[i]);
+
+ ResourceBundle bundle= ResourceBundle.getBundle("org.eclipse.compare.internal.ReplaceWithEditionAction");
+ EditionSelectionDialog d= new EditionSelectionDialog(parent, bundle);
+
+ ITypedElement ti= d.selectEdition(base, editions, null);
+ if (ti instanceof IStreamContentAccessor) {
+ try {
+ InputStream is= ((IStreamContentAccessor)ti).getContents();
+ file.setContents(is, false, true, null);
+ } catch (CoreException ex) {
+ MessageDialog.openError(parent, ACTION_LABEL, ex.getMessage());
+ }
+ }
+ } else
+ MessageDialog.openInformation(parent, ACTION_LABEL, "No local editions available for selected resource.");
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties
new file mode 100644
index 000000000..6f591e9d5
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ReplaceWithEditionAction.properties
@@ -0,0 +1,22 @@
+# =====================================
+# Licensed Materials - Property of IBM,
+# WebSphere Studio Workbench
+# (c) Copyright IBM Corp 2001
+# ====================================
+
+# @(#)ReplaceWithEditionAction.properties
+#
+# Resources for ReplaceWithEditionAction.java
+
+title= Replace from Local History
+
+treeTitleFormat= Editions of "{0}"
+dateIcon= obj16/date.gif
+timeIcon= obj16/time.gif
+
+editionLabel= Local History ({0})
+targetLabel= Workbench
+
+todayFormat= Today ({0})
+yesterdayFormat= Yesterday ({0})
+dayFormat= {0} \ No newline at end of file
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
new file mode 100644
index 000000000..6c6e0735d
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ResourceCompareInput.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.jface.viewers.ISelection;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+
+
+/**
+ * A two-way or three-way compare for arbitrary IResources.
+ */
+class ResourceCompareInput extends CompareEditorInput {
+
+ private ISelection fSelection;
+
+ private class MyDiffNode extends DiffNode {
+ public MyDiffNode(IDiffContainer parent, int description, ITypedElement ancestor, ITypedElement left, ITypedElement right) {
+ super(parent, description, ancestor, left, right);
+ }
+ protected void fireChange() {
+ super.fireChange();
+ setDirty(true);
+ }
+ }
+
+ /**
+ * Creates an compare editor input for the given selection.
+ */
+ ResourceCompareInput(CompareConfiguration config, ISelection selection) {
+ super(config);
+ fSelection= selection;
+ }
+
+ /**
+ * Performs a two-way or three-way diff on the current 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();
+
+ 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);
+
+ } finally {
+ pm.done();
+ }
+ }
+
+ /**
+ * Creates a <code>IStructureComparator</code> for the given input.
+ * Returns <code>null</code> if no <code>IStructureComparator</code>
+ * can be found for the <code>IResource</code>.
+ */
+ private IStructureComparator getStructure(IResource input) {
+
+ if (input instanceof IContainer)
+ return new ResourceNode(input);
+
+ if (input instanceof IFile) {
+ ResourceNode rn= new ResourceNode(input);
+ IFile file= (IFile) input;
+ String type= normalizeCase(file.getFileExtension());
+ if ("JAR".equals(type) || "ZIP".equals(type)) { // FIXME
+
+ 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;
+
+ private static String normalizeCase(String s) {
+ if (NORMALIZE_CASE && s != null)
+ return s.toUpperCase();
+ return s;
+ }
+}
+
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ShowPseudoConflicts.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ShowPseudoConflicts.java
new file mode 100644
index 000000000..9c7f8391d
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ShowPseudoConflicts.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.*;
+
+/**
+ * Toggles the <code>ICompareConfiguration.SHOW_PSEUDO_CONFLICTS</code> property of an
+ * <code>ICompareConfiguration</code>.
+ */
+public class ShowPseudoConflicts extends ChangePropertyAction {
+
+ public ShowPseudoConflicts(ResourceBundle bundle, CompareConfiguration cc) {
+ super(bundle, cc, "action.ShowPseudoConflicts.", CompareConfiguration.SHOW_PSEUDO_CONFLICTS);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Splitter.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Splitter.java
new file mode 100644
index 000000000..14c835e73
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Splitter.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.custom.SashForm;
+
+public class Splitter extends SashForm {
+
+ private static final String VISIBILITY= "org.eclipse.compare.internal.visibility";
+
+
+ public Splitter(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ public void setVisible(Control child, boolean visible) {
+
+ boolean wasEmpty= isEmpty();
+
+ child.setVisible(visible);
+ child.setData(VISIBILITY, new Boolean(visible));
+
+ if (wasEmpty != isEmpty()) {
+ Composite parent= getParent();
+ if (parent instanceof Splitter) {
+ Splitter sp= (Splitter) parent;
+ sp.setVisible(this, visible);
+ sp.layout();
+ }
+ } else {
+ layout();
+ }
+ }
+
+ private boolean isEmpty() {
+ Control[] controls= getChildren();
+ for (int i= 0; i < controls.length; i++)
+ if (isVisible(controls[i]))
+ return false;
+ return true;
+ }
+
+ private boolean isVisible(Control child) {
+ if (child instanceof Sash)
+ return false;
+ Object data= child.getData(VISIBILITY);
+ if (data instanceof Boolean)
+ return ((Boolean)data).booleanValue();
+ return true;
+ }
+
+ public void setMaximizedControl(Control control) {
+ if (control == null || control == getMaximizedControl())
+ super.setMaximizedControl(null);
+ else
+ super.setMaximizedControl(control);
+
+ // walk up
+ Composite parent= getParent();
+ if (parent instanceof Splitter)
+ ((Splitter) parent).setMaximizedControl(this);
+ else
+ layout(true);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextMergeViewerCreator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextMergeViewerCreator.java
new file mode 100644
index 000000000..d316705aa
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextMergeViewerCreator.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+
+/**
+ * A factory object for the <code>TextMergeViewer</code>.
+ * This indirection is necessary because only objects with a default
+ * constructor can be created via an extension point
+ * (this precludes Viewers).
+ */
+public class TextMergeViewerCreator implements IViewerCreator {
+
+ public Viewer createViewer(Composite parent, CompareConfiguration mp) {
+ return new TextMergeViewer(parent, mp);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewer.java
new file mode 100644
index 000000000..6a1ed00e5
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewer.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.IOException;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.Document;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.ICompareInput;
+
+
+public class TextViewer extends AbstractViewer {
+
+ private SourceViewer fSourceViewer;
+ private ICompareInput fInput;
+
+
+ TextViewer(Composite parent) {
+ fSourceViewer= new SourceViewer(parent, null, SWT.H_SCROLL + SWT.V_SCROLL);
+ fSourceViewer.setEditable(false);
+ }
+
+ public Control getControl() {
+ return fSourceViewer.getTextWidget();
+ }
+
+ public void setInput(Object input) {
+ if (input instanceof ICompareInput) {
+ fInput= (ICompareInput) input;
+ ITypedElement left= ((ICompareInput) fInput).getLeft();
+ fSourceViewer.setDocument(new Document(getString(left)));
+
+ } else if (input instanceof IStreamContentAccessor) {
+ fSourceViewer.setDocument(new Document(getString(input)));
+ }
+ }
+
+ public Object getInput() {
+ return fInput;
+ }
+
+ private String getString(Object input) {
+
+ if (input instanceof IStreamContentAccessor) {
+ IStreamContentAccessor sca= (IStreamContentAccessor) input;
+ try {
+ return Utilities.readString(sca.getContents());
+ } catch (CoreException ex) {
+ }
+ }
+ return "";
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewerCreator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewerCreator.java
new file mode 100644
index 000000000..943a775e8
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TextViewerCreator.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.jface.viewers.Viewer;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IViewerCreator;
+
+
+/**
+ * A factory object for the <code>TextMergeViewer</code>.
+ * This indirection is necessary because only objects with a default
+ * constructor can be created via an extension point
+ * (this precludes Viewers).
+ */
+public class TextViewerCreator implements IViewerCreator {
+
+ public Viewer createViewer(Composite parent, CompareConfiguration mp) {
+ return new TextViewer(parent);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TokenComparator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TokenComparator.java
new file mode 100644
index 000000000..62d96e185
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/TokenComparator.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.util.StringTokenizer;
+
+import org.eclipse.compare.rangedifferencer.IRangeComparator;
+import org.eclipse.compare.contentmergeviewer.ITokenComparator;
+
+/**
+ * Implements the <code>ITokenComparator</code> interface for words (or tokens) in a string.
+ * A <code>TokenComparator</code> is used as the input for the <code>RangeDifferencer</code>
+ * engine to perform a token oriented compare on strings.
+ */
+public class TokenComparator implements ITokenComparator {
+
+ private boolean fShouldEscape= true;
+ private String fText;
+ private int fCount;
+ private int[] fStarts;
+ private int[] fLengths;
+
+ /**
+ * Creates a <code>TokenComparator</code> for the given string.
+ *
+ * @param string the string that is split into token
+ */
+ public TokenComparator(String string) {
+
+ if (string != null)
+ fText= string;
+ else
+ fText= "";
+
+ fStarts= new int[fText.length()];
+ fLengths= new int[fText.length()];
+ fCount= 0;
+
+ StringTokenizer tokenizer= new StringTokenizer(fText, " \t\n\r", true);
+
+ for (int pos= 0; tokenizer.hasMoreElements();) {
+ fStarts[fCount]= pos;
+ String s= tokenizer.nextToken();
+ int l= 0;
+ if (s != null)
+ l= s.length();
+ pos += l;
+ fLengths[fCount]= l;
+ fCount++;
+ }
+ }
+
+ /**
+ * Creates a <code>TokenComparator</code> for the given string.
+ *
+ * @param string the string that is split into token
+ * @param shouldEscape
+ */
+ public TokenComparator(String s, boolean shouldEscape) {
+ this(s);
+ fShouldEscape= shouldEscape;
+ }
+
+ /**
+ * Returns the number of token in the string.
+ *
+ * @return number of token in the string
+ */
+ public int getRangeCount() {
+ return fCount;
+ }
+
+ /* (non Javadoc)
+ * see ITokenComparator.getTokenStart
+ */
+ public int getTokenStart(int index) {
+ if (index < fCount)
+ return fStarts[index];
+ return fText.length();
+ }
+
+ /* (non Javadoc)
+ * see ITokenComparator.getTokenLength
+ */
+ public int getTokenLength(int index) {
+ if (index < fCount)
+ return fLengths[index];
+ return 0;
+ }
+
+ /**
+ * Returns the content of tokens in the specified range as a String.
+ * If the number of token is 0 the empty string ("") is returned.
+ *
+ * @param start index of first token
+ * @param length number of tokens
+ * @return the contents of the specified token range as a String
+ */
+ public String extract(int start, int length) {
+ if (start >= fStarts.length)
+ System.out.println("oops");
+ int startPos= fStarts[start];
+ int endPos= 0;
+ if (length > 0) {
+ int e= start + length-1;
+ if (e >= fStarts.length)
+ System.out.println("oops");
+ endPos= fStarts[e] + fLengths[e];
+ } else {
+ endPos= fStarts[start];
+ }
+ //int endPos= getTokenStart(start + length);
+ if (endPos >= fText.length())
+ return fText.substring(startPos);
+ return fText.substring(startPos, endPos);
+ }
+
+ /**
+ * Returns <code>true</code> if a token given by the first index
+ * matches a token specified by the other <code>IRangeComparator</code> and index.
+ *
+ * @param thisIndex the number of the token within this range comparator
+ * @param other the range comparator to compare this with
+ * @param otherIndex the number of the token within the other comparator
+ * @return <code>true</code> if the token are equal
+ */
+ public boolean rangesEqual(int thisIndex, IRangeComparator other, int otherIndex) {
+ if (other != null && getClass() == other.getClass()) {
+ TokenComparator tc= (TokenComparator) other;
+ int thisLen= getTokenLength(thisIndex);
+ int otherLen= tc.getTokenLength(otherIndex);
+ if (thisLen == otherLen)
+ return fText.regionMatches(false, getTokenStart(thisIndex), tc.fText, tc.getTokenStart(otherIndex), thisLen);
+ }
+ return false;
+ }
+
+ /**
+ * Aborts the comparison if the number of tokens is too large.
+ *
+ * @return <code>true</code> to abort a token comparison
+ */
+ public boolean skipRangeComparison(int length, int max, IRangeComparator other) {
+
+ if (!fShouldEscape)
+ return false;
+
+ if (getRangeCount() < 50 || other.getRangeCount() < 50)
+ return false;
+
+ if (max < 100)
+ return false;
+
+ if (length < 100)
+ return false;
+
+ if (max > 800)
+ return true;
+
+ if (length < max / 4)
+ return false;
+
+ return true;
+ }
+
+// public static void main(String args[]) {
+// //String in= "private static boolean isWhitespace(char c) {";
+// //String in= "for (int j= 0; j < l-1; j++) {";
+// String in= "for do";
+// TokenComparator tc= new TokenComparator(in, false);
+//
+// System.out.println("n: " + tc.getRangeCount());
+// System.out.println(in);
+//
+// int p= 0;
+// for (int i= 0; i < tc.getRangeCount(); i++) {
+// int l= tc.getTokenLength(i);
+// System.out.print("<");
+//
+// for (int j= 0; j < l-1; j++)
+// System.out.print(" ");
+// }
+// System.out.println();
+//
+// //System.out.println("extract: <" + tc.extract(16, 1) + ">");
+// }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
new file mode 100644
index 000000000..b280afc1f
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/Utilities.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.jface.util.*;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.compare.CompareConfiguration;
+
+/**
+ * Convenience and utility methods.
+ */
+public class Utilities {
+
+ public static boolean getBoolean(CompareConfiguration cc, String key, boolean dflt) {
+ if (cc != null) {
+ Object value= cc.getProperty(key);
+ if (value instanceof Boolean)
+ return ((Boolean) value).booleanValue();
+ }
+ return dflt;
+ }
+
+ /**
+ * Retrieves the value from a property change event as a boolean.
+ */
+ public static boolean getValue(PropertyChangeEvent event, boolean dflt) {
+ Object newValue= event.getNewValue();
+ if (newValue instanceof Boolean)
+ return ((Boolean)newValue).booleanValue();
+ return dflt;
+ }
+
+ public static void firePropertyChange(ListenerList ll, Object source, String property, Object old, Object newValue) {
+ if (ll != null) {
+ PropertyChangeEvent event= null;
+ Object[] listeners= ll.getListeners();
+ for (int i= 0; i < listeners.length; i++) {
+ IPropertyChangeListener l= (IPropertyChangeListener) listeners[i];
+ if (event == null)
+ event= new PropertyChangeEvent(source, property, old, newValue);
+ l.propertyChange(event);
+ }
+ }
+ }
+
+ public static boolean okToUse(Widget widget) {
+ return widget != null && !widget.isDisposed();
+ }
+
+ public static boolean isMotif() {
+ return false;
+ }
+
+ /**
+ * Returns the elements of the given selection.
+ * Returns an empty array if the selection is empty or if
+ * the given selection is not of type <code>IStructuredSelection</code>.
+ *
+ * @param selection the selection
+ * @return the selected elements
+ */
+ public static Object[] toArray(ISelection selection) {
+ if (!(selection instanceof IStructuredSelection)) {
+ return new Object[0];
+ }
+ IStructuredSelection ss= (IStructuredSelection) selection;
+ return ss.toArray();
+ }
+
+ /**
+ * Convenience method: extract all <code>IResources</code> from given selection.
+ * Never returns null.
+ */
+ public static IResource[] getResources(ISelection selection) {
+
+ List tmp= new ArrayList();
+
+ if (selection instanceof IStructuredSelection) {
+
+ Object[] s= ((IStructuredSelection)selection).toArray();
+
+ for (int i= 0; i < s.length; i++) {
+ Object o= s[i];
+ if (o instanceof IResource) {
+ tmp.add(o);
+ continue;
+ }
+ if (o instanceof IAdaptable) {
+ IAdaptable a= (IAdaptable) o;
+ Object adapter= a.getAdapter(IResource.class);
+ if (adapter instanceof IResource)
+ tmp.add(adapter);
+ continue;
+ }
+ }
+ }
+ IResource[] resourceSelection= new IResource[tmp.size()];
+ tmp.toArray(resourceSelection);
+ return resourceSelection;
+ }
+
+ public static byte[] readBytes(InputStream in) {
+ ByteArrayOutputStream bos= new ByteArrayOutputStream();
+ try {
+ while (true) {
+ int c= in.read();
+ if (c == -1)
+ break;
+ bos.write(c);
+ }
+
+ } catch (IOException ex) {
+ return null;
+
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException x) {
+ }
+ }
+ try {
+ bos.close();
+ } catch (IOException x) {
+ }
+ }
+
+ return bos.toByteArray();
+ }
+
+ /**
+ * Returns null if an error occurred.
+ */
+ public static String readString(InputStream is) {
+ if (is == null)
+ return null;
+ BufferedReader reader= null;
+ try {
+ StringBuffer buffer= new StringBuffer();
+ char[] part= new char[2048];
+ int read= 0;
+ reader= new BufferedReader(new InputStreamReader(is));
+
+ while ((read= reader.read(part)) != -1)
+ buffer.append(part, 0, read);
+
+ return buffer.toString();
+
+ } catch (IOException ex) {
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Initialize the given Action from a ResourceBundle.
+ */
+ public static void initAction(IAction a, ResourceBundle bundle, String prefix) {
+
+ String labelKey= "label";
+ String tooltipKey= "tooltip";
+ String imageKey= "image";
+ String descriptionKey= "description";
+
+ if (prefix != null && prefix.length() > 0) {
+ labelKey= prefix + labelKey;
+ tooltipKey= prefix + tooltipKey;
+ imageKey= prefix + imageKey;
+ descriptionKey= prefix + descriptionKey;
+ }
+
+ a.setText(getString(bundle, labelKey, labelKey));
+ a.setToolTipText(getString(bundle, tooltipKey, null));
+ a.setDescription(getString(bundle, descriptionKey, null));
+
+ String relPath= getString(bundle, imageKey, null);
+ if (relPath != null && relPath.trim().length() > 0) {
+ ImageDescriptor id= CompareUIPlugin.getImageDescriptor(relPath);
+ if (id != null)
+ a.setImageDescriptor(id);
+ }
+ }
+
+ public static String getString(ResourceBundle bundle, String key, String dfltValue) {
+
+ if (bundle != null) {
+ try {
+ return bundle.getString(key);
+ } catch (MissingResourceException x) {
+ }
+ }
+ return dfltValue;
+ }
+
+ public static int getInteger(ResourceBundle bundle, String key, int dfltValue) {
+
+ if (bundle != null) {
+ try {
+ String s= bundle.getString(key);
+ if (s != null)
+ return Integer.parseInt(s);
+ } catch (NumberFormatException x) {
+ } catch (MissingResourceException x) {
+ }
+ }
+ return dfltValue;
+ }
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ViewerDescriptor.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ViewerDescriptor.java
new file mode 100644
index 000000000..d6ccd98aa
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ViewerDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000, 2001
+ */
+package org.eclipse.compare.internal;
+
+import org.eclipse.swt.widgets.Composite;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.compare.*;
+
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Creates <code>Viewer</code>s from an <code>IConfigurationElement</code>.
+ */
+public class ViewerDescriptor implements IViewerDescriptor {
+
+ private final static String CLASS_ATTRIBUTE= "class";
+ private final static String EXTENSIONS_ATTRIBUTE= "extensions";
+
+ private IConfigurationElement fConfiguration;
+ private IViewerCreator fViewerCreator;
+
+ public ViewerDescriptor(IConfigurationElement config) {
+ fConfiguration= config;
+ }
+
+ public Viewer createViewer(Viewer currentViewer, Composite parent, CompareConfiguration mp) {
+ String className= fConfiguration.getAttribute(CLASS_ATTRIBUTE);
+ if (currentViewer != null && currentViewer.getClass().getName().equals(className)) {
+ return currentViewer;
+ }
+ if (fViewerCreator == null) {
+ try {
+ fViewerCreator= (IViewerCreator) fConfiguration.createExecutableExtension(CLASS_ATTRIBUTE);
+ } catch (CoreException e) {
+ }
+ }
+
+ if (fViewerCreator != null) {
+ Viewer viewer= fViewerCreator.createViewer(parent, mp);
+ //if (viewer != null && currentViewer != null && viewer.getClass() == currentViewer.getClass())
+ // return currentViewer;
+ return viewer;
+ }
+
+ return null;
+ }
+
+ public String getExtension() {
+ return fConfiguration.getAttribute(EXTENSIONS_ATTRIBUTE);
+ }
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ZipStructureCreator.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ZipStructureCreator.java
new file mode 100644
index 000000000..d18bc84e5
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/ZipStructureCreator.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000,2001
+ */
+package org.eclipse.compare.internal;
+
+import java.io.*;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.zip.*;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.util.Assert;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.compare.*;
+import org.eclipse.compare.structuremergeviewer.*;
+
+
+public class ZipStructureCreator implements IStructureCreator {
+
+ /**
+ * Common base class for ZipFolder and ZipFile
+ */
+ static abstract class ZipResource implements IStructureComparator, ITypedElement {
+
+ private String fName;
+
+ ZipResource(String name) {
+ fName= name;
+ }
+
+ public String getName() {
+ return fName;
+ }
+
+ public Image getImage() {
+ return CompareUIPlugin.getImage(getType());
+ }
+
+ /**
+ * Returns true if other is ITypedElement and names are equal.
+ * @see IComparator#equals
+ */
+ public boolean equals(Object other) {
+ if (other instanceof ITypedElement)
+ return fName.equals(((ITypedElement) other).getName());
+ return super.equals(other);
+ }
+
+ public int hashCode() {
+ return fName.hashCode();
+ }
+ }
+
+ static class ZipFolder extends ZipResource {
+
+ private HashMap fChildren= new HashMap(10);
+
+ ZipFolder(String name) {
+ super(name);
+ }
+
+ public String getType() {
+ return ITypedElement.FOLDER_TYPE;
+ }
+
+ public Object[] getChildren() {
+ Object[] children= new Object[fChildren.size()];
+ Iterator iter= fChildren.values().iterator();
+ for (int i= 0; iter.hasNext(); i++)
+ children[i]= iter.next();
+ return children;
+ }
+
+ ZipFile createContainer(String path) {
+ String entry= path;
+ int pos= path.indexOf('/');
+ if (pos < 0)
+ pos= path.indexOf('\\');
+ if (pos >= 0) {
+ entry= path.substring(0, pos);
+ path= path.substring(pos + 1);
+ } else if (entry.length() > 0) {
+ ZipFile ze= new ZipFile(entry);
+ fChildren.put(entry, ze);
+ return ze;
+ } else
+ return null;
+
+ ZipFolder folder= null;
+ if (fChildren != null) {
+ Object o= fChildren.get(entry);
+ if (o instanceof ZipFolder)
+ folder= (ZipFolder) o;
+ }
+
+ if (folder == null) {
+ folder= new ZipFolder(entry);
+ fChildren.put(entry, folder);
+ }
+
+ return folder.createContainer(path);
+ }
+ }
+
+ static class ZipFile extends ZipResource implements IStreamContentAccessor {
+
+ private byte[] fContents;
+
+ ZipFile(String name) {
+ super(name);
+ }
+
+ public String getType() {
+ String s= this.getName();
+ int pos= s.lastIndexOf('.');
+ if (pos >= 0)
+ return s.substring(pos + 1);
+ return ITypedElement.UNKNOWN_TYPE;
+ }
+
+ public Object[] getChildren() {
+ return null;
+ }
+
+ public InputStream getContents() {
+ if (fContents == null)
+ fContents= new byte[0];
+ return new ByteArrayInputStream(fContents);
+ }
+
+ byte[] getBytes() {
+ return fContents;
+ }
+
+ void setBytes(byte[] buffer) {
+ fContents= buffer;
+ }
+ }
+
+ private String fTitle;
+
+ public ZipStructureCreator() {
+ this("Zip Archive Compare");
+ }
+
+ public ZipStructureCreator(String title) {
+ fTitle= title;
+ }
+
+ public String getName() {
+ return fTitle;
+ }
+
+ public IStructureComparator getStructure(Object input) {
+
+ InputStream is= null;
+
+ if (input instanceof IStreamContentAccessor) {
+ IStreamContentAccessor sca= (IStreamContentAccessor) input;
+ try {
+ is= sca.getContents();
+ } catch (CoreException ex) {
+ }
+ }
+
+ if (is == null)
+ return null;
+
+ ZipInputStream zip= new ZipInputStream(is);
+ ZipFolder root= new ZipFolder("");
+ try {
+ for (;;) {
+ ZipEntry entry= zip.getNextEntry();
+ if (entry == null)
+ break;
+ //System.out.println(entry.getName() + ": " + entry.getSize() + " " + entry.getCompressedSize());
+
+ ZipFile ze= root.createContainer(entry.getName());
+ if (ze != null) {
+ int length= (int) entry.getSize();
+ if (length >= 0) {
+ byte[] buffer= new byte[length];
+ int offset= 0;
+
+ do {
+ int n= zip.read(buffer, offset, length);
+ offset += n;
+ length -= n;
+ } while (length > 0);
+
+ ze.setBytes(buffer);
+ }
+ }
+ zip.closeEntry();
+ }
+ } catch (IOException ex) {
+ return null;
+ } finally {
+ try {
+ zip.close();
+ } catch (IOException ex) {
+ }
+ }
+
+ if (root.fChildren.size() == 1) {
+ Iterator iter= root.fChildren.values().iterator();
+ return (IStructureComparator) iter.next();
+ }
+ return root;
+ }
+
+ public String getContents(Object o, boolean ignoreWhitespace) {
+ if (o instanceof ZipFile) {
+ byte[] bytes= ((ZipFile)o).getBytes();
+ if (bytes != null)
+ return new String(bytes);
+ return "";
+ }
+ return null;
+ }
+
+ /**
+ * Returns <code>false</code> since we cannot update a zip archive.
+ */
+ public boolean canSave() {
+ return false;
+ }
+
+ /**
+ * Throws <code>AssertionFailedException</code> since we cannot update a zip archive.
+ */
+ public void save(IStructureComparator structure, Object input) {
+ Assert.isTrue(false, "cannot update zip archive");
+ }
+
+ public IStructureComparator locate(Object path, Object source) {
+ return null;
+ }
+
+ public boolean canRewriteTree() {
+ return false;
+ }
+
+ public void rewriteTree(Differencer diff, IDiffContainer root) {
+ }
+}
+

Back to the top