Index: src/java/org/apache/lucene/index/SegmentMergeInfo.java
===================================================================
--- src/java/org/apache/lucene/index/SegmentMergeInfo.java	(revision 761375)
+++ src/java/org/apache/lucene/index/SegmentMergeInfo.java	(working copy)
@@ -22,6 +22,7 @@
 final class SegmentMergeInfo {
   Term term;
   int base;
+  int ord;  // the position of the segment in a MultiReader
   TermEnum termEnum;
   IndexReader reader;
   private TermPositions postings;  // use getPositions()
Index: src/java/org/apache/lucene/index/MultiSegmentReader.java
===================================================================
--- src/java/org/apache/lucene/index/MultiSegmentReader.java	(revision 761375)
+++ src/java/org/apache/lucene/index/MultiSegmentReader.java	(working copy)
@@ -28,6 +28,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.OpenBitSet;
 
 /** 
  * An IndexReader which reads indexes with multiple segments.
@@ -470,10 +471,12 @@
   
     private Term term;
     private int docFreq;
-  
+    final SegmentMergeInfo[] matchingSegments; // null terminated array of matching segments
+
     public MultiTermEnum(IndexReader[] readers, int[] starts, Term t)
       throws IOException {
       queue = new SegmentMergeQueue(readers.length);
+      matchingSegments = new SegmentMergeInfo[readers.length+1];
       for (int i = 0; i < readers.length; i++) {
         IndexReader reader = readers[i];
         TermEnum termEnum;
@@ -484,6 +487,7 @@
           termEnum = reader.terms();
   
         SegmentMergeInfo smi = new SegmentMergeInfo(starts[i], termEnum, reader);
+        smi.ord = i;
         if (t == null ? smi.next() : termEnum.term() != null)
           queue.put(smi);          // initialize queue
         else
@@ -496,7 +500,20 @@
     }
   
     public boolean next() throws IOException {
+      for (int i=0; i<matchingSegments.length; i++) {
+        SegmentMergeInfo smi = matchingSegments[i];
+        if (smi==null) break;
+        if (smi.next())
+          queue.put(smi);
+        else
+          smi.close(); // done with segment
+      }
+      
+      int numMatchingSegments = 0;
+      matchingSegments[0] = null;
+
       SegmentMergeInfo top = (SegmentMergeInfo)queue.top();
+
       if (top == null) {
         term = null;
         return false;
@@ -506,14 +523,13 @@
       docFreq = 0;
   
       while (top != null && term.compareTo(top.term) == 0) {
+        matchingSegments[numMatchingSegments++] = top;
         queue.pop();
         docFreq += top.termEnum.docFreq();    // increment freq
-        if (top.next())
-          queue.put(top);          // restore queue
-        else
-          top.close();          // done with a segment
         top = (SegmentMergeInfo)queue.top();
       }
+
+      matchingSegments[numMatchingSegments] = null;
       return true;
     }
   
@@ -540,7 +556,11 @@
   
     private TermDocs[] readerTermDocs;
     protected TermDocs current;              // == readerTermDocs[pointer]
-  
+
+    private MultiTermEnum tenum;  // the term enum used for seeking... can be null
+    int matchingSegmentPos;  // position into the matching segments from tenum
+    SegmentMergeInfo smi;     // current segment mere info... can be null
+
     public MultiTermDocs(IndexReader[] r, int[] s) {
       readers = r;
       starts = s;
@@ -560,10 +580,16 @@
       this.base = 0;
       this.pointer = 0;
       this.current = null;
+      this.tenum = null;
+      this.smi = null;
+      this.matchingSegmentPos = 0;
     }
   
     public void seek(TermEnum termEnum) throws IOException {
       seek(termEnum.term());
+      if (termEnum instanceof MultiTermEnum) {
+        this.tenum = (MultiTermEnum)termEnum;
+      }
     }
   
     public boolean next() throws IOException {
@@ -572,6 +598,14 @@
           return true;
         }
         else if (pointer < readers.length) {
+          if (tenum != null) {
+            smi = tenum.matchingSegments[matchingSegmentPos++];
+            if (smi==null) {
+              pointer = readers.length;
+              return false;
+            }
+            pointer = smi.ord;
+          }
           base = starts[pointer];
           current = termDocs(pointer++);
         } else {
@@ -585,6 +619,14 @@
       while (true) {
         while (current == null) {
           if (pointer < readers.length) {      // try next segment
+            if (tenum != null) {
+              smi = tenum.matchingSegments[matchingSegmentPos++];
+              if (smi==null) {
+                pointer = readers.length;
+                return 0;
+              }
+              pointer = smi.ord;
+            }
             base = starts[pointer];
             current = termDocs(pointer++);
           } else {
@@ -609,6 +651,14 @@
         if (current != null && current.skipTo(target-base)) {
           return true;
         } else if (pointer < readers.length) {
+          if (tenum != null) {
+            SegmentMergeInfo smi = tenum.matchingSegments[matchingSegmentPos++];
+            if (smi==null) {
+              pointer = readers.length;
+              return false;
+            }
+            pointer = smi.ord;
+          }
           base = starts[pointer];
           current = termDocs(pointer++);
         } else
@@ -620,7 +670,13 @@
       TermDocs result = readerTermDocs[i];
       if (result == null)
         result = readerTermDocs[i] = termDocs(readers[i]);
-      result.seek(term);
+      if (smi != null) {
+        assert(smi.ord == i);
+        assert(smi.termEnum.term().equals(term));
+        result.seek(smi.termEnum);
+      } else {
+        result.seek(term);
+      }
       return result;
     }
   
