You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/10/26 08:18:19 UTC

svn commit: r707945 [1/4] - in /poi/branches/ooxml: ./ src/contrib/src/org/apache/poi/contrib/poibrowser/ src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/ src/java/org/apache/poi/hssf/record/constant/ src/java/org/apache/poi/hss...

Author: josh
Date: Sun Oct 26 00:18:17 2008
New Revision: 707945

URL: http://svn.apache.org/viewvc?rev=707945&view=rev
Log:
Merged revisions 707486,707519,707525,707534,707541-707542,707551,707585,707729,707778,707780,707802 via svnmerge from 
https://svn.apache.org/repos/asf/poi/trunk

........
  r707486 | josh | 2008-10-23 15:28:05 -0700 (Thu, 23 Oct 2008) | 1 line
  
  Converted Ptgs to use LittleEndianOutput
........
  r707519 | josh | 2008-10-23 17:58:49 -0700 (Thu, 23 Oct 2008) | 1 line
  
  Fix for unicode string bug in StyleRecord.  Improvements to WriteAccessRecord.
........
  r707525 | josh | 2008-10-23 19:08:47 -0700 (Thu, 23 Oct 2008) | 1 line
  
  Further conversion of Ptg classes to use LittleEndian input/output interfaces
........
  r707534 | josh | 2008-10-23 20:47:42 -0700 (Thu, 23 Oct 2008) | 1 line
  
  added LittleEndianByteArrayInputStream
........
  r707541 | josh | 2008-10-23 21:30:38 -0700 (Thu, 23 Oct 2008) | 1 line
  
  Removed String methods from LittleEndianInput
........
  r707542 | josh | 2008-10-23 21:40:37 -0700 (Thu, 23 Oct 2008) | 1 line
  
  removing unused code
........
  r707551 | josh | 2008-10-23 22:46:29 -0700 (Thu, 23 Oct 2008) | 1 line
  
  Simplification and code clean-up
........
  r707585 | josh | 2008-10-24 01:58:00 -0700 (Fri, 24 Oct 2008) | 1 line
  
  General clean-up in LittleEndian util class. (Some optimization, some obsolete code removal)
........
  r707729 | josh | 2008-10-24 12:25:11 -0700 (Fri, 24 Oct 2008) | 1 line
  
  Fixed test suite name
........
  r707778 | josh | 2008-10-24 16:13:44 -0700 (Fri, 24 Oct 2008) | 1 line
  
  Optimisation of RecordInputStream - removed intermediate 8K byte buffer.  Expected performance gain was not realised immediately, so LittleEndianInput stuff has been pushed down into DocumentInputStream to help.
........
  r707780 | josh | 2008-10-24 16:19:26 -0700 (Fri, 24 Oct 2008) | 1 line
  
  should have been submitted with c707778
........
  r707802 | josh | 2008-10-24 18:02:37 -0700 (Fri, 24 Oct 2008) | 1 line
  
  Further simplification to RecordInputStream.  Mostly regarding Strings, ContinueRecords and LittleEndianInput
........

Added:
    poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DataInputBlock.java
      - copied unchanged from r707802, poi/trunk/src/java/org/apache/poi/poifs/storage/DataInputBlock.java
    poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
      - copied unchanged from r707802, poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
    poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java
      - copied unchanged from r707802, poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestStyleRecord.java
      - copied unchanged from r707802, poi/trunk/src/testcases/org/apache/poi/hssf/record/TestStyleRecord.java
Removed:
    poi/branches/ooxml/src/java/org/apache/poi/util/DoubleList.java
    poi/branches/ooxml/src/java/org/apache/poi/util/DoubleList2d.java
    poi/branches/ooxml/src/testcases/org/apache/poi/util/TestDoubleList2d.java
Modified:
    poi/branches/ooxml/   (props changed)
    poi/branches/ooxml/src/contrib/src/org/apache/poi/contrib/poibrowser/TreeReaderListener.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Workbook.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CRNRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/StyleRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SubRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SupBookRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/UnicodeString.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtgBase.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/BoolPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/DeletedArea3DPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/DeletedRef3DPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ErrPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ExpPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/FuncPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/FuncVarPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/IntPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/IntersectionPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/MemAreaPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/MemErrPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/MemFuncPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/MissingArgPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/NamePtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/NameXPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/NumberPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Ptg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/RangePtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Ref2DPtgBase.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Ref3DPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/RefErrorPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/RefNPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/RefPtgBase.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/StringPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/TblPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/ValueOperatorPtg.java
    poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
    poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
    poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java
    poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/DocumentBlock.java
    poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java
    poi/branches/ooxml/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java   (props changed)
    poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java
    poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInput.java
    poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndianInputStream.java
    poi/branches/ooxml/src/java/org/apache/poi/util/StringUtil.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTextObjectBaseRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTextObjectRecord.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestcaseRecordInputStream.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/constant/TestConstantValueParser.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestAttrPtg.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java
    poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java
    poi/branches/ooxml/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java
    poi/branches/ooxml/src/testcases/org/apache/poi/poifs/storage/AllPOIFSStorageTests.java
    poi/branches/ooxml/src/testcases/org/apache/poi/poifs/storage/TestDocumentBlock.java
    poi/branches/ooxml/src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java
    poi/branches/ooxml/src/testcases/org/apache/poi/util/AllPOIUtilTests.java
    poi/branches/ooxml/src/testcases/org/apache/poi/util/TestLittleEndian.java
    poi/branches/ooxml/src/testcases/org/apache/poi/util/TestStringUtil.java

Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sun Oct 26 00:18:17 2008
@@ -1 +1 @@
-/poi/trunk:693591-694881,695264-695420,695621,695649-707481
+/poi/trunk:693591-694881,695264-695420,695621,695649-707802

Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Sun Oct 26 00:18:17 2008
@@ -1 +1 @@
-/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-707481
+/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-707802

Modified: poi/branches/ooxml/src/contrib/src/org/apache/poi/contrib/poibrowser/TreeReaderListener.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/contrib/src/org/apache/poi/contrib/poibrowser/TreeReaderListener.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/contrib/src/org/apache/poi/contrib/poibrowser/TreeReaderListener.java (original)
+++ poi/branches/ooxml/src/contrib/src/org/apache/poi/contrib/poibrowser/TreeReaderListener.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -15,11 +14,9 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-        
 
 package org.apache.poi.contrib.poibrowser;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -160,17 +157,7 @@
             throw new RuntimeException(t.getMessage());
         }
 
-        try
-        {
-            is.close();
-        }
-        catch (IOException ex)
-        {
-            System.err.println
-                ("Unexpected exception while closing " +
-                event.getName() + " in " + event.getPath().toString());
-            ex.printStackTrace(System.err);
-        }
+        is.close();
 
         final MutableTreeNode parentNode = getNode(d.path, filename, rootNode);
         final MutableTreeNode nameNode = new DefaultMutableTreeNode(d.name);

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Workbook.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Workbook.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Workbook.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/model/Workbook.java Sun Oct 26 00:18:17 2008
@@ -788,7 +788,7 @@
             if(r instanceof ExtendedFormatRecord) {
             } else if(r instanceof StyleRecord) {
                 StyleRecord sr = (StyleRecord)r;
-                if(sr.getIndex() == xfIndex) {
+                if(sr.getXFIndex() == xfIndex) {
                     return sr;
                 }
             } else {
@@ -806,7 +806,7 @@
         // Style records always follow after 
         //  the ExtendedFormat records
         StyleRecord newSR = new StyleRecord();
-        newSR.setIndex((short)xfIndex);
+        newSR.setXFIndex(xfIndex);
         
         // Find the spot
         int addAt = -1;
@@ -1782,45 +1782,44 @@
      * @see org.apache.poi.hssf.record.StyleRecord
      * @see org.apache.poi.hssf.record.Record
      */
-
     protected Record createStyle(int id) {   // we'll need multiple editions
         StyleRecord retval = new StyleRecord();
 
         switch (id) {
 
             case 0 :
-                retval.setIndex(( short ) 0xffff8010);
-                retval.setBuiltin(( byte ) 3);
+                retval.setXFIndex(0x010);
+                retval.setBuiltinStyle(3);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
 
             case 1 :
-                retval.setIndex(( short ) 0xffff8011);
-                retval.setBuiltin(( byte ) 6);
+                retval.setXFIndex(0x011);
+                retval.setBuiltinStyle(6);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
 
             case 2 :
-                retval.setIndex(( short ) 0xffff8012);
-                retval.setBuiltin(( byte ) 4);
+                retval.setXFIndex(0x012);
+                retval.setBuiltinStyle(4);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
 
             case 3 :
-                retval.setIndex(( short ) 0xffff8013);
-                retval.setBuiltin(( byte ) 7);
+                retval.setXFIndex(0x013);
+                retval.setBuiltinStyle(7);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
 
             case 4 :
-                retval.setIndex(( short ) 0xffff8000);
-                retval.setBuiltin(( byte ) 0);
+                retval.setXFIndex(0x000);
+                retval.setBuiltinStyle(0);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
 
             case 5 :
-                retval.setIndex(( short ) 0xffff8014);
-                retval.setBuiltin(( byte ) 5);
+                retval.setXFIndex(0x014);
+                retval.setBuiltinStyle(5);
                 retval.setOutlineStyleLevel(( byte ) 0xffffffff);
                 break;
         }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CRNRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CRNRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CRNRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CRNRecord.java Sun Oct 26 00:18:17 2008
@@ -18,17 +18,18 @@
 package org.apache.poi.hssf.record;
 
 import org.apache.poi.hssf.record.constant.ConstantValueParser;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
- * Title:       CRN  <P>
- * Description: This record stores the contents of an external cell or cell range <P>
- * REFERENCE:  5.23<P>
+ * Title:       CRN(0x005A) <p/>
+ * Description: This record stores the contents of an external cell or cell range <p/>
+ * REFERENCE:   OOO 5.23<p/>
  *
  * @author josh micich
  */
 public final class CRNRecord extends Record {
-	public final static short sid = 0x5A;
+	public final static short sid = 0x005A;
 
 	private int	 field_1_last_column_index;
 	private int	 field_2_first_column_index;
@@ -45,8 +46,8 @@
 
 
 	public CRNRecord(RecordInputStream in) {
-		field_1_last_column_index = in.readByte() & 0x00FF;
-		field_2_first_column_index = in.readByte() & 0x00FF;
+		field_1_last_column_index = in.readUByte();
+		field_2_first_column_index = in.readUByte();
 		field_3_row_index = in.readShort();
 		int nValues = field_1_last_column_index - field_2_first_column_index + 1;
 		field_4_constant_values = ConstantValueParser.parse(in, nValues);
@@ -68,13 +69,15 @@
 
 	public int serialize(int offset, byte [] data) {
 		int dataSize = getDataSize();
-		LittleEndian.putShort(data, 0 + offset, sid);
-		LittleEndian.putShort(data, 2 + offset, (short) dataSize);
-		LittleEndian.putByte(data, 4 + offset, field_1_last_column_index);
-		LittleEndian.putByte(data, 5 + offset, field_2_first_column_index);
-		LittleEndian.putShort(data, 6 + offset, (short) field_3_row_index);
-		ConstantValueParser.encode(data, 8 + offset, field_4_constant_values);
-		return getRecordSize();
+		int recSize = 4 + dataSize;
+		LittleEndianOutput out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
+		out.writeShort(sid);
+		out.writeShort(dataSize);
+		out.writeByte(field_1_last_column_index);
+		out.writeByte(field_2_first_column_index);
+		out.writeShort(field_3_row_index);
+		ConstantValueParser.encode(out, field_4_constant_values);
+		return recSize;
 	}
 
 	public int getRecordSize() {

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java Sun Oct 26 00:18:17 2008
@@ -27,6 +27,7 @@
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianInputStream;
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.StringUtil;
 
@@ -111,10 +112,10 @@
 				field_3_unicode_flag = ( in.readByte() & 0x01 ) != 0;
 				remaining -= LittleEndian.BYTE_SIZE;
 				if (field_3_unicode_flag) {
-					field_4_ole_classname = in.readUnicodeLEString(nChars);
+					field_4_ole_classname = StringUtil.readUnicodeLE(in, nChars);
 					stringByteCount = nChars * 2;
 				} else {
-					field_4_ole_classname = in.readCompressedUnicode(nChars);
+					field_4_ole_classname = StringUtil.readCompressedUnicode(in, nChars);
 					stringByteCount = nChars;
 				}
 			} else {
@@ -156,12 +157,7 @@
 	}
 
 	private static Ptg readRefPtg(byte[] formulaRawBytes) {
-		byte[] data = new byte[formulaRawBytes.length + 4];
-		LittleEndian.putUShort(data, 0, -5555);
-		LittleEndian.putUShort(data, 2, formulaRawBytes.length);
-		System.arraycopy(formulaRawBytes, 0, data, 4, formulaRawBytes.length);
-		RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
-		in.nextRecord();
+		LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes));
 		byte ptgSid = in.readByte();
 		switch(ptgSid) {
 			case AreaPtg.sid:   return new AreaPtg(in);

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java Sun Oct 26 00:18:17 2008
@@ -51,7 +51,7 @@
                     .append( "=" )
                     .append(ptg.toString() )
                     .append( "\n" )
-                    .append(ptg.toDebugString() )
+                    .append(ptg.toString())
                     .append( "\n" );
         }
     }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java Sun Oct 26 00:18:17 2008
@@ -17,12 +17,12 @@
 
 package org.apache.poi.hssf.record;
 
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianInput;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianInputStream;
 
 /**
  * Title:  Record Input Stream<P>
@@ -34,115 +34,147 @@
 	/** Maximum size of a single record (minus the 4 byte header) without a continue*/
 	public final static short MAX_RECORD_DATA_SIZE = 8224;
 	private static final int INVALID_SID_VALUE = -1;
+	/**
+	 * When {@link #_currentDataLength} has this value, it means that the previous BIFF record is
+	 * finished, the next sid has been properly read, but the data size field has not been read yet.
+	 */
+	private static final int DATA_LEN_NEEDS_TO_BE_READ = -1;
+	private static final byte[] EMPTY_BYTE_ARRAY = { };
 
-	private InputStream in;
-	private short currentSid;
-	private short currentLength = -1;
-	private short nextSid;
-
-	private final byte[] data = new byte[MAX_RECORD_DATA_SIZE];
-	private short recordOffset;
-	private long pos;
-
-  private boolean autoContinue = true;
-
-  public RecordInputStream(InputStream in) throws RecordFormatException {
-    this.in = in;
-    try {
-      nextSid = LittleEndian.readShort(in);
-      //Don't increment the pos just yet (technically we are at the start of
-      //the record stream until nextRecord is called).
-    } catch (IOException ex) {
-      throw new RecordFormatException("Error reading bytes", ex);
-    }
-  }
+	/** {@link LittleEndianInput} facet of the wrapped {@link InputStream} */
+	private final LittleEndianInput _le;
+	/** the record identifier of the BIFF record currently being read */
+	private int _currentSid;
+	/** 
+	 * Length of the data section of the current BIFF record (always 4 less than the total record size).
+	 * When uninitialised, this field is set to {@link #DATA_LEN_NEEDS_TO_BE_READ}.
+	 */
+	private int _currentDataLength;
+	/** 
+	 * The BIFF record identifier for the next record is read when just as the current record
+	 * is finished.
+	 * This field is only really valid during the time that ({@link #_currentDataLength} == 
+	 * {@link #DATA_LEN_NEEDS_TO_BE_READ}).  At most other times its value is not really the 
+	 * 'sid of the next record'.  Wwhile mid-record, this field coincidentally holds the sid 
+	 * of the current record.
+	 */
+	private int _nextSid;
+	/** 
+	 * index within the data section of the current BIFF record
+	 */
+	private int _currentDataOffset;
+
+	public RecordInputStream(InputStream in) throws RecordFormatException {
+		if (in instanceof LittleEndianInput) {
+			// accessing directly is an optimisation
+			_le = (LittleEndianInput) in;
+		} else {
+			// less optimal, but should work OK just the same. Often occurs in junit tests.
+			_le = new LittleEndianInputStream(in);
+		}
+		_nextSid = readNextSid();
+	}
+	
+	/**
+	 * @returns the number of bytes available in the current BIFF record
+	 * @see #remaining()
+	 */
+	public int available() {
+		return remaining();
+	}
 
-	/** This method will read a byte from the current record*/
 	public int read() {
 		checkRecordPosition(LittleEndian.BYTE_SIZE);
-
-		byte result = data[recordOffset];
-		recordOffset += LittleEndian.BYTE_SIZE;
-		pos += LittleEndian.BYTE_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.BYTE_SIZE;
+		return _le.readUByte();
+	}
+	public int read(byte[] b, int off, int len) {
+		int limit = Math.min(len, remaining());
+		if (limit == 0) {
+			return 0;
+		}
+		readFully(b, off,limit);
+		return limit;
 	}
 
-  public short getSid() {
-    return currentSid;
-  }
-
-  public short getLength() {
-    return currentLength;
-  }
-
-  public short getRecordOffset() {
-    return recordOffset;
-  }
-
-  public long getPos() {
-    return pos;
-  }
-
-  public boolean hasNextRecord() {
-    return nextSid != INVALID_SID_VALUE;
-  }
+	public short getSid() {
+		return (short) _currentSid;
+	}
 
-  /** Moves to the next record in the stream.
-   *
-   * <i>Note: The auto continue flag is reset to true</i>
-   */
-  public void nextRecord() throws RecordFormatException {
-    if ((currentLength != -1) && (currentLength != recordOffset)) {
-      System.out.println("WARN. Unread "+remaining()+" bytes of record 0x"+Integer.toHexString(currentSid));
-    }
-    currentSid = nextSid;
-    pos += LittleEndian.SHORT_SIZE;
-    autoContinue = true;
-    try {
-      recordOffset = 0;
-      currentLength = LittleEndian.readShort(in);
-      if (currentLength > MAX_RECORD_DATA_SIZE)
-        throw new RecordFormatException("The content of an excel record cannot exceed "+MAX_RECORD_DATA_SIZE+" bytes");
-      pos += LittleEndian.SHORT_SIZE;
-      in.read(data, 0, currentLength);
-
-      //Read the Sid of the next record
-      if (in.available() < EOFRecord.ENCODED_SIZE) {
-          if (in.available() > 0) {
-              // some scrap left over?
-              // ex45582-22397.xls has one extra byte after the last record
-              // Excel reads that file OK
-          }
-          nextSid = INVALID_SID_VALUE;
-      } else {
-          nextSid = LittleEndian.readShort(in);
-          if (nextSid == INVALID_SID_VALUE) {
-              throw new RecordFormatException("Found sid " + nextSid + " after record with sid 0x"
-                      + Integer.toHexString(currentSid).toUpperCase());
-          }
-      }
-    } catch (IOException ex) {
-      throw new RecordFormatException("Error reading bytes", ex);
-    }
-  }
+	/**
+	 * Note - this method is expected to be called only when completed reading the current BIFF record.
+	 * Calling this before reaching the end of the current record will cause all remaining data to be
+	 * discarded
+	 */
+	public boolean hasNextRecord() {
+		if (_currentDataLength != -1 && _currentDataLength != _currentDataOffset) {
+			System.out.println("WARN. Unread "+remaining()+" bytes of record 0x"+Integer.toHexString(_currentSid));
+			// discard unread data
+			while (_currentDataOffset < _currentDataLength) {
+				readByte();
+			}
+		}
+		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
+			_nextSid = readNextSid();
+		}
+		return _nextSid != INVALID_SID_VALUE;
+	}
 
-  public void setAutoContinue(boolean enable) {
-    this.autoContinue = enable;
-  }
+	/**
+	 * 
+	 * @return the sid of the next record or {@link #INVALID_SID_VALUE} if at end of stream
+	 */
+	private int readNextSid() {
+		int nAvailable  = _le.available();
+		if (nAvailable < EOFRecord.ENCODED_SIZE) {
+			if (nAvailable > 0) {
+				// some scrap left over?
+				// ex45582-22397.xls has one extra byte after the last record
+				// Excel reads that file OK
+			}
+			return INVALID_SID_VALUE;
+		}
+		int result = _le.readUShort();
+		if (result == INVALID_SID_VALUE) {
+			throw new RecordFormatException("Found invalid sid (" + result + ")");
+		}
+		_currentDataLength = DATA_LEN_NEEDS_TO_BE_READ;
+		return result;
+	}
 
-  public boolean getAutoContinue() {
-    return autoContinue;
-  }
+	/** Moves to the next record in the stream.
+	 *
+	 * <i>Note: The auto continue flag is reset to true</i>
+	 */
+	public void nextRecord() throws RecordFormatException {
+		if (_nextSid == INVALID_SID_VALUE) {
+			throw new IllegalStateException("EOF - next record not available");
+		}
+		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
+			throw new IllegalStateException("Cannot call nextRecord() without checking hasNextRecord() first");
+		}
+		_currentSid = _nextSid;
+		_currentDataOffset = 0;
+		_currentDataLength = _le.readUShort();
+		if (_currentDataLength > MAX_RECORD_DATA_SIZE) {
+			throw new RecordFormatException("The content of an excel record cannot exceed "
+					+ MAX_RECORD_DATA_SIZE + " bytes");
+		}
+	}
 
 	private void checkRecordPosition(int requiredByteCount) {
 
-		if (remaining() < requiredByteCount) {
-			if (isContinueNext() && autoContinue) {
-				nextRecord();
-			} else {
-			   throw new ArrayIndexOutOfBoundsException();
-			}
+		int nAvailable = remaining();
+		if (nAvailable >= requiredByteCount) {
+			// all OK
+			return;
 		}
+		if (nAvailable == 0 && isContinueNext()) {
+			nextRecord();
+			return;
+		}
+		throw new RecordFormatException("Not enough data (" + nAvailable 
+				+ ") to read requested (" + requiredByteCount +") bytes");
 	}
 
 	/**
@@ -150,11 +182,8 @@
 	 */
 	public byte readByte() {
 		checkRecordPosition(LittleEndian.BYTE_SIZE);
-
-		byte result = data[recordOffset];
-		recordOffset += LittleEndian.BYTE_SIZE;
-		pos += LittleEndian.BYTE_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.BYTE_SIZE;
+		return _le.readByte();
 	}
 
 	/**
@@ -162,29 +191,20 @@
 	 */
 	public short readShort() {
 		checkRecordPosition(LittleEndian.SHORT_SIZE);
-
-		short result = LittleEndian.getShort(data, recordOffset);
-		recordOffset += LittleEndian.SHORT_SIZE;
-		pos += LittleEndian.SHORT_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.SHORT_SIZE;
+		return _le.readShort();
 	}
 
 	public int readInt() {
 		checkRecordPosition(LittleEndian.INT_SIZE);
-
-		int result = LittleEndian.getInt(data, recordOffset);
-		recordOffset += LittleEndian.INT_SIZE;
-		pos += LittleEndian.INT_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.INT_SIZE;
+		return _le.readInt();
 	}
 
 	public long readLong() {
 		checkRecordPosition(LittleEndian.LONG_SIZE);
-
-		long result = LittleEndian.getLong(data, recordOffset);
-		recordOffset += LittleEndian.LONG_SIZE;
-		pos += LittleEndian.LONG_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.LONG_SIZE;
+		return _le.readLong();
 	}
 
 	/**
@@ -200,22 +220,18 @@
 	 */
 	public int readUShort() {
 		checkRecordPosition(LittleEndian.SHORT_SIZE);
-
-		int result = LittleEndian.getUShort(data, recordOffset);
-		recordOffset += LittleEndian.SHORT_SIZE;
-		pos += LittleEndian.SHORT_SIZE;
-		return result;
+		_currentDataOffset += LittleEndian.SHORT_SIZE;
+		return _le.readUShort();
 	}
 
 	public double readDouble() {
 		checkRecordPosition(LittleEndian.DOUBLE_SIZE);
-		long valueLongBits = LittleEndian.getLong(data, recordOffset);
+		_currentDataOffset += LittleEndian.DOUBLE_SIZE;
+		long valueLongBits = _le.readLong();
 		double result = Double.longBitsToDouble(valueLongBits);
 		if (Double.isNaN(result)) {
 			throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN
 		}
-		recordOffset += LittleEndian.DOUBLE_SIZE;
-		pos += LittleEndian.DOUBLE_SIZE;
 		return result;
 	}
 	public void readFully(byte[] buf) {
@@ -224,9 +240,8 @@
 
 	public void readFully(byte[] buf, int off, int len) {
 		checkRecordPosition(len);
-		System.arraycopy(data, recordOffset, buf, off, len);
-		recordOffset+=len;
-		pos+=len;
+		_le.readFully(buf, off, len);
+		_currentDataOffset+=len;
 	}
 
 	public String readString() {
@@ -315,18 +330,19 @@
     return new UnicodeString(this);
   }
 
-  /** Returns the remaining bytes for the current record.
-   *
-   * @return The remaining bytes of the current record.
-   */
-  public byte[] readRemainder() {
-    int size = remaining();
-    byte[] result = new byte[size];
-    System.arraycopy(data, recordOffset, result, 0, size);
-    recordOffset += size;
-    pos += size;
-    return result;
-  }
+	/** Returns the remaining bytes for the current record.
+	 *
+	  * @return The remaining bytes of the current record.
+	  */
+	public byte[] readRemainder() {
+		int size = remaining();
+		if (size ==0) {
+			return EMPTY_BYTE_ARRAY;
+		}
+		byte[] result = new byte[size];
+		readFully(result);
+		return result;
+	}
 
   /** Reads all byte data for the current record, including any
    *  that overlaps into any following continue records.
@@ -350,19 +366,34 @@
     return out.toByteArray();
   }
 
-  /** The remaining number of bytes in the <i>current</i> record.
-   *
-   * @return The number of bytes remaining in the current record
-   */
-  public int remaining() {
-    return (currentLength - recordOffset);
-  }
+	/** The remaining number of bytes in the <i>current</i> record.
+	 *
+	 * @return The number of bytes remaining in the current record
+	 */
+	public int remaining() {
+		if (_currentDataLength == DATA_LEN_NEEDS_TO_BE_READ) {
+			// already read sid of next record. so current one is finished
+			return 0;
+		}
+		return _currentDataLength - _currentDataOffset;
+	}
 
-  /** Returns true iif a Continue record is next in the excel stream
-   *
-   * @return True when a ContinueRecord is next.
-   */
-  public boolean isContinueNext() {
-    return (nextSid == ContinueRecord.sid);
-  }
+	/**
+	 *
+	 * @return <code>true</code> when a {@link ContinueRecord} is next.
+	 */
+	private boolean isContinueNext() {
+		if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ && _currentDataOffset != _currentDataLength) {
+			throw new IllegalStateException("Should never be called before end of current record");
+		}
+		if (!hasNextRecord()) {
+			return false;
+		}
+		// At what point are records continued?
+		//  - Often from within the char data of long strings (caller is within readStringCommon()).
+		//  - From UnicodeString construction (many different points - call via checkRecordPosition)
+		//  - During TextObjectRecord construction (just before the text, perhaps within the text, 
+		//    and before the formatting run data)
+		return _nextSid == ContinueRecord.sid;
+	}
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/StyleRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/StyleRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/StyleRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/StyleRecord.java Sun Oct 26 00:18:17 2008
@@ -19,332 +19,181 @@
 
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
+import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 
 /**
- * Title:        Style Record<P>
+ * Title:        Style Record (0x0293)<p/>
  * Description:  Describes a builtin to the gui or user defined style<P>
  * REFERENCE:  PG 390 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
  * @author Andrew C. Oliver (acoliver at apache dot org)
  * @author aviks : string fixes for UserDefined Style
- * @version 2.0-pre
  */
 public final class StyleRecord extends Record {
-    public final static short sid = 0x0293;
+	public final static short sid = 0x0293;
 
-    private static final BitField fHighByte = BitFieldFactory.getInstance(0x01);
+	private static final BitField is16BitUnicodeFlag = BitFieldFactory.getInstance(0x01);
 
-    public final static short STYLE_USER_DEFINED = 0;
-    public final static short STYLE_BUILT_IN     = 1;
+	private static final BitField styleIndexMask = BitFieldFactory.getInstance(0x0FFF);
+	private static final BitField isBuiltinFlag  = BitFieldFactory.getInstance(0x8000);
 
-    // shared by both user defined and builtin styles
-    private short             field_1_xf_index;   // TODO: bitfield candidate
-
-    // only for built in styles
-    private byte              field_2_builtin_style;
-    private byte              field_3_outline_style_level;
-
-    // only for user defined styles
-    private short              field_2_name_length; //OO doc says 16 bit length, so we believe
-    private byte               field_3_string_options;
-    private String             field_4_name;
-
-    public StyleRecord()
-    {
-    }
-
-    public StyleRecord(RecordInputStream in)
-    {
-        field_1_xf_index = in.readShort();
-        if (getType() == STYLE_BUILT_IN)
-        {
-            field_2_builtin_style       = in.readByte();
-            field_3_outline_style_level = in.readByte();
-        }
-        else if (getType() == STYLE_USER_DEFINED)
-        {
-            field_2_name_length = in.readShort();
-            
-            // Some files from Crystal Reports lack
-            //  the remaining fields, which is naughty
-            if(in.remaining() > 0) {
-	            field_3_string_options = in.readByte();
-	            
-	            byte[] string = in.readRemainder();
-	            if (fHighByte.isSet(field_3_string_options)) {
-	                field_4_name= StringUtil.getFromUnicodeBE(string, 0, field_2_name_length);
-	            } else {
-	                field_4_name=StringUtil.getFromCompressedUnicode(string, 0, field_2_name_length);
-	            }
-            }
-        }
-
-        // todo sanity check exception to make sure we're one or the other
-    }
-
-    /**
-     * set the entire index field (including the type) (see bit setters that reference this method)
-     *  @param index  bitmask
-     */
-
-    public void setIndex(short index)
-    {
-        field_1_xf_index = index;
-    }
-
-    // bitfields for field 1
-
-    /**
-     * set the type of the style (builtin or user-defined)
-     * @see #STYLE_USER_DEFINED
-     * @see #STYLE_BUILT_IN
-     * @param type of style (userdefined/builtin)
-     * @see #setIndex(short)
-     */
-
-    public void setType(short type)
-    {
-        field_1_xf_index = setField(field_1_xf_index, type, 0x8000, 15);
-    }
-
-    /**
-     * set the actual index of the style extended format record
-     * @see #setIndex(short)
-     * @param index of the xf record
-     */
-
-    public void setXFIndex(short index)
-    {
-        field_1_xf_index = setField(field_1_xf_index, index, 0x1FFF, 0);
-    }
-
-    // end bitfields
-    // only for user defined records
-
-    /**
-     * if this is a user defined record set the length of the style name
-     * @param length of the style's name
-     * @see #setName(String)
-     */
-
-    public void setNameLength(byte length)
-    {
-        field_2_name_length = length;
-    }
-
-    /**
-     * set the style's name
-     * @param name of the style
-     * @see #setNameLength(byte)
-     */
-
-    public void setName(String name)
-    {
-        field_4_name = name;
-        
-        // Fix up the length
-        field_2_name_length = (short)name.length();
-        //TODO set name string options
-    }
-
-    // end user defined
-    // only for buildin records
-
-    /**
-     * if this is a builtin style set teh number of the built in style
-     * @param  builtin style number (0-7)
-     *
-     */
-
-    public void setBuiltin(byte builtin)
-    {
-        field_2_builtin_style = builtin;
-    }
-
-    /**
-     * set the row or column level of the style (if builtin 1||2)
-     */
-
-    public void setOutlineStyleLevel(byte level)
-    {
-        field_3_outline_style_level = level;
-    }
-
-    // end builtin records
-    // field 1
-
-    /**
-     * get the entire index field (including the type) (see bit getters that reference this method)
-     *  @return bitmask
-     */
-
-    public short getIndex()
-    {
-        return field_1_xf_index;
-    }
-
-    // bitfields for field 1
-
-    /**
-     * get the type of the style (builtin or user-defined)
-     * @see #STYLE_USER_DEFINED
-     * @see #STYLE_BUILT_IN
-     * @return type of style (userdefined/builtin)
-     * @see #getIndex()
-     */
-
-    public short getType()
-    {
-        return ( short ) ((field_1_xf_index & 0x8000) >> 15);
-    }
-
-    /**
-     * get the actual index of the style extended format record
-     * @see #getIndex()
-     * @return index of the xf record
-     */
-
-    public short getXFIndex()
-    {
-        return ( short ) (field_1_xf_index & 0x1FFF);
-    }
-
-    // end bitfields
-    // only for user defined records
-
-    /**
-     * if this is a user defined record get the length of the style name
-     * @return length of the style's name
-     * @see #getName()
-     */
-
-    public short getNameLength()
-    {
-        return field_2_name_length;
-    }
-
-    /**
-     * get the style's name
-     * @return name of the style
-     * @see #getNameLength()
-     */
-
-    public String getName()
-    {
-        return field_4_name;
-    }
-
-    // end user defined
-    // only for buildin records
-
-    /**
-     * if this is a builtin style get the number of the built in style
-     * @return  builtin style number (0-7)
-     *
-     */
-
-    public byte getBuiltin()
-    {
-        return field_2_builtin_style;
-    }
-
-    /**
-     * get the row or column level of the style (if builtin 1||2)
-     */
-
-    public byte getOutlineStyleLevel()
-    {
-        return field_3_outline_style_level;
-    }
-
-    // end builtin records
-    public String toString()
-    {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[STYLE]\n");
-        buffer.append("    .xf_index_raw    = ")
-            .append(Integer.toHexString(getIndex())).append("\n");
-        buffer.append("        .type        = ")
-            .append(Integer.toHexString(getType())).append("\n");
-        buffer.append("        .xf_index    = ")
-            .append(Integer.toHexString(getXFIndex())).append("\n");
-        if (getType() == STYLE_BUILT_IN)
-        {
-            buffer.append("    .builtin_style   = ")
-                .append(Integer.toHexString(getBuiltin())).append("\n");
-            buffer.append("    .outline_level   = ")
-                .append(Integer.toHexString(getOutlineStyleLevel()))
-                .append("\n");
-        }
-        else if (getType() == STYLE_USER_DEFINED)
-        {
-            buffer.append("    .name_length     = ")
-                .append(Integer.toHexString(getNameLength())).append("\n");
-            buffer.append("    .name            = ").append(getName())
-                .append("\n");
-        }
-        buffer.append("[/STYLE]\n");
-        return buffer.toString();
-    }
-
-    private short setField(int fieldValue, int new_value, int mask,
-                           int shiftLeft)
-    {
-        return ( short ) ((fieldValue & ~mask)
-                          | ((new_value << shiftLeft) & mask));
-    }
-
-    public int serialize(int offset, byte [] data)
-    {
-        LittleEndian.putShort(data, 0 + offset, sid);
-        if (getType() == STYLE_BUILT_IN)
-        {
-            LittleEndian.putShort(data, 2 + offset,
-                                  (( short ) 0x04));   // 4 bytes (8 total)
-        }
-        else
-        {
-            LittleEndian.putShort(data, 2 + offset,
-                                  (( short ) (getRecordSize()-4)));
-        }
-        LittleEndian.putShort(data, 4 + offset, getIndex());
-        if (getType() == STYLE_BUILT_IN)
-        {
-            data[ 6 + offset ] = getBuiltin();
-            data[ 7 + offset ] = getOutlineStyleLevel();
-        }
-        else
-        {
-            LittleEndian.putShort(data, 6 + offset , getNameLength());
-            data[8+offset]=this.field_3_string_options;
-            StringUtil.putCompressedUnicode(getName(), data, 9 + offset);
-        }
-        return getRecordSize();
-    }
-
-    public int getRecordSize()
-    {
-        int retval;
-
-        if (getType() == STYLE_BUILT_IN)
-        {
-            retval = 8;
-        }
-        else
-        {
-             if (fHighByte.isSet(field_3_string_options))  {
-                 retval= 9+2*getNameLength();
-             }else {
-                retval = 9 + getNameLength();
-             }
-        }
-        return retval;
-    }
-
-    public short getSid()
-    {
-        return sid;
-    }
+	/** shared by both user defined and built-in styles */
+	private int field_1_xf_index;
+
+	// only for built in styles
+	private int field_2_builtin_style;
+	private int field_3_outline_style_level;
+
+	// only for user defined styles
+	private int field_3_string_options;
+	private String field_4_name;
+
+	/**
+	 * creates a new style record, initially set to 'built-in'
+	 */
+	public StyleRecord() {
+		field_1_xf_index = isBuiltinFlag.set(field_1_xf_index);
+	}
+
+	public StyleRecord(RecordInputStream in) {
+		field_1_xf_index = in.readShort();
+		if (isBuiltin()) {
+			field_2_builtin_style	   = in.readByte();
+			field_3_outline_style_level = in.readByte();
+		} else {
+			int field_2_name_length = in.readShort();
+			
+			if(in.remaining() < 1) {
+				// Some files from Crystal Reports lack the is16BitUnicode byte
+				//  the remaining fields, which is naughty
+				if (field_2_name_length != 0) {
+					throw new RecordFormatException("Ran out of data reading style record");
+				}
+				// guess this is OK if the string length is zero
+				field_4_name = "";
+			} else {
+				
+				int is16BitUnicode = in.readByte();
+				if (is16BitUnicodeFlag.isSet(is16BitUnicode)) {
+					field_4_name = StringUtil.readUnicodeLE(in, field_2_name_length);
+				} else {
+					field_4_name = StringUtil.readCompressedUnicode(in, field_2_name_length);
+				}
+			}
+		}
+	}
+
+	/**
+	 * set the actual index of the style extended format record
+	 * @param xfIndex of the xf record
+	 */
+	public void setXFIndex(int xfIndex) {
+		field_1_xf_index = styleIndexMask.setValue(field_1_xf_index, xfIndex);
+	}
+
+	/**
+	 * get the actual index of the style extended format record
+	 * @see #getIndex()
+	 * @return index of the xf record
+	 */
+	public int getXFIndex() {
+		return styleIndexMask.getValue(field_1_xf_index);
+	}
+
+	/**
+	 * set the style's name
+	 * @param name of the style
+	 */
+	public void setName(String name) {
+		field_4_name = name;
+		field_3_string_options = StringUtil.hasMultibyte(name) ? 0x01 : 0x00;
+		field_1_xf_index = isBuiltinFlag.clear(field_1_xf_index);
+	}
+
+	/**
+	 * if this is a builtin style set the number of the built in style
+	 * @param  builtinStyleId style number (0-7)
+	 *
+	 */
+	public void setBuiltinStyle(int builtinStyleId) {
+		field_1_xf_index = isBuiltinFlag.set(field_1_xf_index);
+		field_2_builtin_style = builtinStyleId;
+	}
+
+	/**
+	 * set the row or column level of the style (if builtin 1||2)
+	 */
+	public void setOutlineStyleLevel(int level) {
+		field_3_outline_style_level = level & 0x00FF;
+	}
+
+	public boolean isBuiltin(){
+		return isBuiltinFlag.isSet(field_1_xf_index);
+	}
+
+	/**
+	 * get the style's name
+	 * @return name of the style
+	 */
+	public String getName() {
+		return field_4_name;
+	}
+
+	public String toString() {
+		StringBuffer sb = new StringBuffer();
+
+		sb.append("[STYLE]\n");
+		sb.append("    .xf_index_raw =").append(HexDump.shortToHex(field_1_xf_index)).append("\n");
+		sb.append("        .type     =").append(isBuiltin() ? "built-in" : "user-defined").append("\n");
+		sb.append("        .xf_index =").append(HexDump.shortToHex(getXFIndex())).append("\n");
+		if (isBuiltin()){
+			sb.append("    .builtin_style=").append(HexDump.byteToHex(field_2_builtin_style)).append("\n");
+			sb.append("    .outline_level=").append(HexDump.byteToHex(field_3_outline_style_level)).append("\n");
+		} else {
+			 sb.append("    .name        =").append(getName()).append("\n");
+		}
+		sb.append("[/STYLE]\n");
+		return sb.toString();
+	}
+
+	
+	private int getDataSize() {
+		if (isBuiltin()) {
+			return 4; // short, byte, byte
+		}
+		int size = 2 + 3; // short
+		if (is16BitUnicodeFlag.isSet(field_3_string_options))  {
+			size += 2 * field_4_name.length();
+		} else {
+			size += field_4_name.length();
+		}
+		return size;
+	}
+
+	public int serialize(int offset, byte [] data) {
+		int dataSize = getDataSize();
+		LittleEndian.putShort(data, 0 + offset, sid);
+		LittleEndian.putUShort(data, 2 + offset, dataSize);
+		
+		LittleEndian.putUShort(data, 4 + offset, field_1_xf_index);
+		if (isBuiltin()) {
+			LittleEndian.putByte(data, 6 + offset, field_2_builtin_style);
+			LittleEndian.putByte(data, 7 + offset, field_3_outline_style_level);
+		} else {
+			LittleEndian.putUShort(data, 6 + offset, field_4_name.length());
+			LittleEndian.putByte(data, 8 + offset, field_3_string_options);
+			StringUtil.putCompressedUnicode(getName(), data, 9 + offset);
+		}
+		return 4+dataSize;
+	}
+
+	public int getRecordSize() {
+		return 4 + getDataSize();
+	}
+
+	public short getSid()
+	{
+		return sid;
+	}
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SubRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SubRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SubRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SubRecord.java Sun Oct 26 00:18:17 2008
@@ -27,6 +27,7 @@
 import org.apache.poi.hssf.record.formula.RefPtg;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
 import org.apache.poi.util.LittleEndianInput;
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.LittleEndianOutputStream;
@@ -209,17 +210,12 @@
 			out.writeShort(_unknownShort13);
 		}
 		private static Ptg readRefPtg(byte[] formulaRawBytes) {
-			byte[] data = new byte[formulaRawBytes.length + 4];
-			LittleEndian.putUShort(data, 0, -5555);
-			LittleEndian.putUShort(data, 2, formulaRawBytes.length);
-			System.arraycopy(formulaRawBytes, 0, data, 4, formulaRawBytes.length);
-			RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
-			in.nextRecord();
-		   	byte ptgSid = in.readByte();
+			LittleEndianInput in = new LittleEndianByteArrayInputStream(formulaRawBytes);
+			byte ptgSid = in.readByte();
 			switch(ptgSid) {
 				case AreaPtg.sid:   return new AreaPtg(in);
 				case Area3DPtg.sid: return new Area3DPtg(in);
-				case RefPtg.sid:	return new RefPtg(in);
+				case RefPtg.sid:    return new RefPtg(in);
 				case Ref3DPtg.sid:  return new Ref3DPtg(in);
 			}
 			return null;

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SupBookRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SupBookRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SupBookRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/SupBookRecord.java Sun Oct 26 00:18:17 2008
@@ -84,9 +84,11 @@
      * @param offset of the record's data (provided a big array of the file)
      */
     public SupBookRecord(RecordInputStream in) {
+    	int recLen = in.remaining();
+    	
         field_1_number_of_sheets = in.readShort();
         
-        if(in.getLength() > SMALL_RECORD_SIZE) {
+        if(recLen > SMALL_RECORD_SIZE) {
             // 5.38.1 External References
             _isAddInFunctions = false;
 

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java Sun Oct 26 00:18:17 2008
@@ -25,6 +25,8 @@
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
  * The TXO record (0x01B6) is used to define the properties of a text box. It is
@@ -129,13 +131,7 @@
 		_text = new HSSFRichTextString(text);
 
 		if (field_7_formattingDataLength > 0) {
-			if (in.isContinueNext() && in.remaining() == 0) {
-				in.nextRecord();
-				processFontRuns(in, _text, field_7_formattingDataLength);
-			} else {
-				throw new RecordFormatException(
-						"Expected Continue Record to hold font runs for TextObjectRecord");
-			}
+			processFontRuns(in, _text, field_7_formattingDataLength);
 		}
 	}
 
@@ -154,10 +150,6 @@
 			throw new RecordFormatException("Bad format run data length " + formattingRunDataLength
 					+ ")");
 		}
-		if (in.remaining() != formattingRunDataLength) {
-			throw new RecordFormatException("Expected " + formattingRunDataLength
-					+ " bytes but got " + in.remaining());
-		}
 		int nRuns = formattingRunDataLength / FORMAT_RUN_ENCODED_SIZE;
 		for (int i = 0; i < nRuns; i++) {
 			short index = in.readShort();
@@ -190,36 +182,31 @@
 
 	private int serializeTXORecord(int offset, byte[] data) {
 		int dataSize = getDataSize();
+		int recSize = dataSize+4;
+		LittleEndianOutput out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
 		
-		LittleEndian.putUShort(data, 0 + offset, TextObjectRecord.sid);
-		LittleEndian.putUShort(data, 2 + offset, dataSize);
-
+		out.writeShort(TextObjectRecord.sid);
+		out.writeShort(dataSize);
 		
-		LittleEndian.putUShort(data, 4 + offset, field_1_options);
-		LittleEndian.putUShort(data, 6 + offset, field_2_textOrientation);
-		LittleEndian.putUShort(data, 8 + offset, field_3_reserved4);
-		LittleEndian.putUShort(data, 10 + offset, field_4_reserved5);
-		LittleEndian.putUShort(data, 12 + offset, field_5_reserved6);
-		LittleEndian.putUShort(data, 14 + offset, _text.length());
-		LittleEndian.putUShort(data, 16 + offset, getFormattingDataLength());
-		LittleEndian.putInt(data, 18 + offset, field_8_reserved7);
+		out.writeShort(field_1_options);
+		out.writeShort(field_2_textOrientation);
+		out.writeShort(field_3_reserved4);
+		out.writeShort(field_4_reserved5);
+		out.writeShort(field_5_reserved6);
+		out.writeShort(_text.length());
+		out.writeShort(getFormattingDataLength());
+		out.writeInt(field_8_reserved7);
 		
 		if (_linkRefPtg != null) {
-			int pos = offset+22;
 			int formulaSize = _linkRefPtg.getSize();
-			LittleEndian.putUShort(data, pos, formulaSize);
-			pos += LittleEndian.SHORT_SIZE;
-			LittleEndian.putInt(data, pos, _unknownPreFormulaInt);
-			pos += LittleEndian.INT_SIZE;
-			_linkRefPtg.writeBytes(data, pos);
-			pos += formulaSize;
+			out.writeShort(formulaSize);
+			out.writeInt(_unknownPreFormulaInt);
+			_linkRefPtg.write(out);
 			if (_unknownPostFormulaByte != null) {
-				LittleEndian.putByte(data, pos, _unknownPostFormulaByte.byteValue());
-				pos += LittleEndian.BYTE_SIZE;
+				out.writeByte(_unknownPostFormulaByte.byteValue());
 			}
 		}
-		
-		return 4 + dataSize;
+		return recSize;
 	}
 
 	private int serializeTrailingRecords(int offset, byte[] data) {

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/UnicodeString.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/UnicodeString.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/UnicodeString.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/UnicodeString.java Sun Oct 26 00:18:17 2008
@@ -36,13 +36,8 @@
  * @author  Andrew C. Oliver
  * @author Marc Johnson (mjohnson at apache dot org)
  * @author Glen Stampoultzis (glens at apache.org)
- * @version 2.0-pre
  */
-
-public class UnicodeString
-    implements Comparable
-{
-    public final static short sid = 0xFFF;
+public final class UnicodeString implements Comparable {
     private short             field_1_charCount;     // = 0;
     private byte              field_2_optionflags;   // = 0;
     private String            field_3_string;        // = null;
@@ -53,8 +48,8 @@
     private  static final BitField   richText  = BitFieldFactory.getInstance(0x8);
 
     public static class FormatRun implements Comparable {
-      private short character;
-      private short fontIndex;
+      short character;
+      short fontIndex;
 
       public FormatRun(short character, short fontIndex) {
         this.character = character;
@@ -102,15 +97,6 @@
       setString(str);
     }
 
-    /**
-     * construct a unicode string record and fill its fields, ID is ignored
-     * @param in the RecordInputstream to read the record from
-     */
-
-    public UnicodeString(RecordInputStream in)
-    {
-      fillFields(in); // TODO - inline
-    }
 
 
     public int hashCode()
@@ -142,9 +128,9 @@
                 && field_3_string.equals(other.field_3_string));
         if (!eq) return false;
 
-        //Ok string appears to be equal but now lets compare formatting runs
+        //OK string appears to be equal but now lets compare formatting runs
         if ((field_4_format_runs == null) && (other.field_4_format_runs == null))
-          //Strings are equal, and there are not formtting runs.
+          //Strings are equal, and there are not formatting runs.
           return true;
         if (((field_4_format_runs == null) && (other.field_4_format_runs != null)) ||
              (field_4_format_runs != null) && (other.field_4_format_runs == null))
@@ -186,10 +172,10 @@
     }
 
     /**
+     * construct a unicode string record and fill its fields, ID is ignored
      * @param in the RecordInputstream to read the record from
      */
-    protected void fillFields(RecordInputStream in)
-        {
+    public UnicodeString(RecordInputStream in) {
         field_1_charCount   = in.readShort();
         field_2_optionflags = in.readByte();
 
@@ -206,35 +192,13 @@
             extensionLength = in.readInt();
         }
 
-        //Now need to get the string data.
-        //Turn off autocontinuation so that we can catch the continue boundary
-        in.setAutoContinue(false);
-        StringBuffer tmpString = new StringBuffer(field_1_charCount);
-        int stringCharCount = field_1_charCount;
         boolean isCompressed = ((field_2_optionflags & 1) == 0);
-        while (stringCharCount != 0) {
-          if (in.remaining() == 0) {
-            if (in.isContinueNext()) {
-              in.nextRecord();
-              //Check if we are now reading, compressed or uncompressed unicode.
-              byte optionflags = in.readByte();
-              isCompressed = ((optionflags & 1) == 0);
-            } else
-              throw new RecordFormatException("Expected continue record.");
-          }
-          if (isCompressed) {
-            char ch = (char)in.readUByte(); // avoid sex
-            tmpString.append(ch);
-          } else {
-            char ch = (char) in.readShort();
-            tmpString.append(ch);
-          }
-          stringCharCount --;
+        if (isCompressed) {
+        	field_3_string = in.readCompressedUnicode(field_1_charCount);
+        } else {
+        	field_3_string = in.readUnicodeLEString(field_1_charCount);
         }
-        field_3_string = tmpString.toString();
-        //Turn back on autocontinuation
-        in.setAutoContinue(true);
-
+ 
 
         if (isRichText() && (runCount > 0)) {
           field_4_format_runs = new ArrayList(runCount);
@@ -305,13 +269,8 @@
     }
 
     /**
-     * get the actual string this contains as a java String object
-     *
-     *
-     * @return String
-     *
+     * @return the actual string this contains as a java String object
      */
-
     public String getString()
     {
         return field_3_string;
@@ -341,7 +300,7 @@
             }
         }
         if (useUTF16)
-          //Set the uncomressed bit
+          //Set the uncompressed bit
           field_2_optionflags = highByte.setByte(field_2_optionflags);
         else field_2_optionflags = highByte.clearByte(field_2_optionflags);
     }
@@ -392,7 +351,7 @@
 
       //Make sure that we now say that we are a rich string
       field_2_optionflags = richText.setByte(field_2_optionflags);
-        }
+    }
 
     public Iterator formatIterator() {
       if (field_4_format_runs != null)
@@ -497,8 +456,8 @@
 
         LittleEndian.putShort(data, offset, ContinueRecord.sid);
         offset+=2;
-        //Record the location of the last continue legnth position, but dont write
-        //anything there yet (since we dont know what it will be!)
+        //Record the location of the last continue length position, but don't write
+        //anything there yet (since we don't know what it will be!)
         stats.lastLengthPos = offset;
         offset += 2;
 
@@ -506,7 +465,7 @@
         stats.remainingSize = SSTRecord.MAX_RECORD_SIZE-4;
       }
       return offset;
-        }
+    }
 
     public int serialize(UnicodeRecordStats stats, final int offset, byte [] data)
     {
@@ -514,7 +473,6 @@
 
       //Basic string overhead
       pos = writeContinueIfRequired(stats, 3, pos, data);
-        // byte[] retval = new byte[ 3 + (getString().length() * charsize)];
       LittleEndian.putShort(data, pos, getCharCount());
       pos += 2;
       data[ pos ] = getOptionFlags();
@@ -568,39 +526,39 @@
       //Check to see if the offset occurs mid string, if so then we need to add
       //the byte to start with that represents the first byte of the continue record.
       if (strSize > stats.remainingSize) {
-        //Ok the offset occurs half way through the string, that means that
+        //OK the offset occurs half way through the string, that means that
         //we need an extra byte after the continue record ie we didnt finish
         //writing out the string the 1st time through
 
         //But hang on, how many continue records did we span? What if this is
         //a REALLY long string. We need to work this all out.
-        int ammountThatCantFit = strSize;
+        int amountThatCantFit = strSize;
         int strPos = 0;
-        while (ammountThatCantFit > 0) {
-          int ammountWritten = Math.min(stats.remainingSize, ammountThatCantFit);
-          //Make sure that the ammount that cant fit takes into account
+        while (amountThatCantFit > 0) {
+          int amountWritten = Math.min(stats.remainingSize, amountThatCantFit);
+          //Make sure that the amount that can't fit takes into account
           //whether we are writing double byte unicode
           if (isUncompressedUnicode()) {
             //We have the '-1' here because whether this is the first record or
             //subsequent continue records, there is always the case that the
-            //number of bytes in a string on doube byte boundaries is actually odd.
-            if ( ( (ammountWritten ) % 2) == 1)
-              ammountWritten--;
-          }
-          System.arraycopy(strBytes, strPos, data, pos, ammountWritten);
-          pos += ammountWritten;
-          strPos += ammountWritten;
-          stats.recordSize += ammountWritten;
-          stats.remainingSize -= ammountWritten;
+            //number of bytes in a string on double byte boundaries is actually odd.
+            if ( ( (amountWritten ) % 2) == 1)
+              amountWritten--;
+          }
+          System.arraycopy(strBytes, strPos, data, pos, amountWritten);
+          pos += amountWritten;
+          strPos += amountWritten;
+          stats.recordSize += amountWritten;
+          stats.remainingSize -= amountWritten;
 
           //Ok lets subtract what we can write
-          ammountThatCantFit -= ammountWritten;
+          amountThatCantFit -= amountWritten;
 
           //Each iteration of this while loop is another continue record, unless
           //everything  now fits.
-          if (ammountThatCantFit > 0) {
+          if (amountThatCantFit > 0) {
             //We know that a continue WILL be requied, but use this common method
-            pos = writeContinueIfRequired(stats, ammountThatCantFit, pos, data);
+            pos = writeContinueIfRequired(stats, amountThatCantFit, pos, data);
 
             //The first byte after a continue mid string is the extra byte to
             //indicate if this run is compressed or not.
@@ -686,7 +644,7 @@
         return highByte.isSet(getOptionFlags());
     }
 
-    /** Returns the size of this record, given the ammount of record space
+    /** Returns the size of this record, given the amount of record space
      * remaining, it will also include the size of writing a continue record.
      */
 
@@ -833,13 +791,6 @@
       }
     }
 
-
-
-    public short getSid()
-    {
-        return sid;
-    }
-
     public int compareTo(Object obj)
     {
         UnicodeString str = ( UnicodeString ) obj;
@@ -877,7 +828,7 @@
         }
 
         //Well the format runs are equal as well!, better check the ExtRst data
-        //Which by the way we dont know how to decode!
+        //Which by the way we don't know how to decode!
         if ((field_5_ext_rst == null) && (str.field_5_ext_rst == null))
           return 0;
         if ((field_5_ext_rst == null) && (str.field_5_ext_rst != null))

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/WriteAccessRecord.java Sun Oct 26 00:18:17 2008
@@ -1,4 +1,3 @@
-
 /* ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
@@ -15,111 +14,130 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
-        
 
 package org.apache.poi.hssf.record;
 
+import java.util.Arrays;
+
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 
 /**
- * Title:        Write Access Record<P>
- * Description:  Stores the username of that who owns the spreadsheet generator
- *               (on unix the user's login, on Windoze its the name you typed when
- *                you installed the thing)<P>
- * REFERENCE:  PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
+ * Title: Write Access Record (0x005C)<p/>
+ * 
+ * Description: Stores the username of that who owns the spreadsheet generator (on unix the user's 
+ * login, on Windoze its the name you typed when you installed the thing)
+ * <p/>
+ * REFERENCE: PG 424 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
+ * <p/>
+ * 
  * @author Andrew C. Oliver (acoliver at apache dot org)
- * @version 2.0-pre
  */
-
-public class WriteAccessRecord
-    extends Record
-{
-    public final static short sid = 0x5c;
-    private String            field_1_username;
-
-    public WriteAccessRecord()
-    {
-    }
-
-    public WriteAccessRecord(RecordInputStream in)
-    {
-        byte[] data = in.readRemainder();
-        //The string is always 112 characters (padded with spaces), therefore
-        //this record can not be continued.
-
-        //What a wierd record, it is not really a unicode string because the
-        //header doesnt provide a correct size indication.???
-        //But the header is present, so we need to skip over it.
-        //Odd, Odd, Odd ;-)
-        field_1_username = StringUtil.getFromCompressedUnicode(data, 3, data.length - 3);
-    }
-
-    /**
-     * set the username for the user that created the report.  HSSF uses the logged in user.
-     * @param username of the user who  is logged in (probably "tomcat" or "apache")
-     */
-
-    public void setUsername(String username)
-    {
-        field_1_username = username;
-    }
-
-    /**
-     * get the username for the user that created the report.  HSSF uses the logged in user.  On
-     * natively created M$ Excel sheet this would be the name you typed in when you installed it
-     * in most cases.
-     * @return username of the user who  is logged in (probably "tomcat" or "apache")
-     */
-
-    public String getUsername()
-    {
-        return field_1_username;
-    }
-
-    public String toString()
-    {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[WRITEACCESS]\n");
-        buffer.append("    .name            = ")
-            .append(field_1_username.toString()).append("\n");
-        buffer.append("[/WRITEACCESS]\n");
-        return buffer.toString();
-    }
-
-    public int serialize(int offset, byte [] data)
-    {
-        String       username = getUsername();
-        StringBuffer temp     = new StringBuffer(0x70 - (0x3));
-
-        temp.append(username);
-        while (temp.length() < 0x70 - 0x3)
-        {
-            temp.append(
-                " ");   // (70 = fixed lenght -3 = the overhead bits of unicode string)
-        }
-        username = temp.toString();
-        UnicodeString str = new UnicodeString(username);
-        str.setOptionFlags(( byte ) 0x0);
-
-        LittleEndian.putShort(data, 0 + offset, sid);
-        LittleEndian.putShort(data, 2 + offset, (short)112);   // 112 bytes (115 total)
-        UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
-        stats.recordSize += 4;
-        stats.remainingSize-= 4;
-        str.serialize(stats, 4 + offset, data);
-
-        return getRecordSize();
-    }
-
-    public int getRecordSize()
-    {
-        return 116;
-    }
-
-    public short getSid()
-    {
-        return sid;
-    }
+public final class WriteAccessRecord extends Record {
+	private static final byte PAD_CHAR = (byte) ' ';
+	public final static short sid = 0x005C;
+	private static final int DATA_SIZE = 112;
+	private String field_1_username;
+	/** this record is always padded to a constant length */
+	private byte[] padding;
+
+	public WriteAccessRecord() {
+		setUsername("");
+		padding = new byte[DATA_SIZE - 3];
+	}
+
+	public WriteAccessRecord(RecordInputStream in) {
+		if (in.remaining() > DATA_SIZE) {
+			throw new RecordFormatException("Expected data size (" + DATA_SIZE + ") but got ("
+					+ in.remaining() + ")");
+		}
+		// The string is always 112 characters (padded with spaces), therefore
+		// this record can not be continued.
+
+		int nChars = in.readUShort();
+		int is16BitFlag = in.readUByte();
+		int expectedPadSize = DATA_SIZE - 3;
+		if ((is16BitFlag & 0x01) == 0x00) {
+			field_1_username = StringUtil.readCompressedUnicode(in, nChars);
+			expectedPadSize -= nChars;
+		} else {
+			field_1_username = StringUtil.readUnicodeLE(in, nChars);
+			expectedPadSize -= nChars * 2;
+		}
+		padding = new byte[expectedPadSize];
+		int padSize = in.remaining();
+		in.readFully(padding, 0, padSize);
+		if (padSize < expectedPadSize) {
+			// this occurs in a couple of test examples: "42564.xls",
+			// "bug_42794.xls"
+			Arrays.fill(padding, padSize, expectedPadSize, PAD_CHAR);
+		}
+	}
+
+	/**
+	 * set the username for the user that created the report. HSSF uses the
+	 * logged in user.
+	 * 
+	 * @param username of the user who is logged in (probably "tomcat" or "apache")
+	 */
+	public void setUsername(String username) {
+		boolean is16bit = StringUtil.hasMultibyte(username);
+		int encodedByteCount = 3 + username.length() * (is16bit ? 2 : 1);
+		int paddingSize = DATA_SIZE - encodedByteCount;
+		if (paddingSize < 0) {
+			throw new IllegalArgumentException("Name is too long: " + username);
+		}
+		padding = new byte[paddingSize];
+		Arrays.fill(padding, PAD_CHAR);
+
+		field_1_username = username;
+	}
+
+	/**
+	 * get the username for the user that created the report. HSSF uses the
+	 * logged in user. On natively created M$ Excel sheet this would be the name
+	 * you typed in when you installed it in most cases.
+	 * 
+	 * @return username of the user who is logged in (probably "tomcat" or "apache")
+	 */
+	public String getUsername() {
+		return field_1_username;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[WRITEACCESS]\n");
+		buffer.append("    .name            = ").append(field_1_username.toString()).append("\n");
+		buffer.append("[/WRITEACCESS]\n");
+		return buffer.toString();
+	}
+
+	public int serialize(int offset, byte[] data) {
+		String username = getUsername();
+		boolean is16bit = StringUtil.hasMultibyte(username);
+
+		LittleEndian.putUShort(data, 0 + offset, sid);
+		LittleEndian.putUShort(data, 2 + offset, DATA_SIZE);
+		LittleEndian.putUShort(data, 4 + offset, username.length());
+		LittleEndian.putByte(data, 6 + offset, is16bit ? 0x01 : 0x00);
+		int pos = offset + 7;
+		if (is16bit) {
+			StringUtil.putUnicodeLE(username, data, pos);
+			pos += username.length() * 2;
+		} else {
+			StringUtil.putCompressedUnicode(username, data, pos);
+			pos += username.length();
+		}
+		System.arraycopy(padding, 0, data, pos, padding.length);
+		return 4 + DATA_SIZE;
+	}
+
+	public int getRecordSize() {
+		return 4 + DATA_SIZE;
+	}
+
+	public short getSid() {
+		return sid;
+	}
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java Sun Oct 26 00:18:17 2008
@@ -17,10 +17,11 @@
 
 package org.apache.poi.hssf.record.constant;
 
-import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.hssf.record.UnicodeString;
 import org.apache.poi.hssf.record.UnicodeString.UnicodeRecordStats;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+import org.apache.poi.util.StringUtil;
 
 /**
  * To support Constant Values (2.5.7) as required by the CRN record.
@@ -47,7 +48,7 @@
 		// no instances of this class
 	}
 
-	public static Object[] parse(RecordInputStream in, int nValues) {
+	public static Object[] parse(LittleEndianInput in, int nValues) {
 		Object[] result = new Object[nValues];
 		for (int i = 0; i < result.length; i++) {
 			result[i] = readAConstantValue(in);
@@ -55,7 +56,7 @@
 		return result;
 	}
 
-	private static Object readAConstantValue(RecordInputStream in) {
+	private static Object readAConstantValue(LittleEndianInput in) {
 		byte grbit = in.readByte();
 		switch(grbit) {
 			case TYPE_EMPTY:
@@ -64,7 +65,7 @@
 			case TYPE_NUMBER:
 				return new Double(in.readDouble());
 			case TYPE_STRING:
-				return in.readUnicodeString();
+				return new UnicodeString(StringUtil.readUnicodeString(in));
 			case TYPE_BOOLEAN:
 				return readBoolean(in);
 			case TYPE_ERROR_CODE:
@@ -77,7 +78,7 @@
 		throw new RuntimeException("Unknown grbit value (" + grbit + ")");
 	}
 
-	private static Object readBoolean(RecordInputStream in) {
+	private static Object readBoolean(LittleEndianInput in) {
 		byte val = (byte)in.readLong(); // 7 bytes 'not used'
 		switch(val) {
 			case FALSE_ENCODING:
@@ -116,46 +117,43 @@
 		return urs.recordSize;
 	}
 
-	public static void encode(byte[] data, int offset, Object[] values) {
-		int currentOffset = offset;
+	public static void encode(LittleEndianOutput out, Object[] values) {
 		for (int i = 0; i < values.length; i++) {
-			currentOffset += encodeSingleValue(data, currentOffset, values[i]);
+			encodeSingleValue(out, values[i]);
 		}
 	}
 
-	private static int encodeSingleValue(byte[] data, int offset, Object value) {
+	private static void encodeSingleValue(LittleEndianOutput out, Object value) {
 		if (value == EMPTY_REPRESENTATION) {
-			LittleEndian.putByte(data, offset, TYPE_EMPTY);
-			LittleEndian.putLong(data, offset+1, 0L);
-			return 9;
+			out.writeByte(TYPE_EMPTY);
+			out.writeLong(0L);
+			return;
 		}
 		if (value instanceof Boolean) {
 			Boolean bVal = ((Boolean)value);
-			LittleEndian.putByte(data, offset, TYPE_BOOLEAN);
+			out.writeByte(TYPE_BOOLEAN);
 			long longVal = bVal.booleanValue() ? 1L : 0L;
-			LittleEndian.putLong(data, offset+1, longVal);
-			return 9;
+			out.writeLong(longVal);
+			return;
 		}
 		if (value instanceof Double) {
 			Double dVal = (Double) value;
-			LittleEndian.putByte(data, offset, TYPE_NUMBER);
-			LittleEndian.putDouble(data, offset+1, dVal.doubleValue());
-			return 9;
+			out.writeByte(TYPE_NUMBER);
+			out.writeDouble(dVal.doubleValue());
+			return;
 		}
 		if (value instanceof UnicodeString) {
 			UnicodeString usVal = (UnicodeString) value;
-			LittleEndian.putByte(data, offset, TYPE_STRING);
-			UnicodeRecordStats urs = new UnicodeRecordStats();
-			usVal.serialize(urs, offset +1, data);
-			return 1 + urs.recordSize;
+			out.writeByte(TYPE_STRING);
+			StringUtil.writeUnicodeString(out, usVal.getString());
+			return;
 		}
 		if (value instanceof ErrorConstant) {
 			ErrorConstant ecVal = (ErrorConstant) value;
-			LittleEndian.putByte(data, offset, TYPE_ERROR_CODE);
-			LittleEndian.putUShort(data, offset+1, ecVal.getErrorCode());
-			LittleEndian.putUShort(data, offset+3, 0);
-			LittleEndian.putInt(data, offset+5, 0);
-			return 9;
+			out.writeByte(TYPE_ERROR_CODE);
+			long longVal = ecVal.getErrorCode();
+			out.writeLong(longVal);
+			return;
 		}
 
 		throw new IllegalStateException("Unexpected value type (" + value.getClass().getName() + "'");

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AbstractFunctionPtg.java Sun Oct 26 00:18:17 2008
@@ -98,7 +98,6 @@
         buf.append(")");
     }
 
-    public abstract void writeBytes(byte[] array, int offset);
     public abstract int getSize();
 
 

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java Sun Oct 26 00:18:17 2008
@@ -17,42 +17,48 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
- * Common superclass of 2-D area refs 
+ * Common superclass of 2-D area refs
  */
 public abstract class Area2DPtgBase extends AreaPtgBase {
-	private final static int  SIZE = 9;
+	private final static int SIZE = 9;
 
 	protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
 		super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
 	}
-	protected Area2DPtgBase(RecordInputStream in) {
+
+	protected Area2DPtgBase(LittleEndianInput in)  {
 		readCoordinates(in);
 	}
+
 	protected abstract byte getSid();
 
-	public final void writeBytes(byte [] array, int offset) {
-		LittleEndian.putByte(array, offset+0, getSid() + getPtgClass());
-		writeCoordinates(array, offset+1);       
+	public final void write(LittleEndianOutput out) {
+		out.writeByte(getSid() + getPtgClass());
+		writeCoordinates(out);
 	}
+
 	public Area2DPtgBase(String arearef) {
-    	super(arearef);
+		super(arearef);
 	}
+
 	public final int getSize() {
 		return SIZE;
 	}
+
 	public final String toFormulaString() {
-    	return formatReferenceAsString();
+		return formatReferenceAsString();
+	}
+
+	public final String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(getClass().getName());
+		sb.append(" [");
+		sb.append(formatReferenceAsString());
+		sb.append("]");
+		return sb.toString();
 	}
-    public final String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(getClass().getName());
-        sb.append(" [");
-        sb.append(formatReferenceAsString());
-        sb.append("]");
-        return sb.toString();
-    }
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Area3DPtg.java Sun Oct 26 00:18:17 2008
@@ -17,11 +17,11 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.ss.formula.ExternSheetReferenceToken;
 import org.apache.poi.ss.formula.FormulaRenderingWorkbook;
 import org.apache.poi.ss.formula.WorkbookDependentFormula;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
  * Title:        Area 3D Ptg - 3D reference (Sheet + Area)<P>
@@ -44,7 +44,7 @@
 		setExternSheetIndex( externIdx );
 	}
 
-	public Area3DPtg(RecordInputStream in) {
+	public Area3DPtg(LittleEndianInput in)  {
 		field_1_index_extern_sheet = in.readShort();
 		readCoordinates(in);
 	}
@@ -67,10 +67,10 @@
 		return sb.toString();
 	}
 
-	public void writeBytes(byte[] array, int offset) {
-		LittleEndian.putByte(array, offset + 0, sid + getPtgClass());
-		LittleEndian.putUShort(array, 1 + offset, field_1_index_extern_sheet);
-		writeCoordinates(array, offset+3);
+	public void write(LittleEndianOutput out) {
+		out.writeByte(sid + getPtgClass());
+		out.writeShort(field_1_index_extern_sheet);
+		writeCoordinates(out);
 	}
 
 	public int getSize() {

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaErrPtg.java Sun Oct 26 00:18:17 2008
@@ -17,9 +17,9 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
 
 /**
  * AreaErr - handles deleted cell area references.
@@ -36,16 +36,16 @@
 		unused2 = 0;
 	}
 
-	public AreaErrPtg(RecordInputStream in) {
+	public AreaErrPtg(LittleEndianInput in)  {
 		// 8 bytes unused:
 		unused1 = in.readInt();
 		unused2 = in.readInt();
 	}
 
-	public void writeBytes(byte[] array, int offset) {
-		LittleEndian.putByte(array, offset + 0, sid + getPtgClass());
-		LittleEndian.putInt(array, offset + 1, unused1);
-		LittleEndian.putInt(array, offset + 5, unused2);
+	public void write(LittleEndianOutput out) {
+		out.writeByte(sid + getPtgClass());
+		out.writeInt(unused1);
+		out.writeInt(unused2);
 	}
 
 	public String toFormulaString() {

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaNPtg.java Sun Oct 26 00:18:17 2008
@@ -17,7 +17,7 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndianInput;
 
 /**
  * Specifies a rectangular area of cells A1:A4 for instance.
@@ -26,7 +26,7 @@
 public final class AreaNPtg extends Area2DPtgBase {
 	public final static short sid = 0x2D;
 
-	public AreaNPtg(RecordInputStream in) {
+	public AreaNPtg(LittleEndianInput in)  {
 		super(in);
 	}
 

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java?rev=707945&r1=707944&r2=707945&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/AreaPtg.java Sun Oct 26 00:18:17 2008
@@ -17,7 +17,7 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.LittleEndianInput;
 
 /**
  * Specifies a rectangular area of cells A1:A4 for instance.
@@ -29,7 +29,7 @@
 	public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
 		super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
 	}
-	public AreaPtg(RecordInputStream in) {
+	public AreaPtg(LittleEndianInput in)  {
 		super(in);
 	}
 	public AreaPtg(String arearef) {



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org