Index: lucene/src/java/org/apache/lucene/index/DocInverterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(revision f0571364edbaacae56da0743a3f0a33a2bd17bec)
+++ lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(revision )
@@ -77,7 +77,7 @@
       if (field.isIndexed() && doInvert) {
         
         if (i > 0)
-          fieldState.position += docState.analyzer.getPositionIncrementGap(fieldInfo.name);
+          fieldState.position += docState.analyzer.getPositionIncrementGap(fieldInfo.name) + 1;
 
         if (!field.isTokenized()) {		  // un-tokenized field
           String stringValue = field.stringValue();
@@ -138,8 +138,8 @@
             PositionIncrementAttribute posIncrAttribute = fieldState.attributeSource.addAttribute(PositionIncrementAttribute.class);
             
             consumer.start(field);
-            
+
-            for(;;) {
+            for(boolean firstToken = true; hasMoreTokens; firstToken=false) {
 
               // If we hit an exception in stream.next below
               // (which is fairly common, eg if analyzer
@@ -147,17 +147,15 @@
               // non-aborting and (above) this one document
               // will be marked as deleted, but still
               // consume a docID
-              
+
-              if (!hasMoreTokens) break;
-              
+              //ignore position increment for first token; relying on positionIncrementGap between values
+              if (!firstToken) {
-              final int posIncr = posIncrAttribute.getPositionIncrement();
-              fieldState.position += posIncr;
+                final int posIncr = posIncrAttribute.getPositionIncrement();
+                fieldState.position += posIncr;
-              if (fieldState.position > 0) {
-                fieldState.position--;
-              }
-
-              if (posIncr == 0)
-                fieldState.numOverlap++;
+                if (posIncr == 0)
+                  fieldState.numOverlap++;
+              }
+              assert fieldState.position >= 0 : "LUCENE-1542, pos < 0 doesn't work with payloads";
 
               boolean success = false;
               try {
@@ -173,7 +171,6 @@
                 if (!success)
                   docState.docWriter.setAborting();
               }
-              fieldState.position++;
               if (++fieldState.length >= maxFieldLength) {
                 if (docState.infoStream != null)
                   docState.infoStream.println("maxFieldLength " +maxFieldLength+ " reached for field " + fieldInfo.name + ", ignoring following tokens");
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(revision f0571364edbaacae56da0743a3f0a33a2bd17bec)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(revision )
@@ -4328,10 +4328,10 @@
     TermPositionVector tpv = ((TermPositionVector) r.getTermFreqVector(0, "field"));
     int[] poss = tpv.getTermPositions(0);
     assertEquals(1, poss.length);
-    assertEquals(100, poss[0]);
+    assertEquals(101, poss[0]);
     poss = tpv.getTermPositions(1);
     assertEquals(1, poss.length);
-    assertEquals(101, poss[0]);
+    assertEquals(102, poss[0]);
     r.close();
     dir.close();
   }
