You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2008/06/21 14:03:49 UTC

svn commit: r670186 [4/7] - in /poi/tags/REL_3_1_FINAL: ./ legal/ src/documentation/content/xdocs/ src/examples/src/org/apache/poi/hslf/ src/examples/src/org/apache/poi/hslf/usermodel/ src/examples/src/org/apache/poi/hslf/usermodel/examples/ src/java/o...

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnaryPlusPtg.java Sat Jun 21 05:03:44 2008
@@ -17,63 +17,30 @@
 
 package org.apache.poi.hssf.record.formula;
 
-import java.util.List;
-
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordInputStream;
-
 /**
  * Unary Plus operator
  * does not have any effect on the operand
  * @author Avik Sengupta
  */
-
-public class UnaryPlusPtg extends OperationPtg
-{
-    public final static int  SIZE = 1;
+public final class UnaryPlusPtg extends ValueOperatorPtg {
     public final static byte sid  = 0x12;
     
     private final static String ADD = "+";
 
-    /** Creates new AddPtg */
+    public static final ValueOperatorPtg instance = new UnaryPlusPtg();
 
-    public UnaryPlusPtg()
-    {
-    }
-
-    public UnaryPlusPtg(RecordInputStream in)
-    {
-
-        // doesn't need anything
+    private UnaryPlusPtg() {
+    	// enforce singleton
     }
     
-   
-    public void writeBytes(byte [] array, int offset)
-    {
-        array[ offset + 0 ] = sid;
-    }
-
-    public int getSize()
-    {
-        return SIZE;
-    }
-
-    public int getType()
-    {
-        return this.TYPE_UNARY;
+    protected byte getSid() {
+    	return sid;
     }
 
-    public int getNumberOfOperands()
-    {
+    public int getNumberOfOperands() {
         return 1;
     }
     
-    /** Implementation of method from Ptg */
-    public String toFormulaString(HSSFWorkbook book)
-    {
-        return "+";
-    }
-       
    /** implementation of method from OperationsPtg*/  
     public String toFormulaString(String[] operands) {
         StringBuffer buffer = new StringBuffer();
@@ -81,11 +48,4 @@
         buffer.append(operands[ 0]);
         return buffer.toString();
     }
-    
-    public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
-           
-    public Object clone() {
-      return new UnaryPlusPtg();
-    }
-
 }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnionPtg.java Sat Jun 21 05:03:44 2008
@@ -18,26 +18,23 @@
 package org.apache.poi.hssf.record.formula;
 
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordInputStream;
 
 /**
  * @author Glen Stampoultzis (glens at apache.org)
  */
-public class UnionPtg extends OperationPtg
-{
+public final class UnionPtg extends OperationPtg {
     public final static byte sid  = 0x10;
 
+    public static final OperationPtg instance = new UnionPtg();
 
-    public UnionPtg()
-    {
+    private UnionPtg() {
+    	// enforce singleton
     }
 
-    public UnionPtg(RecordInputStream in)
-    {
-        // doesn't need anything
+    public final boolean isBaseToken() {
+        return true;
     }
 
-
     public int getSize()
     {
         return 1;
@@ -48,17 +45,6 @@
         array[ offset + 0 ] = sid;
     }
 
-    public Object clone()
-    {
-        return new UnionPtg();
-    }
-
-    public int getType()
-    {
-        return TYPE_BINARY;
-    }
-
-    /** Implementation of method from Ptg */
     public String toFormulaString(HSSFWorkbook book)
     {
         return ",";

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/UnknownPtg.java Sat Jun 21 05:03:44 2008
@@ -24,10 +24,7 @@
  * @author  andy
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-
-public class UnknownPtg
-    extends Ptg
-{
+public class UnknownPtg extends Ptg {
     private short size = 1;
 
     /** Creates new UnknownPtg */
@@ -36,12 +33,13 @@
     {
     }
 
-    public UnknownPtg(RecordInputStream in)
-    {
-
+    public UnknownPtg(RecordInputStream in) {
         // doesn't need anything
     }
 
+    public boolean isBaseToken() {
+    	return true;
+    }
     public void writeBytes(byte [] array, int offset)
     {
     }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java Sat Jun 21 05:03:44 2008
@@ -17,7 +17,7 @@
 
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.ReferencePtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
 
 /**
  * @author adeshmukh
@@ -26,9 +26,9 @@
 public final class Ref2DEval implements RefEval {
 
     private final ValueEval value;
-    private final ReferencePtg delegate;
+    private final RefPtg delegate;
     
-    public Ref2DEval(ReferencePtg ptg, ValueEval ve) {
+    public Ref2DEval(RefPtg ptg, ValueEval ve) {
         if(ve == null) {
             throw new IllegalArgumentException("ve must not be null");
         }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFDateUtil.java Sat Jun 21 05:03:44 2008
@@ -220,13 +220,18 @@
     	//  switching stuff, which we can ignore
     	fs = fs.replaceAll(";@", "");
     	
-    	// If it starts with [$-...], then it is a date, but
+    	// If it starts with [$-...], then could be a date, but
     	//  who knows what that starting bit is all about
-    	fs = fs.replaceAll("\\[\\$\\-.*?\\]", "");
+    	fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
+    	
+    	// If it starts with something like [Black] or [Yellow],
+    	//  then it could be a date
+    	fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
     	
     	// Otherwise, check it's only made up, in any case, of:
     	//  y m d h s - / , . :
-    	if(fs.matches("^[yYmMdDhHsS\\-/,. :]+$")) {
+    	// optionally followed by AM/PM
+    	if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP]*$")) {
     		return true;
     	}
     	

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java Sat Jun 21 05:03:44 2008
@@ -40,7 +40,7 @@
 import org.apache.poi.hssf.record.formula.ParenthesisPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
-import org.apache.poi.hssf.record.formula.ReferencePtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
 import org.apache.poi.hssf.record.formula.StringPtg;
 import org.apache.poi.hssf.record.formula.UnionPtg;
 import org.apache.poi.hssf.record.formula.UnknownPtg;
@@ -342,28 +342,28 @@
     }
     private static ValueEval evaluateCell(HSSFWorkbook workbook, HSSFSheet sheet, 
             int srcRowNum, short srcColNum, String cellFormulaText) {
-        FormulaParser parser = new FormulaParser(cellFormulaText, workbook);
-        parser.parse();
-        Ptg[] ptgs = parser.getRPNPtg();
-        // -- parsing over --
-        
+
+    	Ptg[] ptgs = FormulaParser.parse(cellFormulaText, workbook);
 
         Stack stack = new Stack();
         for (int i = 0, iSize = ptgs.length; i < iSize; i++) {
 
             // since we don't know how to handle these yet :(
             Ptg ptg = ptgs[i];
-            if (ptg instanceof ControlPtg) { continue; }
+            if (ptg instanceof ControlPtg) { 
+                // skip Parentheses, Attr, etc
+                continue; 
+            }
             if (ptg instanceof MemErrPtg) { continue; }
             if (ptg instanceof MissingArgPtg) { continue; }
             if (ptg instanceof NamePtg) { 
-            	// named ranges, macro functions
+                // named ranges, macro functions
                 NamePtg namePtg = (NamePtg) ptg;
                 stack.push(new NameEval(namePtg.getIndex()));
                 continue; 
             }
             if (ptg instanceof NameXPtg) {
-            	// TODO - external functions
+                // TODO - external functions
                 continue;
             }
             if (ptg instanceof UnknownPtg) { continue; }
@@ -371,9 +371,6 @@
             if (ptg instanceof OperationPtg) {
                 OperationPtg optg = (OperationPtg) ptg;
 
-                // parens can be ignored since we have RPN tokens
-                if (optg instanceof ParenthesisPtg) { continue; }
-                if (optg instanceof AttrPtg) { continue; }
                 if (optg instanceof UnionPtg) { continue; }
 
                 OperationEval operation = OperationEvaluatorFactory.create(optg);
@@ -389,8 +386,8 @@
                 Eval opresult = invokeOperation(operation, ops, srcRowNum, srcColNum, workbook, sheet);
                 stack.push(opresult);
             }
-            else if (ptg instanceof ReferencePtg) {
-                ReferencePtg refPtg = (ReferencePtg) ptg;
+            else if (ptg instanceof RefPtg) {
+                RefPtg refPtg = (RefPtg) ptg;
                 int colIx = refPtg.getColumn();
                 int rowIx = refPtg.getRow();
                 HSSFRow row = sheet.getRow(rowIx);
@@ -552,7 +549,7 @@
                 Constructor constructor = clazz.getConstructor(AREA3D_CONSTRUCTOR_CLASS_ARRAY);
                 retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
             }
-            else if (ptg instanceof ReferencePtg) {
+            else if (ptg instanceof RefPtg) {
                 Constructor constructor = clazz.getConstructor(REFERENCE_CONSTRUCTOR_CLASS_ARRAY);
                 retval = (OperationEval) constructor.newInstance(new Ptg[] { ptg });
             }
@@ -610,7 +607,7 @@
      * Creates a Ref2DEval for ReferencePtg.
      * Non existent cells are treated as RefEvals containing BlankEval.
      */
-    private static Ref2DEval createRef2DEval(ReferencePtg ptg, HSSFCell cell, 
+    private static Ref2DEval createRef2DEval(RefPtg ptg, HSSFCell cell, 
             HSSFRow row, HSSFSheet sheet, HSSFWorkbook workbook) {
         if (cell == null) {
             return new Ref2DEval(ptg, BlankEval.INSTANCE);

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFName.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFName.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFName.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFName.java Sat Jun 21 05:03:44 2008
@@ -18,7 +18,6 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.model.Workbook;
-import org.apache.poi.hssf.record.BoundSheetRecord;
 import org.apache.poi.hssf.record.NameRecord;
 import org.apache.poi.hssf.util.RangeAddress;
 

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java Sat Jun 21 05:03:44 2008
@@ -55,36 +55,72 @@
         this.record = record;
         this.poifs = poifs;
     }
+    
+    /**
+     * Returns the OLE2 Class Name of the object
+     */
+    public String getOLE2ClassName() {
+    	EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+    	return subRecord.field_5_ole_classname;
+    }
 
     /**
-     * Gets the object data.
+     * Gets the object data. Only call for ones that have
+     *  data though. See {@link #hasDirectoryEntry()}
      *
      * @return the object data as an OLE2 directory.
      * @throws IOException if there was an error reading the data.
      */
-    public DirectoryEntry getDirectory() throws IOException
-    {
+    public DirectoryEntry getDirectory() throws IOException {
+    	EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+
+    	int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
+        String streamName = "MBD" + HexDump.toHex(streamId);
+
+        Entry entry = poifs.getRoot().getEntry(streamName);
+        if (entry instanceof DirectoryEntry) {
+            return (DirectoryEntry) entry;
+        } else {
+            throw new IOException("Stream " + streamName + " was not an OLE2 directory");
+        }
+    }
+    
+    /**
+     * Returns the data portion, for an ObjectData
+     *  that doesn't have an associated POIFS Directory
+     *  Entry
+     */
+    public byte[] getObjectData() {
+    	EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+    	return subRecord.remainingBytes;
+    }
+    
+    /**
+     * Does this ObjectData have an associated POIFS 
+     *  Directory Entry?
+     * (Not all do, those that don't have a data portion)
+     */
+    public boolean hasDirectoryEntry() {
+    	EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+    	
+    	// Field 6 tells you
+    	return (subRecord.field_6_stream_id != 0);
+    }
+    
+    /**
+     * Finds the EmbeddedObjectRefSubRecord, or throws an 
+     *  Exception if there wasn't one
+     */
+    protected EmbeddedObjectRefSubRecord findObjectRecord() {
         Iterator subRecordIter = record.getSubRecords().iterator();
-        while (subRecordIter.hasNext())
-        {
+        
+        while (subRecordIter.hasNext()) {
             Object subRecord = subRecordIter.next();
-            if (subRecord instanceof EmbeddedObjectRefSubRecord)
-            {
-                int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
-                String streamName = "MBD" + HexDump.toHex(streamId);
-
-                Entry entry = poifs.getRoot().getEntry(streamName);
-                if (entry instanceof DirectoryEntry)
-                {
-                    return (DirectoryEntry) entry;
-                }
-                else
-                {
-                    throw new IOException("Stream " + streamName + " was not an OLE2 directory");
-                }
+            if (subRecord instanceof EmbeddedObjectRefSubRecord) {
+            	return (EmbeddedObjectRefSubRecord)subRecord;
             }
         }
-
+        
         throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
     }
 }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java Sat Jun 21 05:03:44 2008
@@ -26,6 +26,7 @@
 import javax.imageio.ImageReader;
 import javax.imageio.stream.ImageInputStream;
 import java.awt.image.BufferedImage;
+import java.awt.*;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.Iterator;
@@ -46,6 +47,20 @@
     public static final int PICTURE_TYPE_PNG = HSSFWorkbook.PICTURE_TYPE_PNG;                // PNG
     public static final int PICTURE_TYPE_DIB = HSSFWorkbook.PICTURE_TYPE_DIB;                // Windows DIB
 
+    /**
+     * width of 1px in columns with default width in units of 1/256 of a character width
+     */
+    private static final float PX_DEFAULT = 32.00f;
+    /**
+     * width of 1px in columns with overridden width in units of 1/256 of a character width
+     */
+    private static final float PX_MODIFIED = 36.56f;
+
+    /**
+     * Height of 1px of a row
+     */
+    private static final int PX_ROW = 15;
+
     int pictureIndex;
     HSSFPatriarch patriarch;
 
@@ -100,59 +115,77 @@
      * @since POI 3.0.2
      */
     public HSSFClientAnchor getPreferredSize(){
-        HSSFClientAnchor anchor = new HSSFClientAnchor();
-
-        EscherBSERecord bse = (EscherBSERecord)patriarch.sheet.book.getBSERecord(pictureIndex);
-        byte[] data = bse.getBlipRecord().getPicturedata();
-        int type = bse.getBlipTypeWin32();
-        switch (type){
-            //we can calculate the preferred size only for JPEG and PNG
-            //other formats like WMF, EMF and PICT are not supported in Java
-            case HSSFWorkbook.PICTURE_TYPE_JPEG:
-            case HSSFWorkbook.PICTURE_TYPE_PNG:
-                BufferedImage img = null;
-                ImageReader r = null;
-                try {
-                    //read the image using javax.imageio.*
-                    ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) );
-                    Iterator i = ImageIO.getImageReaders( iis );
-                    r = (ImageReader) i.next();
-                    r.setInput( iis );
-                    img = r.read(0);
+        HSSFClientAnchor anchor = (HSSFClientAnchor)getAnchor();
 
-                    int[] dpi = getResolution(r);
-                    int imgWidth = img.getWidth()*96/dpi[0];
-                    int imgHeight = img.getHeight()*96/dpi[1];
+        Dimension size = getImageDimension();
 
-                    //Excel measures cells in units of 1/256th of a character width.
-                    //The cell width calculated based on this info is always "off".
-                    //A better approach seems to be to use empirically obtained cell width and row height
-                    int cellwidth = 64;
-                    int rowheight = 17;
-
-                    int col2 = imgWidth/cellwidth;
-                    int row2 = imgHeight/rowheight;
+        float w = 0;
 
-                    int dx2 = (int)((float)(imgWidth % cellwidth)/cellwidth * 1024);
-                    int dy2 = (int)((float)(imgHeight % rowheight)/rowheight * 256);
+        //space in the leftmost cell
+        w += getColumnWidthInPixels(anchor.col1)*(1 - anchor.dx1/1024);
+        short col2 = (short)(anchor.col1 + 1);
+        int dx2 = 0;
 
-                    anchor.setCol2((short)col2);
-                    anchor.setDx2(dx2);
+        while(w < size.width){
+            w += getColumnWidthInPixels(col2++);
+        }
 
-                    anchor.setRow2(row2);
-                    anchor.setDy2(dy2);
+        if(w > size.width) {
+            //calculate dx2, offset in the rightmost cell
+            col2--;
+            float cw = getColumnWidthInPixels(col2);
+            float delta = w - size.width;
+            dx2 = (int)((cw-delta)/cw*1024);
+        }
+        anchor.col2 = col2;
+        anchor.dx2 = dx2;
 
-                } catch (IOException e){
-                    //silently return if ImageIO failed to read the image
-                    log.log(POILogger.WARN, e);
-                    img = null;
-                }
+        float h = 0;
+        h += (1 - anchor.dy1/256)* getRowHeightInPixels(anchor.row1);
+        int row2 = anchor.row1 + 1;
+        int dy2 = 0;
 
-                break;
+        while(h < size.height){
+            h += getRowHeightInPixels(row2++);
         }
+        if(h > size.height) {
+            row2--;
+            float ch = getRowHeightInPixels(row2);
+            float delta = h - size.height;
+            dy2 = (int)((ch-delta)/ch*256);
+        }
+        anchor.row2 = row2;
+        anchor.dy2 = dy2;
+
         return anchor;
     }
 
+    private float getColumnWidthInPixels(short column){
+
+        short cw = patriarch.sheet.getColumnWidth(column);
+        float px = getPixelWidth(column);
+
+        return cw/px;
+    }
+
+    private float getRowHeightInPixels(int i){
+
+        HSSFRow row = patriarch.sheet.getRow(i);
+        float height;
+        if(row != null) height = row.getHeight();
+        else height = patriarch.sheet.getDefaultRowHeight();
+
+        return height/PX_ROW;
+    }
+
+    private float getPixelWidth(short column){
+
+        int def = patriarch.sheet.getDefaultColumnWidth()*256;
+        short cw = patriarch.sheet.getColumnWidth(column);
+
+        return cw == def ? PX_DEFAULT : PX_MODIFIED;
+    }
+
     /**
      * The metadata of PNG and JPEG can contain the width of a pixel in millimeters.
      * Return the the "effective" dpi calculated as <code>25.4/HorizontalPixelSize</code>
@@ -176,4 +209,42 @@
         return new int[]{hdpi, vdpi};
     }
 
+    /**
+     * Return the dimension of this image
+     *
+     * @return image dimension
+     */
+    public Dimension getImageDimension(){
+        EscherBSERecord bse = patriarch.sheet.book.getBSERecord(pictureIndex);
+        byte[] data = bse.getBlipRecord().getPicturedata();
+        int type = bse.getBlipTypeWin32();
+        Dimension size = new Dimension();
+
+        switch (type){
+            //we can calculate the preferred size only for JPEG and PNG
+            //other formats like WMF, EMF and PICT are not supported in Java
+            case HSSFWorkbook.PICTURE_TYPE_JPEG:
+            case HSSFWorkbook.PICTURE_TYPE_PNG:
+            case HSSFWorkbook.PICTURE_TYPE_DIB:
+                try {
+                    //read the image using javax.imageio.*
+                    ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) );
+                    Iterator i = ImageIO.getImageReaders( iis );
+                    ImageReader r = (ImageReader) i.next();
+                    r.setInput( iis );
+                    BufferedImage img = r.read(0);
+
+                    int[] dpi = getResolution(r);
+                    size.width = img.getWidth()*96/dpi[0];
+                    size.height = img.getHeight()*96/dpi[1];
+
+                } catch (IOException e){
+                    //silently return if ImageIO failed to read the image
+                    log.log(POILogger.WARN, e);
+                }
+
+                break;
+        }
+        return size;
+    }
 }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java Sat Jun 21 05:03:44 2008
@@ -276,8 +276,23 @@
 
     /**
      * Get the hssfcell representing a given column (logical cell)
-     *  0-based.  If you ask for a cell that is not defined....
+     *  0-based. If you ask for a cell that is not defined, then
      *  you get a null.
+     * This is the basic call, with no policies applied
+     *
+     * @param cellnum  0 based column number
+     * @return HSSFCell representing that column or null if undefined.
+     */
+    private HSSFCell retrieveCell(int cellnum) {
+        if(cellnum<0||cellnum>=cells.length) return null;
+        return cells[cellnum];
+    }
+    
+    /**
+     * Get the hssfcell representing a given column (logical cell)
+     *  0-based.  If you ask for a cell that is not defined then
+     *  you get a null, unless you have set a different
+     *  {@link MissingCellPolicy} on the base workbook.
      * Short method signature provided to retain binary
      *  compatibility.
      *
@@ -288,24 +303,54 @@
         int ushortCellNum = cellnum & 0x0000FFFF; // avoid sign extension
         return getCell(ushortCellNum);
     }
+    
     /**
      * Get the hssfcell representing a given column (logical cell)
-     *  0-based.  If you ask for a cell that is not defined....
-     *  you get a null.
+     *  0-based.  If you ask for a cell that is not defined then
+     *  you get a null, unless you have set a different
+     *  {@link MissingCellPolicy} on the base workbook.
      *
      * @param cellnum  0 based column number
      * @return HSSFCell representing that column or null if undefined.
      */
     public HSSFCell getCell(int cellnum) {
-        if(cellnum<0||cellnum>=cells.length) return null;
-        return cells[cellnum];
+    	return getCell(cellnum, book.getMissingCellPolicy());
+    }
+    
+    /**
+     * Get the hssfcell representing a given column (logical cell)
+     *  0-based.  If you ask for a cell that is not defined, then
+     *  your supplied policy says what to do
+     *
+     * @param cellnum  0 based column number
+     * @param policy Policy on blank / missing cells
+     * @return representing that column or null if undefined + policy allows.
+     */
+    public HSSFCell getCell(int cellnum, MissingCellPolicy policy) {
+    	HSSFCell cell = retrieveCell(cellnum);
+    	if(policy == RETURN_NULL_AND_BLANK) {
+    		return cell;
+    	}
+    	if(policy == RETURN_BLANK_AS_NULL) {
+    		if(cell == null) return cell;
+    		if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) {
+    			return null;
+    		}
+    		return cell;
+    	}
+    	if(policy == CREATE_NULL_AS_BLANK) {
+    		if(cell == null) {
+    			return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK);
+    		}
+    		return cell;
+    	}
+    	throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
     }
 
     /**
      * get the number of the first cell contained in this row.
      * @return short representing the first logical cell in the row, or -1 if the row does not contain any cells.
      */
-
     public short getFirstCellNum()
     {
         if (getPhysicalNumberOfCells() == 0)
@@ -467,6 +512,26 @@
     }
 
     /**
+     * Used to specify the different possible policies
+     *  if for the case of null and blank cells
+     */
+    public static class MissingCellPolicy {
+    	private static int NEXT_ID = 1;
+    	private final int id;
+    	private MissingCellPolicy() {
+    		this.id = NEXT_ID++;
+    	}
+    }
+
+    /** Missing cells are returned as null, Blank cells are returned as normal */
+    public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy();
+    /** Missing cells are returned as null, as are blank cells */
+    public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy();
+    /** A new, blank cell is created for missing cells. Blank cells are returned as normal */
+    public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy();
+    
+
+    /**
      * @return cell iterator of the physically defined cells. 
      * Note that the 4th element might well not be cell 4, as the iterator
      *  will not return un-defined (null) cells.
@@ -484,6 +549,9 @@
        return cellIterator();
     }
     
+    /**
+     * An iterator over the (physical) cells in the row.
+     */
     private class CellIterator implements Iterator
     {
       int thisId=-1;

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Sat Jun 21 05:03:44 2008
@@ -37,7 +37,7 @@
 import org.apache.poi.hssf.model.Workbook;
 import org.apache.poi.hssf.record.*;
 import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.ReferencePtg;
+import org.apache.poi.hssf.record.formula.RefPtg;
 import org.apache.poi.hssf.util.HSSFCellRangeAddress;
 import org.apache.poi.hssf.util.HSSFDataValidation;
 import org.apache.poi.hssf.util.PaneInformation;
@@ -1304,8 +1304,8 @@
                     Ptg[] ptgs = fp.getRPNPtg();
                     boolean changed = false;
                     for(int i=0; i<ptgs.length; i++) {
-                        if(ptgs[i] instanceof ReferencePtg) {
-                            ReferencePtg rptg = (ReferencePtg)ptgs[i];
+                        if(ptgs[i] instanceof RefPtg) {
+                            RefPtg rptg = (RefPtg)ptgs[i];
                             if(startRow <= rptg.getRowAsInt() &&
                                     rptg.getRowAsInt() <= endRow) {
                                 // References a row that moved

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java Sat Jun 21 05:03:44 2008
@@ -39,7 +39,8 @@
 
 	/**
 	 * A factory method allowing to create a conditional formatting rule
-	 * with a cell comparison operator 
+	 * with a cell comparison operator<p/>
+	 * TODO - formulas containing cell references are currently not parsed properly 
 	 *
 	 * @param comparisonOperation - a constant value from
 	 *		 <tt>{@link HSSFConditionalFormattingRule.ComparisonOperator}</tt>: <p>
@@ -72,8 +73,8 @@
 	/**
 	 * A factory method allowing to create a conditional formatting rule with a formula.<br>
 	 *
-	 * The formatting rules are applied by Excel when the value of the formula not equal to 0.
-	 *
+	 * The formatting rules are applied by Excel when the value of the formula not equal to 0.<p/>
+	 * TODO - formulas containing cell references are currently not parsed properly
 	 * @param formula - formula for the valued, compared with the cell
 	 */
 	public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) {

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java Sat Jun 21 05:03:44 2008
@@ -15,12 +15,6 @@
    limitations under the License.
 ==================================================================== */
 
-
-/*
- * HSSFWorkbook.java
- *
- * Created on September 30, 2001, 3:37 PM
- */
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.POIDocument;
@@ -35,6 +29,7 @@
 import org.apache.poi.hssf.record.formula.Area3DPtg;
 import org.apache.poi.hssf.record.formula.MemFuncPtg;
 import org.apache.poi.hssf.record.formula.UnionPtg;
+import org.apache.poi.hssf.usermodel.HSSFRow.MissingCellPolicy;
 import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.hssf.util.SheetReferences;
 import org.apache.poi.poifs.filesystem.*;
@@ -64,7 +59,6 @@
  * @author  Shawn Laubach (slaubach at apache dot org)
  * @version 2.0-pre
  */
-
 public class HSSFWorkbook extends POIDocument
 {
     private static final int DEBUG = POILogger.DEBUG;
@@ -88,7 +82,7 @@
      * this holds the HSSFSheet objects attached to this workbook
      */
 
-    protected ArrayList sheets;
+    protected List _sheets;
 
     /**
      * this holds the HSSFName objects attached to this workbook
@@ -109,6 +103,13 @@
      * someplace else.
      */
     private HSSFDataFormat formatter;
+    
+    /**
+     * The policy to apply in the event of missing or
+     *  blank cells when fetching from a row.
+     * See {@link MissingCellPolicy}
+     */
+    private MissingCellPolicy missingCellPolicy = HSSFRow.RETURN_NULL_AND_BLANK;
 
 
     /** Extended windows meta file */
@@ -142,7 +143,7 @@
     {
         super(null, null);
         workbook = book;
-        sheets = new ArrayList( INITIAL_CAPACITY );
+        _sheets = new ArrayList( INITIAL_CAPACITY );
         names = new ArrayList( INITIAL_CAPACITY );
     }
 
@@ -233,7 +234,7 @@
            this.directory = null;
         }
 
-        sheets = new ArrayList(INITIAL_CAPACITY);
+        _sheets = new ArrayList(INITIAL_CAPACITY);
         names  = new ArrayList(INITIAL_CAPACITY);
 
         // Grab the data from the workbook stream, however
@@ -263,7 +264,7 @@
 
             HSSFSheet hsheet = new HSSFSheet(this, sheet);
 
-            sheets.add(hsheet);
+            _sheets.add(hsheet);
 
             // workbook.setSheetName(sheets.size() -1, "Sheet"+sheets.size());
         }
@@ -352,8 +353,28 @@
              log.log(POILogger.DEBUG, "convertLabelRecords exit");
      }
 
+	/**
+	 * Retrieves the current policy on what to do when
+	 *  getting missing or blank cells from a row.
+	 * The default is to return blank and null cells.
+	 *  {@link MissingCellPolicy}
+	 */
+	public MissingCellPolicy getMissingCellPolicy() {
+		return missingCellPolicy;
+	}
+
+	/**
+	 * Sets the policy on what to do when
+	 *  getting missing or blank cells from a row.
+	 * This will then apply to all calls to 
+	 *  {@link HSSFRow.getCell()}. See
+	 *  {@link MissingCellPolicy}
+	 */
+	public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) {
+		this.missingCellPolicy = missingCellPolicy;
+	}
 
-    /**
+	/**
      * sets the order of appearance for a given sheet.
      *
      * @param sheetname the name of the sheet to reorder
@@ -361,12 +382,12 @@
      */
 
     public void setSheetOrder(String sheetname, int pos ) {
-        sheets.add(pos,sheets.remove(getSheetIndex(sheetname)));
+        _sheets.add(pos,_sheets.remove(getSheetIndex(sheetname)));
         workbook.setSheetOrder(sheetname, pos);
     }
 
     private void validateSheetIndex(int index) {
-        int lastSheetIx = sheets.size() - 1;
+        int lastSheetIx = _sheets.size() - 1;
         if (index < 0 || index > lastSheetIx) {
             throw new IllegalArgumentException("Sheet index (" 
                     + index +") is out of range (0.." +    lastSheetIx + ")");
@@ -380,7 +401,7 @@
     public void setSelectedTab(int index) {
         
         validateSheetIndex(index);
-        int nSheets = sheets.size();
+        int nSheets = _sheets.size();
         for (int i=0; i<nSheets; i++) {
                getSheetAt(i).setSelected(i == index);
         }
@@ -398,7 +419,7 @@
         for (int i = 0; i < indexes.length; i++) {
             validateSheetIndex(indexes[i]);
         }
-        int nSheets = sheets.size();
+        int nSheets = _sheets.size();
         for (int i=0; i<nSheets; i++) {
             boolean bSelect = false;
             for (int j = 0; j < indexes.length; j++) {
@@ -420,7 +441,7 @@
     public void setActiveSheet(int index) {
         
         validateSheetIndex(index);
-        int nSheets = sheets.size();
+        int nSheets = _sheets.size();
         for (int i=0; i<nSheets; i++) {
              getSheetAt(i).setActive(i == index);
         }
@@ -492,19 +513,15 @@
      * set the sheet name.
      * Will throw IllegalArgumentException if the name is greater than 31 chars
      * or contains /\?*[]
-     * @param sheet number (0 based)
+     * @param sheetIx number (0 based)
      */
-    public void setSheetName(int sheet, String name)
+    public void setSheetName(int sheetIx, String name)
     {
-        if (workbook.doesContainsSheetName( name, sheet ))
+        if (workbook.doesContainsSheetName( name, sheetIx )) {
             throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
-
-        if (sheet > (sheets.size() - 1))
-        {
-            throw new RuntimeException("Sheet out of bounds");
         }
-
-        workbook.setSheetName( sheet, name);
+        validateSheetIndex(sheetIx);
+        workbook.setSheetName(sheetIx, name);
     }
 
 
@@ -516,15 +533,12 @@
      * or contains /\?*[]
      * @param sheet number (0 based)
      */
-    public void setSheetName( int sheet, String name, short encoding )
+    public void setSheetName(int sheetIx, String name, short encoding)
     {
-        if (workbook.doesContainsSheetName( name, sheet ))
+        if (workbook.doesContainsSheetName( name, sheetIx )) {
             throw new IllegalArgumentException( "The workbook already contains a sheet with this name" );
-
-        if (sheet > (sheets.size() - 1))
-        {
-            throw new RuntimeException("Sheet out of bounds");
         }
+        validateSheetIndex(sheetIx);
 
         switch ( encoding ) {
         case ENCODING_COMPRESSED_UNICODE:
@@ -536,51 +550,39 @@
             throw new RuntimeException( "Unsupported encoding" );
         }
 
-        workbook.setSheetName( sheet, name, encoding );
+        workbook.setSheetName( sheetIx, name, encoding );
     }
 
     /**
      * get the sheet name
-     * @param sheet Number
+     * @param sheetIx Number
      * @return Sheet name
      */
-
-    public String getSheetName(int sheet)
+    public String getSheetName(int sheetIx)
     {
-        if (sheet > (sheets.size() - 1))
-        {
-            throw new RuntimeException("Sheet out of bounds");
-        }
-        return workbook.getSheetName(sheet);
+        validateSheetIndex(sheetIx);
+        return workbook.getSheetName(sheetIx);
     }
 
     /**
      * check whether a sheet is hidden
-     * @param sheet Number
+     * @param sheetIx Number
      * @return True if sheet is hidden
      */
-
-    public boolean isSheetHidden(int sheet) {
-        if (sheet > (sheets.size() - 1))
-        {
-            throw new RuntimeException("Sheet out of bounds");
-        }
-        return workbook.isSheetHidden(sheet);
+    public boolean isSheetHidden(int sheetIx) {
+        validateSheetIndex(sheetIx);
+        return workbook.isSheetHidden(sheetIx);
     }
 
     /**
      * Hide or unhide a sheet
      *
-     * @param sheetnum The sheet number
+     * @param sheetIx The sheet index
      * @param hidden True to mark the sheet as hidden, false otherwise
      */
-
-    public void setSheetHidden(int sheet, boolean hidden) {
-        if (sheet > (sheets.size() - 1))
-        {
-            throw new RuntimeException("Sheet out of bounds");
-        }
-        workbook.setSheetHidden(sheet,hidden);
+    public void setSheetHidden(int sheetIx, boolean hidden) {
+        validateSheetIndex(sheetIx);
+        workbook.setSheetHidden(sheetIx, hidden);
     }
 
     /*
@@ -602,12 +604,12 @@
 
     /** Returns the index of the given sheet
      * @param sheet the sheet to look up
-     * @return index of the sheet (0 based)
+     * @return index of the sheet (0 based). <tt>-1</tt> if not found
      */
     public int getSheetIndex(HSSFSheet sheet)
     {
-        for(int i=0; i<sheets.size(); i++) {
-            if(sheets.get(i) == sheet) {
+        for(int i=0; i<_sheets.size(); i++) {
+            if(_sheets.get(i) == sheet) {
                 return i;
             }
         }
@@ -636,9 +638,9 @@
     {
         HSSFSheet sheet = new HSSFSheet(this);
 
-        sheets.add(sheet);
-        workbook.setSheetName(sheets.size() - 1, "Sheet" + (sheets.size() - 1));
-        boolean isOnlySheet = sheets.size() == 1;
+        _sheets.add(sheet);
+        workbook.setSheetName(_sheets.size() - 1, "Sheet" + (_sheets.size() - 1));
+        boolean isOnlySheet = _sheets.size() == 1;
         sheet.setSelected(isOnlySheet);
         sheet.setActive(isOnlySheet);
         return sheet;
@@ -652,13 +654,13 @@
 
     public HSSFSheet cloneSheet(int sheetNum) {
         validateSheetIndex(sheetNum);
-        HSSFSheet srcSheet = (HSSFSheet) sheets.get(sheetNum);
+        HSSFSheet srcSheet = (HSSFSheet) _sheets.get(sheetNum);
         String srcName = workbook.getSheetName(sheetNum);
         HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
         clonedSheet.setSelected(false);
         clonedSheet.setActive(false);
 
-        sheets.add(clonedSheet);
+        _sheets.add(clonedSheet);
         int i = 1;
         while (true) {
             // Try and find the next sheet name that is unique
@@ -672,7 +674,7 @@
 
             //If the sheet name is unique, then set it otherwise move on to the next number.
             if (workbook.getSheetIndex(name) == -1) {
-              workbook.setSheetName(sheets.size()-1, name);
+              workbook.setSheetName(_sheets.size()-1, name);
               break;
             }
         }
@@ -693,14 +695,14 @@
 
     public HSSFSheet createSheet(String sheetname)
     {
-        if (workbook.doesContainsSheetName( sheetname, sheets.size() ))
+        if (workbook.doesContainsSheetName( sheetname, _sheets.size() ))
             throw new IllegalArgumentException( "The workbook already contains a sheet of this name" );
 
         HSSFSheet sheet = new HSSFSheet(this);
 
-        sheets.add(sheet);
-        workbook.setSheetName(sheets.size() - 1, sheetname);
-        boolean isOnlySheet = sheets.size() == 1;
+        _sheets.add(sheet);
+        workbook.setSheetName(_sheets.size() - 1, sheetname);
+        boolean isOnlySheet = _sheets.size() == 1;
         sheet.setSelected(isOnlySheet);
         sheet.setActive(isOnlySheet);
         return sheet;
@@ -713,9 +715,14 @@
 
     public int getNumberOfSheets()
     {
-        return sheets.size();
+        return _sheets.size();
     }
 
+    private HSSFSheet[] getSheets() {
+        HSSFSheet[] result = new HSSFSheet[_sheets.size()];
+        _sheets.toArray(result);
+        return result;
+    }
     /**
      * Get the HSSFSheet object at the given index.
      * @param index of the sheet number (0-based physical & logical)
@@ -724,7 +731,7 @@
 
     public HSSFSheet getSheetAt(int index)
     {
-        return (HSSFSheet) sheets.get(index);
+        return (HSSFSheet) _sheets.get(index);
     }
 
     /**
@@ -737,13 +744,13 @@
     {
         HSSFSheet retval = null;
 
-        for (int k = 0; k < sheets.size(); k++)
+        for (int k = 0; k < _sheets.size(); k++)
         {
             String sheetname = workbook.getSheetName(k);
 
             if (sheetname.equalsIgnoreCase(name))
             {
-                retval = (HSSFSheet) sheets.get(k);
+                retval = (HSSFSheet) _sheets.get(k);
             }
         }
         return retval;
@@ -772,11 +779,11 @@
         boolean wasActive = getSheetAt(index).isActive();
         boolean wasSelected = getSheetAt(index).isSelected();
 
-        sheets.remove(index);
+        _sheets.remove(index);
         workbook.removeSheet(index);
 
         // set the remaining active/selected sheet
-        int nSheets = sheets.size();
+        int nSheets = _sheets.size();
         if (nSheets < 1) {
             // nothing more to do if there are no sheets left
             return;
@@ -902,9 +909,7 @@
 
         if (settingRowAndColumn)
         {
-            MemFuncPtg memFuncPtg = new MemFuncPtg();
-            memFuncPtg.setLenRefSubexpression(23);
-            ptgs.add(memFuncPtg);
+            ptgs.add(new MemFuncPtg(23)); // TODO - where did constant '23' come from?
         }
         if (startColumn >= 0)
         {
@@ -928,8 +933,7 @@
         }
         if (settingRowAndColumn)
         {
-            UnionPtg unionPtg = new UnionPtg();
-            ptgs.add(unionPtg);
+            ptgs.add(UnionPtg.instance);
         }
         nameRecord.setNameDefinition(ptgs);
 
@@ -1152,48 +1156,47 @@
 
     public byte[] getBytes()
     {
-        if (log.check( POILogger.DEBUG ))
+        if (log.check( POILogger.DEBUG )) {
             log.log(DEBUG, "HSSFWorkbook.getBytes()");
+        }
+        
+        HSSFSheet[] sheets = getSheets();
+        int nSheets = sheets.length;
 
         // before getting the workbook size we must tell the sheets that
         // serialization is about to occur.
-        for (int k = 0; k < sheets.size(); k++)
-            ((HSSFSheet) sheets.get(k)).getSheet().preSerialize();
-
-        int wbsize = workbook.getSize();
+        for (int i = 0; i < nSheets; i++) {
+            sheets[i].getSheet().preSerialize();
+        }
 
-        // log.debug("REMOVEME: old sizing method "+workbook.serialize().length);
-        // ArrayList sheetbytes = new ArrayList(sheets.size());
-        int totalsize = wbsize;
+        int totalsize = workbook.getSize();
 
-        for (int k = 0; k < sheets.size(); k++)
-        {
+        // pre-calculate all the sheet sizes and set BOF indexes
+        int[] estimatedSheetSizes = new int[nSheets];
+        for (int k = 0; k < nSheets; k++) {
             workbook.setSheetBof(k, totalsize);
-            totalsize += ((HSSFSheet) sheets.get(k)).getSheet().getSize();
+            int sheetSize = sheets[k].getSheet().getSize();
+            estimatedSheetSizes[k] = sheetSize;
+            totalsize += sheetSize;
         }
 
 
-/*        if (totalsize < 4096)
-        {
-            totalsize = 4096;
-        }*/
         byte[] retval = new byte[totalsize];
         int pos = workbook.serialize(0, retval);
 
-        // System.arraycopy(wb, 0, retval, 0, wb.length);
-        for (int k = 0; k < sheets.size(); k++)
-        {
-
-            // byte[] sb = (byte[])sheetbytes.get(k);
-            // System.arraycopy(sb, 0, retval, pos, sb.length);
-            int len = ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
-                                retval);
-            pos += len;   // sb.length;
+        for (int k = 0; k < nSheets; k++) {
+            int serializedSize = sheets[k].getSheet().serialize(pos, retval);
+            if (serializedSize != estimatedSheetSizes[k]) {
+                // Wrong offset values have been passed in the call to setSheetBof() above.
+                // For books with more than one sheet, this discrepancy would cause excel 
+                // to report errors and loose data while reading the workbook
+                throw new IllegalStateException("Actual serialized sheet size (" + serializedSize 
+                        + ") differs from pre-calculated size (" + estimatedSheetSizes[k] 
+                        + ") for sheet (" + k + ")");
+                // TODO - add similar sanity check to ensure that Sheet.serializeIndexRecord() does not write mis-aligned offsets either
+            }
+            pos += serializedSize;
         }
-/*        for (int k = pos; k < totalsize; k++)
-        {
-            retval[k] = 0;
-        }*/
         return retval;
     }
 

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/AreaReference.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/AreaReference.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/AreaReference.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/AreaReference.java Sat Jun 21 05:03:44 2008
@@ -15,12 +15,13 @@
    limitations under the License.
 ==================================================================== */
 
-
 package org.apache.poi.hssf.util;
 
 import java.util.ArrayList;
 import java.util.StringTokenizer;
 
+import org.apache.poi.hssf.record.formula.AreaI;
+
 public final class AreaReference {
 
     /** The character (!) that separates sheet names from cell references */ 
@@ -50,13 +51,13 @@
         
         // Special handling for whole-column references
         if(parts.length == 2 && parts[0].length() == 1 &&
-        		parts[1].length() == 1 && 
-        		parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
-        		parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
-        	// Represented internally as x$1 to x$65536
-        	//  which is the maximum range of rows
-        	parts[0] = parts[0] + "$1";
-        	parts[1] = parts[1] + "$65536";
+                parts[1].length() == 1 && 
+                parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
+                parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
+            // Represented internally as x$1 to x$65536
+            //  which is the maximum range of rows
+            parts[0] = parts[0] + "$1";
+            parts[1] = parts[1] + "$65536";
         }
         
         _firstCell = new CellReference(parts[0]);
@@ -74,9 +75,9 @@
      * Creates an area ref from a pair of Cell References.
      */
     public AreaReference(CellReference topLeft, CellReference botRight) {
-    	_firstCell = topLeft;
-    	_lastCell = botRight;
-    	_isSingleCell = false;
+        _firstCell = topLeft;
+        _lastCell = botRight;
+        _isSingleCell = false;
     }
 
     /**
@@ -98,17 +99,17 @@
      *  such as C:C or D:G ?
      */
     public static boolean isWholeColumnReference(CellReference topLeft, CellReference botRight) {
-    	// These are represented as something like
-    	//   C$1:C$65535 or D$1:F$0
-    	// i.e. absolute from 1st row to 0th one
-    	if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
-    		botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
-    		return true;
-    	}
-    	return false;
+        // These are represented as something like
+        //   C$1:C$65535 or D$1:F$0
+        // i.e. absolute from 1st row to 0th one
+        if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
+            botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
+            return true;
+        }
+        return false;
     }
     public boolean isWholeColumnReference() {
-    	return isWholeColumnReference(_firstCell, _lastCell);
+        return isWholeColumnReference(_firstCell, _lastCell);
     }
 
     /**
@@ -155,26 +156,26 @@
      * Returns a reference to every cell covered by this area
      */
     public CellReference[] getAllReferencedCells() {
-    	// Special case for single cell reference
-    	if(_isSingleCell) {
-    		return  new CellReference[] { _firstCell, };
-    	}
+        // Special case for single cell reference
+        if(_isSingleCell) {
+            return  new CellReference[] { _firstCell, };
+        }
  
-    	// Interpolate between the two
+        // Interpolate between the two
         int minRow = Math.min(_firstCell.getRow(), _lastCell.getRow());
-    	int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
-    	int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
-    	int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
+        int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
+        int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
+        int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
         String sheetName = _firstCell.getSheetName();
-    	
-    	ArrayList refs = new ArrayList();
-    	for(int row=minRow; row<=maxRow; row++) {
-    		for(int col=minCol; col<=maxCol; col++) {
-    			CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
-    			refs.add(ref);
-    		}
-    	}
-    	return (CellReference[])refs.toArray(new CellReference[refs.size()]);
+        
+        ArrayList refs = new ArrayList();
+        for(int row=minRow; row<=maxRow; row++) {
+            for(int col=minCol; col<=maxCol; col++) {
+                CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
+                refs.add(ref);
+            }
+        }
+        return (CellReference[])refs.toArray(new CellReference[refs.size()]);
     }
 
     /**
@@ -189,14 +190,14 @@
      * @return the text representation of this area reference as it would appear in a formula.
      */
     public String formatAsString() {
-    	// Special handling for whole-column references
-    	if(isWholeColumnReference()) {
-    		return
-    			CellReference.convertNumToColString(_firstCell.getCol())
-    			+ ":" +
-    			CellReference.convertNumToColString(_lastCell.getCol());
-    	}
-    	
+        // Special handling for whole-column references
+        if(isWholeColumnReference()) {
+            return
+                CellReference.convertNumToColString(_firstCell.getCol())
+                + ":" +
+                CellReference.convertNumToColString(_lastCell.getCol());
+        }
+        
         StringBuffer sb = new StringBuffer(32);
         sb.append(_firstCell.formatAsString());
         if(!_isSingleCell) {
@@ -210,6 +211,18 @@
         }
         return sb.toString();
     }
+    /**
+     * Formats a 2-D area as it would appear in a formula.  See formatAsString() (no-arg)
+     */
+    public static String formatAsString(AreaI area) {
+        CellReference topLeft = new CellReference(area.getFirstRow(),area.getFirstColumn(),!area.isFirstRowRelative(),!area.isFirstColRelative());
+        CellReference botRight = new CellReference(area.getLastRow(),area.getLastColumn(),!area.isLastRowRelative(),!area.isLastColRelative());
+        
+        if(isWholeColumnReference(topLeft, botRight)) {
+            return (new AreaReference(topLeft, botRight)).formatAsString();
+        }
+        return topLeft.formatAsString() + ":" + botRight.formatAsString(); 
+    }
     public String toString() {
         StringBuffer sb = new StringBuffer(64);
         sb.append(getClass().getName()).append(" [");

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/HSSFColor.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/HSSFColor.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/HSSFColor.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/hssf/util/HSSFColor.java Sat Jun 21 05:03:44 2008
@@ -15,14 +15,14 @@
    limitations under the License.
 ==================================================================== */
 
-
 package org.apache.poi.hssf.util;
 
-import java.util.*;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
 
 /**
  * Intends to provide support for the very evil index to triplet issue and
- * will likely replace the color contants interface for HSSF 2.0.
+ * will likely replace the color constants interface for HSSF 2.0.
  * This class contains static inner class members for representing colors.
  * Each color has an index (for the standard palette in Excel (tm) ),
  * native (RGB) triplet and string triplet.  The string triplet is as the
@@ -33,14 +33,9 @@
  * @author  Andrew C. Oliver (acoliver at apache dot org)
  * @author  Brian Sanders (bsanders at risklabs dot com) - full default color palette
  */
-
-public class HSSFColor
-{
-    private final static int PALETTE_SIZE = 56;
-    private final static int DISTINCT_COLOR_COUNT = 46;
-
+public class HSSFColor {
+    // TODO make subclass instances immutable
     /** Creates a new instance of HSSFColor */
-
     public HSSFColor()
     {
     }
@@ -52,87 +47,86 @@
      * it takes to create it once per request but you will not hold onto it
      * if you have none of those requests.
      *
-     * @return a hashtable containing all colors mapped to their excel-style 
-     * pallette index
+     * @return a hashtable containing all colors keyed by <tt>Integer</tt> excel-style palette indexes
      */
     public final static Hashtable getIndexHash() {
 
-        Hashtable hash = new Hashtable(PALETTE_SIZE);
+        return createColorsByIndexMap();
+    }
 
-        hash.put(new Integer(HSSFColor.BLACK.index), new HSSFColor.BLACK());
-        hash.put(new Integer(HSSFColor.BROWN.index), new HSSFColor.BROWN());
-        hash.put(new Integer(HSSFColor.OLIVE_GREEN.index),
-                 new HSSFColor.OLIVE_GREEN());
-        hash.put(new Integer(HSSFColor.DARK_GREEN.index), new HSSFColor.DARK_GREEN());
-        hash.put(new Integer(HSSFColor.DARK_TEAL.index), new HSSFColor.DARK_TEAL());
-        hash.put(new Integer(HSSFColor.DARK_BLUE.index), new HSSFColor.DARK_BLUE());
-        hash.put(new Integer(HSSFColor.DARK_BLUE.index2), new HSSFColor.DARK_BLUE());
-        hash.put(new Integer(HSSFColor.INDIGO.index), new HSSFColor.INDIGO());
-        hash.put(new Integer(HSSFColor.GREY_80_PERCENT.index),
-                 new HSSFColor.GREY_80_PERCENT());
-        hash.put(new Integer(HSSFColor.ORANGE.index), new HSSFColor.ORANGE());
-        hash.put(new Integer(HSSFColor.DARK_YELLOW.index),
-                 new HSSFColor.DARK_YELLOW());
-        hash.put(new Integer(HSSFColor.GREEN.index), new HSSFColor.GREEN());
-        hash.put(new Integer(HSSFColor.TEAL.index), new HSSFColor.TEAL());
-        hash.put(new Integer(HSSFColor.TEAL.index2), new HSSFColor.TEAL());
-        hash.put(new Integer(HSSFColor.BLUE.index), new HSSFColor.BLUE());
-        hash.put(new Integer(HSSFColor.BLUE.index2), new HSSFColor.BLUE());
-        hash.put(new Integer(HSSFColor.BLUE_GREY.index), new HSSFColor.BLUE_GREY());
-        hash.put(new Integer(HSSFColor.GREY_50_PERCENT.index),
-                 new HSSFColor.GREY_50_PERCENT());
-        hash.put(new Integer(HSSFColor.RED.index), new HSSFColor.RED());
-        hash.put(new Integer(HSSFColor.LIGHT_ORANGE.index),
-                 new HSSFColor.LIGHT_ORANGE());
-        hash.put(new Integer(HSSFColor.LIME.index), new HSSFColor.LIME());
-        hash.put(new Integer(HSSFColor.SEA_GREEN.index), new HSSFColor.SEA_GREEN());
-        hash.put(new Integer(HSSFColor.AQUA.index), new HSSFColor.AQUA());
-        hash.put(new Integer(HSSFColor.LIGHT_BLUE.index), new HSSFColor.LIGHT_BLUE());
-        hash.put(new Integer(HSSFColor.VIOLET.index), new HSSFColor.VIOLET());
-        hash.put(new Integer(HSSFColor.VIOLET.index2), new HSSFColor.VIOLET());
-        hash.put(new Integer(HSSFColor.GREY_40_PERCENT.index),
-                 new HSSFColor.GREY_40_PERCENT());
-        hash.put(new Integer(HSSFColor.PINK.index), new HSSFColor.PINK());
-        hash.put(new Integer(HSSFColor.PINK.index2), new HSSFColor.PINK());
-        hash.put(new Integer(HSSFColor.GOLD.index), new HSSFColor.GOLD());
-        hash.put(new Integer(HSSFColor.YELLOW.index), new HSSFColor.YELLOW());
-        hash.put(new Integer(HSSFColor.YELLOW.index2), new HSSFColor.YELLOW());
-        hash.put(new Integer(HSSFColor.BRIGHT_GREEN.index),
-                 new HSSFColor.BRIGHT_GREEN());
-        hash.put(new Integer(HSSFColor.BRIGHT_GREEN.index2),
-                 new HSSFColor.BRIGHT_GREEN());
-        hash.put(new Integer(HSSFColor.TURQUOISE.index), new HSSFColor.TURQUOISE());
-        hash.put(new Integer(HSSFColor.TURQUOISE.index2), new HSSFColor.TURQUOISE());
-        hash.put(new Integer(HSSFColor.DARK_RED.index), new HSSFColor.DARK_RED());
-        hash.put(new Integer(HSSFColor.DARK_RED.index2), new HSSFColor.DARK_RED());
-        hash.put(new Integer(HSSFColor.SKY_BLUE.index), new HSSFColor.SKY_BLUE());
-        hash.put(new Integer(HSSFColor.PLUM.index), new HSSFColor.PLUM());
-        hash.put(new Integer(HSSFColor.PLUM.index2), new HSSFColor.PLUM());
-        hash.put(new Integer(HSSFColor.GREY_25_PERCENT.index),
-                 new HSSFColor.GREY_25_PERCENT());
-        hash.put(new Integer(HSSFColor.ROSE.index), new HSSFColor.ROSE());
-        hash.put(new Integer(HSSFColor.LIGHT_YELLOW.index),
-                 new HSSFColor.LIGHT_YELLOW());
-        hash.put(new Integer(HSSFColor.LIGHT_GREEN.index),
-                 new HSSFColor.LIGHT_GREEN());
-        hash.put(new Integer(HSSFColor.LIGHT_TURQUOISE.index),
-                 new HSSFColor.LIGHT_TURQUOISE());
-        hash.put(new Integer(HSSFColor.LIGHT_TURQUOISE.index2),
-                 new HSSFColor.LIGHT_TURQUOISE());
-        hash.put(new Integer(HSSFColor.PALE_BLUE.index), new HSSFColor.PALE_BLUE());
-        hash.put(new Integer(HSSFColor.LAVENDER.index), new HSSFColor.LAVENDER());
-        hash.put(new Integer(HSSFColor.WHITE.index), new HSSFColor.WHITE());
-        hash.put(new Integer(HSSFColor.CORNFLOWER_BLUE.index),
-                 new HSSFColor.CORNFLOWER_BLUE());
-        hash.put(new Integer(HSSFColor.LEMON_CHIFFON.index),
-                 new HSSFColor.LEMON_CHIFFON());
-        hash.put(new Integer(HSSFColor.MAROON.index), new HSSFColor.MAROON());
-        hash.put(new Integer(HSSFColor.ORCHID.index), new HSSFColor.ORCHID());
-        hash.put(new Integer(HSSFColor.CORAL.index), new HSSFColor.CORAL());
-        hash.put(new Integer(HSSFColor.ROYAL_BLUE.index), new HSSFColor.ROYAL_BLUE());
-        hash.put(new Integer(HSSFColor.LIGHT_CORNFLOWER_BLUE.index),
-                 new HSSFColor.LIGHT_CORNFLOWER_BLUE());
-	return hash;
+    private static Hashtable createColorsByIndexMap() {
+        HSSFColor[] colors = getAllColors();
+        Hashtable result = new Hashtable(colors.length * 3 / 2);
+
+        for (int i = 0; i < colors.length; i++) {
+            HSSFColor color = colors[i];
+
+            Integer index1 = new Integer(color.getIndex());
+            if (result.containsKey(index1)) {
+                HSSFColor prevColor = (HSSFColor)result.get(index1);
+                throw new RuntimeException("Dup color index (" + index1
+                        + ") for colors (" + prevColor.getClass().getName()
+                        + "),(" + color.getClass().getName() + ")");
+            }
+            result.put(index1, color);
+        }
+
+        for (int i = 0; i < colors.length; i++) {
+            HSSFColor color = colors[i];
+            Integer index2 = getIndex2(color);
+            if (index2 == null) {
+                // most colors don't have a second index
+                continue;
+            }
+            if (result.containsKey(index2)) {
+                if (false) { // Many of the second indexes clash
+                    HSSFColor prevColor = (HSSFColor)result.get(index2);
+                    throw new RuntimeException("Dup color index (" + index2
+                            + ") for colors (" + prevColor.getClass().getName()
+                            + "),(" + color.getClass().getName() + ")");
+                }
+            }
+            result.put(index2, color);
+        }
+        return result;
+    }
+
+    private static Integer getIndex2(HSSFColor color) {
+
+        Field f;
+        try {
+            f = color.getClass().getDeclaredField("index2");
+        } catch (NoSuchFieldException e) {
+            // can happen because not all colors have a second index
+            return null;
+        }
+
+        Short s;
+        try {
+            s = (Short) f.get(color);
+        } catch (IllegalArgumentException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+        return new Integer(s.intValue());
+    }
+
+    private static HSSFColor[] getAllColors() {
+
+        return new HSSFColor[] {
+                new BLACK(), new BROWN(), new OLIVE_GREEN(), new DARK_GREEN(),
+                new DARK_TEAL(), new DARK_BLUE(), new INDIGO(), new GREY_80_PERCENT(),
+                new ORANGE(), new DARK_YELLOW(), new GREEN(), new TEAL(), new BLUE(),
+                new BLUE_GREY(), new GREY_50_PERCENT(), new RED(), new LIGHT_ORANGE(), new LIME(),
+                new SEA_GREEN(), new AQUA(), new LIGHT_BLUE(), new VIOLET(), new GREY_40_PERCENT(),
+                new PINK(), new GOLD(), new YELLOW(), new BRIGHT_GREEN(), new TURQUOISE(),
+                new DARK_RED(), new SKY_BLUE(), new PLUM(), new GREY_25_PERCENT(), new ROSE(),
+                new LIGHT_YELLOW(), new LIGHT_GREEN(), new LIGHT_TURQUOISE(), new PALE_BLUE(),
+                new LAVENDER(), new WHITE(), new CORNFLOWER_BLUE(), new LEMON_CHIFFON(),
+                new MAROON(), new ORCHID(), new CORAL(), new ROYAL_BLUE(),
+                new LIGHT_CORNFLOWER_BLUE(), new TAN(),
+        };
     }
 
     /**
@@ -142,73 +136,28 @@
      * it takes to create it once per request but you will not hold onto it
      * if you have none of those requests.
      *
-     * @return a hashtable containing all colors mapped to their gnumeric-like
-     * triplet string
+     * @return a hashtable containing all colors keyed by String gnumeric-like triplets
      */
-
     public final static Hashtable getTripletHash()
     {
-        Hashtable hash = new Hashtable(DISTINCT_COLOR_COUNT);
+        return createColorsByHexStringMap();
+    }
+
+    private static Hashtable createColorsByHexStringMap() {
+        HSSFColor[] colors = getAllColors();
+        Hashtable result = new Hashtable(colors.length * 3 / 2);
 
-        hash.put(HSSFColor.BLACK.hexString, new HSSFColor.BLACK());
-        hash.put(HSSFColor.BROWN.hexString, new HSSFColor.BROWN());
-        hash.put(HSSFColor.OLIVE_GREEN.hexString,
-                 new HSSFColor.OLIVE_GREEN());
-        hash.put(HSSFColor.DARK_GREEN.hexString, new HSSFColor.DARK_GREEN());
-        hash.put(HSSFColor.DARK_TEAL.hexString, new HSSFColor.DARK_TEAL());
-        hash.put(HSSFColor.DARK_BLUE.hexString, new HSSFColor.DARK_BLUE());
-        hash.put(HSSFColor.INDIGO.hexString, new HSSFColor.INDIGO());
-        hash.put(HSSFColor.GREY_80_PERCENT.hexString,
-                 new HSSFColor.GREY_80_PERCENT());
-        hash.put(HSSFColor.ORANGE.hexString, new HSSFColor.ORANGE());
-        hash.put(HSSFColor.DARK_YELLOW.hexString,
-                 new HSSFColor.DARK_YELLOW());
-        hash.put(HSSFColor.GREEN.hexString, new HSSFColor.GREEN());
-        hash.put(HSSFColor.TEAL.hexString, new HSSFColor.TEAL());
-        hash.put(HSSFColor.BLUE.hexString, new HSSFColor.BLUE());
-        hash.put(HSSFColor.BLUE_GREY.hexString, new HSSFColor.BLUE_GREY());
-        hash.put(HSSFColor.GREY_50_PERCENT.hexString,
-                 new HSSFColor.GREY_50_PERCENT());
-        hash.put(HSSFColor.RED.hexString, new HSSFColor.RED());
-        hash.put(HSSFColor.LIGHT_ORANGE.hexString,
-                 new HSSFColor.LIGHT_ORANGE());
-        hash.put(HSSFColor.LIME.hexString, new HSSFColor.LIME());
-        hash.put(HSSFColor.SEA_GREEN.hexString, new HSSFColor.SEA_GREEN());
-        hash.put(HSSFColor.AQUA.hexString, new HSSFColor.AQUA());
-        hash.put(HSSFColor.LIGHT_BLUE.hexString, new HSSFColor.LIGHT_BLUE());
-        hash.put(HSSFColor.VIOLET.hexString, new HSSFColor.VIOLET());
-        hash.put(HSSFColor.GREY_40_PERCENT.hexString,
-                 new HSSFColor.GREY_40_PERCENT());
-        hash.put(HSSFColor.PINK.hexString, new HSSFColor.PINK());
-        hash.put(HSSFColor.GOLD.hexString, new HSSFColor.GOLD());
-        hash.put(HSSFColor.YELLOW.hexString, new HSSFColor.YELLOW());
-        hash.put(HSSFColor.BRIGHT_GREEN.hexString,
-                 new HSSFColor.BRIGHT_GREEN());
-        hash.put(HSSFColor.TURQUOISE.hexString, new HSSFColor.TURQUOISE());
-        hash.put(HSSFColor.DARK_RED.hexString, new HSSFColor.DARK_RED());
-        hash.put(HSSFColor.SKY_BLUE.hexString, new HSSFColor.SKY_BLUE());
-        hash.put(HSSFColor.PLUM.hexString, new HSSFColor.PLUM());
-        hash.put(HSSFColor.GREY_25_PERCENT.hexString,
-                 new HSSFColor.GREY_25_PERCENT());
-        hash.put(HSSFColor.ROSE.hexString, new HSSFColor.ROSE());
-        hash.put(HSSFColor.LIGHT_YELLOW.hexString,
-                 new HSSFColor.LIGHT_YELLOW());
-        hash.put(HSSFColor.LIGHT_GREEN.hexString,
-                 new HSSFColor.LIGHT_GREEN());
-        hash.put(HSSFColor.LIGHT_TURQUOISE.hexString,
-                 new HSSFColor.LIGHT_TURQUOISE());
-        hash.put(HSSFColor.PALE_BLUE.hexString, new HSSFColor.PALE_BLUE());
-        hash.put(HSSFColor.LAVENDER.hexString, new HSSFColor.LAVENDER());
-        hash.put(HSSFColor.WHITE.hexString, new HSSFColor.WHITE());
-        hash.put(HSSFColor.CORNFLOWER_BLUE.hexString, new HSSFColor.CORNFLOWER_BLUE());
-        hash.put(HSSFColor.LEMON_CHIFFON.hexString, new HSSFColor.LEMON_CHIFFON());
-        hash.put(HSSFColor.MAROON.hexString, new HSSFColor.MAROON());
-        hash.put(HSSFColor.ORCHID.hexString, new HSSFColor.ORCHID());
-        hash.put(HSSFColor.CORAL.hexString, new HSSFColor.CORAL());
-        hash.put(HSSFColor.ROYAL_BLUE.hexString, new HSSFColor.ROYAL_BLUE());
-        hash.put(HSSFColor.LIGHT_CORNFLOWER_BLUE.hexString,
-                 new HSSFColor.LIGHT_CORNFLOWER_BLUE());
-        return hash;
+        for (int i = 0; i < colors.length; i++) {
+            HSSFColor color = colors[i];
+
+            String hexString = color.getHexString();
+            if (result.containsKey(hexString)) {
+                throw new RuntimeException("Dup color hexString (" + hexString
+                        + ") for color (" + color.getClass().getName() + ")");
+            }
+            result.put(hexString, color);
+        }
+        return result;
     }
 
     /**
@@ -1490,7 +1439,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class CORNFLOWER_BLUE
      */
@@ -1519,8 +1468,8 @@
             return hexString;
         }
     }
-    
-    
+
+
     /**
      * Class LEMON_CHIFFON
      */
@@ -1549,7 +1498,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class MAROON
      */
@@ -1578,7 +1527,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class ORCHID
      */
@@ -1607,7 +1556,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class CORAL
      */
@@ -1636,7 +1585,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class ROYAL_BLUE
      */
@@ -1665,7 +1614,7 @@
             return hexString;
         }
     }
-    
+
     /**
      * Class LIGHT_CORNFLOWER_BLUE
      */
@@ -1694,19 +1643,19 @@
             return hexString;
         }
     }
-    
+
     /**
      * Special Default/Normal/Automatic color.
      * <p><i>Note:</i> This class is NOT in the default HashTables returned by HSSFColor.
      * The index is a special case which is interpreted in the various setXXXColor calls.
-     * 
+     *
      * @author Jason
      *
      */
     public final static class AUTOMATIC extends HSSFColor
     {
-    	private static HSSFColor instance = new AUTOMATIC();
-    	
+        private static HSSFColor instance = new AUTOMATIC();
+
         public final static short   index     = 0x40;
 
         public short getIndex()
@@ -1723,7 +1672,7 @@
         {
             return BLACK.hexString;
         }
-        
+
         public static HSSFColor getInstance() {
           return instance;
         }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlock.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlock.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlock.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlock.java Sat Jun 21 05:03:44 2008
@@ -37,6 +37,7 @@
 {
     private byte[]  _data;
     private boolean _eof;
+    private boolean _hasData;
     private static POILogger log = POILogFactory.getLogger(RawDataBlock.class);
 
     /**
@@ -66,6 +67,7 @@
     		throws IOException {
         _data = new byte[ blockSize ];
         int count = IOUtils.readFully(stream, _data);
+        _hasData = (count > 0);
 
         if (count == -1) {
             _eof = true;
@@ -94,16 +96,21 @@
     /**
      * When we read the data, did we hit end of file?
      *
-     * @return true if no data was read because we were at the end of
-     *         the file, else false
-     *
-     * @exception IOException
+     * @return true if the EoF was hit during this block, or
+     *  false if not. If you have a dodgy short last block, then
+     *  it's possible to both have data, and also hit EoF...
      */
-    public boolean eof()
-        throws IOException
-    {
+    public boolean eof() {
         return _eof;
     }
+    /**
+     * Did we actually find any data to read? It's possible,
+     *  in the event of a short last block, to both have hit
+     *  the EoF, but also to have data
+     */
+    public boolean hasData() {
+    	return _hasData;
+    }
 
     /* ********** START implementation of ListManagedBlock ********** */
 
@@ -117,7 +124,7 @@
     public byte [] getData()
         throws IOException
     {
-        if (eof())
+        if (! hasData())
         {
             throw new IOException("Cannot return empty data");
         }

Modified: poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java (original)
+++ poi/tags/REL_3_1_FINAL/src/java/org/apache/poi/poifs/storage/RawDataBlockList.java Sat Jun 21 05:03:44 2008
@@ -51,12 +51,16 @@
         while (true)
         {
             RawDataBlock block = new RawDataBlock(stream, bigBlockSize);
+            
+            // If there was data, add the block to the list
+            if(block.hasData()) {
+            	blocks.add(block);
+            }
 
-            if (block.eof())
-            {
+            // If the stream is now at the End Of File, we're done
+            if (block.eof()) {
                 break;
             }
-            blocks.add(block);
         }
         setBlocks(( RawDataBlock [] ) blocks.toArray(new RawDataBlock[ 0 ]));
     }

Modified: poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata-asGenerated.txt
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata-asGenerated.txt?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata-asGenerated.txt (original)
+++ poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata-asGenerated.txt Sat Jun 21 05:03:44 2008
@@ -14,7 +14,7 @@
 # limitations under the License.
 
 # Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
-# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
+# from source file 'excelfileformat.odt' (size=356107, md5=0x8f789cb6e75594caf068f8e193004ef4)
 #
 #Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
 
@@ -37,7 +37,7 @@
 15	SIN	1	1	V	V		
 16	COS	1	1	V	V		
 17	TAN	1	1	V	V		
-18	ARCTAN	1	1	V	V		
+18	ATAN	1	1	V	V		
 19	PI	0	0	V	-		
 20	SQRT	1	1	V	V		
 21	EXP	1	1	V	V		
@@ -141,8 +141,8 @@
 169	COUNTA	0	30	V	R		
 183	PRODUCT	0	30	V	R		
 184	FACT	1	1	V	V		
-191	DPRODUCT	3	3	V	R R R		
-192	ISNONTEXT	1	1	V	V		
+189	DPRODUCT	3	3	V	R R R		
+190	ISNONTEXT	1	1	V	V		
 193	STDEVP	1	30	V	R		
 194	VARP	1	30	V	R		
 195	DSTDEVP	3	3	V	R R R		
@@ -184,6 +184,8 @@
 244	INFO	1	1	V	V		
 # New Built-In Sheet Functions in BIFF4
 14	FIXED	2	3	V	V V V		x
+204	USDOLLAR	1	2	V	V V		x
+215	DBCS	1	1	V	V		x
 216	RANK	2	3	V	V R V		
 247	DB	4	5	V	V V V V V		
 252	FREQUENCY	2	2	A	R R		

Modified: poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata.txt
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata.txt?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata.txt (original)
+++ poi/tags/REL_3_1_FINAL/src/resources/main/org/apache/poi/hssf/record/formula/function/functionMetadata.txt Sat Jun 21 05:03:44 2008
@@ -14,11 +14,10 @@
 # limitations under the License.
 
 # Created by (org.apache.poi.hssf.record.formula.function.ExcelFileFormatDocFunctionExtractor)
-# from source file 'excelfileformat.odt' (size=355750, crc=0x2FAEA65A)
+# from source file 'excelfileformat.odt' (size=356107, md5=0x8f789cb6e75594caf068f8e193004ef4)
+#  ! + some manual edits !
 #
 #Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )
-#
-# + some manual edits !
 
 # Built-In Sheet Functions in BIFF2
 0	COUNT	0	30	V	R		
@@ -80,8 +79,8 @@
 58	NPER	3	5	V	V V V V V		
 59	PMT	3	5	V	V V V V V		
 60	RATE	3	6	V	V V V V V V		
-61	MIRR	3	3	V	R V V		
-62	IRR	1	2	V	R V		
+61	MIRR	3	3	V	A V V		
+62	IRR	1	2	V	A V		
 63	RAND	0	0	V	-	x	
 64	MATCH	2	3	V	V R R		
 65	DATE	3	3	V	V V V		
@@ -95,8 +94,8 @@
 73	SECOND	1	1	V	V		
 74	NOW	0	0	V	-	x	
 75	AREAS	1	1	V	R		
-76	ROWS	1	1	V	R		
-77	COLUMNS	1	1	V	R		
+76	ROWS	1	1	V	A		
+77	COLUMNS	1	1	V	A		
 78	OFFSET	3	5	R	R V V V V	x	
 82	SEARCH	2	3	V	V V V		
 83	TRANSPOSE	1	1	A	A		
@@ -186,7 +185,7 @@
 244	INFO	1	1	V	V		
 # New Built-In Sheet Functions in BIFF4
 14	FIXED	2	3	V	V V V		x
-204	USDOLLAR	1	1	V	V		x
+204	USDOLLAR	1	2	V	V V		x
 215	DBCS	1	1	V	V		x
 216	RANK	2	3	V	V R V		
 247	DB	4	5	V	V V V V V		

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hdgf/HDGFDiagram.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hdgf/HDGFDiagram.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hdgf/HDGFDiagram.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hdgf/HDGFDiagram.java Sat Jun 21 05:03:44 2008
@@ -18,6 +18,7 @@
 
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 
 import org.apache.poi.POIDocument;
 import org.apache.poi.hdgf.chunks.ChunkFactory;
@@ -27,6 +28,7 @@
 import org.apache.poi.hdgf.streams.Stream;
 import org.apache.poi.hdgf.streams.StringsStream;
 import org.apache.poi.hdgf.streams.TrailerStream;
+import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.LittleEndian;
@@ -53,14 +55,17 @@
 	private PointerFactory ptrFactory;
 	
 	public HDGFDiagram(POIFSFileSystem fs) throws IOException {
-		super(fs);
+		this(fs.getRoot(), fs);
+	}
+	public HDGFDiagram(DirectoryNode dir, POIFSFileSystem fs) throws IOException {
+		super(dir, fs);
 		
 		DocumentEntry docProps =
-			(DocumentEntry)filesystem.getRoot().getEntry("VisioDocument");
+			(DocumentEntry)dir.getEntry("VisioDocument");
 
 		// Grab the document stream
 		_docstream = new byte[docProps.getSize()];
-		filesystem.createDocumentInputStream("VisioDocument").read(_docstream);
+		dir.createDocumentInputStream("VisioDocument").read(_docstream);
 		
 		// Read in the common POI streams
 		readProperties();
@@ -149,6 +154,10 @@
 		}
 	}
 	
+	public void write(OutputStream out) {
+		throw new IllegalStateException("Writing is not yet implemented, see http://poi.apache.org/hdgf/");
+	}
+	
 	/**
 	 * For testing only
 	 */

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java Sat Jun 21 05:03:44 2008
@@ -51,21 +51,7 @@
         if(!(shape instanceof TextShape)) return false;
 
         TextShape tx = (TextShape)shape;
-        TextRun run = tx.getTextRun();
-        if(run == null) return false;
-
-        Record[] records = run._records;
-        for (int i = 0; i < records.length; i++) {
-            int type = (int)records[i].getRecordType();
-            if (type == RecordTypes.BaseTextPropAtom.typeID ||
-                type == RecordTypes.DateTimeMCAtom.typeID ||
-                type == RecordTypes.GenericDateMCAtom.typeID ||
-                type == RecordTypes.FooterMCAtom.typeID ||
-                type == RecordTypes.SlideNumberMCAtom.typeID
-                    ) return true;
-
-        }
-        return false;
+        return tx.getPlaceholderAtom() != null;
     }
 
     /**

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java Sat Jun 21 05:03:44 2008
@@ -176,16 +176,11 @@
     public PictureData getPictureData(){
         SlideShow ppt = getSheet().getSlideShow();
         PictureData[] pict = ppt.getPictureData();
-        Document doc = ppt.getDocumentRecord();
-        EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
-        EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
 
-        List lst = bstore.getChildRecords();
-        int idx = getPictureIndex();
-        if (idx == 0){
+        EscherBSERecord bse = getEscherBSERecord();
+        if (bse == null){
             logger.log(POILogger.ERROR, "no reference to picture data found ");
         } else {
-            EscherBSERecord bse = (EscherBSERecord)lst.get(idx-1);
             for ( int i = 0; i < pict.length; i++ ) {
                 if (pict[i].getOffset() ==  bse.getOffset()){
                     return pict[i];
@@ -196,6 +191,21 @@
         return null;
     }
 
+    protected EscherBSERecord getEscherBSERecord(){
+        SlideShow ppt = getSheet().getSlideShow();
+        Document doc = ppt.getDocumentRecord();
+        EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
+        EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
+
+        List lst = bstore.getChildRecords();
+        int idx = getPictureIndex();
+        if (idx == 0){
+            return null;
+        } else {
+            return (EscherBSERecord)lst.get(idx-1);
+        }
+    }
+
     /**
      * Name of this picture.
      *
@@ -238,6 +248,10 @@
      */
     protected void afterInsert(Sheet sh){
         super.afterInsert(sh);
+
+        EscherBSERecord bse = getEscherBSERecord();
+        bse.setRef(bse.getRef() + 1);
+
         java.awt.Rectangle anchor = getAnchor();
         if (anchor.equals(new java.awt.Rectangle())){
             setDefaultSize();
@@ -249,21 +263,8 @@
         ShapePainter.paint(this, graphics);
 
         PictureData data = getPictureData();
-        if (data  instanceof Bitmap){
-            BufferedImage img = null;
-            try {
-               	img = ImageIO.read(new ByteArrayInputStream(data.getData()));
-            }
-            catch (Exception e){
-                logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + data.getType());
-                return;
-            }
-            Rectangle anchor = getAnchor();
-            Image scaledImg = img.getScaledInstance(anchor.width, anchor.height, Image.SCALE_SMOOTH);
-            graphics.drawImage(scaledImg, anchor.x, anchor.y, null);
-        } else {
-            logger.log(POILogger.WARN, "Rendering of metafiles is not yet supported. image.type: " + (data == null ? "NA" : data.getClass().getName()));
-        }
+        data.draw(graphics, this);
+
         graphics.setTransform(at);
     }
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java Sat Jun 21 05:03:44 2008
@@ -20,10 +20,12 @@
 import org.apache.poi.ddf.*;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.hslf.record.ColorSchemeAtom;
+import org.apache.poi.hslf.record.Record;
 
 import java.awt.*;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
+import java.util.Iterator;
 
 /**
  *  An abstract simple (non-group) shape.
@@ -284,4 +286,28 @@
         ShapePainter.paint(this, graphics);
         graphics.setTransform(at);
     }
+
+    /**
+     *  Find a record in the underlying EscherClientDataRecord
+     *
+     * @param recordType type of the record to search
+     */
+    protected Record getClientDataRecord(int recordType) {
+        Record oep = null;
+        EscherContainerRecord spContainer = getSpContainer();
+        for (Iterator it = spContainer.getChildRecords().iterator(); it.hasNext();) {
+            EscherRecord obj = (EscherRecord) it.next();
+            if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
+                byte[] data = obj.serialize();
+                Record[] records = Record.findChildRecords(data, 8, data.length - 8);
+                for (int j = 0; j < records.length; j++) {
+                    if (records[j].getRecordType() == recordType) {
+                        return records[j];
+                    }
+                }
+            }
+        }
+        return oep;
+    }
+
 }

Modified: poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java?rev=670186&r1=670185&r2=670186&view=diff
==============================================================================
--- poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java (original)
+++ poi/tags/REL_3_1_FINAL/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java Sat Jun 21 05:03:44 2008
@@ -147,6 +147,7 @@
         int dgId = dgg.getMaxDrawingGroupId() + 1;
         dg.setOptions((short)(dgId << 4));
         dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
+        dgg.setMaxDrawingGroupId(dgId);
 
         for (Iterator it = dgContainer.getChildContainers().iterator(); it.hasNext(); ) {
             EscherContainerRecord c = (EscherContainerRecord)it.next();



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