/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     channingwalton@mac.com - curved line code
 *     gilles.querret@free.fr - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=72995
 *     Max Weninger (max.weninger@windriver.com) - Bug 131895 [Edit] Undo in compare
 *     Max Weninger (max.weninger@windriver.com) - Bug 72936 [Viewers] Show line numbers in comparision
 *     Matt McCutchen (hashproduct+eclipse@gmail.com) - Bug 178968 [Viewers] Lines scrambled and different font size in compare
 *     Matt McCutchen (hashproduct+eclipse@gmail.com) - Bug 191524 [Viewers] Synchronize horizontal scrolling by # characters, not % of longest line
 *     Stephan Herrmann (stephan@cs.tu-berlin.de) - Bug 291695: Element compare fails to use source range
 *     Robin Stocker (robin@nibor.org) - Bug 398594: [Edit] Enable center arrow buttons when editable and for both sides
 *     Robin Stocker (robin@nibor.org) - Bug 399960: [Edit] Make merge arrow buttons easier to hit
 *******************************************************************************/
package org.eclipse.compare.contentmergeviewer;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;

import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareNavigator;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.ICompareNavigator;
import org.eclipse.compare.IEditableContentExtension;
import org.eclipse.compare.IEncodedStreamContentAccessor;
import org.eclipse.compare.INavigatable;
import org.eclipse.compare.ISharedDocumentAdapter;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.SharedDocumentAdapter;
import org.eclipse.compare.internal.BufferedCanvas;
import org.eclipse.compare.internal.ChangeCompareFilterPropertyAction;
import org.eclipse.compare.internal.ChangePropertyAction;
import org.eclipse.compare.internal.CompareContentViewerSwitchingPane;
import org.eclipse.compare.internal.CompareEditor;
import org.eclipse.compare.internal.CompareEditorContributor;
import org.eclipse.compare.internal.CompareEditorSelectionProvider;
import org.eclipse.compare.internal.CompareFilterDescriptor;
import org.eclipse.compare.internal.CompareHandlerService;
import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.internal.ComparePreferencePage;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.internal.DocumentManager;
import org.eclipse.compare.internal.ICompareContextIds;
import org.eclipse.compare.internal.ICompareUIConstants;
import org.eclipse.compare.internal.IMergeViewerTestAdapter;
import org.eclipse.compare.internal.MergeSourceViewer;
import org.eclipse.compare.internal.MergeViewerContentProvider;
import org.eclipse.compare.internal.NavigationEndDialog;
import org.eclipse.compare.internal.OutlineViewerCreator;
import org.eclipse.compare.internal.ShowWhitespaceAction;
import org.eclipse.compare.internal.TextEditorPropertyAction;
import org.eclipse.compare.internal.Utilities;
import org.eclipse.compare.internal.merge.DocumentMerger;
import org.eclipse.compare.internal.merge.DocumentMerger.Diff;
import org.eclipse.compare.internal.merge.DocumentMerger.IDocumentMergerInput;
import org.eclipse.compare.patch.IHunk;
import org.eclipse.compare.rangedifferencer.RangeDifference;
import org.eclipse.compare.structuremergeviewer.DiffNode;
import org.eclipse.compare.structuremergeviewer.DocumentRangeNode;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.compare.structuremergeviewer.IDiffContainer;
import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.core.commands.operations.IOperationHistoryListener;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.commands.operations.OperationHistoryEvent;
import org.eclipse.core.commands.operations.OperationHistoryFactory;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.CursorLinePainter;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.IFindReplaceTargetExtension;
import org.eclipse.jface.text.IFindReplaceTargetExtension3;
import org.eclipse.jface.text.IPositionUpdater;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextPresentationListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TypedListener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.IEncodingSupport;
import org.eclipse.ui.editors.text.IStorageDocumentProvider;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.ChangeEncodingAction;
import org.eclipse.ui.texteditor.FindReplaceAction;
import org.eclipse.ui.texteditor.GotoLineAction;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProviderExtension;
import org.eclipse.ui.texteditor.IElementStateListener;
import org.eclipse.ui.texteditor.IFindReplaceTargetExtension2;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;

import com.ibm.icu.text.MessageFormat;

/**
 * A text merge viewer uses the <code>RangeDifferencer</code> to perform a
 * textual, line-by-line comparison of two (or three) input documents. It is
 * based on the <code>ContentMergeViewer</code> and uses
 * <code>TextViewer</code>s to implement the ancestor, left, and right content
 * areas.
 * <p>
 * In the three-way compare case ranges of differing lines are highlighted and
 * framed with different colors to show whether the difference is an incoming,
 * outgoing, or conflicting change. The <code>TextMergeViewer</code> supports
 * the notion of a current "differing range" and provides toolbar buttons to
 * navigate from one range to the next (or previous).
 * <p>
 * If there is a current "differing range" and the underlying document is
 * editable the <code>TextMergeViewer</code> enables actions in context menu and
 * toolbar to copy a range from one side to the other side, thereby performing a
 * merge operation.
 * <p>
 * In addition to a line-by-line comparison the <code>TextMergeViewer</code>
 * uses a token based compare on differing lines. The token compare is activated
 * when navigating into a range of differing lines. At first the lines are
 * selected as a block. When navigating into this block the token compare shows
 * for every line the differing token by selecting them.
 * <p>
 * The <code>TextMergeViewer</code>'s default token compare works on characters
 * separated by whitespace. If a different strategy is needed (for example, Java
 * tokens in a Java-aware merge viewer), clients can create their own token
 * comparators by implementing the <code>ITokenComparator</code> interface and
 * overriding the <code>TextMergeViewer.createTokenComparator</code> factory
 * method).
 * <p>
 * Access to the <code>TextMergeViewer</code>'s model is by means of an
 * <code>IMergeViewerContentProvider</code>. Its <code>getXContent</code>
 * methods must return either an <code>IDocument</code>, an
 * <code>IDocumentRange</code>, or an <code>IStreamContentAccessor</code>. In
 * the <code>IDocumentRange</code> case the <code>TextMergeViewer</code> works
 * on a subrange of a document. In the <code>IStreamContentAccessor</code> case
 * a document is created internally and initialized from the stream.
 * <p>
 * A <code>TextMergeViewer</code> can be used as is. However clients may
 * subclass to customize the behavior. For example a
 * <code>MergeTextViewer</code> for Java would override the
 * <code>configureTextViewer</code> method to configure the
 * <code>TextViewer</code> for Java source code, the
 * <code>createTokenComparator</code> method to create a Java specific
 * tokenizer.
 * <p>
 * In 3.5 a new API has been introduced to let clients provide their own source
 * viewers implementation with an option to configure them basing on a
 * corresponding editor input.
 *
 * @see org.eclipse.compare.rangedifferencer.RangeDifferencer
 * @see org.eclipse.jface.text.TextViewer
 * @see ITokenComparator
 * @see IDocumentRange
 * @see org.eclipse.compare.IStreamContentAccessor
 */
public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
	private static final String COPY_LEFT_TO_RIGHT_INDICATOR = ">"; //$NON-NLS-1$
	private static final String COPY_RIGHT_TO_LEFT_INDICATOR = "<"; //$NON-NLS-1$
	private static final char ANCESTOR_CONTRIBUTOR = MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR;
	private static final char RIGHT_CONTRIBUTOR = MergeViewerContentProvider.RIGHT_CONTRIBUTOR;
	private static final char LEFT_CONTRIBUTOR = MergeViewerContentProvider.LEFT_CONTRIBUTOR;

	private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$

	static final boolean DEBUG= false;

	private static final boolean FIX_47640= true;

	private static final String[] GLOBAL_ACTIONS= {
		ActionFactory.UNDO.getId(),
		ActionFactory.REDO.getId(),
		ActionFactory.CUT.getId(),
		ActionFactory.COPY.getId(),
		ActionFactory.PASTE.getId(),
		ActionFactory.DELETE.getId(),
		ActionFactory.SELECT_ALL.getId(),
		ActionFactory.FIND.getId(),
		ITextEditorActionDefinitionIds.LINE_GOTO
	};
	private static final String[] TEXT_ACTIONS= {
		MergeSourceViewer.UNDO_ID,
		MergeSourceViewer.REDO_ID,
		MergeSourceViewer.CUT_ID,
		MergeSourceViewer.COPY_ID,
		MergeSourceViewer.PASTE_ID,
		MergeSourceViewer.DELETE_ID,
		MergeSourceViewer.SELECT_ALL_ID,
		MergeSourceViewer.FIND_ID,
		MergeSourceViewer.GOTO_LINE_ID
	};

	private static final String BUNDLE_NAME= "org.eclipse.compare.contentmergeviewer.TextMergeViewerResources"; //$NON-NLS-1$

	// the following symbolic constants must match the IDs in Compare's plugin.xml
	private static final String INCOMING_COLOR= "INCOMING_COLOR"; //$NON-NLS-1$
	private static final String OUTGOING_COLOR= "OUTGOING_COLOR"; //$NON-NLS-1$
	private static final String CONFLICTING_COLOR= "CONFLICTING_COLOR"; //$NON-NLS-1$
	private static final String RESOLVED_COLOR= "RESOLVED_COLOR"; //$NON-NLS-1$
	private static final String ADDITION_COLOR = "ADDITION_COLOR"; //$NON-NLS-1$
	private static final String DELETION_COLOR = "DELETION_COLOR"; //$NON-NLS-1$
	private static final String EDITION_COLOR = "EDITION_COLOR"; //$NON-NLS-1$

	// constants
	/** Width of left and right vertical bar */
	private static final int MARGIN_WIDTH= 6;
	/** Width of center bar */
	private static final int CENTER_WIDTH= 34;
	/** Width of birds eye view */
	private static final int BIRDS_EYE_VIEW_WIDTH= 12;
	/** Width of birds eye view */
	private static final int BIRDS_EYE_VIEW_INSET= 2;
	/** */
	private static final int RESOLVE_SIZE= 5;

	/** line width of change borders */
	private static final int LW= 1;

	private boolean fShowCurrentOnly= false;
	private boolean fShowCurrentOnly2= false;
	private int fMarginWidth= MARGIN_WIDTH;
	private int fTopInset;

	// Colors
	private RGB fBackground;
	private RGB fForeground;

	private boolean fIsUsingSystemForeground= true;
	private boolean fIsUsingSystemBackground= true;

	private static final class ColorPalette {
		public final RGB selected;
		public final RGB normal;
		public final RGB fill;
		public final RGB textFill;

		public ColorPalette(RGB background, String registryKey, RGB defaultRGB) {
			RGB registry = JFaceResources.getColorRegistry().getRGB(registryKey);
			if (registry != null) {
				selected = registry;
			} else {
				selected = defaultRGB;
			}
			normal = interpolate(selected, background, 0.6);
			fill = interpolate(selected, background, 0.9);
			textFill = interpolate(selected, background, 0.8);
		}

		private static RGB interpolate(RGB fg, RGB bg, double scale) {
			if (fg != null && bg != null)
				return new RGB((int) ((1.0 - scale) * fg.red + scale * bg.red),
						(int) ((1.0 - scale) * fg.green + scale * bg.green),
						(int) ((1.0 - scale) * fg.blue + scale * bg.blue));
			if (fg != null)
				return fg;
			if (bg != null)
				return bg;
			return new RGB(128, 128, 128); // a gray
		}
	}

	private ColorPalette incomingPalette;
	private ColorPalette conflictPalette;
	private ColorPalette outgoingPalette;
	private ColorPalette additionPalette;
	private ColorPalette deletionPalette;
	private ColorPalette editionPalette;
	private RGB RESOLVED;

	private IPreferenceStore fPreferenceStore;
	private IPropertyChangeListener fPreferenceChangeListener;

	private HashMap<Object, Position> fNewAncestorRanges= new HashMap<>();
	private HashMap<Object, Position> fNewLeftRanges= new HashMap<>();
	private HashMap<Object, Position> fNewRightRanges= new HashMap<>();

	private MergeSourceViewer fAncestor;
	private MergeSourceViewer fLeft;
	private MergeSourceViewer fRight;

	private int fLeftLineCount;
	private int fRightLineCount;

	private boolean fInScrolling;

	private int fPts[]= new int[8];	// scratch area for polygon drawing

	private int fInheritedDirection;	// inherited direction
	private int fTextDirection;			// requested direction for embedded SourceViewer

	private ActionContributionItem fIgnoreAncestorItem;
	private boolean fHighlightRanges;

	private boolean fShowPseudoConflicts= false;

	private boolean fUseSplines= true;
	private boolean fUseSingleLine= true;
	private boolean fHighlightTokenChanges = false;

	private String fSymbolicFontName;

	private ActionContributionItem fNextDiff;	// goto next difference
	private ActionContributionItem fPreviousDiff;	// goto previous difference
	private ActionContributionItem fCopyDiffLeftToRightItem;
	private ActionContributionItem fCopyDiffRightToLeftItem;

	private CompareHandlerService fHandlerService;

	private boolean fSynchronizedScrolling= true;

	private MergeSourceViewer fFocusPart;

	private boolean fSubDoc= true;
	private IPositionUpdater fPositionUpdater;
	private boolean fIsMac;

	private boolean fHasErrors;


	// SWT widgets
	private BufferedCanvas fAncestorCanvas;
	private BufferedCanvas fLeftCanvas;
	private BufferedCanvas fRightCanvas;
	private Canvas fScrollCanvas;
	private ScrollBar fVScrollBar;
	private Canvas fBirdsEyeCanvas;
	private Canvas fSummaryHeader;
	private HeaderPainter fHeaderPainter;

	// SWT resources to be disposed
	private Map<RGB, Color> fColors;

	// points for center curves
	private double[] fBasicCenterCurve;

	private Button fLeftToRightButton;
	private Button fRightToLeftButton;
	private Diff fButtonDiff;

	private ContributorInfo fLeftContributor;
	private ContributorInfo fRightContributor;
	private ContributorInfo fAncestorContributor;
	private int isRefreshing = 0;
	private int fSynchronziedScrollPosition;
	private ActionContributionItem fNextChange;
	private ActionContributionItem fPreviousChange;
	private ShowWhitespaceAction showWhitespaceAction;
	private InternalOutlineViewerCreator fOutlineViewerCreator;
	private TextEditorPropertyAction toggleLineNumbersAction;
	private IFindReplaceTarget fFindReplaceTarget;
	private ChangePropertyAction fIgnoreWhitespace;
	private List<ChangeCompareFilterPropertyAction> fCompareFilterActions = new ArrayList<>();
	private DocumentMerger fMerger;
	/** The current diff */
	private Diff fCurrentDiff;
	private Diff fSavedDiff;

	// Bug 259362 - Update diffs after undo
	private boolean copyOperationInProgress = false;
	private IUndoableOperation copyUndoable = null;
	private IOperationHistoryListener operationHistoryListener;

	/**
	 * Preference key for highlighting current line.
	 */
	private final static String CURRENT_LINE= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;
	/**
	 * Preference key for highlight color of current line.
	 */
	private final static String CURRENT_LINE_COLOR= AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;

	private List<SourceViewerDecorationSupport> fSourceViewerDecorationSupport = new ArrayList<>(3);
	// whether enhanced viewer configuration has been done
	private boolean isConfigured = false;
	private boolean fRedoDiff = false;

	private final class InternalOutlineViewerCreator extends OutlineViewerCreator implements ISelectionChangedListener {
		@Override
		public Viewer findStructureViewer(Viewer oldViewer,
				ICompareInput input, Composite parent,
				CompareConfiguration configuration) {
			if (input != getInput())
				return null;
			final Viewer v = CompareUI.findStructureViewer(oldViewer, input, parent, configuration);
			if (v != null) {
				v.getControl().addDisposeListener(e -> v.removeSelectionChangedListener(InternalOutlineViewerCreator.this));
				v.addSelectionChangedListener(this);
			}

			return v;
		}

		@Override
		public boolean hasViewerFor(Object input) {
			return true;
		}

		@Override
		public void selectionChanged(SelectionChangedEvent event) {
			ISelection s = event.getSelection();
			if (s instanceof IStructuredSelection) {
				IStructuredSelection ss = (IStructuredSelection) s;
				Object element = ss.getFirstElement();
				Diff diff = findDiff(element);
				if (diff != null)
					setCurrentDiff(diff, true);
			}
		}

		private Diff findDiff(Object element) {
			if (element instanceof ICompareInput) {
				ICompareInput ci = (ICompareInput) element;
				Position p = getPosition(ci.getLeft());
				if (p != null)
					return findDiff(p, true);
				p = getPosition(ci.getRight());
				if (p != null)
					return findDiff(p, false);
			}
			return null;
		}

		private Diff findDiff(Position p, boolean left) {
			for (Iterator<?> iterator = fMerger.rangesIterator(); iterator.hasNext();) {
				Diff diff = (Diff) iterator.next();
				Position diffPos;
				if (left) {
					diffPos = diff.getPosition(LEFT_CONTRIBUTOR);
				} else {
					diffPos = diff.getPosition(RIGHT_CONTRIBUTOR);
				}
				// If the element falls within a diff, highlight that diff
				if (diffPos.offset + diffPos.length >= p.offset && diff.getKind() != RangeDifference.NOCHANGE)
					return diff;
				// Otherwise, highlight the first diff after the elements position
				if (diffPos.offset >= p.offset)
					return diff;
			}
			return null;
		}

		private Position getPosition(ITypedElement left) {
			if (left instanceof DocumentRangeNode) {
				DocumentRangeNode drn = (DocumentRangeNode) left;
				return drn.getRange();
			}
			return null;
		}

		@Override
		public Object getInput() {
			return TextMergeViewer.this.getInput();
		}
	}

	class ContributorInfo implements IElementStateListener, VerifyListener, IDocumentListener, IEncodingSupport {
		private final TextMergeViewer fViewer;
		private final Object fElement;
		private char fLeg;
		private String fEncoding;
		private IDocumentProvider fDocumentProvider;
		private IEditorInput fDocumentKey;
		private ISelection fSelection;
		private int fTopIndex = -1;
		private boolean fNeedsValidation = false;
		private MergeSourceViewer fSourceViewer;

		public ContributorInfo(TextMergeViewer viewer, Object element, char leg) {
			fViewer = viewer;
			fElement = element;
			fLeg = leg;
			if (fElement instanceof IEncodedStreamContentAccessor) {
				try {
					fEncoding = ((IEncodedStreamContentAccessor) fElement).getCharset();
				} catch (CoreException e) {
					// silently ignored
				}
			}
		}

		@Override
		public void setEncoding(String encoding) {
			if (fDocumentKey == null || fDocumentProvider == null) {
				return;
			}
			if (fDocumentProvider instanceof IStorageDocumentProvider) {
				IStorageDocumentProvider provider = (IStorageDocumentProvider) fDocumentProvider;
				String current = provider.getEncoding(fDocumentKey);
				boolean dirty = fDocumentProvider.canSaveDocument(fDocumentKey);
				if (!dirty) {
					String internal = encoding == null ? "" : encoding; //$NON-NLS-1$
					if (!internal.equals(current)) {
						provider.setEncoding(fDocumentKey, encoding);
						try {
							fDocumentProvider.resetDocument(fDocumentKey);
						} catch (CoreException e) {
							CompareUIPlugin.log(e);
						} finally {
							update(true);
							updateStructure(fLeg);
						}
					}
				}
			}
		}

		@Override
		public String getEncoding() {
			if (fDocumentProvider != null && fDocumentKey != null
					&& fDocumentProvider instanceof IStorageDocumentProvider) {
				IStorageDocumentProvider provider = (IStorageDocumentProvider) fDocumentProvider;
				return provider.getEncoding(fDocumentKey);
			}
			return null;
		}

		@Override
		public String getDefaultEncoding() {
			if (fDocumentProvider != null && fDocumentKey != null
					&& fDocumentProvider instanceof IStorageDocumentProvider) {
				IStorageDocumentProvider provider = (IStorageDocumentProvider) fDocumentProvider;
				return provider.getDefaultEncoding();
			}
			return null;
		}

		private String internalGetEncoding() {
			if (fElement instanceof IEncodedStreamContentAccessor) {
				try {
					fEncoding = ((IEncodedStreamContentAccessor) fElement)
							.getCharset();
				} catch (CoreException e) {
					// silently ignored
				}
			}
			if (fEncoding != null) {
				return fEncoding;
			}
			return ResourcesPlugin.getEncoding();
		}

		public void setEncodingIfAbsent(ContributorInfo otherContributor) {
			if (fEncoding == null)
				fEncoding = otherContributor.fEncoding;
		}

		public IDocument getDocument() {
			if (fDocumentProvider != null) {
				IDocument document = fDocumentProvider.getDocument(getDocumentKey());
				if (document != null)
					return document;
			}
			if (fElement instanceof IDocument)
				return (IDocument) fElement;
			if (fElement instanceof IDocumentRange)
				return ((IDocumentRange) fElement).getDocument();
			if (fElement instanceof IStreamContentAccessor)
				return DocumentManager.get(fElement);
			return null;
		}

		public void setDocument(MergeSourceViewer viewer, boolean isEditable) {
			// Ensure that this method is only called once
			Assert.isTrue(fSourceViewer == null);
			fSourceViewer = viewer;
			try {
				internalSetDocument(viewer);
			} catch (RuntimeException e) {
				// The error may be due to a stale entry in the DocumentManager (see bug 184489)
				clearCachedDocument();
				throw e;
			}
			setEditable(viewer.getSourceViewer(), isEditable);
			// Verify changes if the document is editable
			if (isEditable) {
				fNeedsValidation = true;
				viewer.getSourceViewer().getTextWidget().addVerifyListener(this);
			}
		}

		/*
		 * Returns true if a new Document could be installed.
		 */
		private boolean internalSetDocument(MergeSourceViewer tp) {

			if (tp == null)
				return false;

			IDocument newDocument = null;
			Position range= null;

			if (fElement instanceof IDocumentRange) {
				newDocument= ((IDocumentRange) fElement).getDocument();
				range= ((IDocumentRange) fElement).getRange();
				connectToSharedDocument();

			} else if (fElement instanceof IDocument) {
				newDocument= (IDocument) fElement;
				setupDocument(newDocument);

			} else if (fElement instanceof IStreamContentAccessor) {
				newDocument= DocumentManager.get(fElement);
				if (newDocument == null) {
					newDocument = createDocument();
					DocumentManager.put(fElement, newDocument);
					setupDocument(newDocument);
				} else if (fDocumentProvider == null) {
					// Connect to a shared document so we can get the proper save synchronization
					connectToSharedDocument();
				}
			} else if (fElement == null) {	// deletion on one side

				ITypedElement parent= this.fViewer.getParent(fLeg);	// we try to find an insertion position within the deletion's parent

				if (parent instanceof IDocumentRange) {
					newDocument= ((IDocumentRange) parent).getDocument();
					newDocument.addPositionCategory(DIFF_RANGE_CATEGORY);
					Object input= this.fViewer.getInput();
					range= this.fViewer.getNewRange(fLeg, input);
					if (range == null) {
						int pos= 0;
						if (input instanceof ICompareInput)
							pos= this.fViewer.findInsertionPosition(fLeg, (ICompareInput) input);
						range= new Position(pos, 0);
						try {
							newDocument.addPosition(DIFF_RANGE_CATEGORY, range);
						} catch (BadPositionCategoryException ex) {
							// silently ignored
							if (TextMergeViewer.DEBUG) System.out.println("BadPositionCategoryException: " + ex);	//$NON-NLS-1$
						} catch (BadLocationException ex) {
							// silently ignored
							if (TextMergeViewer.DEBUG) System.out.println("BadLocationException: " + ex);	//$NON-NLS-1$
						}
						this.fViewer.addNewRange(fLeg, input, range);
					}
				} else if (parent instanceof IDocument) {
					newDocument= ((IDocumentRange) fElement).getDocument();
				}
			}

			boolean enabled= true;
			if (newDocument == null) {
				newDocument= new Document(""); //$NON-NLS-1$
				enabled= false;
			}

			// Update the viewer document or range
			IDocument oldDoc= tp.getSourceViewer().getDocument();
			if (newDocument != oldDoc) {
				updateViewerDocument(tp, newDocument, range);
			} else {	// same document but different range
				updateViewerDocumentRange(tp, range);
			}
			newDocument.addDocumentListener(this);

			tp.setEnabled(enabled);

			return enabled;
		}

		/*
		 * The viewer document is the same but the range has changed
		 */
		private void updateViewerDocumentRange(MergeSourceViewer tp, Position range) {
			tp.setRegion(range);
			if (this.fViewer.fSubDoc) {
				if (range != null) {
					IRegion r= this.fViewer.normalizeDocumentRegion(tp.getSourceViewer().getDocument(), TextMergeViewer.toRegion(range));
					tp.getSourceViewer().setVisibleRegion(r.getOffset(), r.getLength());
				} else
					tp.getSourceViewer().resetVisibleRegion();
			} else
				tp.getSourceViewer().resetVisibleRegion();
		}

		/*
		 * The viewer has a new document
		 */
		private void updateViewerDocument(MergeSourceViewer tp, IDocument document, Position range) {
			unsetDocument(tp);
			if (document == null)
				return;

			connectPositionUpdater(document);

			// install new document
			tp.setRegion(range);
			SourceViewer sourceViewer = tp.getSourceViewer();
			sourceViewer.setRedraw(false);
			try {
				if (this.fViewer.fSubDoc && range != null) {
					IRegion r= this.fViewer.normalizeDocumentRegion(document, TextMergeViewer.toRegion(range));
					sourceViewer.setDocument(document, r.getOffset(), r.getLength());
				} else {
					sourceViewer.setDocument(document);
				}
			} finally {
				sourceViewer.setRedraw(true);
			}

			tp.rememberDocument(document);
		}

		void connectPositionUpdater(IDocument document) {
			document.addPositionCategory(DIFF_RANGE_CATEGORY);
			if (this.fViewer.fPositionUpdater == null)
				this.fViewer.fPositionUpdater= this.fViewer.new ChildPositionUpdater(DIFF_RANGE_CATEGORY);
			else
				document.removePositionUpdater(this.fViewer.fPositionUpdater);
			document.addPositionUpdater(this.fViewer.fPositionUpdater);
		}

		private void unsetDocument(MergeSourceViewer tp) {
			IDocument oldDoc= internalGetDocument(tp);
			if (oldDoc != null) {
				tp.rememberDocument(null);
				try {
					oldDoc.removePositionCategory(DIFF_RANGE_CATEGORY);
				} catch (BadPositionCategoryException ex) {
					// Ignore
				}
				if (fPositionUpdater != null)
					oldDoc.removePositionUpdater(fPositionUpdater);
				oldDoc.removeDocumentListener(this);
			}
		}

		private IDocument createDocument() {
			// If the content provider is a text content provider, attempt to obtain
			// a shared document (i.e. file buffer)
			IDocument newDoc = connectToSharedDocument();

			if (newDoc == null) {
				IStreamContentAccessor sca= (IStreamContentAccessor) fElement;
				String s= null;

				try {
					String encoding = internalGetEncoding();
					s = Utilities.readString(sca, encoding);
				} catch (CoreException ex) {
					this.fViewer.setError(fLeg, ex.getMessage());
				}

				newDoc= new Document(s != null ? s : ""); //$NON-NLS-1$
			}
			return newDoc;
		}

		/**
		 * Connect to a shared document if possible. Return <code>null</code>
		 * if the connection was not possible.
		 * @return the shared document or <code>null</code> if connection to a
		 * shared document was not possible
		 */
		private IDocument connectToSharedDocument() {
			IEditorInput key = getDocumentKey();
			if (key != null) {
				if (fDocumentProvider != null) {
					// We've already connected and setup the document
					return fDocumentProvider.getDocument(key);
				}
				IDocumentProvider documentProvider = getDocumentProvider();
				if (documentProvider != null) {
					try {
						connect(documentProvider, key);
						setCachedDocumentProvider(key,
								documentProvider);
						IDocument newDoc = documentProvider.getDocument(key);
						this.fViewer.updateDirtyState(key, documentProvider, fLeg);
						return newDoc;
					} catch (CoreException e) {
						// Connection failed. Log the error and continue without a shared document
						CompareUIPlugin.log(e);
					}
				}
			}
			return null;
		}

		private void connect(IDocumentProvider documentProvider, IEditorInput input) throws CoreException {
			final ISharedDocumentAdapter sda = Adapters.adapt(fElement, ISharedDocumentAdapter.class);
			if (sda != null) {
				sda.connect(documentProvider, input);
			} else {
				documentProvider.connect(input);
			}
		}

		private void disconnect(IDocumentProvider provider, IEditorInput input) {
			final ISharedDocumentAdapter sda = Adapters.adapt(fElement, ISharedDocumentAdapter.class);
			if (sda != null) {
				sda.disconnect(provider, input);
			} else {
				provider.disconnect(input);
			}
		}

		private void setCachedDocumentProvider(IEditorInput key,
				IDocumentProvider documentProvider) {
			fDocumentKey = key;
			fDocumentProvider = documentProvider;
			documentProvider.addElementStateListener(this);
		}

		public void disconnect() {
			IDocumentProvider provider = null;
			IEditorInput input = getDocumentKey();
			synchronized(this) {
				if (fDocumentProvider != null) {
					provider = fDocumentProvider;
					fDocumentProvider = null;
					fDocumentKey = null;
				}
			}
			if (provider != null) {
				disconnect(provider, input);
				provider.removeElementStateListener(this);
			}
			// If we have a listener registered with the widget, remove it
			if (fSourceViewer != null) {
				StyledText textWidget = fSourceViewer.getSourceViewer().getTextWidget();
				if (textWidget != null && !textWidget.isDisposed()) {
					if (fNeedsValidation) {
						textWidget.removeVerifyListener(this);
						fNeedsValidation = false;
					}
					IDocument oldDoc= internalGetDocument(fSourceViewer);
					if (oldDoc != null) {
						oldDoc.removeDocumentListener(this);
					}
				}
			}
			clearCachedDocument();
		}

		private void clearCachedDocument() {
			// Finally, remove the document from the document manager
			IDocument doc = DocumentManager.get(fElement);
			if (doc != null)
				DocumentManager.remove(doc);
		}

		private IDocument internalGetDocument(MergeSourceViewer tp) {
			IDocument oldDoc= tp.getSourceViewer().getDocument();
			if (oldDoc == null) {
				oldDoc= tp.getRememberedDocument();
			}
			return oldDoc;
		}

		/**
		 * Return the document key used to obtain a shared document. A <code>null</code>
		 * is returned in the following cases:
		 * <ol>
		 * <li>This contributor does not have a shared document adapter.</li>
		 * <li>This text merge viewer has a document partitioner but uses the default partitioning.</li>
		 * <li>This text merge viewer does not use he default content provider.</li>
		 * </ol>
		 * @return the document key used to obtain a shared document or <code>null</code>
		 */
		private IEditorInput getDocumentKey() {
			if (fDocumentKey != null)
				return fDocumentKey;
			if (isUsingDefaultContentProvider() && fElement != null && canHaveSharedDocument()) {
				ISharedDocumentAdapter sda = Adapters.adapt(fElement, ISharedDocumentAdapter.class);
				if (sda != null) {
					return sda.getDocumentKey(fElement);
				}
			}
			return null;
		}

		private IDocumentProvider getDocumentProvider() {
			if (fDocumentProvider != null)
				return fDocumentProvider;
			// We will only use document providers if the content provider is the
			// default content provider
			if (isUsingDefaultContentProvider()) {
				IEditorInput input = getDocumentKey();
				if (input != null)
					return SharedDocumentAdapter.getDocumentProvider(input);
			}
			return null;
		}

		private boolean isUsingDefaultContentProvider() {
			return fViewer.isUsingDefaultContentProvider();
		}

		private boolean canHaveSharedDocument() {
			return fViewer.canHaveSharedDocument();
		}

		boolean hasSharedDocument(Object object) {
			return (fElement == object &&
					fDocumentProvider != null
					&& fDocumentProvider.getDocument(getDocumentKey()) != null);
		}

		public boolean flush() throws CoreException {
			if (fDocumentProvider != null) {
				IEditorInput input = getDocumentKey();
				IDocument document = fDocumentProvider.getDocument(input);
				if (document != null) {
					final ISharedDocumentAdapter sda = Adapters.adapt(fElement, ISharedDocumentAdapter.class);
					if (sda != null) {
						sda.flushDocument(fDocumentProvider, input, document, false);
						return true;
					}
					try {
						fDocumentProvider.aboutToChange(input);
						fDocumentProvider.saveDocument(new NullProgressMonitor(), input, document, false);
						return true;
					} finally {
						fDocumentProvider.changed(input);
					}
				}
			}
			return false;
		}

		@Override
		public void elementMoved(Object originalElement, Object movedElement) {
			IEditorInput input = getDocumentKey();
			if (input != null && input.equals(originalElement)) {
				// This method will only get called if the buffer is not dirty
				resetDocument();
			}
		}

		@Override
		public void elementDirtyStateChanged(Object element, boolean isDirty) {
			if (!checkState())
				return;
			IEditorInput input = getDocumentKey();
			if (input != null && input.equals(element)) {
				this.fViewer.updateDirtyState(input, getDocumentProvider(), fLeg);
			}
		}

		@Override
		public void elementDeleted(Object element) {
			IEditorInput input = getDocumentKey();
			if (input != null && input.equals(element)) {
				// This method will only get called if the buffer is not dirty
				resetDocument();
			}
		}
		private void resetDocument() {
			// Need to remove the document from the manager before refreshing
			// or the old document will still be found
			clearCachedDocument();
			// TODO: This is fine for now but may need to be revisited if a refresh is performed
			// higher up as well (e.g. perhaps a refresh request that waits until after all parties
			// have been notified).
			if (checkState())
				fViewer.refresh();
		}

		private boolean checkState() {
			if (fViewer == null)
				return false;
			Control control = fViewer.getControl();
			if (control == null)
				return false;
			return !control.isDisposed();
		}

		@Override
		public void elementContentReplaced(Object element) {
			if (!checkState())
				return;
			IEditorInput input = getDocumentKey();
			if (input != null && input.equals(element)) {
				this.fViewer.updateDirtyState(input, getDocumentProvider(), fLeg);

				// recalculate diffs and update controls
				new UIJob(CompareMessages.DocumentMerger_0) {
					@Override
					public IStatus runInUIThread(IProgressMonitor monitor) {
						update(true);
						updateStructure(fLeg);
						return Status.OK_STATUS;
					}
				}.schedule();
			}
		}
		@Override
		public void elementContentAboutToBeReplaced(Object element) {
			// Nothing to do
		}

		public Object getElement() {
			return fElement;
		}

		public void cacheSelection(MergeSourceViewer viewer) {
			if (viewer == null) {
				this.fSelection = null;
				this.fTopIndex = -1;
			} else {
				this.fSelection = viewer.getSourceViewer().getSelection();
				this.fTopIndex = viewer.getSourceViewer().getTopIndex();
			}
		}

		public void updateSelection(MergeSourceViewer viewer, boolean includeScroll) {
			if (fSelection != null)
				viewer.getSourceViewer().setSelection(fSelection);
			if (includeScroll && fTopIndex != -1) {
				viewer.getSourceViewer().setTopIndex(fTopIndex);
			}
		}

		public void transferContributorStateFrom(
				ContributorInfo oldContributor) {
			if (oldContributor != null) {
				fSelection = oldContributor.fSelection;
				fTopIndex = oldContributor.fTopIndex;
				fEncoding = oldContributor.fEncoding;
			}

		}

		public boolean validateChange() {
			if (fElement == null)
				return true;
			if (fDocumentProvider instanceof IDocumentProviderExtension) {
				IDocumentProviderExtension ext = (IDocumentProviderExtension) fDocumentProvider;
				if (ext.isReadOnly(fDocumentKey)) {
					try {
						ext.validateState(fDocumentKey, getControl().getShell());
						ext.updateStateCache(fDocumentKey);
					} catch (CoreException e) {
						ErrorDialog.openError(getControl().getShell(), CompareMessages.TextMergeViewer_12, CompareMessages.TextMergeViewer_13, e.getStatus());
						return false;
					}
				}
				return !ext.isReadOnly(fDocumentKey);
			}
			IEditableContentExtension ext = Adapters.adapt(fElement, IEditableContentExtension.class);
			if (ext != null) {
				if (ext.isReadOnly()) {
					IStatus status = ext.validateEdit(getControl().getShell());
					if (!status.isOK()) {
						if (status.getSeverity() == IStatus.ERROR) {
							ErrorDialog.openError(getControl().getShell(), CompareMessages.TextMergeViewer_14, CompareMessages.TextMergeViewer_15, status);
							return false;
						}
						if (status.getSeverity() == IStatus.CANCEL)
							return false;
					}
				}
			}
			return true;
		}

		@Override
		public void verifyText(VerifyEvent e) {
			if (!validateChange()) {
				e.doit= false;
			}
		}

		@Override
		public void documentAboutToBeChanged(DocumentEvent e) {
			// nothing to do
		}

		@Override
		public void documentChanged(DocumentEvent e) {
			boolean dirty = true;
			if (fDocumentProvider != null && fDocumentKey != null) {
				dirty = fDocumentProvider.canSaveDocument(fDocumentKey);
			}
			TextMergeViewer.this.documentChanged(e, dirty);
			// Remove our verify listener since the document is now dirty
			if (fNeedsValidation && fSourceViewer != null && !fSourceViewer.getSourceViewer().getTextWidget().isDisposed()) {
				fSourceViewer.getSourceViewer().getTextWidget().removeVerifyListener(this);
				fNeedsValidation = false;
			}
		}
	}

	class HeaderPainter implements PaintListener {
		private static final int INSET= BIRDS_EYE_VIEW_INSET;

		private RGB fIndicatorColor;
		private Color fSeparatorColor;

		public HeaderPainter() {
			fSeparatorColor= fSummaryHeader.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
		}

		/*
		 * Returns true on color change
		 */
		public boolean setColor(RGB color) {
			RGB oldColor= fIndicatorColor;
			fIndicatorColor= color;
			if (color == null)
				return oldColor != null;
			if (oldColor != null)
				return !color.equals(oldColor);
			return true;
		}

		private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topLeft, Color bottomRight) {
			gc.setForeground(topLeft);
			gc.drawLine(x, y, x + w -1, y);
			gc.drawLine(x, y, x, y + h -1);

			gc.setForeground(bottomRight);
			gc.drawLine(x + w, y, x + w, y + h);
			gc.drawLine(x, y + h, x + w, y + h);
		}

		@Override
		public void paintControl(PaintEvent e) {
			Point s= fSummaryHeader.getSize();

			if (fIndicatorColor != null) {
				Display d= fSummaryHeader.getDisplay();
				e.gc.setBackground(getColor(d, fIndicatorColor));
				int min= Math.min(s.x, s.y)-2*INSET;
				Rectangle r= new Rectangle((s.x-min)/2, (s.y-min)/2, min, min);
				e.gc.fillRectangle(r);
				if (d != null)
					drawBevelRect(e.gc, r.x, r.y, r.width -1, r.height -1, d.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), d.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));

				e.gc.setForeground(fSeparatorColor);
				e.gc.setLineWidth(0 /* 1 */);
				e.gc.drawLine(0+1, s.y-1, s.x-1-1, s.y-1);
			}
		}
	}

	/*
	 * The position updater used to adapt the positions representing
	 * the child document ranges to changes of the parent document.
	 */
	class ChildPositionUpdater extends DefaultPositionUpdater {
		/*
		 * Creates the position updated.
		 */
		protected ChildPositionUpdater(String category) {
			super(category);
		}

		/*
		 * Child document ranges cannot be deleted other then by calling
		 * freeChildDocument.
		 */
		@Override
		protected boolean notDeleted() {
			return true;
		}

		/*
		 * If an insertion happens at a child document's start offset, the
		 * position is extended rather than shifted. Also, if something is added
		 * right behind the end of the position, the position is extended rather
		 * than kept stable.
		 */
		@Override
		protected void adaptToInsert() {
			if (fPosition == fLeft.getRegion() || fPosition == fRight.getRegion()) {
				int myStart= fPosition.offset;
				int myEnd=   fPosition.offset + fPosition.length;
				myEnd= Math.max(myStart, myEnd);

				int yoursStart= fOffset;
				int yoursEnd=   fOffset + fReplaceLength -1;
				yoursEnd= Math.max(yoursStart, yoursEnd);

				if (myEnd < yoursStart)
					return;

				if (myStart <= yoursStart)
					fPosition.length += fReplaceLength;
				else
					fPosition.offset += fReplaceLength;
			} else {
				super.adaptToInsert();
			}
		}
	}

	private class ChangeHighlighter implements ITextPresentationListener {
		private final MergeSourceViewer viewer;

		public ChangeHighlighter(MergeSourceViewer viewer) {
			this.viewer = viewer;
		}

		@Override
		public void applyTextPresentation(TextPresentation textPresentation) {
			if (!fHighlightTokenChanges)
				return;
			IRegion region= textPresentation.getExtent();
			Diff[] changeDiffs = fMerger.getChangeDiffs(getLeg(viewer), region);
			boolean allOutgoing = allOutgoing();
			for (Diff diff : changeDiffs) {
				StyleRange range = getStyleRange(diff, region, allOutgoing);
				if (range != null)
					textPresentation.mergeStyleRange(range);
			}
		}

		private StyleRange getStyleRange(Diff diff, IRegion region, boolean showAdditionRemoval) {
			//Color cText = getColor(null, getTextColor());
			Color cTextFill = getColor(null, getTextFillColor(diff, showAdditionRemoval));
			if (cTextFill == null)
				return null;
			Position p = diff.getPosition(getLeg(viewer));
			int start = p.getOffset();
			int length = p.getLength();
			// Don't start before the region
			if (start < region.getOffset()) {
				length = length - (region.getOffset() - start);
				start = region.getOffset();
			}
			// Don't go past the end of the region
			int regionEnd = region.getOffset() + region.getLength();
			if (start + length > regionEnd) {
				length = regionEnd - start;
			}
			if (length < 0)
				return null;

			return new StyleRange(start, length, null, cTextFill);
		}

		private RGB getTextFillColor(Diff diff, boolean showAdditionRemoval) {
			ColorPalette palette = getColorPalette(diff, showAdditionRemoval);
			if (palette == null) {
				return null;
			}
			return palette.textFill;
		}
	}

	private class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, IFindReplaceTargetExtension2, IFindReplaceTargetExtension3 {
		@Override
		public boolean canPerformFind() {
			return fFocusPart != null;
		}

		@Override
		public int findAndSelect(int widgetOffset, String findString,
				boolean searchForward, boolean caseSensitive, boolean wholeWord) {
			return Optional.ofNullable(getTarget()).map(
					target -> target.findAndSelect(widgetOffset, findString, searchForward, caseSensitive, wholeWord))
					.orElse(-1);
		}

		private IFindReplaceTarget getTarget() {
			return Optional.ofNullable(fFocusPart).map(MergeSourceViewer::getSourceViewer)
					.map(SourceViewer::getFindReplaceTarget)
					.orElse(null);
		}

		@Override
		public Point getSelection() {
			return Optional.ofNullable(getTarget()).map(target -> target.getSelection())
					.orElse(new Point(-1, -1));
		}

		@Override
		public String getSelectionText() {
			return Optional.ofNullable(getTarget()).map(IFindReplaceTarget::getSelectionText).orElse(""); //$NON-NLS-1$
		}

		@Override
		public boolean isEditable() {
			return Optional.ofNullable(getTarget()).map(IFindReplaceTarget::isEditable).orElse(false);
		}

		@Override
		public void replaceSelection(String text) {
			Optional.ofNullable(getTarget()).ifPresent(target -> target.replaceSelection(text));
		}

		@Override
		public int findAndSelect(int offset, String findString, boolean searchForward, boolean caseSensitive, boolean wholeWord, boolean regExSearch) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension3) {
				return ((IFindReplaceTargetExtension3) findReplaceTarget).findAndSelect(offset, findString, searchForward, caseSensitive, wholeWord, regExSearch);
			}

			// fallback like in org.eclipse.ui.texteditor.FindReplaceTarget
			if (!regExSearch && findReplaceTarget != null)
				return findReplaceTarget.findAndSelect(offset, findString, searchForward, caseSensitive, wholeWord);
			return -1;
		}

		@Override
		public void replaceSelection(String text, boolean regExReplace) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension3) {
				((IFindReplaceTargetExtension3) findReplaceTarget).replaceSelection(text, regExReplace);
				return;
			}

			// fallback like in org.eclipse.ui.texteditor.FindReplaceTarget
			if (!regExReplace && findReplaceTarget != null)
				findReplaceTarget.replaceSelection(text);
		}

		@Override
		public boolean validateTargetState() {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension2) {
				return ((IFindReplaceTargetExtension2) findReplaceTarget).validateTargetState();
			}
			// TODO not sure if true when findReplaceTarget is null
			return true;
		}

		@Override
		public void beginSession() {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).beginSession();
			}
		}

		@Override
		public void endSession() {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).endSession();
			}
		}

		@Override
		public IRegion getScope() {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				return ((IFindReplaceTargetExtension) findReplaceTarget).getScope();
			}
			return null;
		}

		@Override
		public void setScope(IRegion scope) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).setScope(scope);
			}
		}

		@Override
		public Point getLineSelection() {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				return ((IFindReplaceTargetExtension) findReplaceTarget).getLineSelection();
			}
			return null;
		}

		@Override
		public void setSelection(int offset, int length) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).setSelection(offset, length);
			}
		}

		@Override
		public void setScopeHighlightColor(Color color) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).setScopeHighlightColor(color);
			}
		}

		@Override
		public void setReplaceAllMode(boolean replaceAll) {
			IFindReplaceTarget findReplaceTarget = getTarget();
			if (findReplaceTarget instanceof IFindReplaceTargetExtension) {
				((IFindReplaceTargetExtension) findReplaceTarget).setReplaceAllMode(replaceAll);
			}
		}

	}

	//---- MergeTextViewer

	/**
	 * Creates a text merge viewer under the given parent control.
	 *
	 * @param parent the parent control
	 * @param configuration the configuration object
	 */
	public TextMergeViewer(Composite parent, CompareConfiguration configuration) {
		this(parent, SWT.NULL, configuration);
	}

	/**
	 * Creates a text merge viewer under the given parent control.
	 *
	 * @param parent the parent control
	 * @param style SWT style bits for top level composite of this viewer
	 * @param configuration the configuration object
	 */
	public TextMergeViewer(Composite parent, int style, CompareConfiguration configuration) {
		super(style, ResourceBundle.getBundle(BUNDLE_NAME), configuration);

		operationHistoryListener = event -> TextMergeViewer.this.historyNotification(event);
		OperationHistoryFactory.getOperationHistory()
				.addOperationHistoryListener(operationHistoryListener);

		fMerger = new DocumentMerger(new IDocumentMergerInput() {
			@Override
			public ITokenComparator createTokenComparator(String line) {
				return TextMergeViewer.this.createTokenComparator(line);
			}
			@Override
			public CompareConfiguration getCompareConfiguration() {
				return TextMergeViewer.this.getCompareConfiguration();
			}
			@Override
			public IDocument getDocument(char contributor) {
				switch (contributor) {
				case LEFT_CONTRIBUTOR:
					return fLeft.getSourceViewer().getDocument();
				case RIGHT_CONTRIBUTOR:
					return fRight.getSourceViewer().getDocument();
				case ANCESTOR_CONTRIBUTOR:
					return fAncestor.getSourceViewer().getDocument();
				default:
					return null;
				}
			}
			@Override
			public int getHunkStart() {
				return TextMergeViewer.this.getHunkStart();
			}
			@Override
			public Position getRegion(char contributor) {
				switch (contributor) {
				case LEFT_CONTRIBUTOR:
					return fLeft.getRegion();
				case RIGHT_CONTRIBUTOR:
					return fRight.getRegion();
				case ANCESTOR_CONTRIBUTOR:
					return fAncestor.getRegion();
				default:
					return null;
				}
			}
			@Override
			public boolean isHunkOnLeft() {
				ITypedElement left = ((ICompareInput) getInput()).getRight();
				return left != null && Adapters.adapt(left, IHunk.class) != null;
			}
			@Override
			public boolean isIgnoreAncestor() {
				return TextMergeViewer.this.isIgnoreAncestor();
			}
			@Override
			public boolean isPatchHunk() {
				return TextMergeViewer.this.isPatchHunk();
			}

			@Override
			public boolean isShowPseudoConflicts() {
				return fShowPseudoConflicts;
			}
			@Override
			public boolean isThreeWay() {
				return TextMergeViewer.this.isThreeWay();
			}
			@Override
			public boolean isPatchHunkOk() {
				return TextMergeViewer.this.isPatchHunkOk();
			}
		});

		int inheritedStyle= parent.getStyle();
		if ((inheritedStyle & SWT.LEFT_TO_RIGHT) != 0)
			fInheritedDirection= SWT.LEFT_TO_RIGHT;
		else if ((inheritedStyle & SWT.RIGHT_TO_LEFT) != 0)
			fInheritedDirection= SWT.RIGHT_TO_LEFT;
		else
			fInheritedDirection= SWT.NONE;

		if ((style & SWT.LEFT_TO_RIGHT) != 0)
			fTextDirection= SWT.LEFT_TO_RIGHT;
		else if ((style & SWT.RIGHT_TO_LEFT) != 0)
			fTextDirection= SWT.RIGHT_TO_LEFT;
		else
			fTextDirection= SWT.NONE;

		fSymbolicFontName= getSymbolicFontName();

		fIsMac= Util.isMac();

		fPreferenceChangeListener= event -> TextMergeViewer.this.handlePropertyChangeEvent(event);

		fPreferenceStore= createChainedPreferenceStore();
		if (fPreferenceStore != null) {
			fPreferenceStore.addPropertyChangeListener(fPreferenceChangeListener);

			fSynchronizedScrolling= fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING);
			fShowPseudoConflicts= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS);
			//fUseSplines= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES);
			fUseSingleLine= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SINGLE_LINE);
			fHighlightTokenChanges= fPreferenceStore.getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES);
			//fUseResolveUI= fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI);
		}

		buildControl(parent);

		setColors();

		INavigatable nav= new INavigatable() {
			@Override
			public boolean selectChange(int flag) {
				if (flag == INavigatable.FIRST_CHANGE || flag == INavigatable.LAST_CHANGE) {
					selectFirstDiff(flag == INavigatable.FIRST_CHANGE);
					return false;
				}
				return navigate(flag == INavigatable.NEXT_CHANGE, false, false);
			}
			@Override
			public Object getInput() {
				return TextMergeViewer.this.getInput();
			}
			@Override
			public boolean openSelectedChange() {
				return false;
			}
			@Override
			public boolean hasChange(int flag) {
				return getNextVisibleDiff(flag == INavigatable.NEXT_CHANGE, false) != null;
			}
		};
		fComposite.setData(INavigatable.NAVIGATOR_PROPERTY, nav);

		JFaceResources.getFontRegistry().addListener(fPreferenceChangeListener);
		JFaceResources.getColorRegistry().addListener(fPreferenceChangeListener);
		updateFont();
	}

	private static class LineNumberRulerToggleAction extends TextEditorPropertyAction {
		public LineNumberRulerToggleAction(String label, MergeSourceViewer[] viewers, String preferenceKey) {
			super(label, viewers, preferenceKey);
		}

		@Override
		protected boolean toggleState(boolean checked) {
			return true;
		}
	}

	private ChainedPreferenceStore createChainedPreferenceStore() {
		List<IPreferenceStore> stores= new ArrayList<>(2);
		stores.add(getCompareConfiguration().getPreferenceStore());
		stores.add(EditorsUI.getPreferenceStore());
		return new ChainedPreferenceStore(stores.toArray(new IPreferenceStore[stores.size()]));
	}

	/**
	 * Creates a color from the information stored in the given preference store.
	 * Returns <code>null</code> if there is no such information available.
	 * @param store preference store
	 * @param key preference key
	 * @return the color or <code>null</code>
	 */
	private static RGB createColor(IPreferenceStore store, String key) {
		if (!store.contains(key))
			return null;
		if (store.isDefault(key))
			return PreferenceConverter.getDefaultColor(store, key);
		return PreferenceConverter.getColor(store, key);
	}

	private void setColors() {
		fIsUsingSystemBackground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
		if (!fIsUsingSystemBackground)
			fBackground= createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND);

		fIsUsingSystemForeground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT);
		if (!fIsUsingSystemForeground)
			fForeground= createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND);

		updateColors(null);
	}

	private String getSymbolicFontName() {
		Class<?> clazz= getClass();
		do {
			String fontName= clazz.getName();
			if (JFaceResources.getFontRegistry().hasValueFor(fontName))
				return fontName;
			clazz= clazz.getSuperclass();
		} while (clazz != null);
		// use text compare font if no font has been registered for subclass
		return getClass().getName();
	}

	private void updateFont() {
		Font f= JFaceResources.getFont(fSymbolicFontName);
		if (f != null) {
			if (fAncestor != null)
				fAncestor.setFont(f);
			if (fLeft != null)
				fLeft.setFont(f);
			if (fRight != null)
				fRight.setFont(f);
		}
	}

	private void checkForColorUpdate(Display display) {
		if (fIsUsingSystemBackground) {
			RGB bg= display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB();
			if (!bg.equals(getBackground(display))) {
				updateColors(display);
			}
		}
	}

	/**
	 * Sets the viewer's background color to the given RGB value.
	 * If the value is <code>null</code> the system's default background color is used.
	 * @param background the background color or <code>null</code> to use the system's default background color
	 * @since 2.0
	 */
	public void setBackgroundColor(RGB background) {
		fIsUsingSystemBackground= (background == null);
		fBackground= background;
		updateColors(null);
	}

	private RGB getBackground(Display display) {
		if (fBackground != null)
			return fBackground;

		if (display == null)
			display= fComposite.getDisplay();

		return display.getSystemColor(SWT.COLOR_LIST_BACKGROUND).getRGB();
	}

	/**
	 * Sets the viewer's foreground color to the given RGB value.
	 * If the value is <code>null</code> the system's default foreground color is used.
	 * @param foreground the foreground color or <code>null</code> to use the system's default foreground color
	 * @since 2.0
	 */
	public void setForegroundColor(RGB foreground) {
		fIsUsingSystemForeground= (foreground == null);
		fForeground= foreground;
		updateColors(null);
	}

	private void updateColors(Display display) {

		if (display == null)
			display = fComposite.getDisplay();

		Color bgColor = null;
		if (fBackground != null)
			bgColor = getColor(display, fBackground);

		if (fAncestor != null)
			fAncestor.setBackgroundColor(bgColor);
		if (fLeft != null)
			fLeft.setBackgroundColor(bgColor);
		if (fRight != null)
			fRight.setBackgroundColor(bgColor);

		Color fgColor = null;
		if (fForeground != null)
			fgColor = getColor(display, fForeground);

		if (fAncestor != null)
			fAncestor.setForegroundColor(fgColor);
		if (fLeft != null)
			fLeft.setForegroundColor(fgColor);
		if (fRight != null)
			fRight.setForegroundColor(fgColor);

		ColorRegistry registry= JFaceResources.getColorRegistry();

		RGB bg= getBackground(display);

		incomingPalette = new ColorPalette(bg, INCOMING_COLOR, new RGB(0, 0, 255));
		outgoingPalette = new ColorPalette(bg, OUTGOING_COLOR, new RGB(0, 0, 0));
		conflictPalette = new ColorPalette(bg, CONFLICTING_COLOR, new RGB(255, 0, 0));
		additionPalette = new ColorPalette(bg, ADDITION_COLOR, new RGB(0, 255, 0));
		deletionPalette = new ColorPalette(bg, DELETION_COLOR, new RGB(255, 0, 0));
		editionPalette = new ColorPalette(bg, EDITION_COLOR, new RGB(0, 0, 0));

		RESOLVED= registry.getRGB(RESOLVED_COLOR);
		if (RESOLVED == null)
			RESOLVED= new RGB(0, 255, 0);	// GREEN


		updatePresentation();
	}

	private void updatePresentation() {
		refreshBirdsEyeView();
		invalidateLines();
		invalidateTextPresentation();
	}

	/**
	 * Invalidates the current presentation by invalidating the three text viewers.
	 * @since 2.0
	 */
	public void invalidateTextPresentation() {
		if (fAncestor != null)
			fAncestor.getSourceViewer().invalidateTextPresentation();
		if (fLeft != null)
			fLeft.getSourceViewer().invalidateTextPresentation();
		if (fRight != null)
			fRight.getSourceViewer().invalidateTextPresentation();
	}

	/**
	 * Configures the passed text viewer. This method is called after the three
	 * text viewers have been created for the content areas. The
	 * <code>TextMergeViewer</code> implementation of this method will
	 * configure the viewer with a {@link SourceViewerConfiguration}.
	 * Subclasses may reimplement to provide a specific configuration for the
	 * text viewer.
	 *
	 * @param textViewer
	 *            the text viewer to configure
	 */
	protected void configureTextViewer(TextViewer textViewer) {
		// to get undo for all text files, bugzilla 131895, 33665
		if(textViewer instanceof ISourceViewer){
			SourceViewerConfiguration configuration= new SourceViewerConfiguration();
			((ISourceViewer) textViewer).configure(configuration);
		}
	}

	/**
	 * Creates an <code>ITokenComparator</code> which is used to show the
	 * intra line differences.
	 * The <code>TextMergeViewer</code> implementation of this method returns a
	 * tokenizer that breaks a line into words separated by whitespace.
	 * Subclasses may reimplement to provide a specific tokenizer.
	 * @param line the line for which to create the <code>ITokenComparator</code>
	 * @return a ITokenComparator which is used for a second level token compare.
	 */
	protected ITokenComparator createTokenComparator(String line) {
		return new TokenComparator(line);
	}

	/**
	 * Setup the given document for use with this viewer. By default,
	 * the partitioner returned from {@link #getDocumentPartitioner()}
	 * is registered as the default partitioner for the document.
	 * Subclasses that return a partitioner must also override
	 * {@link #getDocumentPartitioning()} if they wish to be able to use shared
	 * documents (i.e. file buffers).
	 * @param document the document to be set up
	 *
	 * @since 3.3
	 */
	protected void setupDocument(IDocument document) {
		String partitioning = getDocumentPartitioning();
		if (partitioning == null || !(document instanceof IDocumentExtension3)) {
			if (document.getDocumentPartitioner() == null) {
				IDocumentPartitioner partitioner= getDocumentPartitioner();
				if (partitioner != null) {
					document.setDocumentPartitioner(partitioner);
					partitioner.connect(document);
				}
			}
		} else {
			IDocumentExtension3 ex3 = (IDocumentExtension3) document;
			if (ex3.getDocumentPartitioner(partitioning) == null) {
				IDocumentPartitioner partitioner= getDocumentPartitioner();
				if (partitioner != null) {
					ex3.setDocumentPartitioner(partitioning, partitioner);
					partitioner.connect(document);
				}
			}
		}
	}

	/**
	 * Returns a document partitioner which is suitable for the underlying content type.
	 * This method is only called if the input provided by the content provider is a
	 * <code>IStreamContentAccessor</code> and an internal document must be obtained. This
	 * document is initialized with the partitioner returned from this method.
	 * <p>
	 * The <code>TextMergeViewer</code> implementation of this method returns
	 * <code>null</code>. Subclasses may reimplement to create a partitioner for a
	 * specific content type. Subclasses that do return a partitioner should also
	 * return a partitioning from {@link #getDocumentPartitioning()} in order to make
	 * use of shared documents (e.g. file buffers).
	 *
	 * @return a document partitioner, or <code>null</code>
	 */
	protected IDocumentPartitioner getDocumentPartitioner() {
		return null;
	}

	/**
	 * Return the partitioning to which the partitioner returned from
	 * {@link #getDocumentPartitioner()} is to be associated. Return <code>null</code>
	 * only if partitioning is not needed or if the subclass
	 * overrode {@link #setupDocument(IDocument)} directly.
	 * By default, <code>null</code> is returned which means that shared
	 * documents that return a partitioner from {@link #getDocumentPartitioner()}
	 * will not be able to use shared documents.
	 * @see IDocumentExtension3
	 * @return a partitioning
	 *
	 * @since 3.3
	 */
	protected String getDocumentPartitioning() {
		return null;
	}

	/**
	 * Called on the viewer disposal.
	 * Unregisters from the compare configuration.
	 * Clients may extend if they have to do additional cleanup.
	 */
	@Override
	protected void handleDispose(DisposeEvent event) {
		OperationHistoryFactory.getOperationHistory().removeOperationHistoryListener(operationHistoryListener);

		if (fHandlerService != null)
			fHandlerService.dispose();

		Object input= getInput();
		removeFromDocumentManager(ANCESTOR_CONTRIBUTOR, input);
		removeFromDocumentManager(LEFT_CONTRIBUTOR, input);
		removeFromDocumentManager(RIGHT_CONTRIBUTOR, input);

		if (DEBUG)
			DocumentManager.dump();

		if (fPreferenceChangeListener != null) {
			JFaceResources.getFontRegistry().removeListener(fPreferenceChangeListener);
			JFaceResources.getColorRegistry().removeListener(fPreferenceChangeListener);
			if (fPreferenceStore != null)
				fPreferenceStore.removePropertyChangeListener(fPreferenceChangeListener);
			fPreferenceChangeListener= null;
		}

		fLeftCanvas= null;
		fRightCanvas= null;
		fVScrollBar= null;
		fBirdsEyeCanvas= null;
		fSummaryHeader= null;

		fAncestorContributor.unsetDocument(fAncestor);
		fLeftContributor.unsetDocument(fLeft);
		fRightContributor.unsetDocument(fRight);

		disconnect(fLeftContributor);
		disconnect(fRightContributor);
		disconnect(fAncestorContributor);

		if (showWhitespaceAction != null)
			showWhitespaceAction.dispose();

		if (toggleLineNumbersAction != null)
			toggleLineNumbersAction.dispose();

		if (fIgnoreWhitespace != null)
			fIgnoreWhitespace.dispose();

		getCompareConfiguration().setProperty(
				ChangeCompareFilterPropertyAction.COMPARE_FILTERS_INITIALIZING,
				Boolean.TRUE);
		disposeCompareFilterActions(false);

		if (fSourceViewerDecorationSupport != null) {
			for (Iterator<SourceViewerDecorationSupport> iterator = fSourceViewerDecorationSupport.iterator(); iterator.hasNext();) {
				iterator.next().dispose();
			}
			fSourceViewerDecorationSupport = null;
		}


		if (fAncestor != null)
			fAncestor.dispose();
		fAncestor = null;
		if (fLeft != null)
			fLeft.dispose();
		fLeft = null;
		if (fRight != null)
			fRight.dispose();
		fRight = null;

		if (fColors != null) {
			Iterator<Color> i= fColors.values().iterator();
			while (i.hasNext()) {
				Color color= i.next();
				if (!color.isDisposed())
					color.dispose();
			}
			fColors= null;
		}
		// don't add anything here, disposing colors should be done last
		super.handleDispose(event);
	}

	private void disconnect(ContributorInfo legInfo) {
		if (legInfo != null)
			legInfo.disconnect();
	}

	//-------------------------------------------------------------------------------------------------------------
	//--- internal ------------------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------------------------------

	/*
	 * Creates the specific SWT controls for the content areas.
	 * Clients must not call or override this method.
	 */
	@Override
	protected void createControls(Composite composite) {
		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.TEXT_MERGE_VIEW);

		// 1st row
		if (fMarginWidth > 0) {
			fAncestorCanvas= new BufferedCanvas(composite, SWT.NONE) {
				@Override
				public void doPaint(GC gc) {
					paintSides(gc, fAncestor, fAncestorCanvas, false);
				}
			};
			fAncestorCanvas.addMouseListener(
				new MouseAdapter() {
					@Override
					public void mouseDown(MouseEvent e) {
						setCurrentDiff2(handleMouseInSides(fAncestorCanvas, fAncestor, e.y), false);
					}
				}
			);
		}

		fAncestor= createPart(composite);
		setEditable(fAncestor.getSourceViewer(), false);
		fAncestor.getSourceViewer().getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() {
			@Override
			public void getName(AccessibleEvent e) {
				e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_ancestor, getCompareConfiguration().getAncestorLabel(getInput()));
			}
		});
		fAncestor.getSourceViewer().addTextPresentationListener(new ChangeHighlighter(fAncestor));

		fSummaryHeader= new Canvas(composite, SWT.NONE);
		fHeaderPainter= new HeaderPainter();
		fSummaryHeader.addPaintListener(fHeaderPainter);
		updateResolveStatus();

		// 2nd row
		if (fMarginWidth > 0) {
			fLeftCanvas= new BufferedCanvas(composite, SWT.NONE) {
				@Override
				public void doPaint(GC gc) {
					paintSides(gc, fLeft, fLeftCanvas, false);
				}
			};
			fLeftCanvas.addMouseListener(
				new MouseAdapter() {
					@Override
					public void mouseDown(MouseEvent e) {
						setCurrentDiff2(handleMouseInSides(fLeftCanvas, fLeft, e.y), false);
					}
				}
			);
		}

		fLeft= createPart(composite);
		fLeft.getSourceViewer().getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling);
		fLeft.getSourceViewer().getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() {
			@Override
			public void getName(AccessibleEvent e) {
				// Check for Mirrored status flag before returning the left label's text.
				e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_left,
						getCompareConfiguration().isMirrored() ? getCompareConfiguration().getRightLabel(getInput())
								: getCompareConfiguration().getLeftLabel(getInput()));
			}
		});
		fLeft.getSourceViewer().addTextPresentationListener(new ChangeHighlighter(fLeft));

		fRight= createPart(composite);
		fRight.getSourceViewer().getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling);
		fRight.getSourceViewer().getTextWidget().getAccessible().addAccessibleListener(new AccessibleAdapter() {
			@Override
			public void getName(AccessibleEvent e) {
				// Check for Mirrored status flag before returning the right label's text.
				e.result = NLS.bind(CompareMessages.TextMergeViewer_accessible_right,
						getCompareConfiguration().isMirrored() ? getCompareConfiguration().getLeftLabel(getInput())
								: getCompareConfiguration().getRightLabel(getInput()));
			}
		});
		fRight.getSourceViewer().addTextPresentationListener(new ChangeHighlighter(fRight));

		IWorkbenchPart part = getCompareConfiguration().getContainer().getWorkbenchPart();
		// part is not available for contexts different than editor
		if (part != null) {
			ISelectionProvider selectionProvider = part.getSite().getSelectionProvider();
			if (selectionProvider instanceof CompareEditorSelectionProvider) {
				CompareEditorSelectionProvider cesp = (CompareEditorSelectionProvider) selectionProvider;
				SourceViewer focusSourceViewer = fFocusPart == null ? null	: fFocusPart.getSourceViewer();
				cesp.setViewers(new SourceViewer[] { fLeft.getSourceViewer(), fRight.getSourceViewer(), fAncestor.getSourceViewer() }, focusSourceViewer);
			}
		}

		hsynchViewport(fAncestor.getSourceViewer(), fLeft.getSourceViewer(), fRight.getSourceViewer());
		hsynchViewport(fLeft.getSourceViewer(), fAncestor.getSourceViewer(), fRight.getSourceViewer());
		hsynchViewport(fRight.getSourceViewer(), fAncestor.getSourceViewer(), fLeft.getSourceViewer());

		if (fMarginWidth > 0) {
			fRightCanvas= new BufferedCanvas(composite, SWT.NONE) {
				@Override
				public void doPaint(GC gc) {
					paintSides(gc, fRight, fRightCanvas, fSynchronizedScrolling);
				}
			};
			fRightCanvas.addMouseListener(
				new MouseAdapter() {
					@Override
					public void mouseDown(MouseEvent e) {
						setCurrentDiff2(handleMouseInSides(fRightCanvas, fRight, e.y), false);
					}
				}
			);
		}

		fScrollCanvas= new Canvas(composite, SWT.V_SCROLL);
		Rectangle trim= fLeft.getSourceViewer().getTextWidget().computeTrim(0, 0, 0, 0);
		fTopInset= trim.y;

		fVScrollBar= fScrollCanvas.getVerticalBar();
		fVScrollBar.setIncrement(1);
		fVScrollBar.setVisible(true);
		fVScrollBar.addListener(SWT.Selection,
			e -> {
				int vpos= ((ScrollBar) e.widget).getSelection();
				synchronizedScrollVertical(vpos);
			}
		);

		fBirdsEyeCanvas= new BufferedCanvas(composite, SWT.NONE) {
			@Override
			public void doPaint(GC gc) {
				paintBirdsEyeView(this, gc);
			}
		};
		fBirdsEyeCanvas.addMouseListener(
			new MouseAdapter() {
				@Override
				public void mouseDown(MouseEvent e) {
					setCurrentDiff2(handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y), true);
				}
			}
		);
		fBirdsEyeCanvas.addMouseMoveListener(
			new MouseMoveListener() {
				private Cursor fLastCursor;

				@Override
				public void mouseMove(MouseEvent e) {
					Cursor cursor= null;
					Diff diff= handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y);
					if (diff != null && diff.getKind() != RangeDifference.NOCHANGE)
						cursor= e.widget.getDisplay().getSystemCursor(SWT.CURSOR_HAND);
					if (fLastCursor != cursor) {
						fBirdsEyeCanvas.setCursor(cursor);
						fLastCursor= cursor;
					}
				}
			}
		);

		IWorkbenchPart workbenchPart = getCompareConfiguration().getContainer().getWorkbenchPart();
		if (workbenchPart != null) {
			IContextService service = workbenchPart.getSite().getService(IContextService.class);
			if (service != null) {
				service.activateContext("org.eclipse.ui.textEditorScope"); //$NON-NLS-1$
			}
		}
	}

	private void hsynchViewport(final TextViewer tv1, final TextViewer tv2, final TextViewer tv3) {
		final StyledText st1= tv1.getTextWidget();
		final StyledText st2= tv2.getTextWidget();
		final StyledText st3= tv3.getTextWidget();
		final ScrollBar sb1= st1.getHorizontalBar();
		sb1.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if (fSynchronizedScrolling) {
					int v= sb1.getSelection();
					if (st2.isVisible())
						st2.setHorizontalPixel(v);
					if (st3.isVisible())
						st3.setHorizontalPixel(v);
				}
			}
		});
	}

	private void setCurrentDiff2(Diff diff, boolean reveal) {
		if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) {
			//fCurrentDiff= null;
			setCurrentDiff(diff, reveal);
		}
	}

	private Diff handleMouseInSides(Canvas canvas, MergeSourceViewer tp, int my) {

		int lineHeight= tp.getSourceViewer().getTextWidget().getLineHeight();
		int visibleHeight= tp.getViewportHeight();

		if (! fHighlightRanges)
			return null;

		if (fMerger.hasChanges()) {
			int shift= tp.getVerticalScrollOffset() + (2-LW);

			Point region= new Point(0, 0);
			char leg = getLeg(tp);
			for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
				Diff diff = (Diff) iterator.next();
				if (diff.isDeleted())
					continue;

				if (fShowCurrentOnly2 && !isCurrentDiff(diff))
					continue;

				tp.getLineRange(diff.getPosition(leg), region);
				int y= (region.x * lineHeight) + shift;
				int h= region.y * lineHeight;

				if (y+h < 0)
					continue;
				if (y >= visibleHeight)
					break;

				if (my >= y && my < y+h)
					return diff;
			}
		}
		return null;
	}

	private Diff getDiffUnderMouse(Canvas canvas, int mx, int my, Rectangle r) {

		if (! fSynchronizedScrolling)
			return null;

		int lineHeight= fLeft.getSourceViewer().getTextWidget().getLineHeight();
		int visibleHeight= fRight.getViewportHeight();

		Point size= canvas.getSize();
		int w= size.x;

		if (! fHighlightRanges)
			return null;

		if (fMerger.hasChanges()) {
			int lshift= fLeft.getVerticalScrollOffset();
			int rshift= fRight.getVerticalScrollOffset();

			Point region= new Point(0, 0);

			for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
				Diff diff = (Diff) iterator.next();
				if (diff.isDeleted())
					continue;

				if (fShowCurrentOnly2 && !isCurrentDiff(diff))
					continue;

				fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
				int ly= (region.x * lineHeight) + lshift;
				int lh= region.y * lineHeight;

				fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
				int ry= (region.x * lineHeight) + rshift;
				int rh= region.y * lineHeight;

				if (Math.max(ly+lh, ry+rh) < 0)
					continue;
				if (Math.min(ly, ry) >= visibleHeight)
					break;

				int SIZE = 20;
				int cx= (w-SIZE)/2;
				int cy= ((ly+lh/2) + (ry+rh/2) - SIZE)/2;
				if (my >= cy && my < cy+SIZE && mx >= cx && mx < cx+SIZE) {
					if (r != null) {
						r.x= cx;
						r.y= cy;
						r.width= SIZE;
						r.height= SIZE;
					}
					return diff;
				}
			}
		}
		return null;
	}

	private Diff handlemouseInBirdsEyeView(Canvas canvas, int my) {
		return fMerger.findDiff(getViewportHeight(), fSynchronizedScrolling, canvas.getSize(), my);
	}

	private void paintBirdsEyeView(Canvas canvas, GC gc) {

		Color c;
		Rectangle r= new Rectangle(0, 0, 0, 0);
		int yy, hh;

		Point size= canvas.getSize();

		int virtualHeight= fSynchronizedScrolling ? fMerger.getVirtualHeight() : fMerger.getRightHeight();
		if (virtualHeight < getViewportHeight())
			return;

		Display display= canvas.getDisplay();
		int y= 0;
		boolean allOutgoing = allOutgoing();
		for (Iterator<Diff> iterator = fMerger.rangesIterator(); iterator.hasNext();) {
			Diff diff = iterator.next();
			int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
											: diff.getRightHeight();

			if (fMerger.useChange(diff)) {

				yy= (y*size.y)/virtualHeight;
				hh= (h*size.y)/virtualHeight;
				if (hh < 3)
					hh= 3;

				c = getColor(display, getFillColor(diff, allOutgoing));
				if (c != null) {
					gc.setBackground(c);
					gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh);
				}
				c = getColor(display, getStrokeColor(diff, allOutgoing));
				if (c != null) {
					gc.setForeground(c);
					r.x= BIRDS_EYE_VIEW_INSET;
					r.y= yy;
					r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1;
					r.height= hh;
					if (isCurrentDiff(diff)) {
						gc.setLineWidth(2);
						r.x++;
						r.y++;
						r.width--;
						r.height--;
					} else {
						gc.setLineWidth(0 /* 1 */);
					}
					gc.drawRectangle(r);
				}
			}

			y+= h;
		}
	}

	private void refreshBirdsEyeView() {
		if (fBirdsEyeCanvas != null)
			fBirdsEyeCanvas.redraw();
	}

	/**
	 * Override to give focus to the pane that previously had focus or to a suitable
	 * default pane.
	 * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handleSetFocus()
	 * @since 3.3
	 */
	@Override
	protected boolean handleSetFocus() {
		if (fRedoDiff) {
			new UIJob(CompareMessages.DocumentMerger_0) {
				@Override
				public IStatus runInUIThread(IProgressMonitor monitor) {
					update(true);
					updateStructure();
					return Status.OK_STATUS;
				}
			}.schedule();
			fRedoDiff = false;
		}
		if (fFocusPart == null) {
			if (fLeft != null && fLeft.getEnabled()) {
				fFocusPart= fLeft;
			} else if (fRight != null && fRight.getEnabled()) {
				fFocusPart= fRight;
			} else if (fAncestor != null && fAncestor.getEnabled()) {
				fFocusPart= fAncestor;
			}
		}
		if (fFocusPart != null) {
			StyledText st= fFocusPart.getSourceViewer().getTextWidget();
			if (st != null)
				return st.setFocus();
		}
		return false;	// could not set focus
	}


	class HoverResizer extends Resizer {
		Canvas fCanvas;
		public HoverResizer(Canvas c, int dir) {
			super(c, dir);
			fCanvas= c;
		}
		@Override
		public void mouseMove(MouseEvent e) {
			if (!fIsDown && fUseSingleLine && isAnySideEditable() && handleMouseMoveOverCenter(fCanvas, e.x, e.y))
				return;
			super.mouseMove(e);
		}
	}

	@Override
	protected final Control createCenterControl(Composite parent) {
		if (fSynchronizedScrolling) {
			final Canvas canvas= new BufferedCanvas(parent, SWT.NONE) {
				@Override
				public void doPaint(GC gc) {
					paintCenter(this, gc);
				}
			};
			new HoverResizer(canvas, HORIZONTAL);

			Cursor normalCursor= canvas.getDisplay().getSystemCursor(SWT.CURSOR_ARROW);
			int style= fIsMac ? SWT.FLAT : SWT.PUSH;

			fLeftToRightButton= new Button(canvas, style);
			fLeftToRightButton.setCursor(normalCursor);
			fLeftToRightButton.setText(COPY_LEFT_TO_RIGHT_INDICATOR);
			fLeftToRightButton.setToolTipText(
					Utilities.getString(getResourceBundle(), "action.CopyDiffLeftToRight.tooltip")); //$NON-NLS-1$
			fLeftToRightButton.pack();
			fLeftToRightButton.setVisible(false);
			fLeftToRightButton.addSelectionListener(
				new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						handleCenterButtonSelection(true);
					}
				}
			);

			fRightToLeftButton= new Button(canvas, style);
			fRightToLeftButton.setCursor(normalCursor);
			fRightToLeftButton.setText(COPY_RIGHT_TO_LEFT_INDICATOR);
			fRightToLeftButton.setToolTipText(
					Utilities.getString(getResourceBundle(), "action.CopyDiffRightToLeft.tooltip")); //$NON-NLS-1$
			fRightToLeftButton.pack();
			fRightToLeftButton.setVisible(false);
			fRightToLeftButton.addSelectionListener(
					new SelectionAdapter() {
						@Override
						public void widgetSelected(SelectionEvent e) {
							handleCenterButtonSelection(false);
						}
					}
			);

			return canvas;
		}
		return super.createCenterControl(parent);
	}

	private void handleCenterButtonSelection(boolean leftToRight) {
		fLeftToRightButton.setVisible(false);
		fRightToLeftButton.setVisible(false);
		if (fButtonDiff != null) {
			setCurrentDiff(fButtonDiff, false);
			copy(fCurrentDiff, leftToRight, false);
		}
	}

	private boolean handleMouseMoveOverCenter(Canvas canvas, int x, int y) {
		Rectangle r= new Rectangle(0, 0, 0, 0);
		Diff diff= getDiffUnderMouse(canvas, x, y, r);
		if (diff != fButtonDiff) {
			if (diff != null) {
				fButtonDiff= diff;
				boolean leftEditable= fLeft.getSourceViewer().isEditable();
				boolean rightEditable= fRight.getSourceViewer().isEditable();
				if (leftEditable && rightEditable) {
					int height= r.height;
					int leftToRightY= r.y - height/2;
					int rightToLeftY= leftToRightY + height;
					Rectangle bounds = canvas.getBounds();
					if (leftToRightY < 0) {
						// button must not be hidden at top
						leftToRightY= 0;
						rightToLeftY= height;
					} else if (rightToLeftY + height > bounds.height) {
						// button must not be hidden at bottom
						leftToRightY= bounds.height - height - height;
						rightToLeftY= leftToRightY + height;
					}
					Rectangle leftToRightBounds= new Rectangle(r.x, leftToRightY, r.width, r.height);
					fLeftToRightButton.setBounds(leftToRightBounds);
					fLeftToRightButton.setVisible(true);
					Rectangle rightToLeftBounds= new Rectangle(r.x, rightToLeftY, r.width, r.height);
					fRightToLeftButton.setBounds(rightToLeftBounds);
					fRightToLeftButton.setVisible(true);
				} else if (leftEditable) {
					fRightToLeftButton.setBounds(r);
					fRightToLeftButton.setVisible(true);
					fLeftToRightButton.setVisible(false);
				} else if (rightEditable) {
					fLeftToRightButton.setBounds(r);
					fLeftToRightButton.setVisible(true);
					fRightToLeftButton.setVisible(false);
				} else
					fButtonDiff= null;
			} else {
				fRightToLeftButton.setVisible(false);
				fLeftToRightButton.setVisible(false);
				fButtonDiff= null;
			}
		}
		return fButtonDiff != null;
	}

	@Override
	protected final int getCenterWidth() {
		if (fSynchronizedScrolling)
			return CENTER_WIDTH;
		return super.getCenterWidth();
	}

	private int getDirection() {
		switch (fTextDirection) {
		case SWT.LEFT_TO_RIGHT:
		case SWT.RIGHT_TO_LEFT:
			if (fInheritedDirection == fTextDirection)
				return SWT.NONE;
			return fTextDirection;
		default:
			return fInheritedDirection;
		}
	}

	/**
	 * Creates a new source viewer. This method is called when creating and
	 * initializing the content areas of the merge viewer (see
	 * {@link #createControls(Composite)}). It is called three
	 * times for each text part of the comparison: ancestor, left, right.
	 * Clients may implement to provide their own type of source viewers. The
	 * viewer is not expected to be configured with a source viewer
	 * configuration.
	 *
	 * @param parent
	 *            the parent of the viewer's control
	 * @param textOrientation
	 *            style constant bit for text orientation
	 * @return Default implementation returns an instance of
	 *         {@link SourceViewer}.
	 * @since 3.5
	 */
	protected SourceViewer createSourceViewer(Composite parent, int textOrientation) {
		return new SourceViewer(parent, new CompositeRuler(), textOrientation | SWT.H_SCROLL | SWT.V_SCROLL);
	}

	/**
	 * Tells whether the given text viewer is backed by an editor.
	 *
	 * @param textViewer the text viewer to check
	 * @return <code>true</code> if the viewer is backed by an editor
	 * @since 3.5
	 */
	protected boolean isEditorBacked(ITextViewer textViewer) {
		return false;
	}

	/**
	 * Returns an editor input for the given source viewer. The method returns
	 * <code>null</code> when no input is available, for example when the input
	 * for the merge viewer has not been set yet.
	 *
	 * @param sourceViewer
	 *            the source viewer to get input for
	 * @return input for the given viewer or <code>null</code> when no input is
	 *         available
	 *
	 * @since 3.5
	 */
	protected IEditorInput getEditorInput(ISourceViewer sourceViewer) {
		if (fLeft != null && sourceViewer == fLeft.getSourceViewer())
			if (fLeftContributor != null)
				return fLeftContributor.getDocumentKey();
		if (fRight != null && sourceViewer == fRight.getSourceViewer())
			if (fRightContributor != null)
				return fRightContributor.getDocumentKey();
		if (fAncestor != null
				&& sourceViewer == fAncestor.getSourceViewer())
			if (fAncestorContributor != null)
				return fAncestorContributor.getDocumentKey();
		return null;
	}

	/*
	 * Creates and initializes a text part.
	 */
	private MergeSourceViewer createPart(Composite parent) {
		final MergeSourceViewer viewer = new MergeSourceViewer(
				createSourceViewer(parent, getDirection()),
				getResourceBundle(), getCompareConfiguration().getContainer());
		final StyledText te= viewer.getSourceViewer().getTextWidget();

		if (!fConfirmSave)
			viewer.hideSaveAction();

		te.addPaintListener(
			e -> paint(e, viewer)
		);
		te.addKeyListener(
			new KeyAdapter() {
				@Override
				public void keyPressed(KeyEvent e) {
					handleSelectionChanged(viewer);
				}
			}
		);
		te.addMouseListener(
			new MouseAdapter() {
				@Override
				public void mouseDown(MouseEvent e) {
					//syncViewport(part);
					handleSelectionChanged(viewer);
				}
			}
		);

		te.addFocusListener(
			new FocusAdapter() {
				@Override
				public void focusGained(FocusEvent fe) {
					setActiveViewer(viewer, true);
				}
				@Override
				public void focusLost(FocusEvent fe) {
					setActiveViewer(viewer, false);
				}
			}
		);

		viewer.getSourceViewer().addViewportListener(
			verticalPosition -> syncViewport(viewer)
		);

		Font font= JFaceResources.getFont(fSymbolicFontName);
		if (font != null)
			te.setFont(font);

		if (fBackground != null)	// not default
			te.setBackground(getColor(parent.getDisplay(), fBackground));

		// Add the find action to the popup menu of the viewer
		contributeFindAction(viewer);

		contributeGotoLineAction(viewer);

		contributeChangeEncodingAction(viewer);

		contributeDiffBackgroundListener(viewer);

		return viewer;
	}

	private void setActiveViewer(MergeSourceViewer viewer, boolean activate) {
		connectContributedActions(viewer, activate);
		if (activate) {
			fFocusPart= viewer;
			connectGlobalActions(fFocusPart);
		} else {
			connectGlobalActions(null);
		}
	}

	private SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
		SourceViewerDecorationSupport support = new SourceViewerDecorationSupport(viewer, null, null, EditorsUI.getSharedTextColors());
		support.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
		fSourceViewerDecorationSupport.add(support);
		return support;
	}

	private void contributeFindAction(MergeSourceViewer viewer) {
		IAction action;
		IWorkbenchPart wp = getCompareConfiguration().getContainer().getWorkbenchPart();
		if (wp != null)
			action = new FindReplaceAction(getResourceBundle(), "Editor.FindReplace.", wp); //$NON-NLS-1$
		else
			action = new FindReplaceAction(getResourceBundle(), "Editor.FindReplace.", viewer.getSourceViewer().getControl().getShell(), getFindReplaceTarget()); //$NON-NLS-1$
		action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE);
		viewer.addAction(MergeSourceViewer.FIND_ID, action);
	}

	private void contributeGotoLineAction(MergeSourceViewer viewer) {
		IAction action = new GotoLineAction(viewer.getAdapter(ITextEditor.class));
		action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
		viewer.addAction(MergeSourceViewer.GOTO_LINE_ID, action);
	}

	private void contributeChangeEncodingAction(MergeSourceViewer viewer) {
		IAction action = new ChangeEncodingAction(getTextEditorAdapter());
		viewer.addAction(MergeSourceViewer.CHANGE_ENCODING_ID, action);
	}

	private void contributeDiffBackgroundListener(final MergeSourceViewer viewer) {
		viewer.getSourceViewer().getTextWidget().addLineBackgroundListener(
				event -> {
					StyledText textWidget = viewer.getSourceViewer().getTextWidget();
					if (textWidget != null) {

						int caret = textWidget.getCaretOffset();
						int length = event.lineText.length();

						if (event.lineOffset <= caret
								&& caret <= event.lineOffset + length) {
							// current line, do nothing
							// decorated by CursorLinePainter
						} else {
							// find diff for the event line
							Diff diff = findDiff(viewer, event.lineOffset,
									event.lineOffset + length);
							if (diff != null && updateDiffBackground(diff)) {
								// highlights only the event line, not the
								// whole diff
								event.lineBackground = getColor(fComposite
										.getDisplay(), getFillColor(diff, allOutgoing()));
							}
						}
					}
				});
	}

	private void connectGlobalActions(final MergeSourceViewer part) {
		if (fHandlerService != null) {
			if (part != null)
				part.updateActions();
			fHandlerService.updatePaneActionHandlers(() -> {
				for (int i= 0; i < GLOBAL_ACTIONS.length; i++) {
					IAction action= null;
					if (part != null) {
						action= part.getAction(TEXT_ACTIONS[i]);
					}
					fHandlerService.setGlobalActionHandler(GLOBAL_ACTIONS[i], action);
				}
			});
		}
	}

	private void connectContributedActions(final MergeSourceViewer viewer, final boolean connect) {
		if (fHandlerService != null) {
			fHandlerService.updatePaneActionHandlers(() -> {
				if (viewer != null) {
					setActionsActivated(viewer.getSourceViewer(), connect);
					if (isEditorBacked(viewer.getSourceViewer()) && connect) {
						/*
						 * If editor backed, activating contributed actions
						 * might have disconnected actions provided in
						 * CompareEditorContributor => when connecting,
						 * refresh active editor in the contributor, when
						 * disconnecting do nothing. See bug 261229.
						 */
						IWorkbenchPart part = getCompareConfiguration().getContainer().getWorkbenchPart();
						if (part instanceof CompareEditor) {
							((CompareEditor) part).refreshActionBarsContributor();
						}
					}
				}
			});
		}
	}

	/**
	 * Activates or deactivates actions of the given source viewer.
	 * <p>
	 * The default implementation does nothing, but clients should override to properly react to
	 * viewers switching.
	 * </p>
	 *
	 * @param sourceViewer the source viewer
	 * @param state <code>true</code> if activated
	 * @since 3.5
	 */
	protected void setActionsActivated(SourceViewer sourceViewer, boolean state) {
		// default implementation does nothing
	}

	private IDocument getElementDocument(char type, Object element) {
		if (element instanceof IDocument) {
			return (IDocument) element;
		}
		ITypedElement te= Utilities.getLeg(type, element);
		// First check the contributors for the document
		IDocument document = null;
		switch (type) {
		case ANCESTOR_CONTRIBUTOR:
			document = getDocument(te, fAncestorContributor);
			break;
		case LEFT_CONTRIBUTOR:
			document = getDocument(te, fLeftContributor);
			break;
		case RIGHT_CONTRIBUTOR:
			document = getDocument(te, fRightContributor);
			break;
		default:
			break;
		}
		if (document != null)
			return document;
		// The document is not associated with the input of the viewer so try to find the document
		return Utilities.getDocument(type, element, isUsingDefaultContentProvider(), canHaveSharedDocument());
	}

	private boolean isUsingDefaultContentProvider() {
		return getContentProvider() instanceof MergeViewerContentProvider;
	}

	private boolean canHaveSharedDocument() {
		return getDocumentPartitioning() != null
			|| getDocumentPartitioner() == null;
	}

	private IDocument getDocument(ITypedElement te, ContributorInfo info) {
		if (info != null && info.getElement() == te)
			return info.getDocument();
		return null;
	}

	IDocument getDocument(char type, Object input) {
		IDocument doc= getElementDocument(type, input);
		if (doc != null)
			return doc;

		if (input instanceof IDiffElement) {
			IDiffContainer parent= ((IDiffElement) input).getParent();
			return getElementDocument(type, parent);
		}
		return null;
	}

	/*
	 * Returns true if the given inputs map to the same documents
	 */
	boolean sameDoc(char type, Object newInput, Object oldInput) {
		IDocument newDoc= getDocument(type, newInput);
		IDocument oldDoc= getDocument(type, oldInput);
		return newDoc == oldDoc;
	}

	/**
	 * Overridden to prevent save confirmation if new input is sub document of current input.
	 * @param newInput the new input of this viewer, or <code>null</code> if there is no new input
	 * @param oldInput the old input element, or <code>null</code> if there was previously no input
	 * @return <code>true</code> if saving was successful, or if the user didn't want to save (by pressing 'NO' in the confirmation dialog).
	 * @since 2.0
	 */
	@Override
	protected boolean doSave(Object newInput, Object oldInput) {
		// TODO: Would be good if this could be restated in terms of Saveables and moved up
		if (oldInput != null && newInput != null) {
			// check whether underlying documents have changed.
			if (sameDoc(ANCESTOR_CONTRIBUTOR, newInput, oldInput) &&
					sameDoc(LEFT_CONTRIBUTOR, newInput, oldInput) &&
						sameDoc(RIGHT_CONTRIBUTOR, newInput, oldInput)) {
				if (DEBUG) System.out.println("----- Same docs !!!!");	//$NON-NLS-1$
				return false;
			}
		}

		if (DEBUG) System.out.println("***** New docs !!!!");	//$NON-NLS-1$

		removeFromDocumentManager(ANCESTOR_CONTRIBUTOR, oldInput);
		removeFromDocumentManager(LEFT_CONTRIBUTOR, oldInput);
		removeFromDocumentManager(RIGHT_CONTRIBUTOR, oldInput);

		if (DEBUG)
			DocumentManager.dump();

		return super.doSave(newInput, oldInput);
	}

	private void removeFromDocumentManager(char leg, Object oldInput) {
		IDocument document= getDocument(leg, oldInput);
		if (document != null)
			DocumentManager.remove(document);
	}

	private ITypedElement getParent(char type) {
		Object input= getInput();
		if (input instanceof IDiffElement) {
			IDiffContainer parent= ((IDiffElement) input).getParent();
			return Utilities.getLeg(type, parent);
		}
		return null;
	}

	/*
	 * Initializes the text viewers of the three content areas with the given input objects.
	 * Subclasses may extend.
	 */
	@Override
	protected void updateContent(Object ancestor, Object left, Object right) {
		boolean emptyInput= (ancestor == null && left == null && right == null);

		Object input= getInput();

		configureCompareFilterActions(input, ancestor, left, right);

		Position leftRange= null;
		Position rightRange= null;

		// if one side is empty use container
		if (FIX_47640 && !emptyInput && (left == null || right == null)) {
			if (input instanceof IDiffElement) {
				IDiffContainer parent= ((IDiffElement) input).getParent();
				if (parent instanceof ICompareInput) {
					ICompareInput ci= (ICompareInput) parent;

					if (ci.getAncestor() instanceof IDocumentRange
							|| ci.getLeft() instanceof IDocumentRange
							|| ci.getRight() instanceof IDocumentRange) {
						if (left instanceof IDocumentRange)
							leftRange= ((IDocumentRange) left).getRange();
						if (right instanceof IDocumentRange)
							rightRange= ((IDocumentRange) right).getRange();

						ancestor= ci.getAncestor();
						left= getCompareConfiguration().isMirrored() ? ci.getRight() : ci.getLeft();
						right= getCompareConfiguration().isMirrored() ? ci.getLeft() : ci.getRight();
					}
				}
			}
		}

		fHighlightRanges= left != null && right != null;

		resetDiffs();
		fHasErrors= false; // start with no errors

		IMergeViewerContentProvider cp= getMergeContentProvider();

		if (cp instanceof MergeViewerContentProvider) {
			MergeViewerContentProvider mcp= (MergeViewerContentProvider) cp;
			mcp.setAncestorError(null);
			mcp.setLeftError(null);
			mcp.setRightError(null);
		}

		// Record current contributors so we disconnect after creating the new ones.
		// This is done in case the old and new use the same document.
		ContributorInfo oldLeftContributor = fLeftContributor;
		ContributorInfo oldRightContributor = fRightContributor;
		ContributorInfo oldAncestorContributor = fAncestorContributor;

		// Create the new contributor
		fLeftContributor = createLegInfoFor(left, LEFT_CONTRIBUTOR);
		fRightContributor = createLegInfoFor(right, RIGHT_CONTRIBUTOR);
		fAncestorContributor = createLegInfoFor(ancestor, ANCESTOR_CONTRIBUTOR);

		fLeftContributor.transferContributorStateFrom(oldLeftContributor);
		fRightContributor.transferContributorStateFrom(oldRightContributor);
		fAncestorContributor.transferContributorStateFrom(oldAncestorContributor);

		// Now disconnect the old ones
		disconnect(oldLeftContributor);
		disconnect(oldRightContributor);
		disconnect(oldAncestorContributor);

		// Get encodings from streams. If an encoding is null, abide by the other one
		// Defaults to workbench encoding only if both encodings are null
		fLeftContributor.setEncodingIfAbsent(fRightContributor);
		fRightContributor.setEncodingIfAbsent(fLeftContributor);
		fAncestorContributor.setEncodingIfAbsent(fLeftContributor);

		if (!isConfigured) {
			configureSourceViewer(fAncestor.getSourceViewer(), false, null);
			configureSourceViewer(fLeft.getSourceViewer(), isLeftEditable() && cp.isLeftEditable(input), fLeftContributor);
			configureSourceViewer(fRight.getSourceViewer(), isRightEditable() && cp.isRightEditable(input), fRightContributor);
			isConfigured = true; // configure once
		}

		// set new documents
		fLeftContributor.setDocument(fLeft, isLeftEditable() && cp.isLeftEditable(input));
		fLeftLineCount= fLeft.getLineCount();

		fRightContributor.setDocument(fRight, isRightEditable() && cp.isRightEditable(input));
		fRightLineCount= fRight.getLineCount();

		fAncestorContributor.setDocument(fAncestor, false);

		setSyncScrolling(fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING));

		update(false);

		if (!fHasErrors && !emptyInput && !fComposite.isDisposed()) {
			if (isRefreshing()) {
				fLeftContributor.updateSelection(fLeft, !fSynchronizedScrolling);
				fRightContributor.updateSelection(fRight, !fSynchronizedScrolling);
				fAncestorContributor.updateSelection(fAncestor, !fSynchronizedScrolling);
				if (fSynchronizedScrolling && fSynchronziedScrollPosition != -1) {
					synchronizedScrollVertical(fSynchronziedScrollPosition);
				}
			} else {
				if (isPatchHunk()) {
					if (right != null && Adapters.adapt(right, IHunk.class) != null)
						fLeft.getSourceViewer().setTopIndex(getHunkStart());
					else
						fRight.getSourceViewer().setTopIndex(getHunkStart());
				} else {
					Diff selectDiff= null;
					if (FIX_47640) {
						if (leftRange != null)
							selectDiff= fMerger.findDiff(LEFT_CONTRIBUTOR, leftRange);
						else if (rightRange != null)
							selectDiff= fMerger.findDiff(RIGHT_CONTRIBUTOR, rightRange);
					}
					if (selectDiff != null)
						setCurrentDiff(selectDiff, true);
					else
						selectFirstDiff(true);
				}
			}
		}

	}

	private void configureSourceViewer(SourceViewer sourceViewer, boolean editable, ContributorInfo contributor) {
		setEditable(sourceViewer, editable);
		configureTextViewer(sourceViewer);
		if (editable && contributor != null) {
			IDocument document = sourceViewer.getDocument();
			if (document != null)
				contributor.connectPositionUpdater(document);
		}
		if (!isCursorLinePainterInstalled(sourceViewer))
			getSourceViewerDecorationSupport(sourceViewer).install(fPreferenceStore);
	}

	private boolean isCursorLinePainterInstalled(SourceViewer viewer) {
		Listener[] listeners = viewer.getTextWidget().getListeners(3001/*StyledText.LineGetBackground*/);
		for (Listener l : listeners) {
			if (l instanceof TypedListener) {
				TypedListener listener = (TypedListener) l;
				if (listener.getEventListener() instanceof CursorLinePainter)
					return true;
			}
		}
		return false;
	}

	/**
	 * Sets the editable state of the given source viewer.
	 *
	 * @param sourceViewer
	 *            the source viewer
	 * @param state
	 *            the state
	 * @since 3.5
	 */
	protected void setEditable(ISourceViewer sourceViewer, boolean state) {
		sourceViewer.setEditable(state);
	}

	private boolean isRefreshing() {
		return isRefreshing > 0;
	}

	private ContributorInfo createLegInfoFor(Object element, char leg) {
		return new ContributorInfo(this, element, leg);
	}

	private boolean updateDiffBackground(Diff diff) {

		if (!fHighlightRanges)
			return false;

		if (diff == null || diff.isToken())
			return false;

		if (fShowCurrentOnly && !isCurrentDiff(diff))
			return false;

		return true;
	}

	/*
	 * Called whenever one of the documents changes.
	 * Sets the dirty state of this viewer and updates the lines.
	 * Implements IDocumentListener.
	 */
	private void documentChanged(DocumentEvent e, boolean dirty) {
		final IDocument doc= e.getDocument();

		if (doc == fLeft.getSourceViewer().getDocument()) {
			setLeftDirty(dirty);
		} else if (doc == fRight.getSourceViewer().getDocument()) {
			setRightDirty(dirty);
		}
		if (!isLeftDirty() && !isRightDirty()) {
			fRedoDiff = false;
			final Diff oldDiff = getLastDiff();
			new UIJob(CompareMessages.DocumentMerger_0) {
				@Override
				public IStatus runInUIThread(IProgressMonitor monitor) {
					if (!getControl().isDisposed()) {
						doDiff();
						if (!getControl().isDisposed()) {
							Diff newDiff = findNewDiff(oldDiff);
							if (newDiff != null) {
								updateStatus(newDiff);
								setCurrentDiff(newDiff, true);
							}
							invalidateLines();
							updateLines(doc);
						}
					}
					return Status.OK_STATUS;
				}
			}.schedule();
		} else {
			updateLines(doc);
		}
	}


	private void saveDiff() {
			fSavedDiff = fCurrentDiff;
	}

	private Diff getLastDiff() {
		if (fCurrentDiff != null) {
			return fCurrentDiff;
		}
		return fSavedDiff;
	}


	private Diff findNewDiff(Diff oldDiff) {
		if (oldDiff == null)
			return null;
		Diff newDiff = findNewDiff(oldDiff, LEFT_CONTRIBUTOR);
		if (newDiff == null) {
			newDiff = findNewDiff(oldDiff, RIGHT_CONTRIBUTOR);
		}
		return newDiff;
	}

	private Diff findNewDiff(Diff oldDiff, char type) {
		int offset = oldDiff.getPosition(type).offset;
		int length = oldDiff.getPosition(type).length;

		// DocumentMerger.findDiff method doesn't really work well with 0-length
		// diffs
		if (length == 0) {
			if (offset > 0)
				offset--;
			length = 1;
		}
		return fMerger.findDiff(type, offset, offset + length);
	}

	/*
	 * This method is called if a range of text on one side is copied into an empty sub-document
	 * on the other side. The method returns the position where the sub-document is placed into the base document.
	 * This default implementation determines the position by using the text range differencer.
	 * However this position is not always optimal for specific types of text.
	 * So subclasses (which are aware of the type of text they are dealing with)
	 * may override this method to find a better position where to insert a newly added
	 * piece of text.
	 * @param type the side for which the insertion position should be determined: 'A' for ancestor, 'L' for left hand side, 'R' for right hand side.
	 * @param input the current input object of this viewer
	 * @since 2.0
	 */
	protected int findInsertionPosition(char type, ICompareInput input) {

		ITypedElement other= null;
		char otherType= 0;

		switch (type) {
		case ANCESTOR_CONTRIBUTOR:
			other= input.getLeft();
			otherType= LEFT_CONTRIBUTOR;
			if (other == null) {
				other= input.getRight();
				otherType= RIGHT_CONTRIBUTOR;
			}
			break;
		case LEFT_CONTRIBUTOR:
			other= input.getRight();
			otherType= RIGHT_CONTRIBUTOR;
			if (other == null) {
				other= input.getAncestor();
				otherType= ANCESTOR_CONTRIBUTOR;
			}
			break;
		case RIGHT_CONTRIBUTOR:
			other= input.getLeft();
			otherType= LEFT_CONTRIBUTOR;
			if (other == null) {
				other= input.getAncestor();
				otherType= ANCESTOR_CONTRIBUTOR;
			}
			break;
		default:
			break;
		}

		if (other instanceof IDocumentRange) {
			IDocumentRange dr= (IDocumentRange) other;
			Position p= dr.getRange();
			Diff diff= findDiff(otherType, p.offset);
			return fMerger.findInsertionPoint(diff, type);
		}
		return 0;
	}

	private void setError(char type, String message) {
		IMergeViewerContentProvider cp= getMergeContentProvider();
		if (cp instanceof MergeViewerContentProvider) {
			MergeViewerContentProvider mcp= (MergeViewerContentProvider) cp;
			switch (type) {
			case ANCESTOR_CONTRIBUTOR:
				mcp.setAncestorError(message);
				break;
			case LEFT_CONTRIBUTOR:
				mcp.setLeftError(message);
				break;
			case RIGHT_CONTRIBUTOR:
				mcp.setRightError(message);
				break;
			default:
				break;
			}
		}
		fHasErrors= true;
	}

	private void updateDirtyState(IEditorInput key,
			IDocumentProvider documentProvider, char type) {
		boolean dirty = documentProvider.canSaveDocument(key);
		boolean oldLeftDirty = isLeftDirty();
		boolean oldRightDirty = isRightDirty();
		if (type == LEFT_CONTRIBUTOR)
			setLeftDirty(dirty);
		else if (type == RIGHT_CONTRIBUTOR)
			setRightDirty(dirty);
		if ((oldLeftDirty && !isLeftDirty())
				|| (oldRightDirty && !isRightDirty())) {
			/*
			 * Dirty state has changed from true to false, combined dirty state
			 * is false. _In most cases_ this means that save has taken place
			 * outside compare editor. Ask to redo diff calculation when the
			 * editor gets focus.
			 *
			 * However, undoing all the changes made in another editor would
			 * result in asking for redo diff as well. In this case, we set the
			 * flag back to false, see
			 * TextMergeViewer.documentChanged(DocumentEvent, boolean)
			 */
			fRedoDiff = true;
		}
	}

	private Position getNewRange(char type, Object input) {
		switch (type) {
		case ANCESTOR_CONTRIBUTOR:
			return fNewAncestorRanges.get(input);
		case LEFT_CONTRIBUTOR:
			return fNewLeftRanges.get(input);
		case RIGHT_CONTRIBUTOR:
			return fNewRightRanges.get(input);
		default:
			return null;
		}
	}

	private void addNewRange(char type, Object input, Position range) {
		switch (type) {
		case ANCESTOR_CONTRIBUTOR:
			fNewAncestorRanges.put(input, range);
			break;
		case LEFT_CONTRIBUTOR:
			fNewLeftRanges.put(input, range);
			break;
		case RIGHT_CONTRIBUTOR:
			fNewRightRanges.put(input, range);
			break;
		default:
			break;
		}
	}

	/**
	 * Returns the contents of the underlying document as an array of bytes using the current workbench encoding.
	 *
	 * @param left if <code>true</code> the contents of the left side is returned; otherwise the right side
	 * @return the contents of the left or right document or null
	 */
	@Override
	protected byte[] getContents(boolean left) {
		MergeSourceViewer v= left ? fLeft : fRight;
		if (v != null) {
			IDocument d= v.getSourceViewer().getDocument();
			if (d != null) {
				String contents= d.get();
				if (contents != null) {
					byte[] bytes;
					try {
						bytes= contents.getBytes(left ? fLeftContributor.internalGetEncoding() : fRightContributor.internalGetEncoding());
					} catch(UnsupportedEncodingException ex) {
						// use default encoding
						bytes= contents.getBytes();
					}
					return bytes;
				}
			}
		}
		return null;
	}

	private IRegion normalizeDocumentRegion(IDocument doc, IRegion region) {

		if (region == null || doc == null)
			return region;

		int maxLength= doc.getLength();

		int start= region.getOffset();
		if (start < 0)
			start= 0;
		else if (start > maxLength)
			start= maxLength;

		int length= region.getLength();
		if (length < 0)
			length= 0;
		else if (start + length > maxLength)
			length= maxLength - start;

		return new Region(start, length);
	}

	@Override
	protected final void handleResizeAncestor(int x, int y, int width, int height) {
		if (width > 0) {
			Rectangle trim= fLeft.getSourceViewer().getTextWidget().computeTrim(0, 0, 0, 0);
			int scrollbarHeight= trim.height;
			if (Utilities.okToUse(fAncestorCanvas))
				fAncestorCanvas.setVisible(true);
			if (fAncestor.isControlOkToUse())
				fAncestor.getSourceViewer().getTextWidget().setVisible(true);

			if (fAncestorCanvas != null) {
				fAncestorCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight);
				x+= fMarginWidth;
				width-= fMarginWidth;
			}
			fAncestor.setBounds(x, y, width, height);
		} else {
			if (Utilities.okToUse(fAncestorCanvas))
				fAncestorCanvas.setVisible(false);
			if (fAncestor.isControlOkToUse()) {
				StyledText t= fAncestor.getSourceViewer().getTextWidget();
				t.setVisible(false);
				fAncestor.setBounds(0, 0, 0, 0);
				if (fFocusPart == fAncestor) {
					fFocusPart= fLeft;
					fFocusPart.getSourceViewer().getTextWidget().setFocus();
				}
			}
		}
	}

	@Override
		protected final void handleResizeLeftRight(int x, int y, int width1, int centerWidth, int width2,  int height) {
			if (fBirdsEyeCanvas != null)
				width2-= BIRDS_EYE_VIEW_WIDTH;

		Rectangle trim= fLeft.getSourceViewer().getTextWidget().computeTrim(0, 0, 0, 0);
		int scrollbarHeight= trim.height + trim.x;

		Composite composite= (Composite) getControl();

		int leftTextWidth= width1;
		if (fLeftCanvas != null) {
			fLeftCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight);
			x+= fMarginWidth;
			leftTextWidth-= fMarginWidth;
		}

		fLeft.setBounds(x, y, leftTextWidth, height);
		x+= leftTextWidth;

		if (fCenter == null || fCenter.isDisposed())
			fCenter= createCenterControl(composite);
		fCenter.setBounds(x, y, centerWidth, height-scrollbarHeight);
		x+= centerWidth;

		if (!fSynchronizedScrolling) {	// canvas is to the left of text
			if (fRightCanvas != null) {
				fRightCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight);
				fRightCanvas.redraw();
				x+= fMarginWidth;
			}
			// we draw the canvas to the left of the text widget
		}

		int scrollbarWidth= 0;
		if (fSynchronizedScrolling && fScrollCanvas != null) {
			trim= fLeft.getSourceViewer().getTextWidget().computeTrim(0, 0, 0, 0);
				// one pixel was cut off
			scrollbarWidth= trim.width + 2*trim.x+1;
		}
		int rightTextWidth= width2-scrollbarWidth;
		if (fRightCanvas != null)
			rightTextWidth-= fMarginWidth;
		fRight.setBounds(x, y, rightTextWidth, height);
		x+= rightTextWidth;

		if (fSynchronizedScrolling) {
			if (fRightCanvas != null) {	// canvas is to the right of the text
				fRightCanvas.setBounds(x, y, fMarginWidth, height-scrollbarHeight);
				x+= fMarginWidth;
			}
			if (fScrollCanvas != null)
				fScrollCanvas.setBounds(x, y, scrollbarWidth, height-scrollbarHeight);
		}

			if (fBirdsEyeCanvas != null) {
				int verticalScrollbarButtonHeight= scrollbarWidth;
			int horizontalScrollbarButtonHeight= scrollbarHeight;
			if (fIsMac) {
				verticalScrollbarButtonHeight+= 2;
				horizontalScrollbarButtonHeight= 18;
			}
				if (fSummaryHeader != null)
				fSummaryHeader.setBounds(x+scrollbarWidth, y, BIRDS_EYE_VIEW_WIDTH, verticalScrollbarButtonHeight);
				y+= verticalScrollbarButtonHeight;
				fBirdsEyeCanvas.setBounds(x+scrollbarWidth, y, BIRDS_EYE_VIEW_WIDTH, height-(2*verticalScrollbarButtonHeight+horizontalScrollbarButtonHeight));
			}

		// doesn't work since TextEditors don't have their correct size yet.
		updateVScrollBar();
		refreshBirdsEyeView();
	}

	/*
	 * Track selection changes to update the current Diff.
	 */
	private void handleSelectionChanged(MergeSourceViewer tw) {
		Point p= tw.getSourceViewer().getSelectedRange();
		Diff d= findDiff(tw, p.x, p.x+p.y);
		updateStatus(d);
		setCurrentDiff(d, false);	// don't select or reveal
	}

	private static IRegion toRegion(Position position) {
		if (position != null)
			return new Region(position.getOffset(), position.getLength());
		return null;
	}

	//---- the differencing

	/**
	 * Perform a two level 2- or 3-way diff.
	 * The first level is based on line comparison, the second level on token comparison.
	 */
	private void doDiff() {
		IDocument lDoc= fLeft.getSourceViewer().getDocument();
		IDocument rDoc= fRight.getSourceViewer().getDocument();
		if (lDoc == null || rDoc == null)
			return;
		fAncestor.resetLineBackground();
		fLeft.resetLineBackground();
		fRight.resetLineBackground();
		saveDiff();
		fCurrentDiff= null;
		try {
			fMerger.doDiff();
		} catch (CoreException e) {
			CompareUIPlugin.log(e.getStatus());
			String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
			String msg= Utilities.getString(getResourceBundle(), "tooComplexError.message"); //$NON-NLS-1$
			MessageDialog.openError(fComposite.getShell(), title, msg);
		}

		invalidateTextPresentation();
	}

	private Diff findDiff(char type, int pos) {
		try {
			return fMerger.findDiff(type, pos);
		} catch (CoreException e) {
			CompareUIPlugin.log(e.getStatus());
			String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
			String msg= Utilities.getString(getResourceBundle(), "tooComplexError.message"); //$NON-NLS-1$
			MessageDialog.openError(fComposite.getShell(), title, msg);
			return null;
		}
	}

	private void resetPositions(IDocument doc) {
		if (doc == null)
			return;
		try {
			doc.removePositionCategory(DIFF_RANGE_CATEGORY);
		} catch (BadPositionCategoryException e) {
			// Ignore
		}
		doc.addPositionCategory(DIFF_RANGE_CATEGORY);
	}

	//---- update UI stuff

	private void updateControls() {
		if (getControl().isDisposed())
			return;

		boolean leftToRight= false;
		boolean rightToLeft= false;

		updateStatus(fCurrentDiff);
		updateResolveStatus();

		if (fCurrentDiff != null) {
			IMergeViewerContentProvider cp= getMergeContentProvider();
			if (cp != null) {
				if (!isPatchHunk()) {
					rightToLeft= cp.isLeftEditable(getInput());
					leftToRight= cp.isRightEditable(getInput());
				}
			}
		}

		if (fDirectionLabel != null) {
			if (fHighlightRanges && fCurrentDiff != null && isThreeWay() && !isIgnoreAncestor()) {
				fDirectionLabel.setImage(fCurrentDiff.getImage());
			} else {
				fDirectionLabel.setImage(null);
			}
		}

		if (fCopyDiffLeftToRightItem != null)
			fCopyDiffLeftToRightItem.getAction().setEnabled(leftToRight);
		if (fCopyDiffRightToLeftItem != null)
			fCopyDiffRightToLeftItem.getAction().setEnabled(rightToLeft);

		if (fNextDiff != null) {
			IAction a = fNextDiff.getAction();
			a.setEnabled(isNavigationButtonEnabled(true, false));
		}
		if (fPreviousDiff != null) {
			IAction a = fPreviousDiff.getAction();
			a.setEnabled(isNavigationButtonEnabled(false, false));
		}
		if (fNextChange != null) {
			IAction a = fNextChange.getAction();
			a.setEnabled(isNavigationButtonEnabled(true, true));
		}
		if (fPreviousChange != null) {
			IAction a = fPreviousChange.getAction();
			a.setEnabled(isNavigationButtonEnabled(false, true));
		}
	}

	private boolean isNavigationButtonEnabled(boolean down, boolean deep) {
		String value = fPreferenceStore
				.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION);
		if (value.equals(ICompareUIConstants.PREF_VALUE_DO_NOTHING)) {
			return getNextVisibleDiff(down, deep) != null;
		} else if (value.equals(ICompareUIConstants.PREF_VALUE_LOOP)) {
			return isNavigationPossible();
		} else if (value.equals(ICompareUIConstants.PREF_VALUE_NEXT)) {
			return getNextVisibleDiff(down, deep) != null || hasNextElement(down);
		} else if (value.equals(ICompareUIConstants.PREF_VALUE_PROMPT)) {
			return isNavigationPossible() || hasNextElement(true);
		}
		Assert.isTrue(false);
		return false;
	}

	private void updateResolveStatus() {

		RGB rgb= null;

		if (showResolveUI()) {
			// we only show red or green if there is at least one incoming or conflicting change
			int unresolvedIncoming= 0;
			int unresolvedConflicting= 0;

			if (fMerger.hasChanges()) {
				for (Iterator<?> iterator = fMerger.changesIterator(); iterator	.hasNext();) {
					Diff d = (Diff) iterator.next();
						if (!d.isResolved()) {
							if (d.getKind() == RangeDifference.CONFLICT) {
								unresolvedConflicting++;
								break; // we can stop here because a conflict has the maximum priority
							}
							unresolvedIncoming++;
						}
				}
			}

			if (unresolvedConflicting > 0)
				rgb= conflictPalette.selected;
			else if (unresolvedIncoming > 0)
				rgb= incomingPalette.selected;
			else
				rgb= RESOLVED;
		}

		if (fHeaderPainter.setColor(rgb))
			fSummaryHeader.redraw();
	}

	private void updateStatus(Diff diff) {

		String diffDescription;

		if (diff == null) {
			diffDescription= CompareMessages.TextMergeViewer_diffDescription_noDiff_format;
		} else {

			if (diff.isToken())		// we don't show special info for token diffs
				diff= diff.getParent();

			String format= CompareMessages.TextMergeViewer_diffDescription_diff_format;
			diffDescription= MessageFormat.format(format,
				getDiffType(diff),						// 0: diff type
				getDiffNumber(diff),					// 1: diff number
				getDiffRange(fLeft, diff.getPosition(LEFT_CONTRIBUTOR)),		// 2: left start line
				getDiffRange(fRight, diff.getPosition(RIGHT_CONTRIBUTOR))	// 3: left end line
			);
		}

		String format= CompareMessages.TextMergeViewer_statusLine_format;
		String s= MessageFormat.format(format,
			getCursorPosition(fLeft),	// 0: left column
			getCursorPosition(fRight),	// 1: right column
			diffDescription				// 2: diff description
		);

		getCompareConfiguration().getContainer().setStatusMessage(s);
	}

	private String getDiffType(Diff diff) {
		String s= ""; 	//$NON-NLS-1$
		switch(diff.getKind()) {
		case RangeDifference.LEFT:
			s= getCompareConfiguration().isMirrored() ?
					CompareMessages.TextMergeViewer_direction_incoming :
					CompareMessages.TextMergeViewer_direction_outgoing;
			break;
		case RangeDifference.RIGHT:
			s= getCompareConfiguration().isMirrored() ?
					CompareMessages.TextMergeViewer_direction_outgoing :
					CompareMessages.TextMergeViewer_direction_incoming;
			break;
		case RangeDifference.CONFLICT:
			s= CompareMessages.TextMergeViewer_direction_conflicting;
			break;
		default:
			break;
		}
		String format= CompareMessages.TextMergeViewer_diffType_format;
		return MessageFormat.format(format, s, diff.changeType());
	}

	private String getDiffNumber(Diff diff) {
		// find the diff's number
		int diffNumber= 0;
		if (fMerger.hasChanges()) {
			for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
				Diff d = (Diff) iterator.next();
				diffNumber++;
				if (d == diff)
					break;
			}
		}
		return Integer.toString(diffNumber);
	}

	private String getDiffRange(MergeSourceViewer v, Position pos) {
		Point p= v.getLineRange(pos, new Point(0, 0));
		int startLine= p.x+1;
		int endLine= p.x+p.y;

		String format;
		if (endLine < startLine)
			format= CompareMessages.TextMergeViewer_beforeLine_format;
		else
			format= CompareMessages.TextMergeViewer_range_format;
		return MessageFormat.format(format, Integer.toString(startLine), Integer.toString(endLine));
	}

	/*
	 * Returns a description of the cursor position.
	 *
	 * @return a description of the cursor position
	 */
	private String getCursorPosition(MergeSourceViewer v) {
		if (v != null) {
			StyledText styledText= v.getSourceViewer().getTextWidget();

			IDocument document= v.getSourceViewer().getDocument();
			if (document != null) {
				int offset= v.getSourceViewer().getVisibleRegion().getOffset();
				int caret= offset + styledText.getCaretOffset();

				try {
					int line=document.getLineOfOffset(caret);

					int lineOffset= document.getLineOffset(line);
					int occurrences= 0;
					for (int i= lineOffset; i < caret; i++)
						if ('\t' == document.getChar(i))
							++ occurrences;

					int tabWidth= styledText.getTabs();
					int column= caret - lineOffset + (tabWidth -1) * occurrences;

					String format= CompareMessages.TextMergeViewer_cursorPosition_format;
					return MessageFormat.format(format,
						Integer.toString(line + 1), Integer.toString(column + 1) );
				} catch (BadLocationException x) {
					// silently ignored
				}
			}
		}
		return "";	//$NON-NLS-1$
	}

	@Override
	protected void updateHeader() {
		super.updateHeader();

		updateControls();
	}

	/*
	 * Creates the two items for copying a difference range from one side to the other
	 * and adds them to the given toolbar manager.
	 */
	@Override
	protected void createToolItems(ToolBarManager tbm) {
		fHandlerService= CompareHandlerService.createFor(getCompareConfiguration().getContainer(), fLeft.getSourceViewer().getControl().getShell());

		final String ignoreAncestorActionKey= "action.IgnoreAncestor.";	//$NON-NLS-1$
		Action ignoreAncestorAction= new Action() {
			@Override
			public void run() {
				// First make sure the ancestor is hidden
				if (!isIgnoreAncestor())
					getCompareConfiguration().setProperty(ICompareUIConstants.PROP_ANCESTOR_VISIBLE, Boolean.FALSE);
				// Then set the property to ignore the ancestor
				getCompareConfiguration().setProperty(ICompareUIConstants.PROP_IGNORE_ANCESTOR, Boolean.valueOf(!isIgnoreAncestor()));
				Utilities.initToggleAction(this, getResourceBundle(), ignoreAncestorActionKey, isIgnoreAncestor());
			}
		};
		ignoreAncestorAction.setChecked(isIgnoreAncestor());
		Utilities.initAction(ignoreAncestorAction, getResourceBundle(), ignoreAncestorActionKey);
		Utilities.initToggleAction(ignoreAncestorAction, getResourceBundle(), ignoreAncestorActionKey, isIgnoreAncestor());

		fIgnoreAncestorItem= new ActionContributionItem(ignoreAncestorAction);
		fIgnoreAncestorItem.setVisible(false);
		tbm.appendToGroup("modes", fIgnoreAncestorItem); //$NON-NLS-1$

		tbm.add(new Separator());

		Action a= new Action() {
			@Override
			public void run() {
				if (navigate(true, false, false)) {
					endOfDocumentReached(true);
				}
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.NextDiff."); //$NON-NLS-1$
		fNextDiff= new ActionContributionItem(a);
		tbm.appendToGroup("navigation", fNextDiff); //$NON-NLS-1$
		// Don't register this action since it is probably registered by the container

		a= new Action() {
			@Override
			public void run() {
				if (navigate(false, false, false)) {
					endOfDocumentReached(false);
				}
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.PrevDiff."); //$NON-NLS-1$
		fPreviousDiff= new ActionContributionItem(a);
		tbm.appendToGroup("navigation", fPreviousDiff); //$NON-NLS-1$
		// Don't register this action since it is probably registered by the container

		a= new Action() {
			@Override
			public void run() {
				if (navigate(true, false, true)) {
					endOfDocumentReached(true);
				}
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.NextChange."); //$NON-NLS-1$
		fNextChange= new ActionContributionItem(a);
		tbm.appendToGroup("navigation", fNextChange); //$NON-NLS-1$
		fHandlerService.registerAction(a, "org.eclipse.compare.selectNextChange");	//$NON-NLS-1$

		a= new Action() {
			@Override
			public void run() {
				if (navigate(false, false, true)) {
					endOfDocumentReached(false);
				}
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.PrevChange."); //$NON-NLS-1$
		fPreviousChange= new ActionContributionItem(a);
		tbm.appendToGroup("navigation", fPreviousChange); //$NON-NLS-1$
		fHandlerService.registerAction(a, "org.eclipse.compare.selectPreviousChange");	//$NON-NLS-1$

		a= new Action() {
			@Override
			public void run() {
				copyDiffLeftToRight();
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.CopyDiffLeftToRight."); //$NON-NLS-1$
		fCopyDiffLeftToRightItem= new ActionContributionItem(a);
		fCopyDiffLeftToRightItem.setVisible(isRightEditable());
		tbm.appendToGroup("merge", fCopyDiffLeftToRightItem); //$NON-NLS-1$
		fHandlerService.registerAction(a, "org.eclipse.compare.copyLeftToRight");	//$NON-NLS-1$

		a= new Action() {
			@Override
			public void run() {
				copyDiffRightToLeft();
			}
		};
		Utilities.initAction(a, getResourceBundle(), "action.CopyDiffRightToLeft."); //$NON-NLS-1$
		fCopyDiffRightToLeftItem= new ActionContributionItem(a);
		fCopyDiffRightToLeftItem.setVisible(isLeftEditable());
		tbm.appendToGroup("merge", fCopyDiffRightToLeftItem); //$NON-NLS-1$
		fHandlerService.registerAction(a, "org.eclipse.compare.copyRightToLeft");	//$NON-NLS-1$

		fIgnoreWhitespace= ChangePropertyAction.createIgnoreWhiteSpaceAction(getResourceBundle(), getCompareConfiguration());
		fIgnoreWhitespace.setActionDefinitionId(ICompareUIConstants.COMMAND_IGNORE_WHITESPACE);
		fLeft.addTextAction(fIgnoreWhitespace);
		fRight.addTextAction(fIgnoreWhitespace);
		fAncestor.addTextAction(fIgnoreWhitespace);
		fHandlerService.registerAction(fIgnoreWhitespace, fIgnoreWhitespace.getActionDefinitionId());

		boolean needsLeftPainter= !isEditorBacked(fLeft.getSourceViewer());
		boolean needsRightPainter= !isEditorBacked(fRight.getSourceViewer());
		boolean needsAncestorPainter= !isEditorBacked(fAncestor.getSourceViewer());
		showWhitespaceAction = new ShowWhitespaceAction(
				new MergeSourceViewer[] {fLeft, fRight, fAncestor},
				new boolean[] {needsLeftPainter, needsRightPainter, needsAncestorPainter });
		fHandlerService.registerAction(showWhitespaceAction, ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS);

		toggleLineNumbersAction = new LineNumberRulerToggleAction(CompareMessages.TextMergeViewer_16,
				new MergeSourceViewer[] { fLeft, fRight, fAncestor },
				AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER);
		fHandlerService.registerAction(toggleLineNumbersAction, ITextEditorActionDefinitionIds.LINENUMBER_TOGGLE);
	}

	private void configureCompareFilterActions(Object input, Object ancestor,
			Object left, Object right) {
		if (getCompareConfiguration() == null) {
			return;
		}

		CompareFilterDescriptor[] compareFilterDescriptors = CompareUIPlugin.getDefault().findCompareFilters(input);
		Object current = getCompareConfiguration()
				.getProperty(ChangeCompareFilterPropertyAction.COMPARE_FILTER_ACTIONS);
		boolean currentFiltersMatch = false;
		if (current != null && current instanceof List
				&& ((List<?>) current).size() == compareFilterDescriptors.length) {
			currentFiltersMatch = true;
			@SuppressWarnings("unchecked")
			List<ChangeCompareFilterPropertyAction> currentFilterActions = (List<ChangeCompareFilterPropertyAction>) current;
			for (CompareFilterDescriptor compareFilterDescriptor : compareFilterDescriptors) {
				boolean match = false;
				for (int j = 0; j < currentFilterActions.size(); j++) {
					if (compareFilterDescriptor.getFilterId().equals(currentFilterActions.get(j).getFilterId())) {
						match = true;
						break;
					}
				}
				if (!match) {
					currentFiltersMatch = false;
					break;
				}
			}
		}
		if (!currentFiltersMatch) {
			getCompareConfiguration().setProperty(ChangeCompareFilterPropertyAction.COMPARE_FILTERS_INITIALIZING,
					Boolean.TRUE);
			disposeCompareFilterActions(true);
			fCompareFilterActions.clear();
			for (CompareFilterDescriptor compareFilterDescriptor : compareFilterDescriptors) {
				ChangeCompareFilterPropertyAction compareFilterAction = new ChangeCompareFilterPropertyAction(compareFilterDescriptor, getCompareConfiguration());
				compareFilterAction.setInput(input, ancestor, left, right);
				fCompareFilterActions.add(compareFilterAction);
				fLeft.addTextAction(compareFilterAction);
				fRight.addTextAction(compareFilterAction);
				fAncestor.addTextAction(compareFilterAction);

				if (getCompareConfiguration().getContainer().getActionBars() != null) {
					getCompareConfiguration().getContainer().getActionBars().getToolBarManager()
							.appendToGroup(CompareEditorContributor.FILTER_SEPARATOR, compareFilterAction);
					if (compareFilterAction.getActionDefinitionId() != null)
						getCompareConfiguration()
								.getContainer()
								.getActionBars()
								.setGlobalActionHandler(compareFilterAction.getActionDefinitionId(),
										compareFilterAction);
				}
			}
			if (!fCompareFilterActions.isEmpty() && getCompareConfiguration().getContainer().getActionBars() != null) {
				getCompareConfiguration().getContainer().getActionBars().getToolBarManager().markDirty();
				getCompareConfiguration().getContainer().getActionBars().getToolBarManager().update(true);
				getCompareConfiguration().getContainer().getActionBars().updateActionBars();
			}
			getCompareConfiguration().setProperty(ChangeCompareFilterPropertyAction.COMPARE_FILTER_ACTIONS,
					fCompareFilterActions);
			getCompareConfiguration().setProperty(ChangeCompareFilterPropertyAction.COMPARE_FILTERS_INITIALIZING, null);
		} else {
			for (int i = 0; i < fCompareFilterActions.size(); i++) {
				fCompareFilterActions.get(i).setInput(input, ancestor, left, right);
			}
		}
	}

	private void disposeCompareFilterActions(boolean updateActionBars) {
		Iterator<ChangeCompareFilterPropertyAction> compareFilterActionsIterator = fCompareFilterActions
				.iterator();
		while (compareFilterActionsIterator.hasNext()) {
			ChangeCompareFilterPropertyAction compareFilterAction = compareFilterActionsIterator
					.next();
			fLeft.removeTextAction(compareFilterAction);
			fRight.removeTextAction(compareFilterAction);
			fAncestor.removeTextAction(compareFilterAction);
			if (updateActionBars
					&& getCompareConfiguration().getContainer().getActionBars() != null) {
				getCompareConfiguration().getContainer().getActionBars()
						.getToolBarManager()
						.remove(compareFilterAction.getId());
				if (compareFilterAction.getActionDefinitionId() != null)
					getCompareConfiguration()
							.getContainer()
							.getActionBars()
							.setGlobalActionHandler(
									compareFilterAction.getActionDefinitionId(),
									null);
			}
			compareFilterAction.dispose();
		}
		if (updateActionBars
				&& !fCompareFilterActions.isEmpty()
				&& getCompareConfiguration().getContainer().getActionBars() != null) {
			getCompareConfiguration().getContainer().getActionBars()
					.getToolBarManager().markDirty();
			getCompareConfiguration().getContainer().getActionBars()
					.getToolBarManager().update(true);
		}
		fCompareFilterActions.clear();
		getCompareConfiguration().setProperty(
				ChangeCompareFilterPropertyAction.COMPARE_FILTERS, null);
		getCompareConfiguration().setProperty(
				ChangeCompareFilterPropertyAction.COMPARE_FILTER_ACTIONS, null);
	}

	@Override
	protected void handlePropertyChangeEvent(PropertyChangeEvent event) {
		String key= event.getProperty();

		if (key.equals(CompareConfiguration.IGNORE_WHITESPACE)
				|| key.equals(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS)
				|| (key.equals(ChangeCompareFilterPropertyAction.COMPARE_FILTERS) && getCompareConfiguration()
						.getProperty(
								ChangeCompareFilterPropertyAction.COMPARE_FILTERS_INITIALIZING) == null)) {

			fShowPseudoConflicts= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS);

			update(true);
			// selectFirstDiff(true);
			if (fFocusPart != null)
				handleSelectionChanged(fFocusPart);

//		} else if (key.equals(ComparePreferencePage.USE_SPLINES)) {
//			fUseSplines= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SPLINES);
//			invalidateLines();

		} else if (key.equals(ComparePreferencePage.USE_SINGLE_LINE)) {
			fUseSingleLine= fPreferenceStore.getBoolean(ComparePreferencePage.USE_SINGLE_LINE);
//			fUseResolveUI= fUseSingleLine;
			fBasicCenterCurve= null;
			updateControls();
			invalidateLines();

		} else if (key.equals(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES)) {
			fHighlightTokenChanges= fPreferenceStore.getBoolean(ComparePreferencePage.HIGHLIGHT_TOKEN_CHANGES);
			updateControls();
			updatePresentation();

//		} else if (key.equals(ComparePreferencePage.USE_RESOLVE_UI)) {
//			fUseResolveUI= fPreferenceStore.getBoolean(ComparePreferencePage.USE_RESOLVE_UI);
//			updateResolveStatus();
//			invalidateLines();

		} else if (key.equals(fSymbolicFontName)) {
			updateFont();
			invalidateLines();

		} else if (key.equals(INCOMING_COLOR) || key.equals(OUTGOING_COLOR) || key.equals(CONFLICTING_COLOR)
				|| key.equals(RESOLVED_COLOR) || key.equals(ADDITION_COLOR) || key.equals(DELETION_COLOR)
				|| key.equals(EDITION_COLOR)) {
			updateColors(null);
			invalidateLines();
			invalidateTextPresentation();

		} else if (key.equals(ComparePreferencePage.SYNCHRONIZE_SCROLLING)) {
			boolean b= fPreferenceStore.getBoolean(ComparePreferencePage.SYNCHRONIZE_SCROLLING);
			setSyncScrolling(b);

		} else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)) {
			if (!fIsUsingSystemBackground) {
				setBackgroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND));
			}

		} else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
			fIsUsingSystemBackground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT);
			if (fIsUsingSystemBackground) {
				setBackgroundColor(null);
			} else {
				setBackgroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND));
			}
		} else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND)) {
			if (!fIsUsingSystemForeground) {
				setForegroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND));
			}

		} else if (key.equals(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT)) {
			fIsUsingSystemForeground= fPreferenceStore.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT);
			if (fIsUsingSystemForeground) {
				setForegroundColor(null);
			} else {
				setForegroundColor(createColor(fPreferenceStore, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND));
			}
		} else if (key.equals(ICompareUIConstants.PREF_NAVIGATION_END_ACTION)) {
			updateControls();
		} else if (key.equals(CompareContentViewerSwitchingPane.DISABLE_CAPPING_TEMPORARILY)) {
			if (Boolean.TRUE.equals(event.getNewValue())) {
				getCompareConfiguration().setProperty(CompareContentViewerSwitchingPane.DISABLE_CAPPING_TEMPORARILY, null);
				handleCompareInputChange();
			}
		} else {
			super.handlePropertyChangeEvent(event);

			if (key.equals(ICompareUIConstants.PROP_IGNORE_ANCESTOR)) {
				update(true);
				selectFirstDiff(true);
			}
		}
	}

	private void selectFirstDiff(boolean first) {

		if (fLeft == null || fRight == null) {
			return;
		}
		if (fLeft.getSourceViewer().getDocument() == null || fRight.getSourceViewer().getDocument() == null) {
			return;
		}

		Diff firstDiff= null;
		if (first)
			firstDiff= findNext(fRight, -1, -1, false);
		else
			firstDiff= findPrev(fRight, 9999999, 9999999, false);
		setCurrentDiff(firstDiff, true);
	}



	private void setSyncScrolling(boolean newMode) {
		if (fSynchronizedScrolling != newMode) {
			fSynchronizedScrolling= newMode;

			scrollVertical(0, 0, 0, null);

			// throw away central control (Sash or Canvas)
			Control center= getCenterControl();
			if (center != null && !center.isDisposed())
				center.dispose();

			fLeft.getSourceViewer().getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling);
			fRight.getSourceViewer().getTextWidget().getVerticalBar().setVisible(!fSynchronizedScrolling);

			fComposite.layout(true);
		}
	}

	@Override
	protected void updateToolItems() {
		if (fCopyDiffLeftToRightItem != null) {
			fCopyDiffLeftToRightItem.setVisible(isRightEditable());
		}
		if (fCopyDiffRightToLeftItem != null) {
			fCopyDiffRightToLeftItem.setVisible(isLeftEditable());
		}

		//only update toolbar items if diffs need to be calculated (which
		//dictates whether a toolbar gets added at all)
		if (!isPatchHunk()){
			if (fIgnoreAncestorItem != null)
				fIgnoreAncestorItem.setVisible(isThreeWay());

			if (fCopyDiffLeftToRightItem != null) {
				IAction a= fCopyDiffLeftToRightItem.getAction();
				if (a != null)
					a.setEnabled(a.isEnabled() && !fHasErrors);
			}
			if (fCopyDiffRightToLeftItem != null) {
				IAction a= fCopyDiffRightToLeftItem.getAction();
				if (a != null)
					a.setEnabled(a.isEnabled() && !fHasErrors);
			}
		}
		super.updateToolItems();
	}

	//---- painting lines

	private void updateLines(IDocument d) {
		boolean left= false;
		boolean right= false;

		// FIXME: this optimization is incorrect because
		// it doesn't take replace operations into account where
		// the old and new line count does not differ
		if (d == fLeft.getSourceViewer().getDocument()) {
			int l= fLeft.getLineCount();
			left= fLeftLineCount != l;
			fLeftLineCount= l;
		} else if (d == fRight.getSourceViewer().getDocument()) {
			int l= fRight.getLineCount();
			right= fRightLineCount != l;
			fRightLineCount= l;
		}

		if (left || right) {
			if (left) {
				if (fLeftCanvas != null)
					fLeftCanvas.redraw();
			} else {
				if (fRightCanvas != null)
					fRightCanvas.redraw();
			}
			Control center= getCenterControl();
			if (center != null)
				center.redraw();

			updateVScrollBar();
			refreshBirdsEyeView();
		}
	}

	private void invalidateLines() {
		if (isThreeWay() && isAncestorVisible()) {
			if (Utilities.okToUse(fAncestorCanvas))
				fAncestorCanvas.redraw();
			if (fAncestor != null && fAncestor.isControlOkToUse())
				fAncestor.getSourceViewer().getTextWidget().redraw();
		}

		if (Utilities.okToUse(fLeftCanvas))
			fLeftCanvas.redraw();

		if (fLeft != null && fLeft.isControlOkToUse())
			fLeft.getSourceViewer().getTextWidget().redraw();

		if (Utilities.okToUse(getCenterControl()))
			getCenterControl().redraw();

		if (fRight != null && fRight.isControlOkToUse())
			fRight.getSourceViewer().getTextWidget().redraw();

		if (Utilities.okToUse(fRightCanvas))
			fRightCanvas.redraw();
	}

	private boolean showResolveUI() {
		if (!isThreeWay() || isIgnoreAncestor())
			return false;
		return isAnySideEditable();
	}

	private boolean isAnySideEditable() {
		// we only enable the new resolve UI if exactly one side is editable
		return isLeftEditable() || isRightEditable();
	}

	private void paintCenter(Canvas canvas, GC g) {

		Display display= canvas.getDisplay();

		checkForColorUpdate(display);

		if (! fSynchronizedScrolling)
			return;

		int lineHeightLeft= fLeft.getSourceViewer().getTextWidget().getLineHeight();
		int lineHeightRight= fRight.getSourceViewer().getTextWidget().getLineHeight();
		int visibleHeight= fRight.getViewportHeight();

		Point size= canvas.getSize();
		int x= 0;
		int w= size.x;

		g.setBackground(canvas.getBackground());
		g.fillRectangle(x+1, 0, w-2, size.y);

		// draw thin line between center ruler and both texts
		g.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
		g.fillRectangle(0, 0, 1, size.y);
		g.fillRectangle(w - 1, 0, 1, size.y);

		if (! fHighlightRanges)
			return;

		if (fMerger.hasChanges()) {
			int lshift= fLeft.getVerticalScrollOffset();
			int rshift= fRight.getVerticalScrollOffset();

			Point region= new Point(0, 0);

			boolean allOutgoing = allOutgoing();
			for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
				Diff diff = (Diff) iterator.next();
				if (diff.isDeleted())
					continue;

				if (fShowCurrentOnly2 && !isCurrentDiff(diff))
					continue;

				fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
				int ly= (region.x * lineHeightLeft) + lshift;
				int lh= region.y * lineHeightLeft;

				fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
				int ry= (region.x * lineHeightRight) + rshift;
				int rh= region.y * lineHeightRight;

				if (Math.max(ly+lh, ry+rh) < 0)
					continue;
				if (Math.min(ly, ry) >= visibleHeight)
					break;

				fPts[0]= x;	fPts[1]= ly;	fPts[2]= w;	fPts[3]= ry;
				fPts[6]= x;	fPts[7]= ly+lh;	fPts[4]= w;	fPts[5]= ry+rh;

				Color fillColor = getColor(display, getFillColor(diff, allOutgoing));
				Color strokeColor = getColor(display, getStrokeColor(diff, allOutgoing));

				if (fUseSingleLine) {
					int w2= 3;

					g.setBackground(fillColor);
					g.fillRectangle(0, ly, w2, lh);		// left
					g.fillRectangle(w-w2, ry, w2, rh);	// right

					g.setLineWidth(0 /* LW */);
					g.setForeground(strokeColor);
					g.drawRectangle(0-1, ly, w2, lh);	// left
					g.drawRectangle(w-w2, ry, w2, rh);	// right

					if (fUseSplines) {
						int[] points= getCenterCurvePoints(w2, ly+lh/2, w-w2, ry+rh/2);
						for (int i= 1; i < points.length; i++)
							g.drawLine(w2+i-1, points[i-1], w2+i, points[i]);
					} else {
						g.drawLine(w2, ly+lh/2, w-w2, ry+rh/2);
					}
				} else {
					// two lines
					if (fUseSplines) {
						g.setBackground(fillColor);

						g.setLineWidth(0 /* LW */);
						g.setForeground(strokeColor);

						int[] topPoints= getCenterCurvePoints(fPts[0], fPts[1], fPts[2], fPts[3]);
						int[] bottomPoints= getCenterCurvePoints(fPts[6], fPts[7], fPts[4], fPts[5]);
						g.setForeground(fillColor);
						g.drawLine(0, bottomPoints[0], 0, topPoints[0]);
						for (int i= 1; i < bottomPoints.length; i++) {
							g.setForeground(fillColor);
							g.drawLine(i, bottomPoints[i], i, topPoints[i]);
							g.setForeground(strokeColor);
							g.drawLine(i-1, topPoints[i-1], i, topPoints[i]);
							g.drawLine(i-1, bottomPoints[i-1], i, bottomPoints[i]);
						}
					} else {
						g.setBackground(fillColor);
						g.fillPolygon(fPts);

						g.setLineWidth(0 /* LW */);
						g.setForeground(strokeColor);
						g.drawLine(fPts[0], fPts[1], fPts[2], fPts[3]);
						g.drawLine(fPts[6], fPts[7], fPts[4], fPts[5]);
					}
				}

				if (fUseSingleLine && isAnySideEditable()) {
					// draw resolve state
					int cx= (w-RESOLVE_SIZE)/2;
					int cy= ((ly+lh/2) + (ry+rh/2) - RESOLVE_SIZE)/2;

					g.setBackground(fillColor);
					g.fillRectangle(cx, cy, RESOLVE_SIZE, RESOLVE_SIZE);

					g.setForeground(strokeColor);
					g.drawRectangle(cx, cy, RESOLVE_SIZE, RESOLVE_SIZE);
				}
			}
		}
	}

	private int[] getCenterCurvePoints(int startx, int starty, int endx, int endy) {
		if (fBasicCenterCurve == null)
			buildBaseCenterCurve(endx-startx);
		double height= endy - starty;
		height= height/2;
		int width= endx-startx;
		int[] points= new int[width];
		for (int i= 0; i < width; i++) {
			points[i]= (int) (-height * fBasicCenterCurve[i] + height + starty);
		}
		return points;
	}

	private void buildBaseCenterCurve(int w) {
		double width= w;
		fBasicCenterCurve= new double[getCenterWidth()];
		for (int i= 0; i < getCenterWidth(); i++) {
			double r= i / width;
			fBasicCenterCurve[i]= Math.cos(Math.PI * r);
		}
	}

	private void paintSides(GC g, MergeSourceViewer tp, Canvas canvas, boolean right) {

		Display display= canvas.getDisplay();

		int lineHeight= tp.getSourceViewer().getTextWidget().getLineHeight();
		int visibleHeight= tp.getViewportHeight();

		Point size= canvas.getSize();
		int x= 0;
		int w= fMarginWidth;
		int w2= w/2;

		g.setBackground(canvas.getBackground());
		g.fillRectangle(x, 0, w, size.y);

		// draw thin line between ruler and text
		g.setBackground(display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
		if (right)
			g.fillRectangle(0, 0, 1, size.y);
		else
			g.fillRectangle(size.x - 1, 0, 1, size.y);

		if (! fHighlightRanges)
			return;

		if (fMerger.hasChanges()) {
			boolean allOutgoing = allOutgoing();
			int shift= tp.getVerticalScrollOffset() + (2-LW);

			Point region= new Point(0, 0);
			char leg = getLeg(tp);
			for (Iterator<Diff> iterator = fMerger.changesIterator(); iterator.hasNext();) {
				Diff diff = iterator.next();
				if (diff.isDeleted())
					continue;

				if (fShowCurrentOnly2 && !isCurrentDiff(diff))
					continue;

				tp.getLineRange(diff.getPosition(leg), region);
				int y= (region.x * lineHeight) + shift;
				int h= region.y * lineHeight;

				if (y+h < 0)
					continue;
				if (y >= visibleHeight)
					break;

				g.setBackground(getColor(display, getFillColor(diff, allOutgoing)));
				if (right)
					g.fillRectangle(x, y, w2, h);
				else
					g.fillRectangle(x+w2, y, w2, h);

				g.setLineWidth(0 /* LW */);
				g.setForeground(getColor(display, getStrokeColor(diff, allOutgoing)));
				if (right)
					g.drawRectangle(x-1, y-1, w2, h);
				else
					g.drawRectangle(x+w2, y-1, w2, h);
			}
		}
	}

	private boolean allOutgoing() {
		boolean allOutgoing = !isThreeWay();
		for (Iterator<Diff> iterator = fMerger.changesIterator(); allOutgoing && iterator.hasNext();) {
			Diff diff = iterator.next();
			allOutgoing &= !diff.isDeleted()
					&& (diff.getKind() == RangeDifference.NOCHANGE || diff.getKind() == RangeDifference.CHANGE);
		}
		return allOutgoing;
	}

	private void paint(PaintEvent event, MergeSourceViewer tp) {

		if (! fHighlightRanges)
			return;
		if (!fMerger.hasChanges())
			return;

		Control canvas= (Control) event.widget;
		GC g= event.gc;

		Display display= canvas.getDisplay();

		int lineHeight= tp.getSourceViewer().getTextWidget().getLineHeight();
		int w= canvas.getSize().x;
		int shift= tp.getVerticalScrollOffset() + (2-LW);
		int maxh= event.y+event.height; 	// visibleHeight

		shift += fTopInset;

		Point range= new Point(0, 0);

		char leg = getLeg(tp);
		boolean allOutgoing = allOutgoing();
		for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
			Diff diff = (Diff) iterator.next();
			if (diff.isDeleted())
				continue;

			if (fShowCurrentOnly && !isCurrentDiff(diff))
				continue;

			tp.getLineRange(diff.getPosition(leg), range);
			int y= (range.x * lineHeight) + shift;
			int h= range.y * lineHeight;

			if (y+h < event.y)
				continue;
			if (y > maxh)
				break;

			g.setBackground(getColor(display, getStrokeColor(diff, allOutgoing)));
			g.fillRectangle(0, y-1, w, LW);
			g.fillRectangle(0, y+h-1, w, LW);
		}
	}

	private RGB getFillColor(Diff diff, boolean showAdditionRemoval) {
		boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff;
		if (selected) {
			return getBackground(null);
		}
		ColorPalette palette = getColorPalette(diff, showAdditionRemoval);
		if (palette == null) {
			return null;
		}
		return palette.fill;
	}

	private ColorPalette getColorPalette(Diff diff, boolean showAdditionRemoval) {
		if (isThreeWay() && !isIgnoreAncestor()) {
			switch (diff.getKind()) {
			case RangeDifference.RIGHT:
				if (!getCompareConfiguration().isMirrored())
					return incomingPalette;
				return outgoingPalette;
			case RangeDifference.ANCESTOR:
			case RangeDifference.CONFLICT:
				return conflictPalette;
			case RangeDifference.LEFT:
				if (!getCompareConfiguration().isMirrored())
					return outgoingPalette;
				return incomingPalette;
			default:
				return null;
			}
		}
		if (showAdditionRemoval) {
			if (diff.getPosition(LEFT_CONTRIBUTOR).getLength() == 0) {
				return deletionPalette;
			}
			if (diff.getPosition(RIGHT_CONTRIBUTOR).getLength() == 0) {
				return additionPalette;
			}
			return editionPalette;
		}
		return outgoingPalette;
	}

	private RGB getStrokeColor(Diff diff, boolean showAdditionRemoval) {
		ColorPalette palette = getColorPalette(diff, showAdditionRemoval);
		if (palette == null) {
			return null;
		}
		boolean selected = fCurrentDiff != null && fCurrentDiff.getParent() == diff;
		return selected ? palette.selected : palette.normal;
	}

	private Color getColor(Display display, RGB rgb) {
		if (rgb == null)
			return null;
		if (fColors == null)
			fColors= new HashMap<RGB, Color>(20);
		Color c= fColors.get(rgb);
		if (c == null) {
			c= new Color(display, rgb);
			fColors.put(rgb, c);
		}
		return c;
	}

	//---- Navigating and resolving Diffs

	private Diff getNextVisibleDiff(boolean down, boolean deep) {
		Diff diff= null;
		MergeSourceViewer part= getNavigationPart();
		if (part == null)
			return null;
		Point s = part.getSourceViewer().getSelectedRange();
		char leg = getLeg(part);
		for (;;) {
			diff = null;
			diff = internalGetNextDiff(down, deep, part, s);
			if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
					&& !isAncestorVisible()) {
				Position position = diff.getPosition(leg);
				s = new Point(position.getOffset(), position.getLength());
				diff= null;
				continue;
			}
			break;
		}
		return diff;
	}

	private Diff internalGetNextDiff(boolean down, boolean deep, MergeSourceViewer part, Point s) {
		if (fMerger.hasChanges()) {
			if (down)
				return findNext(part, s.x, s.x+s.y, deep);
			return findPrev(part, s.x, s.x+s.y, deep);
		}
		return null;
	}

	private MergeSourceViewer getNavigationPart() {
		MergeSourceViewer part= fFocusPart;
		if (part == null)
			part= fRight;
		return part;
	}

	private Diff getWrappedDiff(Diff diff, boolean down) {
		return fMerger.getWrappedDiff(diff, down);
	}

	/*
	 * Returns true if end (or beginning) of document reached.
	 */
	private boolean navigate(boolean down, boolean wrap, boolean deep) {
		Diff diff= null;
		boolean wrapped = false;
		for (;;) {
			diff = getNextVisibleDiff(down, deep);
			if (diff == null && wrap) {
				if (wrapped)
					// We've already wrapped once so break out
					break;
				wrapped = true;
				diff = getWrappedDiff(diff, down);
			}
			if (diff != null)
				setCurrentDiff(diff, true, deep);
			if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
					&& !isAncestorVisible())
				continue;
			break;
		}
		return diff == null;
	}

	private void endOfDocumentReached(boolean down) {
		Control c= getControl();
		if (Utilities.okToUse(c)) {
			handleEndOfDocumentReached(c.getShell(), down);
		}
	}

	private void handleEndOfDocumentReached(Shell shell, boolean next) {
		IPreferenceStore store = CompareUIPlugin.getDefault().getPreferenceStore();
		String value = store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION);
		if (!value.equals(ICompareUIConstants.PREF_VALUE_PROMPT)) {
			performEndOfDocumentAction(shell, store, ICompareUIConstants.PREF_NAVIGATION_END_ACTION, next);
		} else {
			shell.getDisplay().beep();
			String loopMessage;
			String nextMessage;
			String message;
			String title;
			if (next) {
				title = CompareMessages.TextMergeViewer_0;
				message = CompareMessages.TextMergeViewer_1;
				loopMessage = CompareMessages.TextMergeViewer_2;
				nextMessage = CompareMessages.TextMergeViewer_3;
			} else {
				title = CompareMessages.TextMergeViewer_4;
				message = CompareMessages.TextMergeViewer_5;
				loopMessage = CompareMessages.TextMergeViewer_6;
				nextMessage = CompareMessages.TextMergeViewer_7;
			}
			String[] localLoopOption = new String[] { loopMessage, ICompareUIConstants.PREF_VALUE_LOOP };
			String[] nextElementOption = new String[] { nextMessage, ICompareUIConstants.PREF_VALUE_NEXT};
			String[] doNothingOption = new String[] { CompareMessages.TextMergeViewer_17, ICompareUIConstants.PREF_VALUE_DO_NOTHING};
			NavigationEndDialog dialog = new NavigationEndDialog(shell,
					title,
					null,
					message,
					new String[][] {
					localLoopOption,
					nextElementOption,
					doNothingOption
			});
			int result = dialog.open();
			if (result == Window.OK) {
				performEndOfDocumentAction(shell, store, ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL, next);
				if (dialog.getToggleState()) {
					String oldValue = store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION);
					store.putValue(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL));
					store.firePropertyChangeEvent(ICompareUIConstants.PREF_NAVIGATION_END_ACTION, oldValue, store.getString(ICompareUIConstants.PREF_NAVIGATION_END_ACTION_LOCAL));
				}
			}
		}
	}

	private void performEndOfDocumentAction(Shell shell, IPreferenceStore store, String key, boolean next) {
		String value = store.getString(key);
		if (value.equals(ICompareUIConstants.PREF_VALUE_DO_NOTHING)) {
			return;
		}
		if (value.equals(ICompareUIConstants.PREF_VALUE_NEXT)) {
			ICompareNavigator navigator = getCompareConfiguration()
					.getContainer().getNavigator();
			if (hasNextElement(next)) {
				navigator.selectChange(next);
			}
		} else {
			selectFirstDiff(next);
		}
	}

	private boolean hasNextElement(boolean down) {
		ICompareNavigator navigator = getCompareConfiguration().getContainer().getNavigator();
		if (navigator instanceof CompareNavigator) {
			CompareNavigator n = (CompareNavigator) navigator;
			return n.hasChange(down);
		}
		return false;
	}

	/*
	 * Find the Diff that overlaps with the given TextPart's text range.
	 * If the range doesn't overlap with any range <code>null</code>
	 * is returned.
	 */
	private Diff findDiff(MergeSourceViewer tp, int rangeStart, int rangeEnd) {
		char contributor = getLeg(tp);
		return fMerger.findDiff(contributor, rangeStart, rangeEnd);
	}

	private Diff findNext(MergeSourceViewer tp, int start, int end, boolean deep) {
		return fMerger.findNext(getLeg(tp), start, end, deep);
	}

	private Diff findPrev(MergeSourceViewer tp, int start, int end, boolean deep) {
		return fMerger.findPrev(getLeg(tp), start, end, deep);
	}

	/*
	 * Set the currently active Diff and update the toolbars controls and lines.
	 * If <code>revealAndSelect</code> is <code>true</code> the Diff is revealed and
	 * selected in both TextParts.
	 */
	private void setCurrentDiff(Diff d, boolean revealAndSelect) {
		setCurrentDiff(d, revealAndSelect, false);
	}

	/*
	 * Set the currently active Diff and update the toolbars controls and lines.
	 * If <code>revealAndSelect</code> is <code>true</code> the Diff is revealed and
	 * selected in both TextParts.
	 */
	private void setCurrentDiff(Diff d, boolean revealAndSelect, boolean deep) {

//		if (d == fCurrentDiff)
//			return;
		boolean diffChanged = fCurrentDiff != d;

		if (fLeftToRightButton != null && !fLeftToRightButton.isDisposed())
			fLeftToRightButton.setVisible(false);
		if (fRightToLeftButton != null && !fRightToLeftButton.isDisposed())
			fRightToLeftButton.setVisible(false);

		if (d != null && revealAndSelect) {

			// before we set fCurrentDiff we change the selection
			// so that the paint code uses the old background colors
			// otherwise selection isn't drawn correctly
			if (d.isToken() || !fHighlightTokenChanges || deep || !d.hasChildren()) {
				if (isThreeWay() && !isIgnoreAncestor())
					fAncestor.setSelection(d.getPosition(ANCESTOR_CONTRIBUTOR));
				fLeft.setSelection(d.getPosition(LEFT_CONTRIBUTOR));
				fRight.setSelection(d.getPosition(RIGHT_CONTRIBUTOR));
			} else {
				if (isThreeWay() && !isIgnoreAncestor())
					fAncestor.setSelection(new Position(d.getPosition(ANCESTOR_CONTRIBUTOR).offset, 0));
				fLeft.setSelection(new Position(d.getPosition(LEFT_CONTRIBUTOR).offset, 0));
				fRight.setSelection(new Position(d.getPosition(RIGHT_CONTRIBUTOR).offset, 0));
			}

			// now switch diffs
			saveDiff();
			fCurrentDiff= d;
			revealDiff(d, d.isToken());
		} else {
			saveDiff();
			fCurrentDiff= d;
		}

		updateControls();
		if (diffChanged)
			invalidateLines();
		refreshBirdsEyeView();
	}

	/*
	 * Smart determines whether
	 */
	private void revealDiff(Diff d, boolean smart) {

		boolean ancestorIsVisible= false;
		boolean leftIsVisible= false;
		boolean rightIsVisible= false;

		if (smart) {
			Point region= new Point(0, 0);
			// find the starting line of the diff in all text widgets
			int ls= fLeft.getLineRange(d.getPosition(LEFT_CONTRIBUTOR), region).x;
			int rs= fRight.getLineRange(d.getPosition(RIGHT_CONTRIBUTOR), region).x;

			if (isThreeWay() && !isIgnoreAncestor()) {
				int as= fAncestor.getLineRange(d.getPosition(ANCESTOR_CONTRIBUTOR), region).x;
				if (as >= fAncestor.getSourceViewer().getTopIndex() && as <= fAncestor.getSourceViewer().getBottomIndex())
					ancestorIsVisible= true;
			}

			if (ls >= fLeft.getSourceViewer().getTopIndex() && ls <= fLeft.getSourceViewer().getBottomIndex())
				leftIsVisible= true;

			if (rs >= fRight.getSourceViewer().getTopIndex() && rs <= fRight.getSourceViewer().getBottomIndex())
				rightIsVisible= true;
		}

		// vertical scrolling
		if (!leftIsVisible || !rightIsVisible) {
			int avpos= 0, lvpos= 0, rvpos= 0;

			MergeSourceViewer allButThis= null;
			if (leftIsVisible) {
				avpos= lvpos= rvpos= realToVirtualPosition(LEFT_CONTRIBUTOR, fLeft.getSourceViewer().getTopIndex());
				allButThis= fLeft;
			} else if (rightIsVisible) {
				avpos= lvpos= rvpos= realToVirtualPosition(RIGHT_CONTRIBUTOR, fRight.getSourceViewer().getTopIndex());
				allButThis= fRight;
			} else if (ancestorIsVisible) {
				avpos= lvpos= rvpos= realToVirtualPosition(ANCESTOR_CONTRIBUTOR, fAncestor.getSourceViewer().getTopIndex());
				allButThis= fAncestor;
			} else {
				int vpos= 0;
				for (Iterator<?> iterator = fMerger.rangesIterator(); iterator.hasNext();) {
					Diff diff = (Diff) iterator.next();
					if (diff == d)
						break;
					if (fSynchronizedScrolling) {
						vpos+= diff.getMaxDiffHeight();
					} else {
						avpos+= diff.getAncestorHeight();
						lvpos+= diff.getLeftHeight();
						rvpos+= diff.getRightHeight();
					}
				}
				if (fSynchronizedScrolling)
					avpos= lvpos= rvpos= vpos;
				int delta= fRight.getViewportLines()/4;
				avpos-= delta;
				if (avpos < 0)
					avpos= 0;
				lvpos-= delta;
				if (lvpos < 0)
					lvpos= 0;
				rvpos-= delta;
				if (rvpos < 0)
					rvpos= 0;
			}

			scrollVertical(avpos, lvpos, rvpos, allButThis);

			if (fVScrollBar != null)
				fVScrollBar.setSelection(avpos);
		}

		// horizontal scrolling
		if (d.isToken()) {
			// we only scroll horizontally for token diffs
			reveal(fAncestor, d.getPosition(ANCESTOR_CONTRIBUTOR));
			reveal(fLeft, d.getPosition(LEFT_CONTRIBUTOR));
			reveal(fRight, d.getPosition(RIGHT_CONTRIBUTOR));
		} else {
			// in all other cases we reset the horizontal offset
			hscroll(fAncestor);
			hscroll(fLeft);
			hscroll(fRight);
		}
	}

	private static void reveal(MergeSourceViewer v, Position p) {
		if (v != null && p != null) {
			StyledText st= v.getSourceViewer().getTextWidget();
			if (st != null) {
				Rectangle r= st.getClientArea();
				if (!r.isEmpty())	// workaround for #7320: Next diff scrolls when going into current diff
					v.getSourceViewer().revealRange(p.offset, p.length);
			}
		}
	}

	private static void hscroll(MergeSourceViewer v) {
		if (v != null) {
			StyledText st= v.getSourceViewer().getTextWidget();
			if (st != null)
				st.setHorizontalIndex(0);
		}
	}

	//--------------------------------------------------------------------------------

	void copyAllUnresolved(boolean leftToRight) {
		if (fMerger.hasChanges() && isThreeWay() && !isIgnoreAncestor()) {
			IRewriteTarget target= leftToRight ? fRight.getSourceViewer().getRewriteTarget() : fLeft.getSourceViewer().getRewriteTarget();
			boolean compoundChangeStarted= false;
			try {
				for (Iterator<?> iterator = fMerger.changesIterator(); iterator.hasNext();) {
					Diff diff = (Diff) iterator.next();
					switch (diff.getKind()) {
					case RangeDifference.LEFT:
						if (leftToRight) {
							if (!compoundChangeStarted) {
								target.beginCompoundChange();
								compoundChangeStarted= true;
							}
							copy(diff, leftToRight);
						}
						break;
					case RangeDifference.RIGHT:
						if (!leftToRight) {
							if (!compoundChangeStarted) {
								target.beginCompoundChange();
								compoundChangeStarted= true;
							}
							copy(diff, leftToRight);
						}
						break;
					default:
						continue;
					}
				}
			} finally {
				if (compoundChangeStarted) {
					target.endCompoundChange();
				}
			}
		}
	}

	/*
	 * Copy whole document from one side to the other.
	 */
	@Override
	protected void copy(boolean leftToRight) {
		if (!validateChange(!leftToRight))
			return;
		if (showResolveUI()) {
			copyAllUnresolved(leftToRight);
			invalidateLines();
			return;
		}
		copyOperationInProgress = true;
		if (leftToRight) {
			if (fLeft.getEnabled()) {
				// copy text
				String text= fLeft.getSourceViewer().getTextWidget().getText();
				fRight.getSourceViewer().getTextWidget().setText(text);
				fRight.setEnabled(true);
			} else {
				// delete
				fRight.getSourceViewer().getTextWidget().setText(""); //$NON-NLS-1$
				fRight.setEnabled(false);
			}
			fRightLineCount= fRight.getLineCount();
			setRightDirty(true);
		} else {
			if (fRight.getEnabled()) {
				// copy text
				String text= fRight.getSourceViewer().getTextWidget().getText();
				fLeft.getSourceViewer().getTextWidget().setText(text);
				fLeft.setEnabled(true);
			} else {
				// delete
				fLeft.getSourceViewer().getTextWidget().setText(""); //$NON-NLS-1$
				fLeft.setEnabled(false);
			}
			fLeftLineCount= fLeft.getLineCount();
			setLeftDirty(true);
		}
		copyOperationInProgress = false;
		update(false);
		selectFirstDiff(true);
	}

	private void historyNotification(OperationHistoryEvent event) {
		switch (event.getEventType()) {
		case OperationHistoryEvent.OPERATION_ADDED:
			if (copyOperationInProgress) {
				copyUndoable = event.getOperation();
			}
			break;
		case OperationHistoryEvent.UNDONE:
			if (copyUndoable == event.getOperation()) {
				update(false);
			}
			break;
		default:
			// Nothing to do
			break;
		}
	}

	private void copyDiffLeftToRight() {
		copy(fCurrentDiff, true, false);
	}

	private void copyDiffRightToLeft() {
		copy(fCurrentDiff, false, false);
	}

	/*
	 * Copy the contents of the given diff from one side to the other.
	 */
	private void copy(Diff diff, boolean leftToRight, boolean gotoNext) {
		if (copy(diff, leftToRight)) {
			if (gotoNext) {
				navigate(true, true, false /* don't step in */);
			} else {
				revealDiff(diff, true);
				updateControls();
			}
		}
	}

	/*
	 * Copy the contents of the given diff from one side to the other but
	 * doesn't reveal anything.
	 * Returns true if copy was successful.
	 */
	private boolean copy(Diff diff, boolean leftToRight) {

		if (diff != null) {
			if (!validateChange(!leftToRight))
				return false;
			if (leftToRight) {
				fRight.setEnabled(true);
			} else {
				fLeft.setEnabled(true);
			}
			boolean result = fMerger.copy(diff, leftToRight);
			if (result)
				updateResolveStatus();
			return result;
		}
		return false;
	}

	private boolean validateChange(boolean left) {
		ContributorInfo info;
		if (left)
			info = fLeftContributor;
		else
			info = fRightContributor;

		return info.validateChange();
	}

	//---- scrolling

	/*
	 * The height of the TextEditors in lines.
	 */
	private int getViewportHeight() {
		StyledText te= fLeft.getSourceViewer().getTextWidget();

		int vh= te.getClientArea().height;
		if (vh == 0) {
			Rectangle trim= te.computeTrim(0, 0, 0, 0);
			int scrollbarHeight= trim.height;

			int headerHeight= getHeaderHeight();

			Composite composite= (Composite) getControl();
			Rectangle r= composite.getClientArea();

			vh= r.height-headerHeight-scrollbarHeight;
		}

		return vh / te.getLineHeight();
	}

	/*
	 * Returns the virtual position for the given view position.
	 */
	private int realToVirtualPosition(char contributor, int vpos) {
		if (! fSynchronizedScrolling)
			return vpos;
		return fMerger.realToVirtualPosition(contributor, vpos);
	}

	private void scrollVertical(int avpos, int lvpos, int rvpos, MergeSourceViewer allBut) {

		int s= 0;

		if (fSynchronizedScrolling) {
			s= fMerger.getVirtualHeight() - rvpos;
			int height= fRight.getViewportLines()/4;
			if (s < 0)
				s= 0;
			if (s > height)
				s= height;
		}

		fInScrolling= true;

		if (isThreeWay() && allBut != fAncestor) {
			if (fSynchronizedScrolling || allBut == null) {
				int y= virtualToRealPosition(ANCESTOR_CONTRIBUTOR, avpos+s)-s;
				fAncestor.vscroll(y);
			}
		}

		if (allBut != fLeft) {
			if (fSynchronizedScrolling || allBut == null) {
				int y= virtualToRealPosition(LEFT_CONTRIBUTOR, lvpos+s)-s;
				fLeft.vscroll(y);
			}
		}

		if (allBut != fRight) {
			if (fSynchronizedScrolling || allBut == null) {
				int y= virtualToRealPosition(RIGHT_CONTRIBUTOR, rvpos+s)-s;
				fRight.vscroll(y);
			}
		}

		fInScrolling= false;

		if (isThreeWay() && fAncestorCanvas != null)
			fAncestorCanvas.repaint();

		if (fLeftCanvas != null)
			fLeftCanvas.repaint();

		Control center= getCenterControl();
		if (center instanceof BufferedCanvas)
			((BufferedCanvas) center).repaint();

		if (fRightCanvas != null)
			fRightCanvas.repaint();
	}

	/*
	 * Updates Scrollbars with viewports.
	 */
	private void syncViewport(MergeSourceViewer w) {

		if (fInScrolling)
			return;

		int ix= w.getSourceViewer().getTopIndex();
		int ix2= w.getDocumentRegionOffset();

		int viewPosition= realToVirtualPosition(getLeg(w), ix-ix2);

		scrollVertical(viewPosition, viewPosition, viewPosition, w);	// scroll all but the given views

		if (fVScrollBar != null) {
			int value= Math.max(0, Math.min(viewPosition, fMerger.getVirtualHeight() - getViewportHeight()));
			fVScrollBar.setSelection(value);
			//refreshBirdEyeView();
		}
	}

	/**
	 */
	private void updateVScrollBar() {

		if (Utilities.okToUse(fVScrollBar) && fSynchronizedScrolling) {
			int virtualHeight= fMerger.getVirtualHeight();
			int viewPortHeight= getViewportHeight();
			int pageIncrement= viewPortHeight-1;
			int thumb= (viewPortHeight > virtualHeight) ? virtualHeight : viewPortHeight;

			fVScrollBar.setPageIncrement(pageIncrement);
			fVScrollBar.setMaximum(virtualHeight);
			fVScrollBar.setThumb(thumb);
		}
	}

	/*
	 * maps given virtual position into a real view position of this view.
	 */
	private int virtualToRealPosition(char contributor, int v) {
		if (! fSynchronizedScrolling)
			return v;
		return fMerger.virtualToRealPosition(contributor, v);
	}

	@Override
	void flushLeftSide(Object oldInput, IProgressMonitor monitor){
		IMergeViewerContentProvider content= getMergeContentProvider();
		Object leftContent = content.getLeftContent(oldInput);

		if (leftContent != null && isLeftEditable() && isLeftDirty()) {
			if (fLeftContributor.hasSharedDocument(leftContent)) {
				if (flush(fLeftContributor))
					setLeftDirty(false);
			}
		}

		if (!(content instanceof MergeViewerContentProvider) || isLeftDirty()) {
			super.flushLeftSide(oldInput, monitor);
		}
	}

	@Override
	void flushRightSide(Object oldInput, IProgressMonitor monitor){
		IMergeViewerContentProvider content= getMergeContentProvider();
		Object rightContent = content.getRightContent(oldInput);

		if (rightContent != null && isRightEditable() && isRightDirty()) {
			if (fRightContributor.hasSharedDocument(rightContent)) {
				if (flush(fRightContributor))
					setRightDirty(false);
			}
		}

		if (!(content instanceof MergeViewerContentProvider) || isRightDirty()) {
			super.flushRightSide(oldInput, monitor);
		}
	}

	@Override
	protected void flushContent(Object oldInput, IProgressMonitor monitor) {
		flushLeftSide(oldInput, monitor);
		flushRightSide(oldInput, monitor);

		IMergeViewerContentProvider content = getMergeContentProvider();

		if (!(content instanceof MergeViewerContentProvider) || isLeftDirty() || isRightDirty()) {
			super.flushContent(oldInput, monitor);
		}
	}

	private boolean flush(final ContributorInfo info) {
		try {
			return info.flush();
		} catch (CoreException e) {
			handleException(e);
		}
		return false;
	}

	private void handleException(Throwable throwable) {
		// TODO: Should show error to the user
		if (throwable instanceof InvocationTargetException) {
			InvocationTargetException ite = (InvocationTargetException) throwable;
			handleException(ite.getTargetException());
			return;
		}
		CompareUIPlugin.log(throwable);
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Class<T> adapter) {
		if (adapter == IMergeViewerTestAdapter.class) {
			return (T) new IMergeViewerTestAdapter() {
				@Override
				public IDocument getDocument(char leg) {
					switch (leg) {
					case LEFT_CONTRIBUTOR:
						return fLeft.getSourceViewer().getDocument();
					case RIGHT_CONTRIBUTOR:
						return fRight.getSourceViewer().getDocument();
					case ANCESTOR_CONTRIBUTOR:
						return fAncestor.getSourceViewer().getDocument();
					default:
						return null;
					}
				}

				@Override
				public int getChangesCount() {
					return fMerger.changesCount();
				}
			};
		}
		if (adapter == OutlineViewerCreator.class) {
			if (fOutlineViewerCreator == null)
				fOutlineViewerCreator = new InternalOutlineViewerCreator();
			return (T) fOutlineViewerCreator;

		}
		if (adapter == IFindReplaceTarget.class)
			return (T) getFindReplaceTarget();
		if (adapter == CompareHandlerService.class)
			return (T) fHandlerService;
		if (adapter == CompareHandlerService[].class) {
			return (T) new CompareHandlerService[] { fHandlerService,
					super.getCompareHandlerService() };
		}
		if (adapter == IEditorInput.class) {
			// return active editor input
			if (fLeft != null && fLeft == fFocusPart)
				if (fLeftContributor != null)
					return (T) fLeftContributor.getDocumentKey();
			if (fRight != null && fRight == fFocusPart)
				if (fRightContributor != null)
					return (T) fRightContributor.getDocumentKey();
			if (fAncestor != null && fAncestor == fFocusPart)
				if (fAncestorContributor != null)
					return (T) fAncestorContributor.getDocumentKey();
		}
		return null;
	}

	@Override
	protected void handleCompareInputChange() {
		try {
			beginRefresh();
			super.handleCompareInputChange();
		} finally {
			endRefresh();
		}
	}

	private void beginRefresh() {
		isRefreshing++;
		fLeftContributor.cacheSelection(fLeft);
		fRightContributor.cacheSelection(fRight);
		fAncestorContributor.cacheSelection(fAncestor);
		if (fSynchronizedScrolling) {
			fSynchronziedScrollPosition = fVScrollBar.getSelection();
		}

	}

	private void endRefresh() {
		isRefreshing--;
		fLeftContributor.cacheSelection(null);
		fRightContributor.cacheSelection(null);
		fAncestorContributor.cacheSelection(null);
		fSynchronziedScrollPosition = -1;
	}

	private void synchronizedScrollVertical(int vpos) {
		scrollVertical(vpos, vpos, vpos, null);
	}

	private boolean isIgnoreAncestor() {
		return Utilities.getBoolean(getCompareConfiguration(), ICompareUIConstants.PROP_IGNORE_ANCESTOR, false);
	}

	/* package */ void update(boolean includeControls) {
		if (getControl().isDisposed())
			return;
		if (fHasErrors) {
			resetDiffs();
		} else {
			doDiff();
		}

		if (includeControls)
			updateControls();

		updateVScrollBar();
		updatePresentation();
	}

	private void resetDiffs() {
		// clear stuff
		saveDiff();
		fCurrentDiff= null;
		fMerger.reset();
		resetPositions(fLeft.getSourceViewer().getDocument());
		resetPositions(fRight.getSourceViewer().getDocument());
		resetPositions(fAncestor.getSourceViewer().getDocument());
	}

	private boolean isPatchHunk() {
		return Utilities.isHunk(getInput());
	}

	private boolean isPatchHunkOk() {
		if (isPatchHunk())
			return Utilities.isHunkOk(getInput());
		return false;
	}

	/**
	 * Return the provided start position of the hunk in the target file.
	 * @return the provided start position of the hunk in the target file
	 */
	private int getHunkStart() {
		Object input = getInput();
		if (input != null && input instanceof DiffNode){
			ITypedElement right = ((DiffNode) input).getRight();
			if (right != null) {
				Object element = Adapters.adapt(right, IHunk.class);
				if (element instanceof IHunk)
					return ((IHunk) element).getStartPosition();
			}
			ITypedElement left = ((DiffNode) input).getLeft();
			if (left != null) {
				Object element = Adapters.adapt(left, IHunk.class);
				if (element instanceof IHunk)
					return ((IHunk) element).getStartPosition();
			}
		}
		return 0;
	}

	private IFindReplaceTarget getFindReplaceTarget() {
		if (fFindReplaceTarget == null)
			fFindReplaceTarget= new FindReplaceTarget();
		return fFindReplaceTarget;
	}

	/* package */ char getLeg(MergeSourceViewer w) {
		if (w == fLeft)
			return LEFT_CONTRIBUTOR;
		if (w == fRight)
			return RIGHT_CONTRIBUTOR;
		if (w == fAncestor)
			return ANCESTOR_CONTRIBUTOR;
		return ANCESTOR_CONTRIBUTOR;
	}

	private boolean isCurrentDiff(Diff diff) {
		if (diff == null)
			return false;
		if (diff == fCurrentDiff)
			return true;
		if (fCurrentDiff != null && fCurrentDiff.getParent() == diff)
			return true;
		return false;
	}

	private boolean isNavigationPossible() {
		if (fCurrentDiff == null && fMerger.hasChanges())
			return true;
		else if (fMerger.changesCount() > 1)
			return true;
		else if (fCurrentDiff != null && fCurrentDiff.hasChildren())
			return true;
		else if (fCurrentDiff != null && fCurrentDiff.isToken())
			return true;
		return false;
	}

	/**
	 * This method returns {@link ITextEditor} used in the
	 * {@link ChangeEncodingAction}. It provides implementation of methods that
	 * are used by the action by delegating them to {@link ContributorInfo} that
	 * corresponds to the side that has focus.
	 *
	 * @return the text editor adapter
	 */
	private ITextEditor getTextEditorAdapter() {
		return new ITextEditor() {
			@Override
			public void close(boolean save) {
			}
			@Override
			public void doRevertToSaved() {
			}
			@Override
			public IAction getAction(String actionId) {
				return null;
			}
			@Override
			public IDocumentProvider getDocumentProvider() {
				return null;
			}
			@Override
			public IRegion getHighlightRange() {
				return null;
			}
			@Override
			public ISelectionProvider getSelectionProvider() {
				return null;
			}

			@Override
			public boolean isEditable() {
				return false;
			}

			@Override
			public void removeActionActivationCode(String actionId) {
			}

			@Override
			public void resetHighlightRange() {
			}

			@Override
			public void selectAndReveal(int offset, int length) {
			}

			@Override
			public void setAction(String actionId, IAction action) {
			}

			@Override
			public void setActionActivationCode(String actionId,
					char activationCharacter, int activationKeyCode,
					int activationStateMask) {
			}

			@Override
			public void setHighlightRange(int offset, int length, boolean moveCursor) {
			}

			@Override
			public void showHighlightRangeOnly(boolean showHighlightRangeOnly) {
			}

			@Override
			public boolean showsHighlightRangeOnly() {
				return false;
			}

			@Override
			public IEditorInput getEditorInput() {
				if (fFocusPart == fAncestor && fAncestorContributor != null) {
					return fAncestorContributor.getDocumentKey();
				} else if (fFocusPart == fLeft && fLeftContributor != null) {
					return fLeftContributor.getDocumentKey();
				} else if (fFocusPart == fRight && fRightContributor != null) {
					return fRightContributor.getDocumentKey();
				} else {
					return null;
				}
			}

			@Override
			public IEditorSite getEditorSite() {
				return null;
			}

			@Override
			public void init(IEditorSite site, IEditorInput input)
					throws PartInitException {
			}

			@Override
			public void addPropertyListener(IPropertyListener listener) {
			}

			@Override
			public void createPartControl(Composite parent) {
			}

			@Override
			public void dispose() {
			}

			@Override
			public IWorkbenchPartSite getSite() {
				return new IWorkbenchPartSite() {
					@Override
					public String getId() {
						return null;
					}
					@Override
					@Deprecated
					public IKeyBindingService getKeyBindingService() {
						return null;
					}
					@Override
					public IWorkbenchPart getPart() {
						return null;
					}
					@Override
					public String getPluginId() {
						return null;
					}
					@Override
					public String getRegisteredName() {
						return null;
					}
					@Override
					public void registerContextMenu(MenuManager menuManager,
							ISelectionProvider selectionProvider) {
					}
					@Override
					public void registerContextMenu(String menuId,
							MenuManager menuManager,
							ISelectionProvider selectionProvider) {
					}
					@Override
					public IWorkbenchPage getPage() {
						return null;
					}
					@Override
					public ISelectionProvider getSelectionProvider() {
						return null;
					}
					@Override
					public Shell getShell() {
						return fComposite.getShell();
					}
					@Override
					public IWorkbenchWindow getWorkbenchWindow() {
						return null;
					}
					@Override
					public void setSelectionProvider(ISelectionProvider provider) {
					}
					@Override
					public <T> T getAdapter(Class<T> adapter) {
						return null;
					}
					@Override
					public <T> T getService(Class<T> api) {
						return null;
					}
					@Override
					public boolean hasService(Class<?> api) {
						return false;
					}
				};
			}

			@Override
			public String getTitle() {
				return null;
			}

			@Override
			public Image getTitleImage() {
				return null;
			}

			@Override
			public String getTitleToolTip() {
				return null;
			}

			@Override
			public void removePropertyListener(IPropertyListener listener) {
			}

			@Override
			public void setFocus() {
			}

			@Override
			@SuppressWarnings("unchecked")
			public <T> T getAdapter(Class<T> adapter) {
				if (adapter == IEncodingSupport.class) {
					if (fFocusPart == fAncestor) {
						return (T) getEncodingSupport(fAncestorContributor);
					} else if (fFocusPart == fLeft) {
						return (T) getEncodingSupport(fLeftContributor);
					} else if (fFocusPart == fRight) {
						return (T) getEncodingSupport(fRightContributor);
					}
				}
				return null;
			}

			private IEncodingSupport getEncodingSupport(ContributorInfo contributor) {
				if (contributor != null && contributor.getDefaultEncoding() != null) {
					return contributor;
				}
				return null;
			}

			@Override
			public void doSave(IProgressMonitor monitor) {
			}

			@Override
			public void doSaveAs() {
			}

			@Override
			public boolean isDirty() {
				if (fFocusPart == fLeft) {
					return isLeftDirty();
				} else if (fFocusPart == fRight) {
					return isRightDirty();
				}
				return false;
			}

			@Override
			public boolean isSaveAsAllowed() {
				// Implementing interface method
				return false;
			}

			@Override
			public boolean isSaveOnCloseNeeded() {
				// Implementing interface method
				return false;
			}
		};
	}

	private void updateStructure() {
		getCompareConfiguration().setProperty("ALL_STRUCTURE_REFRESH", null); //$NON-NLS-1$
	}

	private void updateStructure(char leg) {
		String key = null;
		switch (leg) {
		case ANCESTOR_CONTRIBUTOR:
			key = "ANCESTOR_STRUCTURE_REFRESH"; //$NON-NLS-1$
			break;
		case LEFT_CONTRIBUTOR:
			key = "LEFT_STRUCTURE_REFRESH"; //$NON-NLS-1$
			break;
		case RIGHT_CONTRIBUTOR:
			key = "RIGHT_STRUCTURE_REFRESH"; //$NON-NLS-1$
			break;
		default:
			break;
		}
		Assert.isNotNull(key);
		getCompareConfiguration().setProperty(key, null);
	}
}
