/** * 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) { [...] INavigatable nav= new INavigatable() { public boolean selectChange(int flag) { if (flag == INavigatable.FIRST_CHANGE || flag == INavigatable.LAST_CHANGE) { selectFirstDiff(flag == INavigatable.FIRST_CHANGE, false); <<--- fix return false; } return navigate(flag == INavigatable.NEXT_CHANGE, false, false); } public Object getInput() { return TextMergeViewer.this.getInput(); } public boolean openSelectedChange() { return false; } public boolean hasChange(int flag) { return getNextVisibleDiff(flag == INavigatable.NEXT_CHANGE, false) != null; } }; fComposite.setData(INavigatable.NAVIGATOR_PROPERTY, nav); fBirdsEyeCursor= new Cursor(parent.getDisplay(), SWT.CURSOR_HAND); JFaceResources.getFontRegistry().addListener(fPreferenceChangeListener); JFaceResources.getColorRegistry().addListener(fPreferenceChangeListener); updateFont(); } [...] /* * Initializes the text viewers of the three content areas with the given input objects. * Subclasses may extend. */ protected void updateContent(Object ancestor, Object left, Object right) { [...] 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 && Utilities.getAdapter(right, IHunk.class) != null) fLeft.setTopIndex(getHunkStart()); else fRight.setTopIndex(getHunkStart()); } else { Diff selectDiff= null; if (FIX_47640) { if (leftRange != null) selectDiff= findDiff(LEFT_CONTRIBUTOR, leftRange); else if (rightRange != null) selectDiff= findDiff(RIGHT_CONTRIBUTOR, rightRange); } if (selectDiff != null) setCurrentDiff(selectDiff, true); else selectFirstDiff(true, false); <<--- fix } } } } [...] /* * Creates the two items for copying a difference range from one side to the other * and adds them to the given toolbar manager. */ protected void createToolItems(ToolBarManager tbm) { [...] Action a= new Action() { public void run() { if (navigate(true, false, false)) { endOfDocumentReached(true, false); <<--- fix } } }; 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() { public void run() { if (navigate(false, false, false)) { endOfDocumentReached(false, false); <<--- fix } } }; 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() { public void run() { if (navigate(true, false, true)) { endOfDocumentReached(true, true); <<--- fix } } }; 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() { public void run() { if (navigate(false, false, true)) { endOfDocumentReached(false, true); <<--- fix } } }; [...] } /* (non-Javadoc) * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#handlePropertyChangeEvent(org.eclipse.jface.util.PropertyChangeEvent) */ protected void handlePropertyChangeEvent(PropertyChangeEvent event) { String key= event.getProperty(); if (key.equals(CompareConfiguration.IGNORE_WHITESPACE) || key.equals(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS)) { fShowPseudoConflicts= fPreferenceStore.getBoolean(ComparePreferencePage.SHOW_PSEUDO_CONFLICTS); update(true); selectFirstDiff(true, false); <<--- fix // [...] } else { super.handlePropertyChangeEvent(event); if (key.equals(ICompareUIConstants.PROP_IGNORE_ANCESTOR)) { update(false); selectFirstDiff(true, false); <<--- fix } } } private void selectFirstDiff(boolean first, boolean deep) { <<--- fix if (fLeft == null || fRight == null) { return; } if (fLeft.getDocument() == null || fRight.getDocument() == null) { return; } Diff firstDiff= null; if (first) firstDiff= findNext(fRight, fChangeDiffs, -1, -1, deep); <<--- fix else firstDiff= findPrev(fRight, fChangeDiffs, 9999999, 9999999, deep); <<--- fix setCurrentDiff(firstDiff, true); } [...] private void endOfDocumentReached(boolean down, boolean deep) { <<--- fix Control c= getControl(); if (Utilities.okToUse(c)) { handleEndOfDocumentReached(c.getShell(), down, deep); <<--- fix } } private void handleEndOfDocumentReached(Shell shell, boolean next, boolean deep) { <<--- fix [...] } else { String message; String title; if (next) { title = CompareMessages.TextMergeViewer_8; message = CompareMessages.TextMergeViewer_9; } else { title = CompareMessages.TextMergeViewer_10; message = CompareMessages.TextMergeViewer_11; } if (MessageDialog.openQuestion(shell, title, message)) { selectFirstDiff(next, deep); <<--- fix } } } private void performEndOfDocumentAction(Shell shell, IPreferenceStore store, String key, boolean next) { String value = store.getString(key); if (value.equals(ICompareUIConstants.PREF_VALUE_NEXT)) { ICompareNavigator navigator = getCompareConfiguration().getContainer().getNavigator(); if (hasNextElement(next)) navigator.selectChange(next); else shell.getDisplay().beep(); } else { selectFirstDiff(next, false); <<--- fix } } [...] private static Diff findNext(MergeSourceViewer tp, List v, int start, int end, boolean deep) { for (int i= 0; i < v.size(); i++) { Diff diff= (Diff) v.get(i); Position p= diff.getPosition(tp); if (p != null) { int startOffset= p.getOffset(); if ((deep && end <= startOffset) || (!deep && end < startOffset)) { <<--- fix if (deep && diff.fDiffs != null) { // If we are going deep, find the first change in the diff return findNext(tp, diff.fDiffs, start, start, deep); } return diff; } if (deep && diff.fDiffs != null) { Diff d= null; int endOffset= startOffset + p.getLength(); if (start == startOffset && (end == endOffset || end == endOffset-1)) { d= findNext(tp, diff.fDiffs, start-1, start-1, deep); } else if (end < endOffset) { d= findNext(tp, diff.fDiffs, start, end, deep); } if (d != null) return d; } } } return null; } private static Diff findPrev(MergeSourceViewer tp, List v, int start, int end, boolean deep) { for (int i= v.size()-1; i >= 0; i--) { Diff diff= (Diff) v.get(i); Position p= diff.getPosition(tp); if (p != null) { int startOffset= p.getOffset(); int endOffset= startOffset + p.getLength(); if (start >= endOffset) { <<--- fix if (deep && diff.fDiffs != null) { // If we are going deep, find the last change in the diff return findPrev(tp, diff.fDiffs, end, end, deep); } return diff; } if (deep && diff.fDiffs != null) { Diff d= null; if (start == startOffset && end == endOffset) { // A whole diff is selected so we'll fall through // and go the the last change in the previous diff } else if (start >= startOffset) { <<--- fix d= findPrev(tp, diff.fDiffs, start, end, deep); } if (d != null) return d; } } } return null; } [...] /* * Copy whole document from one side to the other. */ protected void copy(boolean leftToRight) { [...] update(false); selectFirstDiff(true, false); <--- fix } [...] }