]> source.dussan.org Git - poi.git/commitdiff
fix 47286 - Word documents saves in wrong format if source contains form elements
authorSergey Vladimirov <sergey@apache.org>
Mon, 25 Jul 2011 13:58:05 +0000 (13:58 +0000)
committerSergey Vladimirov <sergey@apache.org>
Mon, 25 Jul 2011 13:58:05 +0000 (13:58 +0000)
correctly translate char=>byte on saving CHPX and PAPX tables

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1150704 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/model/CHPBinTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/CHPFormattedDiskPage.java
src/scratchpad/src/org/apache/poi/hwpf/model/PAPBinTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/PAPFormattedDiskPage.java
src/scratchpad/src/org/apache/poi/hwpf/model/PAPX.java
src/scratchpad/testcases/org/apache/poi/hwpf/model/TestCHPBinTable.java
src/scratchpad/testcases/org/apache/poi/hwpf/model/TestPAPBinTable.java

index ffa1196f5c9786d9de76e9c8dc45dcba3f3cda77..b426be0e687d6e1268696a96986754ebff6f1ffc 100644 (file)
@@ -255,7 +255,7 @@ public final class HWPFDocument extends HWPFDocumentCore
 
         _text = _tpt.getText();
         _cbt.rebuild( _cft );
-        _pbt.rebuild( _text, _dataStream, _cft );
+        _pbt.rebuild( _text, _cft );
 
         boolean preserve = false;
         try
@@ -643,7 +643,7 @@ public final class HWPFDocument extends HWPFDocumentCore
 
     // write out the CHPBinTable.
     _fib.setFcPlcfbteChpx(tableOffset);
-    _cbt.writeTo(docSys, fcMin);
+    _cbt.writeTo(docSys, fcMin, _cft.getTextPieceTable());
     _fib.setLcbPlcfbteChpx(tableStream.getOffset() - tableOffset);
     tableOffset = tableStream.getOffset();
 
@@ -657,7 +657,7 @@ public final class HWPFDocument extends HWPFDocumentCore
 
     // write out the PAPBinTable.
     _fib.setFcPlcfbtePapx(tableOffset);
-    _pbt.writeTo(docSys, fcMin, _cft.getTextPieceTable());
+    _pbt.writeTo(docSys, _cft.getTextPieceTable());
     _fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset);
     tableOffset = tableStream.getOffset();
 
index 551e90b750e3d9e03d6092b4d964f0da6361bf52..25a2df35a33f5a63a68c3915d219e7719872663b 100644 (file)
@@ -37,6 +37,7 @@ import org.apache.poi.hwpf.sprm.SprmBuffer;
 import org.apache.poi.hwpf.sprm.SprmIterator;
 import org.apache.poi.hwpf.sprm.SprmOperation;
 import org.apache.poi.poifs.common.POIFSConstants;
+import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -46,6 +47,7 @@ import org.apache.poi.util.POILogger;
  *
  * @author Ryan Ackley
  */
+@Internal
 public class CHPBinTable
 {
     private static final POILogger logger = POILogFactory
@@ -54,9 +56,6 @@ public class CHPBinTable
   /** List of character properties.*/
   protected ArrayList<CHPX> _textRuns = new ArrayList<CHPX>();
 
-  /** So we can know if things are unicode or not */
-  private TextPieceTable tpt;
-
   public CHPBinTable()
   {
   }
@@ -78,7 +77,7 @@ public class CHPBinTable
      * Constructor used to read a binTable in from a Word document.
      */
     public CHPBinTable( byte[] documentStream, byte[] tableStream, int offset,
-            int size, TextPieceTable tpt )
+            int size, CharIndexTranslator translator )
     {
         long start = System.currentTimeMillis();
         /*
@@ -90,7 +89,6 @@ public class CHPBinTable
          * further partitions an interval into runs of exception text."
          */
         PlexOfCps bte = new PlexOfCps( tableStream, offset, size, 4 );
-        this.tpt = tpt;
 
     int length = bte.length();
     for (int x = 0; x < length; x++)
@@ -101,7 +99,7 @@ public class CHPBinTable
       int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE * pageNum;
 
       CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage(documentStream,
-        pageOffset, tpt);
+        pageOffset, translator);
 
       int fkpSize = cfkp.size();
 
@@ -126,7 +124,8 @@ public class CHPBinTable
             SprmBuffer[] sprmBuffers = complexFileTable.getGrpprls();
 
             // adding CHPX from fast-saved SPRMs
-            for ( TextPiece textPiece : tpt.getTextPieces() )
+            for ( TextPiece textPiece : complexFileTable.getTextPieceTable()
+                    .getTextPieces() )
             {
                 PropertyModifier prm = textPiece.getPieceDescriptor().getPrm();
                 if ( !prm.isComplex() )
@@ -396,7 +395,7 @@ public class CHPBinTable
   public void insert(int listIndex, int cpStart, SprmBuffer buf)
   {
 
-    CHPX insertChpx = new CHPX(0, 0, tpt,buf);
+    CHPX insertChpx = new CHPX(0, 0, buf);
 
     // Ensure character offsets are really characters
     insertChpx.setStart(cpStart);
@@ -416,7 +415,7 @@ public class CHPBinTable
        //  Original, until insert at point
        //  New one
        //  Clone of original, on to the old end
-        CHPX clone = new CHPX(0, 0, tpt,chpx.getSprmBuf());
+        CHPX clone = new CHPX(0, 0, chpx.getSprmBuf());
         // Again ensure contains character based offsets no matter what
         clone.setStart(cpStart);
         clone.setEnd(chpx.getEnd());
@@ -452,7 +451,7 @@ public class CHPBinTable
     return _textRuns;
   }
 
-  public void writeTo(HWPFFileSystem sys, int fcMin)
+  public void writeTo(HWPFFileSystem sys, int fcMin, CharIndexTranslator translator)
     throws IOException
   {
 
@@ -482,29 +481,32 @@ public class CHPBinTable
     docOffset = docStream.getOffset();
     int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
 
-    // get the ending fc
-    CHPX lastRun = _textRuns.get(_textRuns.size() - 1); 
-    int endingFc = lastRun.getEnd();
-    endingFc += fcMin;
-
+        // get the ending fc
+        // CHPX lastRun = _textRuns.get(_textRuns.size() - 1);
+        // int endingFc = lastRun.getEnd();
+        // endingFc += fcMin;
+        int endingFc = translator.getByteIndex( _textRuns.get(
+                _textRuns.size() - 1 ).getEnd() );
 
     ArrayList<CHPX> overflow = _textRuns;
     do
     {
       CHPX startingProp = overflow.get(0);
-      int start = startingProp.getStart() + fcMin;
+            // int start = startingProp.getStart() + fcMin;
+            int start = translator.getByteIndex( startingProp.getStart() );
 
       CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage();
       cfkp.fill(overflow);
 
-            byte[] bufFkp = cfkp.toByteArray( tpt );
+            byte[] bufFkp = cfkp.toByteArray( translator );
       docStream.write(bufFkp);
       overflow = cfkp.getOverflow();
 
       int end = endingFc;
       if (overflow != null)
       {
-        end = overflow.get(0).getStart() + fcMin;
+          // end = overflow.get(0).getStart() + fcMin;
+          end = translator.getByteIndex( overflow.get( 0 ).getStart() );
       }
 
       byte[] intHolder = new byte[4];
index 2144df04e82038d8952bedb3fd2f46caa8ef7d76..2f1215c4e6d96dea8dea2cf711310cabf73f5ab5 100644 (file)
@@ -21,9 +21,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.poi.hwpf.sprm.SprmBuffer;
+import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
 
 /**
  * Represents a CHP fkp. The style properties for paragraph and character runs
@@ -41,11 +40,9 @@ import org.apache.poi.util.POILogger;
  *
  * @author Ryan Ackley
  */
+@Internal
 public final class CHPFormattedDiskPage extends FormattedDiskPage
 {
-    private static final POILogger logger = POILogFactory
-            .getLogger( CHPFormattedDiskPage.class );
-
     private static final int FC_SIZE = 4;
 
     private ArrayList<CHPX> _chpxList = new ArrayList<CHPX>();
@@ -76,7 +73,7 @@ public final class CHPFormattedDiskPage extends FormattedDiskPage
      * read from a Word file).
      */
     public CHPFormattedDiskPage( byte[] documentStream, int offset,
-            TextPieceTable tpt )
+            CharIndexTranslator translator )
     {
         super( documentStream, offset );
 
@@ -85,8 +82,8 @@ public final class CHPFormattedDiskPage extends FormattedDiskPage
             int bytesStartAt = getStart( x );
             int bytesEndAt = getEnd( x );
 
-            int charStartAt = tpt.getCharIndex( bytesStartAt );
-            int charEndAt = tpt.getCharIndex( bytesEndAt, charStartAt );
+            int charStartAt = translator.getCharIndex( bytesStartAt );
+            int charEndAt = translator.getCharIndex( bytesEndAt, charStartAt );
 
             // TODO: CHECK!
             // CHPX chpx = new CHPX( bytesStartAt, bytesEndAt, tpt, getGrpprl( x
@@ -146,75 +143,76 @@ public final class CHPFormattedDiskPage extends FormattedDiskPage
         return toByteArray( translator );
     }
 
-    protected byte[] toByteArray(CharIndexTranslator translator)
+    protected byte[] toByteArray( CharIndexTranslator translator )
     {
-      byte[] buf = new byte[512];
-      int size = _chpxList.size();
-      int grpprlOffset = 511;
-      int offsetOffset = 0;
-      int fcOffset = 0;
-
-      // total size is currently the size of one FC
-      int totalSize = FC_SIZE + 2;
-
-      int index = 0;
-      for (; index < size; index++)
-      {
-        int grpprlLength = (_chpxList.get(index)).getGrpprl().length;
-
-        // check to see if we have enough room for an FC, the grpprl offset,
-        // the grpprl size byte and the grpprl.
-        totalSize += (FC_SIZE + 2 + grpprlLength);
-        // if size is uneven we will have to add one so the first grpprl falls
-        // on a word boundary
-        if (totalSize > 511 + (index % 2))
+        byte[] buf = new byte[512];
+        int size = _chpxList.size();
+        int grpprlOffset = 511;
+        int offsetOffset = 0;
+        int fcOffset = 0;
+
+        // total size is currently the size of one FC
+        int totalSize = FC_SIZE + 2;
+
+        int index = 0;
+        for ( ; index < size; index++ )
         {
-          totalSize -= (FC_SIZE + 2 + grpprlLength);
-          break;
+            int grpprlLength = ( _chpxList.get( index ) ).getGrpprl().length;
+
+            // check to see if we have enough room for an FC, the grpprl offset,
+            // the grpprl size byte and the grpprl.
+            totalSize += ( FC_SIZE + 2 + grpprlLength );
+            // if size is uneven we will have to add one so the first grpprl
+            // falls
+            // on a word boundary
+            if ( totalSize > 511 + ( index % 2 ) )
+            {
+                totalSize -= ( FC_SIZE + 2 + grpprlLength );
+                break;
+            }
+
+            // grpprls must fall on word boundaries
+            if ( ( 1 + grpprlLength ) % 2 > 0 )
+            {
+                totalSize += 1;
+            }
         }
 
-        // grpprls must fall on word boundaries
-        if ((1 + grpprlLength) % 2 > 0)
+        // see if we couldn't fit some
+        if ( index != size )
         {
-          totalSize += 1;
+            _overFlow = new ArrayList<CHPX>();
+            _overFlow.addAll( _chpxList.subList( index, size ) );
         }
-      }
 
-      // see if we couldn't fit some
-      if (index != size)
-      {
-        _overFlow = new ArrayList<CHPX>();
-        _overFlow.addAll(_chpxList.subList(index, size));
-      }
+        // index should equal number of CHPXs that will be in this fkp now.
+        buf[511] = (byte) index;
 
-      // index should equal number of CHPXs that will be in this fkp now.
-      buf[511] = (byte)index;
+        offsetOffset = ( FC_SIZE * index ) + FC_SIZE;
+        // grpprlOffset = offsetOffset + index + (grpprlOffset % 2);
 
-      offsetOffset = (FC_SIZE * index) + FC_SIZE;
-      //grpprlOffset =  offsetOffset + index + (grpprlOffset % 2);
-
-      CHPX chpx = null;
-      for (int x = 0; x < index; x++)
-      {
-        chpx = _chpxList.get(x);
-        byte[] grpprl = chpx.getGrpprl();
+        CHPX chpx = null;
+        for ( int x = 0; x < index; x++ )
+        {
+            chpx = _chpxList.get( x );
+            byte[] grpprl = chpx.getGrpprl();
 
             LittleEndian.putInt( buf, fcOffset,
                     translator.getByteIndex( chpx.getStart() ) );
 
-        grpprlOffset -= (1 + grpprl.length);
-        grpprlOffset -= (grpprlOffset % 2);
-        buf[offsetOffset] = (byte)(grpprlOffset/2);
-        buf[grpprlOffset] = (byte)grpprl.length;
-        System.arraycopy(grpprl, 0, buf, grpprlOffset + 1, grpprl.length);
+            grpprlOffset -= ( 1 + grpprl.length );
+            grpprlOffset -= ( grpprlOffset % 2 );
+            buf[offsetOffset] = (byte) ( grpprlOffset / 2 );
+            buf[grpprlOffset] = (byte) grpprl.length;
+            System.arraycopy( grpprl, 0, buf, grpprlOffset + 1, grpprl.length );
 
-        offsetOffset += 1;
-        fcOffset += FC_SIZE;
-      }
+            offsetOffset += 1;
+            fcOffset += FC_SIZE;
+        }
         // put the last chpx's end in
         LittleEndian.putInt( buf, fcOffset,
                 translator.getByteIndex( chpx.getEnd() ) );
-      return buf;
+        return buf;
     }
 
 }
index e93fb0774141048b948147942f50bf93c233bfd0..b6ec456d220841973f69f5dda1be8eb3428488f3 100644 (file)
@@ -52,7 +52,6 @@ public class PAPBinTable
             .getLogger( PAPBinTable.class );
 
   protected ArrayList<PAPX> _paragraphs = new ArrayList<PAPX>();
-  byte[] _dataStream;
 
   public PAPBinTable()
   {
@@ -72,7 +71,8 @@ public class PAPBinTable
     }
 
     public PAPBinTable( byte[] documentStream, byte[] tableStream,
-            byte[] dataStream, int offset, int size, TextPieceTable tpt )
+            byte[] dataStream, int offset, int size,
+            CharIndexTranslator charIndexTranslator )
     {
         long start = System.currentTimeMillis();
 
@@ -89,7 +89,8 @@ public class PAPBinTable
                         * pageNum;
 
                 PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(
-                        documentStream, dataStream, pageOffset, tpt );
+                        documentStream, dataStream, pageOffset,
+                        charIndexTranslator );
 
                 int fkpSize = pfkp.size();
 
@@ -108,7 +109,7 @@ public class PAPBinTable
                 Integer.valueOf( _paragraphs.size() ), " elements)" );
     }
 
-    public void rebuild( final StringBuilder docText, byte[] dataStream,
+    public void rebuild( final StringBuilder docText,
             ComplexFileTable complexFileTable )
     {
         long start = System.currentTimeMillis();
@@ -152,7 +153,7 @@ public class PAPBinTable
                     newSprmBuffer.append( sprmBuffer.toByteArray() );
 
                     PAPX papx = new PAPX( textPiece.getStart(),
-                            textPiece.getEnd(), newSprmBuffer, dataStream );
+                            textPiece.getEnd(), newSprmBuffer );
                     _paragraphs.add( papx );
                 }
             }
@@ -233,7 +234,7 @@ public class PAPBinTable
                         ") has no PAPX. Creating new one." );
                 // create it manually
                 PAPX papx = new PAPX( startInclusive, endExclusive,
-                        new SprmBuffer( 2 ), dataStream );
+                        new SprmBuffer( 2 ) );
                 newPapxs.add( papx );
 
                 lastParStart = endExclusive;
@@ -272,8 +273,7 @@ public class PAPBinTable
                 else
                     sprmBuffer.append( papx.getGrpprl(), 2 );
             }
-            PAPX newPapx = new PAPX( startInclusive, endExclusive, sprmBuffer,
-                    dataStream );
+            PAPX newPapx = new PAPX( startInclusive, endExclusive, sprmBuffer );
             newPapxs.add( newPapx );
 
             lastParStart = endExclusive;
@@ -285,14 +285,12 @@ public class PAPBinTable
                 Long.valueOf( System.currentTimeMillis() - start ), " ms (",
                 Integer.valueOf( _paragraphs.size() ), " elements)" );
         start = System.currentTimeMillis();
-
-        _dataStream = dataStream;
     }
 
   public void insert(int listIndex, int cpStart, SprmBuffer buf)
   {
 
-    PAPX forInsert = new PAPX(0, 0, buf, _dataStream);
+    PAPX forInsert = new PAPX(0, 0, buf);
 
     // Ensure character offsets are really characters
     forInsert.setStart(cpStart);
@@ -322,7 +320,7 @@ public class PAPBinTable
        //  Original, until insert at point
        //  New one
        //  Clone of original, on to the old end
-        PAPX clone = new PAPX(0, 0, clonedBuf, _dataStream);
+        PAPX clone = new PAPX(0, 0, clonedBuf);
         // Again ensure contains character based offsets no matter what
         clone.setStart(cpStart);
         clone.setEnd(currentPap.getEnd());
@@ -399,11 +397,12 @@ public class PAPBinTable
     return _paragraphs;
   }
 
-    public void writeTo( HWPFFileSystem sys, int fcMin, CharIndexTranslator translator ) throws IOException
+    public void writeTo( HWPFFileSystem sys, CharIndexTranslator translator ) throws IOException
     {
 
     HWPFOutputStream docStream = sys.getStream("WordDocument");
     OutputStream tableStream = sys.getStream("1Table");
+    HWPFOutputStream dataStream = sys.getStream("1Table");
 
     PlexOfCps binTable = new PlexOfCps(4);
 
@@ -420,28 +419,32 @@ public class PAPBinTable
     docOffset = docStream.getOffset();
     int pageNum = docOffset/POIFSConstants.SMALLER_BIG_BLOCK_SIZE;
 
-    // get the ending fc
-    int endingFc = _paragraphs.get(_paragraphs.size() - 1).getEnd();
-    endingFc += fcMin;
-
+        // get the ending fc
+        // int endingFc = _paragraphs.get(_paragraphs.size() - 1).getEnd();
+        // endingFc += fcMin;
+        int endingFc = translator.getByteIndex( _paragraphs.get(
+                _paragraphs.size() - 1 ).getEnd() );
 
     ArrayList<PAPX> overflow = _paragraphs;
     do
     {
       PAPX startingProp = overflow.get(0);
-      int start = startingProp.getStart() + fcMin;
 
-      PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(_dataStream);
+            // int start = startingProp.getStart() + fcMin;
+            int start = translator.getByteIndex( startingProp.getStart() );
+
+      PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage();
       pfkp.fill(overflow);
 
-      byte[] bufFkp = pfkp.toByteArray(translator, fcMin);
+      byte[] bufFkp = pfkp.toByteArray(dataStream, translator);
       docStream.write(bufFkp);
       overflow = pfkp.getOverflow();
 
       int end = endingFc;
       if (overflow != null)
       {
-        end = overflow.get(0).getStart() + fcMin;
+                // end = overflow.get(0).getStart() + fcMin;
+                end = translator.getByteIndex( overflow.get( 0 ).getStart() );
       }
 
       byte[] intHolder = new byte[4];
index 4edb3b23e695800bf27b3c0cc37d15a1dcb6c4c4..29c838c6ac5bc4dc1f573269b8d94f02f105fa9f 100644 (file)
 
 package org.apache.poi.hwpf.model;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
 
@@ -48,12 +50,17 @@ public final class PAPFormattedDiskPage extends FormattedDiskPage {
 
     private ArrayList<PAPX> _papxList = new ArrayList<PAPX>();
     private ArrayList<PAPX> _overFlow;
-    private byte[] _dataStream;
 
+    /**
+     * @deprecated Use {@link #PAPFormattedDiskPage()} instead
+     */
+    public PAPFormattedDiskPage( byte[] dataStream )
+    {
+        this();
+    }
 
-    public PAPFormattedDiskPage(byte[] dataStream)
+    public PAPFormattedDiskPage()
     {
-      _dataStream = dataStream;
     }
 
     /**
@@ -73,20 +80,22 @@ public final class PAPFormattedDiskPage extends FormattedDiskPage {
      * Creates a PAPFormattedDiskPage from a 512 byte array
      */
     public PAPFormattedDiskPage( byte[] documentStream, byte[] dataStream,
-            int offset, TextPieceTable tpt )
+            int offset, CharIndexTranslator translator )
     {
         super( documentStream, offset );
         for ( int x = 0; x < _crun; x++ )
         {
-            int startAt = getStart( x );
-            int endAt = getEnd( x );
+            int bytesStartAt = getStart( x );
+            int bytesEndAt = getEnd( x );
 
-            PAPX papx = new PAPX( startAt, endAt, tpt, getGrpprl( x ),
+            int charStartAt = translator.getCharIndex( bytesStartAt );
+            int charEndAt = translator.getCharIndex( bytesEndAt, charStartAt );
+
+            PAPX papx = new PAPX( charStartAt, charEndAt, getGrpprl( x ),
                     getParagraphHeight( x ), dataStream );
             _papxList.add( papx );
         }
         _fkp = null;
-        _dataStream = dataStream;
     }
 
     /**
@@ -158,163 +167,181 @@ public final class PAPFormattedDiskPage extends FormattedDiskPage {
     /**
      * Creates a byte array representation of this data structure. Suitable for
      * writing to a Word document.
-     *
-     * @param fcMin The file offset in the main stream where text begins.
+     * 
+     * @param dataStream required if PAPX is too big to fit in FKP
+     * 
      * @return A byte array representing this data structure.
+     * @throws IOException
+     *             if an I/O error occurs.
      */
-    protected byte[] toByteArray(CharIndexTranslator translator, int fcMin)
+    protected byte[] toByteArray( HWPFOutputStream dataStream,
+            CharIndexTranslator translator ) throws IOException
     {
-      byte[] buf = new byte[512];
-      int size = _papxList.size();
-      int grpprlOffset = 0;
-      int bxOffset = 0;
-      int fcOffset = 0;
-      byte[] lastGrpprl = new byte[0];
-
-      // total size is currently the size of one FC
-      int totalSize = FC_SIZE;
-
-      int index = 0;
-      for (; index < size; index++)
-      {
-        byte[] grpprl = _papxList.get(index).getGrpprl();
-        int grpprlLength = grpprl.length;
-
-        // is grpprl huge?
-        if(grpprlLength > 488)
+        byte[] buf = new byte[512];
+        int size = _papxList.size();
+        int grpprlOffset = 0;
+        int bxOffset = 0;
+        int fcOffset = 0;
+        byte[] lastGrpprl = new byte[0];
+
+        // total size is currently the size of one FC
+        int totalSize = FC_SIZE;
+
+        int index = 0;
+        for ( ; index < size; index++ )
         {
-          grpprlLength = 8; // set equal to size of sprmPHugePapx grpprl
+            byte[] grpprl = _papxList.get( index ).getGrpprl();
+            int grpprlLength = grpprl.length;
+
+            // is grpprl huge?
+            if ( grpprlLength > 488 )
+            {
+                grpprlLength = 8; // set equal to size of sprmPHugePapx grpprl
+            }
+
+            // check to see if we have enough room for an FC, a BX, and the
+            // grpprl
+            // and the 1 byte size of the grpprl.
+            int addition = 0;
+            if ( !Arrays.equals( grpprl, lastGrpprl ) )
+            {
+                addition = ( FC_SIZE + BX_SIZE + grpprlLength + 1 );
+            }
+            else
+            {
+                addition = ( FC_SIZE + BX_SIZE );
+            }
+
+            totalSize += addition;
+
+            // if size is uneven we will have to add one so the first grpprl
+            // falls
+            // on a word boundary
+            if ( totalSize > 511 + ( index % 2 ) )
+            {
+                totalSize -= addition;
+                break;
+            }
+
+            // grpprls must fall on word boundaries
+            if ( grpprlLength % 2 > 0 )
+            {
+                totalSize += 1;
+            }
+            else
+            {
+                totalSize += 2;
+            }
+            lastGrpprl = grpprl;
         }
 
-        // check to see if we have enough room for an FC, a BX, and the grpprl
-        // and the 1 byte size of the grpprl.
-        int addition = 0;
-        if (!Arrays.equals(grpprl, lastGrpprl))
-        {
-          addition = (FC_SIZE + BX_SIZE + grpprlLength + 1);
-        }
-        else
+        // see if we couldn't fit some
+        if ( index != size )
         {
-          addition = (FC_SIZE + BX_SIZE);
+            _overFlow = new ArrayList<PAPX>();
+            _overFlow.addAll( _papxList.subList( index, size ) );
         }
 
-        totalSize += addition;
+        // index should equal number of papxs that will be in this fkp now.
+        buf[511] = (byte) index;
 
-        // if size is uneven we will have to add one so the first grpprl falls
-        // on a word boundary
-        if (totalSize > 511 + (index % 2))
-        {
-          totalSize -= addition;
-          break;
-        }
+        bxOffset = ( FC_SIZE * index ) + FC_SIZE;
+        grpprlOffset = 511;
 
-        // grpprls must fall on word boundaries
-        if (grpprlLength % 2 > 0)
+        PAPX papx = null;
+        lastGrpprl = new byte[0];
+        for ( int x = 0; x < index; x++ )
         {
-          totalSize += 1;
-        }
-        else
-        {
-          totalSize += 2;
-        }
-        lastGrpprl = grpprl;
-      }
-
-      // see if we couldn't fit some
-      if (index != size)
-      {
-        _overFlow = new ArrayList<PAPX>();
-        _overFlow.addAll(_papxList.subList(index, size));
-      }
-
-      // index should equal number of papxs that will be in this fkp now.
-      buf[511] = (byte)index;
-
-      bxOffset = (FC_SIZE * index) + FC_SIZE;
-      grpprlOffset =  511;
-
-      PAPX papx = null;
-      lastGrpprl = new byte[0];
-      for (int x = 0; x < index; x++)
-      {
-        papx = _papxList.get(x);
-        byte[] phe = papx.getParagraphHeight().toByteArray();
-        byte[] grpprl = papx.getGrpprl();
-
-        // is grpprl huge?
-        if(grpprl.length > 488)
-        {
-          // if so do we have storage at getHugeGrpprlOffset()
-          int hugeGrpprlOffset = papx.getHugeGrpprlOffset();
-          if(hugeGrpprlOffset == -1) // then we have no storage...
-          {
-            throw new UnsupportedOperationException(
-                  "This Paragraph has no dataStream storage.");
-          }
-          // we have some storage...
-
-          // get the size of the existing storage
-          int maxHugeGrpprlSize = LittleEndian.getUShort(_dataStream, hugeGrpprlOffset);
-
-          if (maxHugeGrpprlSize < grpprl.length-2) { // grpprl.length-2 because we don't store the istd
-              throw new UnsupportedOperationException(
-                  "This Paragraph's dataStream storage is too small.");
-          }
-
-          // store grpprl at hugeGrpprlOffset
-          System.arraycopy(grpprl, 2, _dataStream, hugeGrpprlOffset + 2,
-                           grpprl.length - 2); // grpprl.length-2 because we don't store the istd
-          LittleEndian.putUShort(_dataStream, hugeGrpprlOffset, grpprl.length - 2);
-
-          // grpprl = grpprl containing only a sprmPHugePapx2
-          int istd = LittleEndian.getUShort(grpprl, 0);
-          grpprl = new byte[8];
-          LittleEndian.putUShort(grpprl, 0, istd);
-          LittleEndian.putUShort(grpprl, 2, 0x6646); // sprmPHugePapx2
-          LittleEndian.putInt(grpprl, 4, hugeGrpprlOffset);
-        }
-
-        boolean same = Arrays.equals(lastGrpprl, grpprl);
-        if (!same)
-        {
-          grpprlOffset -= (grpprl.length + (2 - grpprl.length % 2));
-          grpprlOffset -= (grpprlOffset % 2);
-        }
-            // LittleEndian.putInt( buf, fcOffset,
-            // papx.getStartBytes() );
+            papx = _papxList.get( x );
+            byte[] phe = papx.getParagraphHeight().toByteArray();
+            byte[] grpprl = papx.getGrpprl();
+
+            // is grpprl huge?
+            if ( grpprl.length > 488 )
+            {
+                // if so do we have storage at getHugeGrpprlOffset()
+                // int hugeGrpprlOffset = papx.getHugeGrpprlOffset();
+                // if ( hugeGrpprlOffset == -1 ) // then we have no storage...
+                // {
+                // throw new UnsupportedOperationException(
+                // "This Paragraph has no dataStream storage." );
+                // }
+                // we have some storage...
+
+                // get the size of the existing storage
+                // int maxHugeGrpprlSize = LittleEndian.getUShort( dataStream,
+                // hugeGrpprlOffset );
+                //
+                // if ( maxHugeGrpprlSize < grpprl.length - 2 )
+                // { // grpprl.length-2 because we don't store the istd
+                // throw new UnsupportedOperationException(
+                // "This Paragraph's dataStream storage is too small." );
+                // }
+
+                // store grpprl at hugeGrpprlOffset
+                // grpprl.length-2 because we don't store the istd
+                // System.arraycopy( grpprl, 2, dataStream, hugeGrpprlOffset +
+                // 2,
+                // grpprl.length - 2 );
+                // LittleEndian.putUShort( dataStream, hugeGrpprlOffset,
+                // grpprl.length - 2 );
+
+                byte[] hugePapx = new byte[grpprl.length - 2];
+                System.arraycopy( grpprl, 2, hugePapx, 0, grpprl.length - 2 );
+                int dataStreamOffset = dataStream.getOffset();
+                dataStream.write( hugePapx );
+
+                // grpprl = grpprl containing only a sprmPHugePapx2
+                int istd = LittleEndian.getUShort( grpprl, 0 );
+
+                grpprl = new byte[8];
+                LittleEndian.putUShort( grpprl, 0, istd );
+                LittleEndian.putUShort( grpprl, 2, 0x6646 ); // sprmPHugePapx2
+                LittleEndian.putInt( grpprl, 4, dataStreamOffset );
+            }
+
+            boolean same = Arrays.equals( lastGrpprl, grpprl );
+            if ( !same )
+            {
+                grpprlOffset -= ( grpprl.length + ( 2 - grpprl.length % 2 ) );
+                grpprlOffset -= ( grpprlOffset % 2 );
+            }
+            // LittleEndian.putInt( buf, fcOffset, papx.getStartBytes() );
             LittleEndian.putInt( buf, fcOffset,
                     translator.getByteIndex( papx.getStart() ) );
-        buf[bxOffset] = (byte)(grpprlOffset/2);
-        System.arraycopy(phe, 0, buf, bxOffset + 1, phe.length);
+            buf[bxOffset] = (byte) ( grpprlOffset / 2 );
+            System.arraycopy( phe, 0, buf, bxOffset + 1, phe.length );
+
+            /*
+             * refer to the section on PAPX in the spec. Places a size on the
+             * front of the PAPX. Has to do with how the grpprl stays on word
+             * boundaries.
+             */
+            if ( !same )
+            {
+                int copyOffset = grpprlOffset;
+                if ( ( grpprl.length % 2 ) > 0 )
+                {
+                    buf[copyOffset++] = (byte) ( ( grpprl.length + 1 ) / 2 );
+                }
+                else
+                {
+                    buf[++copyOffset] = (byte) ( ( grpprl.length ) / 2 );
+                    copyOffset++;
+                }
+                System.arraycopy( grpprl, 0, buf, copyOffset, grpprl.length );
+                lastGrpprl = grpprl;
+            }
+
+            bxOffset += BX_SIZE;
+            fcOffset += FC_SIZE;
 
-        // refer to the section on PAPX in the spec. Places a size on the front
-        // of the PAPX. Has to do with how the grpprl stays on word
-        // boundaries.
-        if (!same)
-        {
-          int copyOffset = grpprlOffset;
-          if ( (grpprl.length % 2) > 0)
-          {
-            buf[copyOffset++] = (byte) ( (grpprl.length + 1) / 2);
-          }
-          else
-          {
-            buf[++copyOffset] = (byte) ( (grpprl.length) / 2);
-            copyOffset++;
-          }
-          System.arraycopy(grpprl, 0, buf, copyOffset, grpprl.length);
-          lastGrpprl = grpprl;
         }
 
-        bxOffset += BX_SIZE;
-        fcOffset += FC_SIZE;
-
-      }
-
         // LittleEndian.putInt(buf, fcOffset, papx.getEndBytes() + fcMin);
         LittleEndian.putInt( buf, fcOffset,
                 translator.getByteIndex( papx.getEnd() ) );
-      return buf;
+        return buf;
     }
 
     /**
index 5c9ab60886ecd085cf0cd51e954aeb96f6cacf98..53c8d1fe5e41a9e180c0eabaf0022953b1d90f3b 100644 (file)
@@ -22,6 +22,7 @@ import org.apache.poi.hwpf.sprm.ParagraphSprmUncompressor;
 import org.apache.poi.hwpf.sprm.SprmBuffer;
 import org.apache.poi.hwpf.sprm.SprmOperation;
 import org.apache.poi.hwpf.usermodel.ParagraphProperties;
+import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
 
 /**
@@ -33,11 +34,11 @@ import org.apache.poi.util.LittleEndian;
  *
  * @author Ryan Ackley
  */
+@Internal
 @SuppressWarnings( "deprecation" )
 public final class PAPX extends BytePropertyNode<PAPX> {
 
   private ParagraphHeight _phe;
-  private int _hugeGrpprlOffset = -1;
 
   public PAPX(int fcStart, int fcEnd, CharIndexTranslator translator, byte[] papx, ParagraphHeight phe, byte[] dataStream)
   {
@@ -48,6 +49,17 @@ public final class PAPX extends BytePropertyNode<PAPX> {
       _buf = buf;
   }
 
+    public PAPX( int charStart, int charEnd, byte[] papx, ParagraphHeight phe,
+            byte[] dataStream )
+    {
+        super( charStart, charEnd, new SprmBuffer( papx, 2 ) );
+        _phe = phe;
+        SprmBuffer buf = findHuge( new SprmBuffer( papx, 2 ), dataStream );
+        if ( buf != null )
+            _buf = buf;
+    }
+
+    @Deprecated
   public PAPX(int fcStart, int fcEnd, CharIndexTranslator translator, SprmBuffer buf, byte[] dataStream)
   {
     super(fcStart, fcEnd, translator, buf);
@@ -57,13 +69,10 @@ public final class PAPX extends BytePropertyNode<PAPX> {
       _buf = buf;
   }
 
-    public PAPX( int charStart, int charEnd, SprmBuffer buf, byte[] dataStream )
+    public PAPX( int charStart, int charEnd, SprmBuffer buf )
     {
         super( charStart, charEnd, buf );
         _phe = new ParagraphHeight();
-        buf = findHuge( buf, dataStream );
-        if ( buf != null )
-            _buf = buf;
     }
 
   private SprmBuffer findHuge(SprmBuffer buf, byte[] datastream)
@@ -87,8 +96,6 @@ public final class PAPX extends BytePropertyNode<PAPX> {
             // copy Grpprl from dataStream
             System.arraycopy(datastream, hugeGrpprlOffset + 2, hugeGrpprl, 2,
                              grpprlSize);
-            // save a pointer to where we got the huge Grpprl from
-            _hugeGrpprlOffset = hugeGrpprlOffset;
             return new SprmBuffer(hugeGrpprl, 2);
           }
         }
@@ -108,11 +115,6 @@ public final class PAPX extends BytePropertyNode<PAPX> {
     return ((SprmBuffer)_buf).toByteArray();
   }
 
-  public int getHugeGrpprlOffset()
-  {
-    return _hugeGrpprlOffset;
-  }
-
   public short getIstd()
   {
     byte[] buf = getGrpprl();
index 8e26e5ac1f212d363d3548ddec1ca6bc1d0f1410..006fc77ddfaf44f661f3c840d55dfbd1f57685c3 100644 (file)
@@ -50,7 +50,7 @@ public final class TestCHPBinTable
 
     HWPFFileSystem fileSys = new HWPFFileSystem();
 
-    _cHPBinTable.writeTo(fileSys, 0);
+    _cHPBinTable.writeTo(fileSys, 0, fakeTPT);
     ByteArrayOutputStream tableOut = fileSys.getStream("1Table");
     ByteArrayOutputStream mainOut =  fileSys.getStream("WordDocument");
 
index e21cee3573e05049d8cd77899d8d37af6b30ee9b..b9e3287f40f25aabe25cfc59cad8a8aa69d20b1d 100644 (file)
@@ -53,7 +53,7 @@ public final class TestPAPBinTable extends TestCase
 
         HWPFFileSystem fileSys = new HWPFFileSystem();
 
-        _pAPBinTable.writeTo( fileSys, 0, fakeTPT );
+        _pAPBinTable.writeTo( fileSys, fakeTPT );
         ByteArrayOutputStream tableOut = fileSys.getStream( "1Table" );
         ByteArrayOutputStream mainOut = fileSys.getStream( "WordDocument" );