fix for bug 58417
diff --git a/org.eclipse.search.tests/src/org/eclipse/search/core/tests/TestSearchResult.java b/org.eclipse.search.tests/src/org/eclipse/search/core/tests/TestSearchResult.java
index b8bb4e4..2242971 100644
--- a/org.eclipse.search.tests/src/org/eclipse/search/core/tests/TestSearchResult.java
+++ b/org.eclipse.search.tests/src/org/eclipse/search/core/tests/TestSearchResult.java
@@ -11,13 +11,13 @@
 package org.eclipse.search.core.tests;
 
 import junit.framework.TestCase;
+
 import org.eclipse.search.ui.ISearchQuery;
 import org.eclipse.search.ui.ISearchResultListener;
 import org.eclipse.search.ui.SearchResultEvent;
 import org.eclipse.search.ui.text.AbstractTextSearchResult;
 import org.eclipse.search.ui.text.Match;
 import org.eclipse.search.ui.text.MatchEvent;
-import org.eclipse.search2.internal.ui.InternalSearchUI;
 
 
 /**
@@ -29,7 +29,6 @@
 	public void testAddMatch() {
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		String object= "object"; //$NON-NLS-1$
 		
@@ -42,11 +41,82 @@
 		result.addMatch(match1);
 		assertEquals(result.getMatchCount(), 2);
 	}
+
+	public void testAddMatchDifferentStart() {
+		ISearchQuery query= new NullQuery();
+		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
+		
+		String object= "object"; //$NON-NLS-1$
+		
+		Match match1= new Match(object, 2, 0);
+		result.addMatch(match1);
+		assertEquals(result.getMatchCount(), 1);
+		Match match2= new Match(object, 1, 1);
+		result.addMatch(match2);
+		Match match3= new Match(object, 0, 2);
+		result.addMatch(match3);
+		Match[] matches= result.getMatches(object);
+		assertTrue("matches[0]", matches[0] == match3);
+		assertTrue("matches[1]", matches[1] == match2);
+		assertTrue("matches[2]", matches[2] == match1);
+	}
+
+	public void testAddMatchDifferentStartInOrder() {
+		ISearchQuery query= new NullQuery();
+		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
+		
+		String object= "object"; //$NON-NLS-1$
+		
+		Match match1= new Match(object, 0, 0);
+		result.addMatch(match1);
+		assertEquals(result.getMatchCount(), 1);
+		Match match2= new Match(object, 1, 1);
+		result.addMatch(match2);
+		Match match3= new Match(object, 2, 2);
+		result.addMatch(match3);
+		Match[] matches= result.getMatches(object);
+		assertTrue("matches[0]", matches[0] == match1);
+		assertTrue("matches[1]", matches[1] == match2);
+		assertTrue("matches[2]", matches[2] == match3);
+	}
+
+	public void testAddMatchDifferentLength() {
+		ISearchQuery query= new NullQuery();
+		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
+		
+		String object= "object"; //$NON-NLS-1$
+		
+		Match match1= new Match(object, 1, 1);
+		result.addMatch(match1);
+		assertEquals(result.getMatchCount(), 1);
+		Match match2= new Match(object, 1, 0);
+		result.addMatch(match2);
+		Match[] matches= result.getMatches(object);
+		assertTrue("matches[0]", matches[0] == match2);
+		assertTrue("matches[1]", matches[1] == match1);
+	}
+	
+	public void testAddMatchOrderPreserving() {
+		ISearchQuery query= new NullQuery();
+		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
+		
+		String object= "object"; //$NON-NLS-1$
+		
+		Match match1= new Match(object, 1, 0);
+		result.addMatch(match1);
+		assertEquals(result.getMatchCount(), 1);
+		Match match2= new Match(object, 1, 0);
+		result.addMatch(match2);
+		Match[] matches= result.getMatches(object);
+		assertTrue("matches[0]", matches[0] == match1);
+		assertTrue("matches[1]", matches[1] == match2);
+	}
+
+
 	
 	public void testAddMatches() {
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		String object= "object"; //$NON-NLS-1$
 		
@@ -61,7 +131,6 @@
 	public void testRemoveMatch() {
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		String object= "object"; //$NON-NLS-1$
 		
@@ -81,7 +150,6 @@
 	public void testRemoveMatches() {
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		String object= "object"; //$NON-NLS-1$
 		
@@ -101,7 +169,6 @@
 	
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		result.addListener(new ISearchResultListener() {
 			public void searchResultChanged(SearchResultEvent e) {
@@ -144,7 +211,6 @@
 	
 		ISearchQuery query= new NullQuery();
 		AbstractTextSearchResult result= (AbstractTextSearchResult) query.getSearchResult();
-		InternalSearchUI.getInstance().addQuery(query);
 		
 		result.addListener(new ISearchResultListener() {
 			public void searchResultChanged(SearchResultEvent e) {
diff --git a/org.eclipse.search.tests/src/org/eclipse/search/tests/filesearch/SortingTest.java b/org.eclipse.search.tests/src/org/eclipse/search/tests/filesearch/SortingTest.java
new file mode 100644
index 0000000..bcc35ab
--- /dev/null
+++ b/org.eclipse.search.tests/src/org/eclipse/search/tests/filesearch/SortingTest.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.search.tests.filesearch;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.search.internal.core.text.TextSearchScope;
+import org.eclipse.search.internal.ui.text.FileSearchQuery;
+import org.eclipse.search.ui.NewSearchUI;
+import org.eclipse.search.ui.text.AbstractTextSearchResult;
+import org.eclipse.search.ui.text.Match;
+
+public class SortingTest extends TestCase {
+	FileSearchQuery fQuery1;
+
+	public SortingTest(String name) {
+		super(name);
+	}
+		
+	public static Test allTests() {
+		return new JUnitSetup(new TestSuite(SortingTest.class));
+	}
+	
+	public static Test suite() {
+		return allTests();
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		
+		TextSearchScope scope= TextSearchScope.newWorkspaceScope();
+		scope.addExtension("*.java");
+		fQuery1= new FileSearchQuery(scope,  "", "Test");
+	}
+	
+	public void testSorted() throws Exception {
+		NewSearchUI.activateSearchResultView();
+		NewSearchUI.runQueryInForeground(null, fQuery1);
+		AbstractTextSearchResult result= (AbstractTextSearchResult) fQuery1.getSearchResult();
+		int originalMatchCount= result.getMatchCount();
+		List allMatches= new ArrayList(originalMatchCount);
+		
+		// first, collect all matches
+		Object[] elements= result.getElements();
+		for (int i= 0; i < elements.length; i++) {
+			Match[] matches= result.getMatches(elements[i]);
+			for (int j= 0; j < matches.length; j++) {
+				allMatches.add(matches[j]);
+			}
+		}
+		// now remove them and readd them in reverse order
+		result.removeAll();
+		assertTrue("removed all matches", result.getMatchCount() == 0);
+		
+		for (int i= allMatches.size()-1; i >= 0; i--) {
+			result.addMatch((Match) allMatches.get(i));
+		}
+		
+		assertEquals("Test that all matches have been added again", result.getMatchCount(), originalMatchCount);
+		
+		// now check that they're ordered by position.
+		for (int i= 0; i < elements.length; i++) {
+			Match[] matches= result.getMatches(elements[i]);
+			assertTrue("has matches", matches.length > 0);
+			for (int j= 1; j < matches.length; j++) {
+				assertTrue("order problem", isLessOrEqual(matches[j-1], matches[j]));
+			}
+		}
+	}
+
+	private boolean isLessOrEqual(Match match, Match match2) {
+		int diff= match2.getOffset() - match.getOffset();
+		if (diff > 0)
+			return true;
+		else if (diff < 0)
+			return false;
+		else {
+			// equal offset, have to look at the length.
+			diff= match2.getLength() - match.getLength();
+			if (diff >= 0)
+				return true;
+			return false;
+		}
+	}
+	
+}
diff --git a/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchResult.java b/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchResult.java
index 325f5d3..d786624 100644
--- a/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchResult.java
+++ b/org.eclipse.search/new search/org/eclipse/search/ui/text/AbstractTextSearchResult.java
@@ -123,12 +123,40 @@
 			fElementsToMatches.put(match.getElement(), matches);
 		}
 		if (!matches.contains(match)) {
-			matches.add(match);
+			insertSorted(matches, match);
 			return true;
 		}
 		return false;
 	}
 	
+	private static void insertSorted(List matches, Match match) {
+		if (matches.size() == 0) {
+			matches.add(match);
+			return;
+		}
+		int insertIndex= getInsertIndex(matches, match, 0, matches.size());
+		matches.add(insertIndex, match);
+	}
+	
+	private static int getInsertIndex(List matches, Match match, int min, int max) {
+		if (min == max)
+			return min;
+		int middle= (min+max)/2;
+		int compareResult= compare(match, (Match) matches.get(middle));
+		if (compareResult == 0)
+			return middle+1;
+		if (compareResult > 0)
+			return getInsertIndex(matches, match, min, middle);
+		return getInsertIndex(matches, match, middle+1, max);
+	}
+
+	private static int compare(Match match1, Match match2) {
+		int diff= match2.getOffset()-match1.getOffset();
+		if (diff != 0)
+			return diff;
+		return match2.getLength()-match1.getLength();
+	}
+
 	/**
 	 * Removes all matches from this search result.
 	 * <p>