]> source.dussan.org Git - poi.git/commitdiff
Reached first milestone
authorSaid Ryan Ackley <sackley@apache.org>
Tue, 15 Jul 2003 03:23:40 +0000 (03:23 +0000)
committerSaid Ryan Ackley <sackley@apache.org>
Tue, 15 Jul 2003 03:23:40 +0000 (03:23 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353212 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/HWPFDocument.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/CHPBinTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/Ffn.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/FileInformationBlock.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/FontTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/PAPBinTable.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/PAPFormattedDiskPage.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/StyleDescription.java
src/scratchpad/src/org/apache/poi/hwpf/model/hdftypes/StyleSheet.java
src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestDocumentProperties.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestFontTable.java [new file with mode: 0644]

index 9b685ddca1cbb6346081c09cf2fffd18935f2b35..a1a87d2cd09409ac892d7bcd3b9a015a05e9dfd4 100644 (file)
@@ -57,14 +57,23 @@ package org.apache.poi.hwpf;
 import java.io.InputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileOutputStream;
 
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.common.POIFSConstants;
 
 import org.apache.poi.hwpf.model.hdftypes.*;
+import org.apache.poi.hwpf.model.io.*;
 
 
 /**
+ *
+ * This class acts as the bucket that we throw all of the Word data structures
+ * into.
+ *
  * @author Ryan Ackley
  */
 public class HWPFDocument
@@ -76,11 +85,40 @@ public class HWPFDocument
   private FileInformationBlock _fib;
 
   /** main document stream buffer*/
-  byte[] _mainStream;
+  private byte[] _mainStream;
 
   /** table stream buffer*/
-  byte[] _tableStream;
+  private byte[] _tableStream;
+
+  /** Document wide Properties*/
+  private DocumentProperties _dop;
+
+  /** Contains text of the document wrapped in a obfuscated Wod data structure*/
+  private ComplexFileTable _cft;
+
+  /** Contains formatting properties for text*/
+  private CHPBinTable _cbt;
+
+  /** Contains formatting properties for paragraphs*/
+  private PAPBinTable _pbt;
+
+  /** Contains formatting properties for sections.*/
+  private SectionTable _st;
+
+  /** Holds styles for this document.*/
+  private StyleSheet _ss;
+
+  /** Holds fonts for this document.*/
+  private FontTable _ft;
+
 
+  /**
+   * This constructor loads a Word document from an InputStream.
+   *
+   * @param istream The InputStream that contains the Word document.
+   * @throws IOException If there is an unexpected IOException from the passed
+   *         in InputStream.
+   */
   public HWPFDocument(InputStream istream) throws IOException
   {
     //do Ole stuff
@@ -110,23 +148,148 @@ public class HWPFDocument
     // get the start of text in the main stream
     int fcMin = _fib.getFcMin();
 
-    DocumentProperties dop = new DocumentProperties(_tableStream, _fib.getFcDop());
-    ComplexFileTable cft = new ComplexFileTable(_mainStream, _tableStream, _fib.getFcClx(), fcMin);
-    CHPBinTable cbt = new CHPBinTable(_mainStream, _tableStream, _fib.getFcPlcfbteChpx(), _fib.getLcbPlcfbteChpx(), fcMin);
-    PAPBinTable pbt = new PAPBinTable(_mainStream, _tableStream, _fib.getFcPlcfbtePapx(), _fib.getLcbPlcfbtePapx(), fcMin);
-    SectionTable st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin);
-    StyleSheet ss = new StyleSheet(_tableStream, _fib.getFcStshf());
+    // load up our standard structures.
+    _dop = new DocumentProperties(_tableStream, _fib.getFcDop());
+    _cft = new ComplexFileTable(_mainStream, _tableStream, _fib.getFcClx(), fcMin);
+    _cbt = new CHPBinTable(_mainStream, _tableStream, _fib.getFcPlcfbteChpx(), _fib.getLcbPlcfbteChpx(), fcMin);
+    _pbt = new PAPBinTable(_mainStream, _tableStream, _fib.getFcPlcfbtePapx(), _fib.getLcbPlcfbtePapx(), fcMin);
+    _st = new SectionTable(_mainStream, _tableStream, _fib.getFcPlcfsed(), _fib.getLcbPlcfsed(), fcMin);
+    _ss = new StyleSheet(_tableStream, _fib.getFcStshf());
+    _ft = new FontTable(_tableStream, _fib.getFcSttbfffn(), _fib.getLcbSttbfffn());
 
     int x = 0;
 
   }
 
+  /**
+   * Writes out the word file that is represented by an instance of this class.
+   *
+   * @param out The OutputStream to write to.
+   * @throws IOException If there is an unexpected IOException from the passed
+   *         in OutputStream.
+   */
+  public void write(OutputStream out)
+    throws IOException
+  {
+    // initialize our streams for writing.
+    HWPFFileSystem docSys = new HWPFFileSystem();
+    HWPFOutputStream mainStream = docSys.getStream("WordDocument");
+    HWPFOutputStream tableStream = docSys.getStream("1Table");
+    int tableOffset = 0;
+
+    // clear the offsets and sizes in our FileInformationBlock.
+    _fib.clearOffsetsSizes();
+
+    // determine the FileInformationBLock size
+    int fibSize = _fib.getSize();
+    fibSize  += POIFSConstants.BIG_BLOCK_SIZE -
+        (fibSize % POIFSConstants.BIG_BLOCK_SIZE);
+
+    // preserve space for the FileInformationBlock because we will be writing
+    // it after we write everything else.
+    byte[] placeHolder = new byte[fibSize];
+    mainStream.write(placeHolder);
+    int mainOffset = mainStream.getOffset();
+
+    // write out the StyleSheet.
+    _fib.setFcStshf(tableOffset);
+    _ss.writeTo(tableStream);
+    _fib.setLcbStshf(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+
+    // get fcMin and fcMac because we will be writing the actual text with the
+    // complex table.
+    int fcMin = mainOffset;
+
+    // write out the Complex table, includes text.
+    _fib.setFcClx(tableOffset);
+    _cft.writeTo(docSys);
+    _fib.setLcbClx(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+    int fcMac = mainStream.getOffset();
+
+    // write out the CHPBinTable.
+    _fib.setFcPlcfbteChpx(tableOffset);
+    _cbt.writeTo(docSys, fcMin);
+    _fib.setLcbPlcfbteChpx(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+
+    // write out the PAPBinTable.
+    _fib.setFcPlcfbtePapx(tableOffset);
+    _pbt.writeTo(docSys, fcMin);
+    _fib.setLcbPlcfbtePapx(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+
+    // write out the SectionTable.
+    _fib.setFcPlcfsed(tableOffset);
+    _st.writeTo(docSys, fcMin);
+    _fib.setLcbPlcfsed(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+
+    // write out the FontTable.
+    _fib.setFcSttbfffn(tableOffset);
+    _ft.writeTo(docSys);
+    _fib.setLcbSttbfffn(tableStream.getOffset() - tableOffset);
+    tableOffset = tableStream.getOffset();
+
+    // write out the DocumentProperties.
+    _fib.setFcDop(tableOffset);
+    byte[] buf = new byte[_dop.getSize()];
+    _fib.setLcbDop(_dop.getSize());
+    _dop.serialize(buf, 0);
+    tableStream.write(buf);
+
+    // set some variables in the FileInformationBlock.
+    _fib.setFcMin(fcMin);
+    _fib.setFcMac(fcMac);
+    _fib.setCbMac(mainStream.getOffset());
+
+    // make sure that the table and doc stream use big blocks.
+    byte[] mainBuf = mainStream.toByteArray();
+    if (mainBuf.length < 4096)
+    {
+      byte[] tempBuf = new byte[4096];
+      System.arraycopy(mainBuf, 0, tempBuf, 0, mainBuf.length);
+      mainBuf = tempBuf;
+    }
+    byte[] tableBuf = tableStream.toByteArray();
+    if (tableBuf.length < 4096)
+    {
+      byte[] tempBuf = new byte[4096];
+      System.arraycopy(tableBuf, 0, tempBuf, 0, tableBuf.length);
+      tableBuf = tempBuf;
+    }
+
+    // write out the FileInformationBlock.
+    _fib.serialize(mainBuf, 0);
+
+    // spit out the Word document.
+    POIFSFileSystem pfs = new POIFSFileSystem();
+    pfs.createDocument(new ByteArrayInputStream(mainBuf), "WordDocument");
+    pfs.createDocument(new ByteArrayInputStream(tableBuf), "1Table");
+
+    pfs.writeFilesystem(out);
+  }
+
+  /**
+   * Takes two arguments, 1) name of the Word file to read in 2) location to
+   * write it out at.
+   * @param args
+   */
   public static void main(String[] args)
   {
+
     try
     {
       HWPFDocument doc = new HWPFDocument(new FileInputStream(args[0]));
 
+      OutputStream out = new FileOutputStream(args[1]);
+      doc.write(out);
+
+      out.flush();
+      out.close();
+
+
     }
     catch (Throwable t)
     {
index 0b74c23ceba0bc00d6400f96869a0069b1aa853d..c8614daf0fa8d0f94dfcc47cccf7a51118c6d664 100644 (file)
@@ -142,7 +142,7 @@ public class CHPBinTable
       int end = endingFc;
       if (overflow != null)
       {
-        end = ((PropertyNode)overflow.get(0)).getStart();
+        end = ((PropertyNode)overflow.get(0)).getStart() + fcMin;
       }
 
       byte[] intHolder = new byte[4];
index 92113a3abf04076b5e3836870451aaf3efd1100a..265ca7479bf84f7567865a318a067d7bd911fc46 100644 (file)
@@ -56,93 +56,212 @@ package org.apache.poi.hwpf.model.hdftypes;
 
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.LittleEndian;
+import java.util.Arrays;
 
-
+/**
+ * FFN - Font Family Name. FFN is a data structure that stores the names of the Main
+ * Font and that of Alternate font as an array of characters. It has also a header
+ * that stores info about the whole structure and the fonts
+ *
+ * @author Praveen Mathew
+ */
 public class Ffn
 {
-  private int field1_cbFfnM1;            //total length of FFN - 1.
-  private byte field2;
+  private int field_1_cbFfnM1;//total length of FFN - 1.
+  private byte field_2;
     private  static BitField _prq = new BitField(0x0003);// pitch request
     private  static BitField _fTrueType = new BitField(0x0004);// when 1, font is a TrueType font
     private  static BitField _ff = new BitField(0x0070);
-  private short field3_wWeight;// base weight of font
-  private byte field4_chs;// character set identifier
-  private byte field5_ixchSzAlt;  // index into ffn.szFfn to the name of
+  private short field_3_wWeight;// base weight of font
+  private byte field_4_chs;// character set identifier
+  private byte field_5_ixchSzAlt;  // index into ffn.szFfn to the name of
                                   // the alternate font
-  private byte [] panose = new byte[10];                  //????
-  private byte [] fontSig         = new byte[24]; //????
+  private byte [] field_6_panose = new byte[10];//????
+  private byte [] field_7_fontSig = new byte[24];//????
 
   // zero terminated string that records name of font, cuurently not
   // supporting Extended chars
-  private char [] xszFfn;
+  private char [] field_8_xszFfn;
+
+  // extra facilitator members
   private int xszFfnLength;
 
   public Ffn(byte[] buf, int offset)
   {
-    field1_cbFfnM1 = LittleEndian.getUnsignedByte(buf, offset);
+         int offsetTmp = offset;
+
+         field_1_cbFfnM1 = LittleEndian.getUnsignedByte(buf,offset);
     offset += LittleEndian.BYTE_SIZE;
-    field2 = buf[offset];
+         field_2 = buf[offset];
     offset += LittleEndian.BYTE_SIZE;
-    field3_wWeight = LittleEndian.getShort(buf, offset);
+         field_3_wWeight = LittleEndian.getShort(buf, offset);
     offset += LittleEndian.SHORT_SIZE;
-    field4_chs = buf[offset];
+         field_4_chs = buf[offset];
     offset += LittleEndian.BYTE_SIZE;
-    field5_ixchSzAlt = buf[offset];
+         field_5_ixchSzAlt = buf[offset];
     offset += LittleEndian.BYTE_SIZE;
 
     // read panose and fs so we can write them back out.
-    System.arraycopy(buf, offset, panose, 0, panose.length);
-    offset += panose.length;
-    System.arraycopy(buf, offset, fontSig, 0, fontSig.length);
-    offset += fontSig.length;
+    System.arraycopy(buf, offset, field_6_panose, 0, field_6_panose.length);
+    offset += field_6_panose.length;
+    System.arraycopy(buf, offset, field_7_fontSig, 0, field_7_fontSig.length);
+    offset += field_7_fontSig.length;
 
-    xszFfnLength = this.getSize() - offset;
-    xszFfn = new char[xszFfnLength];
+         offsetTmp = offset - offsetTmp;
+    xszFfnLength = this.getSize() - offsetTmp;
+         field_8_xszFfn = new char[xszFfnLength];
 
     for(int i = 0; i < xszFfnLength; i++)
     {
-      xszFfn[i] = (char)LittleEndian.getUnsignedByte(buf, offset);
+           field_8_xszFfn[i] = (char)LittleEndian.getUnsignedByte(buf, offset);
       offset += LittleEndian.BYTE_SIZE;
     }
 
 
   }
 
-  public int getField1_cbFfnM1()
+  public int getField_1_cbFfnM1()
+  {
+    return  field_1_cbFfnM1;
+  }
+
+  public byte getField_2()
+  {
+         return  field_2;
+  }
+
+  public short getField_3_wWeight()
+  {
+         return  field_3_wWeight;
+  }
+
+  public byte getField_4_chs()
+  {
+         return  field_4_chs;
+  }
+
+  public byte getField_5_ixchSzAlt()
+  {
+         return  field_5_ixchSzAlt;
+  }
+
+  public byte [] getField_6_panose()
+  {
+         return  field_6_panose;
+  }
+
+  public byte [] getField_7_fontSig()
+  {
+         return  field_7_fontSig;
+  }
+
+  public char [] getField_8_xszFfn()
   {
-    return  field1_cbFfnM1;
+         return  field_8_xszFfn;
   }
 
   public int getSize()
   {
-    return (field1_cbFfnM1 + 1);
+    return (field_1_cbFfnM1 + 1);
   }
 
   public char [] getMainFontName()
   {
-    char [] temp = new char[field5_ixchSzAlt];
-    System.arraycopy(xszFfn,0,temp,0,temp.length);
+    char [] temp = new char[field_5_ixchSzAlt];
+    System.arraycopy(field_8_xszFfn,0,temp,0,temp.length);
     return temp;
   }
 
   public char [] getAltFontName()
   {
-    char [] temp = new char[xszFfnLength - field5_ixchSzAlt];
-    System.arraycopy(xszFfn, field5_ixchSzAlt, temp, 0, temp.length);
+    char [] temp = new char[xszFfnLength - field_5_ixchSzAlt];
+    System.arraycopy(field_8_xszFfn, field_5_ixchSzAlt, temp, 0, temp.length);
     return temp;
   }
 
-  public void setField1_cbFfnM1(short field1_cbFfnM1)
+  public void setField_1_cbFfnM1(int field_1_cbFfnM1)
   {
-    this.field1_cbFfnM1 = field1_cbFfnM1;
+    this.field_1_cbFfnM1 = field_1_cbFfnM1;
   }
 
-  protected byte[] toByteArray()
+  // changed protected to public
+  public byte[] toByteArray()
   {
-     //return buf;
-     return null;
+    int offset = 0;
+    byte[] buf = new byte[this.getSize()];
+
+    buf[offset] = (byte)field_1_cbFfnM1;
+    offset += LittleEndian.BYTE_SIZE;
+    buf[offset] = field_2;
+    offset += LittleEndian.BYTE_SIZE;
+    LittleEndian.putShort(buf, offset, field_3_wWeight);
+    offset += LittleEndian.SHORT_SIZE;
+    buf[offset] = field_4_chs;
+    offset += LittleEndian.BYTE_SIZE;
+    buf[offset] = field_5_ixchSzAlt;
+    offset += LittleEndian.BYTE_SIZE;
+
+    System.arraycopy(field_6_panose,0,buf, offset,field_6_panose.length);
+    offset += field_6_panose.length;
+    System.arraycopy(field_7_fontSig,0,buf, offset, field_7_fontSig.length);
+    offset += field_7_fontSig.length;
+
+    for(int i = 0; i < field_8_xszFfn.length; i++)
+    {
+      buf[offset] = (byte)field_8_xszFfn[i];
+        offset += LittleEndian.BYTE_SIZE;
+    }
+
+      return buf;
+
+    }
+
+    public boolean equals(Object o)
+    {
+    boolean retVal = true;
+
+    if (((Ffn)o).getField_1_cbFfnM1() == field_1_cbFfnM1)
+    {
+      if(((Ffn)o).getField_2() == field_2)
+      {
+      if(((Ffn)o).getField_3_wWeight() == field_3_wWeight)
+      {
+        if(((Ffn)o).getField_4_chs() == field_4_chs)
+        {
+        if(((Ffn)o).getField_5_ixchSzAlt() == field_5_ixchSzAlt)
+        {
+          if(Arrays.equals(((Ffn)o).getField_6_panose(),field_6_panose))
+          {
+          if(Arrays.equals(((Ffn)o).getField_7_fontSig(),field_7_fontSig))
+          {
+                  if(!(Arrays.equals(((Ffn)o).getField_8_xszFfn(),field_8_xszFfn)))
+                    retVal = false;
+          }
+          else
+            retVal = false;
+          }
+          else
+          retVal = false;
+        }
+        else
+          retVal = false;
+        }
+        else
+        retVal = false;
+      }
+      else
+        retVal = false;
+      }
+      else
+      retVal = false;
+    }
+    else
+      retVal = false;
+
+    return retVal;
   }
 
 
 }
 
+
index b3ccca32bfaf3033e225f9eb87dd3323840a1b3d..ead8a4d367dc1999ce0d2164cf75beaa4478164a 100644 (file)
@@ -55,6 +55,9 @@
 
 package org.apache.poi.hwpf.model.hdftypes;
 
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.LittleEndian;
 
@@ -66,6 +69,7 @@ import org.apache.poi.hwpf.model.hdftypes.definitions.FIBAbstractType;
  * @author  andy
  */
 public class FileInformationBlock extends FIBAbstractType
+  implements Cloneable
 {
 
     /** Creates a new instance of FileInformationBlock */
@@ -74,5 +78,48 @@ public class FileInformationBlock extends FIBAbstractType
         fillFields(mainDocument, (short)0, (short)0);
     }
 
+    public void clearOffsetsSizes()
+    {
+      try
+      {
+        Field[] fields = FileInformationBlock.class.getSuperclass().getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+
+        for (int x = 0; x < fields.length; x++)
+        {
+          String name = fields[x].getName();
+          int index = name.indexOf('_');
+          if (index != -1)
+          {
+            int nextIndex = name.indexOf('_', index + 1);
+            if (nextIndex != -1)
+            {
+              // clear any field greater than field_53
+              if (Integer.parseInt(name.substring(index + 1, nextIndex)) > 53)
+              {
+                fields[x].setInt(this, 0);
+              }
+            }
+          }
+        }
+      }
+      catch (IllegalAccessException iae)
+      {
+        iae.printStackTrace();
+      }
+    }
+
+    public Object clone()
+    {
+      try
+      {
+        return super.clone();
+      }
+      catch (CloneNotSupportedException e)
+      {
+        e.printStackTrace();
+        return null;
+      }
+    }
 }
 
index 7384be129f2068d5569409aa1d684b5342ae2632..ad3dfdc5ef195f5bf8ec6a52cdd8b4c18bc09f55 100644 (file)
 
 package org.apache.poi.hwpf.model.hdftypes;
 
-import org.apache.poi.util.BitField;
+import java.io.IOException;
+import org.apache.poi.hwpf.model.io.HWPFFileSystem;
+import org.apache.poi.hwpf.model.io.HWPFOutputStream;
 import org.apache.poi.util.LittleEndian;
 
-
+/**
+ * FontTable or in MS terminology sttbfffn is a common data structure written in all
+ * Word files. The sttbfffn is an sttbf where each string is an FFN structure instead
+ * of pascal-style strings. An sttbf is a string Table stored in file. Thus sttbffn
+ * is like an Sttbf with an array of FFN structures that stores the font name strings
+ *
+ * @author Praveen Mathew
+ */
 public class FontTable
 {
-  private short exntdChar; // strings are extended character if = 0xFFFF
-  private short stringCount; // how many strings are included in the string table
-  private short extraDataSz; // size in bytes of the extra data
-
-  private int lcbSttbfffn; // count of bytes in sttbfffn
-  private boolean isExtndChar;
+  private short _stringCount;// how many strings are included in the string table
+  private short _extraDataSz;// size in bytes of the extra data
 
+  // added extra facilitator members
+  private int lcbSttbfffn;// count of bytes in sttbfffn
+  private int fcSttbfffn;// table stream offset for sttbfffn
 
   // FFN structure containing strings of font names
-  private Ffn     [] fontNames = null;
+  private Ffn[] _fontNames = null;
+
 
   public FontTable(byte[] buf, int offset, int lcbSttbfffn)
   {
     this.lcbSttbfffn = lcbSttbfffn;
+    this.fcSttbfffn = offset;
 
-    exntdChar = LittleEndian.getShort(buf, offset);
+    _stringCount = LittleEndian.getShort(buf, offset);
     offset += LittleEndian.SHORT_SIZE;
-    stringCount = LittleEndian.getShort(buf, offset);
+    _extraDataSz = LittleEndian.getShort(buf, offset);
     offset += LittleEndian.SHORT_SIZE;
-    extraDataSz = LittleEndian.getShort(buf, offset);
-    offset += LittleEndian.SHORT_SIZE;
-
-    if ((exntdChar & 0xFFFF) == 0xFFFF)
-    {
-      isExtndChar = true;
-    }
-    else
-    {
-      isExtndChar = false;
-    }
 
-    fontNames = new Ffn[stringCount]; //Ffn corresponds to a Pascal style String in STTBF.
+    _fontNames = new Ffn[_stringCount]; //Ffn corresponds to a Pascal style String in STTBF.
 
-    for(int i = 0;i<stringCount; i++)
+    for(int i = 0;i<_stringCount; i++)
     {
-      // some mistake in the fields we have chosen
-      if(offset >= this.getSize())
-      {
-        System.out.println("Total size of Sttbfn mismatched with calculated size");
-        break;
-      }
-
-      fontNames[i] = new Ffn(buf,offset);
-      offset += fontNames[i].getSize();
+      _fontNames[i] = new Ffn(buf,offset);
+      offset += _fontNames[i].getSize();
     }
   }
 
-  public boolean isExtndChar()
+  public short getStringCount()
   {
-    return  isExtndChar;
+    return  _stringCount;
   }
 
-  public short getStringCount()
+  public short getExtraDataSz()
+  {
+       return _extraDataSz;
+  }
+
+  public Ffn[] getFontNames()
   {
-    return  stringCount;
+       return _fontNames;
   }
 
   public int getSize()
@@ -124,31 +121,76 @@ public class FontTable
 
   public char [] getMainFont(int chpFtc )
   {
-    if(chpFtc >= stringCount)
+    if(chpFtc >= _stringCount)
     {
       System.out.println("Mismatch in chpFtc with stringCount");
       return null;
     }
 
-    return fontNames[chpFtc].getMainFontName();
+    return _fontNames[chpFtc].getMainFontName();
   }
 
   public char [] getAltFont(int chpFtc )
   {
-    if(chpFtc >= stringCount)
+    if(chpFtc >= _stringCount)
     {
       System.out.println("Mismatch in chpFtc with stringCount");
       return null;
     }
 
-    return fontNames[chpFtc].getAltFontName();
+    return _fontNames[chpFtc].getAltFontName();
   }
 
   public void setStringCount(short stringCount)
   {
-    this.stringCount = stringCount;
+    this._stringCount = stringCount;
   }
 
+  public void writeTo(HWPFFileSystem sys)
+         throws IOException
+  {
+         HWPFOutputStream tableStream = sys.getStream("1Table");
+
+         byte[] buf = new byte[LittleEndian.SHORT_SIZE];
+         LittleEndian.putShort(buf, _stringCount);
+         tableStream.write(buf);
+         LittleEndian.putShort(buf, _extraDataSz);
+         tableStream.write(buf);
+
+         for(int i = 0; i < _fontNames.length; i++)
+         {
+               tableStream.write(_fontNames[i].toByteArray());
+         }
+
+  }
+
+  public boolean equals(Object o)
+  {
+       boolean retVal = true;
+
+    if(((FontTable)o).getStringCount() == _stringCount)
+    {
+      if(((FontTable)o).getExtraDataSz() == _extraDataSz)
+      {
+        Ffn[] fontNamesNew = ((FontTable)o).getFontNames();
+        for(int i = 0;i<_stringCount; i++)
+        {
+          if(!(_fontNames[i].equals(fontNamesNew[i])))
+            retVal = false;
+        }
+      }
+      else
+        retVal = false;
+    }
+    else
+           retVal = false;
+
+
+         return retVal;
+  }
+
+
 
 }
 
+
index 18cb0d12ef2ad0638e49be815da15aceeac43bae..92b4698f5b8572f9a6c7a7b9d3952575806c81b1 100644 (file)
@@ -141,7 +141,7 @@ public class PAPBinTable
       int end = endingFc;
       if (overflow != null)
       {
-        end = ((PropertyNode)overflow.get(0)).getStart();
+        end = ((PropertyNode)overflow.get(0)).getStart() + fcMin;
       }
 
       byte[] intHolder = new byte[4];
index 4887c7dabd259debf45ed043550123bfebdbf412..f9ca0e3901d1ac4b1f8d6a9adc3458a03a49aefc 100644 (file)
@@ -58,6 +58,7 @@ import org.apache.poi.util.LittleEndian;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Arrays;
 
 /**
  * Represents a PAP FKP. The style properties for paragraph and character runs
@@ -152,6 +153,7 @@ public class PAPFormattedDiskPage extends FormattedDiskPage
       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;
@@ -159,16 +161,28 @@ public class PAPFormattedDiskPage extends FormattedDiskPage
       int index = 0;
       for (; index < size; index++)
       {
-        int grpprlLength = ((PAPX)_papxList.get(index)).getGrpprl().length;
+        byte[] grpprl = ((PAPX)_papxList.get(index)).getGrpprl();
+        int grpprlLength = grpprl.length;
 
         // check to see if we have enough room for an FC, a BX, and the grpprl
         // and the 1 byte size of the grpprl.
-        totalSize += (FC_SIZE + BX_SIZE + grpprlLength + 1);
+        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 -= (FC_SIZE + BX_SIZE + grpprlLength);
+          totalSize -= addition;
           break;
         }
 
@@ -181,6 +195,7 @@ public class PAPFormattedDiskPage extends FormattedDiskPage
         {
           totalSize += 2;
         }
+        lastGrpprl = grpprl;
       }
 
       // see if we couldn't fit some
@@ -197,14 +212,19 @@ public class PAPFormattedDiskPage extends FormattedDiskPage
       grpprlOffset =  511;
 
       PAPX papx = null;
+      lastGrpprl = new byte[0];
       for (int x = 0; x < index; x++)
       {
         papx = (PAPX)_papxList.get(x);
         byte[] phe = papx.getParagraphHeight().toByteArray();
         byte[] grpprl = papx.getGrpprl();
 
-        grpprlOffset -= (grpprl.length + (2 - grpprl.length % 2));
-        grpprlOffset -= (grpprlOffset % 2);
+        boolean same = Arrays.equals(lastGrpprl, grpprl);
+        if (!same)
+        {
+          grpprlOffset -= (grpprl.length + (2 - grpprl.length % 2));
+          grpprlOffset -= (grpprlOffset % 2);
+        }
         LittleEndian.putInt(buf, fcOffset, papx.getStart() + fcMin);
         buf[bxOffset] = (byte)(grpprlOffset/2);
         System.arraycopy(phe, 0, buf, bxOffset + 1, phe.length);
@@ -212,20 +232,25 @@ public class PAPFormattedDiskPage extends FormattedDiskPage
         // 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.
-        int copyOffset = grpprlOffset;
-        if ((grpprl.length % 2) > 0)
-        {
-          buf[copyOffset++] = (byte)((grpprl.length + 1)/2);
-        }
-        else
+        if (!same)
         {
-          buf[++copyOffset] = (byte)((grpprl.length)/2);
-          copyOffset++;
+          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;
         }
-        System.arraycopy(grpprl, 0, buf, copyOffset, grpprl.length);
 
         bxOffset += BX_SIZE;
         fcOffset += FC_SIZE;
+
       }
       // put the last papx's end in
       LittleEndian.putInt(buf, fcOffset, papx.getEnd() + fcMin);
index 483dd2ab66d9c3836b2efc3da67fe48041dd0688..a55c33a65bcdac5e7d90d1dff742eff87f7ecca1 100644 (file)
@@ -146,38 +146,42 @@ public class StyleDescription implements HDFType
 
       // the spec only refers to two possible upxs but it mentions
       // that more may be added in the future
-      int add = 0;
+      int varOffset = grupxStart;
       int numUPX = _numUPX.getValue(_infoShort3);
       for(int x = 0; x < numUPX; x++)
       {
-          int upxSize = LittleEndian.getShort(std, grupxStart + add);
+          int upxSize = LittleEndian.getShort(std, varOffset);
+          varOffset += LittleEndian.SHORT_SIZE;
           if(_styleTypeCode.getValue(_infoShort2) == PARAGRAPH_STYLE)
           {
               if(x == 0)
               {
-                  _istd = LittleEndian.getShort(std, grupxStart + add + 2);
+                  _istd = LittleEndian.getShort(std, varOffset);
+                  varOffset += LittleEndian.SHORT_SIZE;
                   int grrprlSize = upxSize - 2;
-                  _papx = new byte[upxSize];
-                  System.arraycopy(std, grupxStart + add + 4, _papx, 0, grrprlSize);
+                  _papx = new byte[grrprlSize];
+                  System.arraycopy(std, varOffset, _papx, 0, grrprlSize);
+                  varOffset += grrprlSize;
               }
               else if(x == 1)
               {
                   _chpx = new byte[upxSize];
-                  System.arraycopy(std, grupxStart + add + 2, _chpx, 0, upxSize);
+                  System.arraycopy(std, varOffset, _chpx, 0, upxSize);
+                  varOffset += upxSize;
               }
           }
           else if(_styleTypeCode.getValue(_infoShort2) == CHARACTER_STYLE && x == 0)
           {
               _chpx = new byte[upxSize];
-              System.arraycopy(std, grupxStart + add + 2, _chpx, 0, upxSize);
+              System.arraycopy(std, varOffset, _chpx, 0, upxSize);
           }
 
           // the upx will always start on a word boundary.
           if(upxSize % 2 == 1)
           {
-              ++upxSize;
+              ++varOffset;
           }
-          add += 2 + upxSize;
+
       }
 
 
@@ -259,7 +263,7 @@ public class StyleDescription implements HDFType
     //only worry about papx and chpx for upxs
     if(_styleTypeCode.getValue(_infoShort2) == PARAGRAPH_STYLE)
     {
-      LittleEndian.putShort(buf, offset, (short)_papx.length);
+      LittleEndian.putShort(buf, offset, (short)(_papx.length + 2));
       offset += LittleEndian.SHORT_SIZE;
       LittleEndian.putShort(buf, offset, (short)_istd);
       offset += LittleEndian.SHORT_SIZE;
index a4e7f8b44fb41fdff5507ab5a8069432018db654..a0c7cae13da44cf10dc2ea6f5457d1ce211e2236 100644 (file)
@@ -161,7 +161,7 @@ public class StyleSheet implements HDFType
     throws IOException
   {
     int offset = 0;
-    // add two bytes so we can prepend the styelsheet w/ its size
+    // add two bytes so we can prepend the stylesheet w/ its size
     byte[] buf = new byte[_stshiLength + 2];
     LittleEndian.putShort(buf, offset, (short)_stshiLength);
     offset += LittleEndian.SHORT_SIZE;
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestDocumentProperties.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestDocumentProperties.java
new file mode 100644 (file)
index 0000000..5e08844
--- /dev/null
@@ -0,0 +1,75 @@
+package org.apache.poi.hwpf.model.hdftypes;
+
+import junit.framework.*;
+import org.apache.poi.hwpf.*;
+
+import java.lang.reflect.*;
+import java.util.Arrays;
+
+public class TestDocumentProperties
+  extends TestCase
+{
+  private DocumentProperties _documentProperties = null;
+  private HWPFDocFixture _hWPFDocFixture;
+
+  public TestDocumentProperties(String name)
+  {
+    super(name);
+  }
+
+
+  public void testReadWrite()
+    throws Exception
+  {
+    int size = _documentProperties.getSize();
+    byte[] buf = new byte[size];
+
+    _documentProperties.serialize(buf, 0);
+
+    DocumentProperties newDocProperties =
+      new DocumentProperties(buf, 0);
+
+    Field[] fields = DocumentProperties.class.getSuperclass().getDeclaredFields();
+    AccessibleObject.setAccessible(fields, true);
+
+    for (int x = 0; x < fields.length; x++)
+    {
+      if (!fields[x].getType().isArray())
+      {
+        assertEquals(fields[x].get(_documentProperties),
+                     fields[x].get(newDocProperties));
+      }
+      else
+      {
+        byte[] buf1 = (byte[])fields[x].get(_documentProperties);
+        byte[] buf2 = (byte[])fields[x].get(newDocProperties);
+        Arrays.equals(buf1, buf2);
+      }
+    }
+
+  }
+
+  protected void setUp()
+    throws Exception
+  {
+    super.setUp();
+    /**@todo verify the constructors*/
+
+    _hWPFDocFixture = new HWPFDocFixture(this);
+
+    _hWPFDocFixture.setUp();
+
+    _documentProperties = new DocumentProperties(_hWPFDocFixture._tableStream, _hWPFDocFixture._fib.getFcDop());
+  }
+
+  protected void tearDown()
+    throws Exception
+  {
+    _documentProperties = null;
+    _hWPFDocFixture.tearDown();
+
+    _hWPFDocFixture = null;
+    super.tearDown();
+  }
+
+}
diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestFontTable.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/hdftypes/TestFontTable.java
new file mode 100644 (file)
index 0000000..e17e078
--- /dev/null
@@ -0,0 +1,121 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache POI" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache POI", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.poi.hwpf.model.hdftypes;
+
+import junit.framework.*;
+import org.apache.poi.hwpf.*;
+import org.apache.poi.hwpf.model.io.*;
+
+import java.io.*;
+import java.util.*;
+
+public class TestFontTable
+  extends TestCase
+{
+  private FontTable _fontTable = null;
+  private HWPFDocFixture _hWPFDocFixture;
+
+  public TestFontTable(String name)
+  {
+    super(name);
+  }
+
+  public void testReadWrite()
+    throws Exception
+  {
+    FileInformationBlock fib = _hWPFDocFixture._fib;
+    byte[] tableStream = _hWPFDocFixture._tableStream;
+
+    int fcSttbfffn = fib.getFcSttbfffn();
+    int lcbSttbfffn = fib.getLcbSttbfffn();
+
+    _fontTable = new FontTable(tableStream, fcSttbfffn, lcbSttbfffn);
+
+    HWPFFileSystem fileSys = new HWPFFileSystem();
+
+    _fontTable.writeTo(fileSys);
+    HWPFOutputStream  tableOut = fileSys.getStream("1Table");
+
+
+    byte[] newTableStream = tableOut.toByteArray();
+
+
+    FontTable newFontTable = new FontTable(newTableStream, 0, newTableStream.length);
+
+         assertTrue(_fontTable.equals(newFontTable));
+
+  }
+
+  protected void setUp()
+    throws Exception
+  {
+    super.setUp();
+    /**@todo verify the constructors*/
+    _hWPFDocFixture = new HWPFDocFixture(this);
+
+    _hWPFDocFixture.setUp();
+  }
+
+  protected void tearDown()
+    throws Exception
+  {
+    _hWPFDocFixture.tearDown();
+
+    _hWPFDocFixture = null;
+    super.tearDown();
+  }
+
+}
+