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 2009/06/07 17:39:55 UTC

svn commit: r782402 [6/8] - in /poi/tags/REL_3_5_BETA6: ./ src/contrib/src/org/apache/poi/contrib/poibrowser/ src/documentation/ src/documentation/content/xdocs/ src/documentation/content/xdocs/hpsf/ src/documentation/content/xdocs/news/ src/documentat...

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/Sheet.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/Sheet.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/Sheet.java Sun Jun  7 15:39:51 2009
@@ -57,7 +57,6 @@
 import org.apache.poi.hssf.record.ScenarioProtectRecord;
 import org.apache.poi.hssf.record.SelectionRecord;
 import org.apache.poi.hssf.record.UncalcedRecord;
-import org.apache.poi.hssf.record.UnknownRecord;
 import org.apache.poi.hssf.record.WSBoolRecord;
 import org.apache.poi.hssf.record.WindowTwoRecord;
 import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
@@ -106,7 +105,7 @@
 
     private static POILogger            log              = POILogFactory.getLogger(Sheet.class);
 
-    private List<RecordBase>             records;
+    private List<RecordBase>             _records;
     protected PrintGridlinesRecord       printGridlines    =     null;
     protected GridsetRecord              gridset           =     null;
     private   GutsRecord                 _gutsRecord;
@@ -118,10 +117,10 @@
     protected ProtectRecord              protect           =     null;
     protected ObjectProtectRecord        objprotect        =     null;
     protected ScenarioProtectRecord      scenprotect       =     null;
-    protected PasswordRecord             password          =     null;
+    protected PasswordRecord             _password          =     null;
 
     protected WindowTwoRecord            windowTwo         =     null;
-    protected SelectionRecord            selection         =     null;
+    protected SelectionRecord            _selection         =     null;
     /** java object always present, but if empty no BIFF records are written */
     private final MergedCellsTable       _mergedCellsTable;
     /** always present in this POI object, not always written to Excel file */
@@ -165,7 +164,8 @@
         _mergedCellsTable = new MergedCellsTable();
         RowRecordsAggregate rra = null;
 
-        records            = new ArrayList<RecordBase>(128);
+        List<RecordBase> records = new ArrayList<RecordBase>(128);
+        _records = records; // needed here due to calls to findFirstRecordLocBySid before we're done
         int dimsloc = -1;
 
         if (rs.peekNextSid() != BOFRecord.sid) {
@@ -207,7 +207,7 @@
                 records.add(rra); //only add the aggregate once
                 continue;
             }
-            
+
             if (CustomViewSettingsRecordAggregate.isBeginRecord(recSid)) {
                 // This happens three times in test sample file "29982.xls"
                 // Also several times in bugzilla samples 46840-23373 and 46840-23374
@@ -217,28 +217,13 @@
 
             if (PageSettingsBlock.isComponentRecord(recSid)) {
                 if (_psBlock == null) {
-                    // typical case - just one PSB (so far)
+                    // first PSB record encountered - read all of them:
                     _psBlock = new PageSettingsBlock(rs);
                     records.add(_psBlock);
-                    continue;
-                }
-                if (recSid == UnknownRecord.HEADER_FOOTER_089C) {
-                    // test samples: SharedFormulaTest.xls, ex44921-21902.xls, ex42570-20305.xls
-                    _psBlock.addLateHeaderFooter(rs.getNext());
-                    continue;
-                }
-                // Some apps write PLS, WSBOOL, <psb> but PLS is part of <psb>
-                // This happens in the test sample file "NoGutsRecords.xls" and "WORKBOOK_in_capitals.xls"
-                // In this case the first PSB is two records back
-                int prevPsbIx = records.size()-2;
-                if (_psBlock != records.get(prevPsbIx) || !(records.get(prevPsbIx+1) instanceof WSBoolRecord)) {
-                    // not quite the expected situation
-                    throw new RuntimeException("two Page Settings Blocks found in the same sheet");
+                } else {
+                    // one or more PSB records found after some intervening non-PSB records
+                    _psBlock.addLateRecords(rs);
                 }
-                records.remove(prevPsbIx); // WSBOOL will drop down one position.
-                PageSettingsBlock latePsb = new PageSettingsBlock(rs);
-                _psBlock = mergePSBs(_psBlock, latePsb);
-                records.add(_psBlock);
                 continue;
             }
 
@@ -247,7 +232,7 @@
                 _mergedCellsTable.read(rs);
                 continue;
             }
-            
+
             if (recSid == BOFRecord.sid) {
                 ChartSubstreamRecordAggregate chartAgg = new ChartSubstreamRecordAggregate(rs);
                 if (false) {
@@ -308,7 +293,7 @@
             }
             else if ( recSid == SelectionRecord.sid )
             {
-                selection = (SelectionRecord) rec;
+                _selection = (SelectionRecord) rec;
             }
             else if ( recSid == WindowTwoRecord.sid )
             {
@@ -328,7 +313,7 @@
             }
             else if ( recSid == PasswordRecord.sid )
             {
-                password = (PasswordRecord) rec;
+                _password = (PasswordRecord) rec;
             }
             else if ( recSid == GutsRecord.sid )
             {
@@ -372,34 +357,7 @@
                 recs.add(r);
             }});
     }
-    /**
-     * Hack to recover from the situation where the page settings block has been split by
-     * an intervening {@link WSBoolRecord}
-     */
-    private static PageSettingsBlock mergePSBs(PageSettingsBlock a, PageSettingsBlock b) {
-        List<Record> temp = new ArrayList<Record>();
-        RecordTransferrer rt = new RecordTransferrer(temp);
-        a.visitContainedRecords(rt);
-        b.visitContainedRecords(rt);
-        RecordStream rs = new RecordStream(temp, 0);
-        PageSettingsBlock result = new PageSettingsBlock(rs);
-        if (rs.hasNext()) {
-            throw new RuntimeException("PageSettingsBlocks did not merge properly");
-        }
-        return result;
-    }
-
-    private static final class RecordTransferrer  implements RecordVisitor {
 
-        private final List<Record> _destList;
-
-        public RecordTransferrer(List<Record> destList) {
-            _destList = destList;
-        }
-        public void visitRecord(Record r) {
-            _destList.add(r);
-        }
-    }
     private static final class RecordCloner implements RecordVisitor {
 
         private final List<RecordBase> _destList;
@@ -420,9 +378,9 @@
      * belongs to a sheet.
      */
     public Sheet cloneSheet() {
-        List<RecordBase> clonedRecords = new ArrayList<RecordBase>(records.size());
-        for (int i = 0; i < records.size(); i++) {
-            RecordBase rb = records.get(i);
+        List<RecordBase> clonedRecords = new ArrayList<RecordBase>(_records.size());
+        for (int i = 0; i < _records.size(); i++) {
+            RecordBase rb = _records.get(i);
             if (rb instanceof RecordAggregate) {
                 ((RecordAggregate) rb).visitContainedRecords(new RecordCloner(clonedRecords));
                 continue;
@@ -445,7 +403,7 @@
     }
     private Sheet() {
         _mergedCellsTable = new MergedCellsTable();
-        records = new ArrayList<RecordBase>(32);
+        List<RecordBase> records = new ArrayList<RecordBase>(32);
 
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "Sheet createsheet from scratch called");
@@ -487,12 +445,13 @@
         records.add(_rowsAggregate);
         // 'Sheet View Settings'
         records.add(windowTwo = createWindowTwo());
-        selection = createSelection();
-        records.add(selection);
+        _selection = createSelection();
+        records.add(_selection);
 
         records.add(_mergedCellsTable); // MCT comes after 'Sheet View Settings'
         records.add(EOFRecord.instance);
 
+        _records = records;
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "Sheet createsheet from scratch exit");
     }
@@ -534,8 +493,7 @@
         return mrt.getNumberOfMergedRegions()-1;
     }
 
-    public void removeMergedRegion(int index)
-    {
+    public void removeMergedRegion(int index) {
         //safety checks
         MergedCellsTable mrt = getMergedRecords();
         if (index >= mrt.getNumberOfMergedRegions()) {
@@ -559,7 +517,7 @@
     public ConditionalFormattingTable getConditionalFormattingTable() {
         if (condFormatting == null) {
             condFormatting = new ConditionalFormattingTable();
-            RecordOrderer.addNewSheetRecord(records, condFormatting);
+            RecordOrderer.addNewSheetRecord(_records, condFormatting);
         }
         return condFormatting;
     }
@@ -597,8 +555,8 @@
 
         boolean haveSerializedIndex = false;
 
-        for (int k = 0; k < records.size(); k++) {
-            RecordBase record = records.get(k);
+        for (int k = 0; k < _records.size(); k++) {
+            RecordBase record = _records.get(k);
 
             if (record instanceof RecordAggregate) {
                 RecordAggregate agg = (RecordAggregate) record;
@@ -639,8 +597,8 @@
 
         int result = 0;
         // start just after BOF record (INDEX is not present in this list)
-        for (int j = bofRecordIndex + 1; j < records.size(); j++) {
-            RecordBase tmpRec = records.get(j);
+        for (int j = bofRecordIndex + 1; j < _records.size(); j++) {
+            RecordBase tmpRec = _records.get(j);
             if (tmpRec instanceof RowRecordsAggregate) {
                 break;
             }
@@ -671,12 +629,10 @@
         }
         DimensionsRecord d = _dimensions;
 
-        if (col.getColumn() > d.getLastCol())
-        {
+        if (col.getColumn() > d.getLastCol()) {
             d.setLastCol(( short ) (col.getColumn() + 1));
         }
-        if (col.getColumn() < d.getFirstCol())
-        {
+        if (col.getColumn() < d.getFirstCol()) {
             d.setFirstCol(col.getColumn());
         }
         _rowsAggregate.insertCell(col);
@@ -733,18 +689,15 @@
      * @param row the row record to be added
      */
 
-    public void addRow(RowRecord row)
-    {
+    public void addRow(RowRecord row) {
         if (log.check( POILogger.DEBUG ))
             log.log(POILogger.DEBUG, "addRow ");
         DimensionsRecord d = _dimensions;
 
-        if (row.getRowNumber() >= d.getLastRow())
-        {
+        if (row.getRowNumber() >= d.getLastRow()) {
             d.setLastRow(row.getRowNumber() + 1);
         }
-        if (row.getRowNumber() < d.getFirstRow())
-        {
+        if (row.getRowNumber() < d.getFirstRow()) {
             d.setFirstRow(row.getRowNumber());
         }
 
@@ -944,10 +897,11 @@
         retval.setColLevelMax(( short ) 0);
         return retval;
     }
+
     private GutsRecord getGutsRecord() {
         if (_gutsRecord == null) {
             GutsRecord result = createGuts();
-            RecordOrderer.addNewSheetRecord(records, result);
+            RecordOrderer.addNewSheetRecord(_records, result);
             _gutsRecord = result;
         }
 
@@ -995,17 +949,14 @@
     }
 
     /**
-     * get whether gridlines are printed.
-     * @return true if printed
+     * @return <code>true</code> if gridlines are printed
      */
-
-    public boolean isGridsPrinted()
-    {
+    public boolean isGridsPrinted() {
         if (gridset == null) {
             gridset = createGridset();
             //Insert the newlycreated Gridset record at the end of the record (just before the EOF)
             int loc = findFirstRecordLocBySid(EOFRecord.sid);
-            records.add(loc, gridset);
+            _records.add(loc, gridset);
         }
         return !gridset.getGridset();
     }
@@ -1014,9 +965,7 @@
      * set whether gridlines printed or not.
      * @param value     True if gridlines printed.
      */
-
-    public void setGridsPrinted(boolean value)
-    {
+    public void setGridsPrinted(boolean value) {
         gridset.setGridset(!value);
     }
 
@@ -1031,9 +980,7 @@
     /**
      * set the default row height for the sheet (if the rows do not define their own height)
      */
-
-    public void setDefaultRowHeight(short dch)
-    {
+    public void setDefaultRowHeight(short dch) {
         defaultrowheight.setRowHeight(dch);
     }
 
@@ -1041,9 +988,7 @@
      * get the default row height for the sheet (if the rows do not define their own height)
      * @return  default row height
      */
-
-    public short getDefaultRowHeight()
-    {
+    public short getDefaultRowHeight() {
         return defaultrowheight.getRowHeight();
     }
 
@@ -1055,7 +1000,6 @@
      * @see #setColumnWidth(int, int)
      * @return column width in units of 1/256th of a character width
      */
-
     public int getColumnWidth(int columnIndex) {
 
         ColumnInfoRecord ci = _columnInfos.findColumnInfo(columnIndex);
@@ -1099,7 +1043,7 @@
      */
     public void setColumnWidth(int column, int width) {
         if(width > 255*256) throw new IllegalArgumentException("The maximum column width for an individual cell is 255 characters.");
-        
+
         setColumn(column, null, new Integer(width), null, null, null);
     }
 
@@ -1202,15 +1146,12 @@
         return new SelectionRecord(0, 0);
     }
 
-    public short getTopRow()
-    {
+    public short getTopRow() {
         return (windowTwo==null) ? (short) 0 : windowTwo.getTopRow();
     }
 
-    public void setTopRow(short topRow)
-    {
-        if (windowTwo!=null)
-        {
+    public void setTopRow(short topRow) {
+        if (windowTwo!=null) {
             windowTwo.setTopRow(topRow);
         }
     }
@@ -1219,7 +1160,7 @@
      * Sets the left column to show in desktop window pane.
      * @param leftCol the left column to show in desktop window pane
      */
-    public void setLeftCol(short leftCol){
+    public void setLeftCol(short leftCol) {
         if (windowTwo!=null) {
             windowTwo.setLeftCol(leftCol);
         }
@@ -1235,13 +1176,11 @@
      * @see org.apache.poi.hssf.record.SelectionRecord
      * @return row the active row index
      */
-    public int getActiveCellRow()
-    {
-        if (selection == null)
-        {
+    public int getActiveCellRow() {
+        if (_selection == null) {
             return 0;
         }
-        return selection.getActiveCellRow();
+        return _selection.getActiveCellRow();
     }
 
     /**
@@ -1250,12 +1189,10 @@
      * @param row the row index
      * @see org.apache.poi.hssf.record.SelectionRecord
      */
-    public void setActiveCellRow(int row)
-    {
+    public void setActiveCellRow(int row) {
         //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
-        if (selection != null)
-        {
-            selection.setActiveCellRow(row);
+        if (_selection != null) {
+            _selection.setActiveCellRow(row);
         }
     }
 
@@ -1264,10 +1201,10 @@
      * @return column of the active cell
      */
     public short getActiveCellCol() {
-        if (selection == null) {
+        if (_selection == null) {
             return 0;
         }
-        return (short)selection.getActiveCellCol();
+        return (short)_selection.getActiveCellCol();
     }
 
     /**
@@ -1276,24 +1213,21 @@
      * @param col the column index
      * @see org.apache.poi.hssf.record.SelectionRecord
      */
-    public void setActiveCellCol(short col)
-    {
+    public void setActiveCellCol(short col) {
         //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
-        if (selection != null)
+        if (_selection != null)
         {
-            selection.setActiveCellCol(col);
+            _selection.setActiveCellCol(col);
         }
     }
 
-    public List<RecordBase> getRecords()
-    {
-        return records;
+    public List<RecordBase> getRecords() {
+        return _records;
     }
 
     /**
      * Gets the gridset record for this sheet.
      */
-
     public GridsetRecord getGridsetRecord()
     {
         return gridset;
@@ -1302,14 +1236,12 @@
     /**
      * Returns the first occurrence of a record matching a particular sid.
      */
-
-    public Record findFirstRecordBySid(short sid)
-    {
+    public Record findFirstRecordBySid(short sid) {
         int ix = findFirstRecordLocBySid(sid);
         if (ix < 0) {
             return null;
         }
-        return (Record) records.get(ix);
+        return (Record) _records.get(ix);
     }
 
     /**
@@ -1318,20 +1250,15 @@
      *
      * @param sclRecord     The record to set.
      */
-    public void setSCLRecord(SCLRecord sclRecord)
-    {
+    public void setSCLRecord(SCLRecord sclRecord) {
         int oldRecordLoc = findFirstRecordLocBySid(SCLRecord.sid);
-        if (oldRecordLoc == -1)
-        {
+        if (oldRecordLoc == -1) {
             // Insert it after the window record
             int windowRecordLoc = findFirstRecordLocBySid(WindowTwoRecord.sid);
-            records.add(windowRecordLoc+1, sclRecord);
-        }
-        else
-        {
-            records.set(oldRecordLoc, sclRecord);
+            _records.add(windowRecordLoc+1, sclRecord);
+        } else {
+            _records.set(oldRecordLoc, sclRecord);
         }
-
     }
 
     /**
@@ -1342,9 +1269,9 @@
      *          is made.
      */
     public int findFirstRecordLocBySid( short sid ) { // TODO - remove this method
-        int max = records.size();
+        int max = _records.size();
         for (int i=0; i< max; i++) {
-            Object rb = records.get(i);
+            Object rb = _records.get(i);
             if (!(rb instanceof Record)) {
                 continue;
             }
@@ -1393,11 +1320,10 @@
      * @param topRow        Top row visible in bottom pane
      * @param leftmostColumn   Left column visible in right pane.
      */
-    public void createFreezePane(int colSplit, int rowSplit, int topRow, int leftmostColumn )
-    {
+    public void createFreezePane(int colSplit, int rowSplit, int topRow, int leftmostColumn) {
         int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
         if (paneLoc != -1)
-            records.remove(paneLoc);
+            _records.remove(paneLoc);
 
         int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
         PaneRecord pane = new PaneRecord();
@@ -1405,21 +1331,16 @@
         pane.setY((short)rowSplit);
         pane.setTopRow((short) topRow);
         pane.setLeftColumn((short) leftmostColumn);
-        if (rowSplit == 0)
-        {
+        if (rowSplit == 0) {
             pane.setTopRow((short)0);
             pane.setActivePane((short)1);
-        }
-        else if (colSplit == 0)
-        {
+        } else if (colSplit == 0) {
             pane.setLeftColumn((short)64);
             pane.setActivePane((short)2);
-        }
-        else
-        {
+        } else {
             pane.setActivePane((short)0);
         }
-        records.add(loc+1, pane);
+        _records.add(loc+1, pane);
 
         windowTwo.setFreezePanes(true);
         windowTwo.setFreezePanesNoSplit(true);
@@ -1442,11 +1363,10 @@
      * @see #PANE_UPPER_LEFT
      * @see #PANE_UPPER_RIGHT
      */
-    public void createSplitPane(int xSplitPos, int ySplitPos, int topRow, int leftmostColumn, int activePane )
-    {
+    public void createSplitPane(int xSplitPos, int ySplitPos, int topRow, int leftmostColumn, int activePane) {
         int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
         if (paneLoc != -1)
-            records.remove(paneLoc);
+            _records.remove(paneLoc);
 
         int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
         PaneRecord r = new PaneRecord();
@@ -1455,7 +1375,7 @@
         r.setTopRow((short) topRow);
         r.setLeftColumn((short) leftmostColumn);
         r.setActivePane((short) activePane);
-        records.add(loc+1, r);
+        _records.add(loc+1, r);
 
         windowTwo.setFreezePanes(false);
         windowTwo.setFreezePanesNoSplit(false);
@@ -1467,7 +1387,7 @@
 
     /**
      * Returns the information regarding the currently configured pane (split or freeze).
-     * @return null if no pane configured, or the pane information.
+     * @return <code>null</code> if no pane configured, or the pane information.
      */
     public PaneInformation getPaneInformation() {
       PaneRecord rec = (PaneRecord)findFirstRecordBySid(PaneRecord.sid);
@@ -1478,14 +1398,12 @@
                                  rec.getLeftColumn(), (byte)rec.getActivePane(), windowTwo.getFreezePanes());
     }
 
-    public SelectionRecord getSelection()
-    {
-        return selection;
+    public SelectionRecord getSelection() {
+        return _selection;
     }
 
-    public void setSelection( SelectionRecord selection )
-    {
-        this.selection = selection;
+    public void setSelection( SelectionRecord selection) {
+        _selection = selection;
     }
 
     /**
@@ -1512,32 +1430,30 @@
         return retval;
     }
 
-    /** Returns the ProtectRecord.
-     * If one is not contained in the sheet, then one is created.
+    /**
+     * @return the ProtectRecord. If one is not contained in the sheet, then one is created.
      */
-    public ProtectRecord getProtect()
-    {
+    public ProtectRecord getProtect() {
         if (protect == null) {
             protect = new ProtectRecord(false);
             // Insert the newly created protect record just before DefaultColWidthRecord
             int loc = findFirstRecordLocBySid(DefaultColWidthRecord.sid);
-            records.add(loc, protect);
+            _records.add(loc, protect);
         }
         return protect;
     }
 
-    /** Returns the PasswordRecord.
-     * If one is not contained in the sheet, then one is created.
+    /**
+     * @return the PasswordRecord. If one is not contained in the sheet, then one is created.
      */
-    public PasswordRecord getPassword()
-    {
-        if (password == null) {
-            password = createPassword();
+    public PasswordRecord getPassword() {
+        if (_password == null) {
+            _password = createPassword();
             //Insert the newly created password record at the end of the record (just before the EOF)
             int loc = findFirstRecordLocBySid(EOFRecord.sid);
-            records.add(loc, password);
+            _records.add(loc, _password);
         }
-        return password;
+        return _password;
     }
 
     /**
@@ -1548,8 +1464,6 @@
     }
 
     /**
-
-    /**
      * Sets whether the gridlines are shown in a viewer.
      * @param show whether to show gridlines or not
      */
@@ -1558,8 +1472,7 @@
     }
 
     /**
-     * Returns if gridlines are displayed.
-     * @return whether gridlines are displayed
+     * @return <code>true</code> if gridlines are displayed
      */
     public boolean isDisplayGridlines() {
     return windowTwo.getDisplayGridlines();
@@ -1620,12 +1533,10 @@
      * @param drawingManager The DrawingManager2 for our workbook
      * @param createIfMissing Should one be created if missing?
      */
-    public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing)
-    {
+    public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) {
         int loc = findFirstRecordLocBySid(DrawingRecord.sid);
         boolean noDrawingRecordsFound = (loc == -1);
-        if (noDrawingRecordsFound)
-        {
+        if (noDrawingRecordsFound) {
             if(!createIfMissing) {
                 // None found, and not allowed to add in
                 return -1;
@@ -1633,35 +1544,29 @@
 
             EscherAggregate aggregate = new EscherAggregate( drawingManager );
             loc = findFirstRecordLocBySid(EscherAggregate.sid);
-            if (loc == -1)
-            {
+            if (loc == -1) {
                 loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
-            }
-            else
-            {
+            } else {
                 getRecords().remove(loc);
             }
             getRecords().add( loc, aggregate );
             return loc;
         }
-        else
-        {
-            List<RecordBase> records = getRecords();
-            EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
-            int startloc = loc;
-            while ( loc + 1 < records.size()
-                    && records.get( loc ) instanceof DrawingRecord
-                    && records.get( loc + 1 ) instanceof ObjRecord )
-            {
-                loc += 2;
-            }
-            int endloc = loc-1;
-            for(int i = 0; i < (endloc - startloc + 1); i++)
-                records.remove(startloc);
-            records.add(startloc, r);
+        List<RecordBase> records = getRecords();
+        EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
+        int startloc = loc;
+        while ( loc + 1 < records.size()
+                && records.get( loc ) instanceof DrawingRecord
+                && records.get( loc + 1 ) instanceof ObjRecord )
+        {
+            loc += 2;
+        }
+        int endloc = loc-1;
+        for(int i = 0; i < (endloc - startloc + 1); i++)
+            records.remove(startloc);
+        records.add(startloc, r);
 
-            return startloc;
-        }
+        return startloc;
     }
 
     /**
@@ -1669,13 +1574,12 @@
      * For instance the escher aggregates size needs to be calculated before
      * serialization so that the dgg record (which occurs first) can be written.
      */
-    public void preSerialize()
-    {
-        for ( Iterator iterator = getRecords().iterator(); iterator.hasNext(); )
-        {
-            RecordBase r = (RecordBase) iterator.next();
-            if (r instanceof EscherAggregate)
-                r.getRecordSize();   // Trigger flatterning of user model and corresponding update of dgg record.
+    public void preSerialize() {
+        for (RecordBase r: getRecords()) {
+            if (r instanceof EscherAggregate) {
+                // Trigger flattening of user model and corresponding update of dgg record.
+                r.getRecordSize();
+            }
         }
     }
 
@@ -1683,7 +1587,7 @@
     public PageSettingsBlock getPageSettings() {
         if (_psBlock == null) {
             _psBlock = new PageSettingsBlock();
-            RecordOrderer.addNewSheetRecord(records, _psBlock);
+            RecordOrderer.addNewSheetRecord(_records, _psBlock);
         }
         return _psBlock;
     }
@@ -1711,18 +1615,18 @@
         prec.setProtect(true);
         pass.setPassword(PasswordRecord.hashPassword(password));
         if((objprotect == null && objects) || (scenprotect != null && scenarios)) {
-            protIdx = records.indexOf( protect );
+            protIdx = _records.indexOf( protect );
         }
         if(objprotect == null && objects) {
             ObjectProtectRecord rec = createObjectProtect();
             rec.setProtect(true);
-            records.add(protIdx+1,rec);
+            _records.add(protIdx+1,rec);
             objprotect = rec;
         }
         if(scenprotect == null && scenarios) {
             ScenarioProtectRecord srec = createScenarioProtect();
             srec.setProtect(true);
-            records.add(protIdx+2,srec);
+            _records.add(protIdx+2,srec);
             scenprotect = srec;
         }
     }
@@ -1780,12 +1684,10 @@
         recalcRowGutter();
     }
 
-    private void recalcRowGutter()
-    {
+    private void recalcRowGutter() {
         int maxLevel = 0;
         Iterator iterator = _rowsAggregate.getIterator();
-        while ( iterator.hasNext() )
-        {
+        while (iterator.hasNext()) {
             RowRecord rowRecord = (RowRecord) iterator.next();
             maxLevel = Math.max(rowRecord.getOutlineLevel(), maxLevel);
         }
@@ -1800,7 +1702,7 @@
     public DataValidityTable getOrCreateDataValidityTable() {
         if (_dataValidityTable == null) {
             DataValidityTable result = new DataValidityTable();
-            RecordOrderer.addNewSheetRecord(records, result);
+            RecordOrderer.addNewSheetRecord(_records, result);
             _dataValidityTable = result;
         }
         return _dataValidityTable;
@@ -1811,8 +1713,8 @@
      */
     public NoteRecord[] getNoteRecords() {
         List<NoteRecord> temp = new ArrayList<NoteRecord>();
-        for(int i=records.size()-1; i>=0; i--) {
-            RecordBase rec = records.get(i);
+        for(int i=_records.size()-1; i>=0; i--) {
+            RecordBase rec = _records.get(i);
             if (rec instanceof NoteRecord) {
                 temp.add((NoteRecord) rec);
             }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/SimpleFilledShape.java Sun Jun  7 15:39:51 2009
@@ -101,7 +101,7 @@
         ObjRecord obj = new ObjRecord();
         CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
         c.setObjectType( (short) ( (HSSFSimpleShape) shape ).getShapeType() );
-        c.setObjectId( (short) ( shapeId ) );
+        c.setObjectId( shapeId );
         c.setLocked( true );
         c.setPrintable( true );
         c.setAutofill( true );

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/TextboxShape.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/TextboxShape.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/TextboxShape.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/model/TextboxShape.java Sun Jun  7 15:39:51 2009
@@ -59,7 +59,7 @@
         ObjRecord obj = new ObjRecord();
         CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
         c.setObjectType( (short) ( (HSSFSimpleShape) shape ).getShapeType() );
-        c.setObjectId( (short) ( shapeId ) );
+        c.setObjectId( shapeId );
         c.setLocked( true );
         c.setPrintable( true );
         c.setAutofill( true );

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/CommonObjectDataSubRecord.java Sun Jun  7 15:39:51 2009
@@ -69,7 +69,7 @@
     public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
     
     private  short      field_1_objectType;
-    private  short      field_2_objectId;
+    private  int        field_2_objectId;
     private  short      field_3_option;
     private  int        field_4_reserved1;
     private  int        field_5_reserved2;
@@ -86,7 +86,7 @@
             throw new RecordFormatException("Expected size 18 but got (" + size + ")");
         }
         field_1_objectType             = in.readShort();
-        field_2_objectId               = in.readShort();
+        field_2_objectId               = in.readUShort();
         field_3_option                 = in.readShort();
         field_4_reserved1              = in.readInt();
         field_5_reserved2              = in.readInt();
@@ -252,7 +252,7 @@
     /**
      * Get the object id field for the CommonObjectData record.
      */
-    public short getObjectId()
+    public int getObjectId()
     {
         return field_2_objectId;
     }
@@ -260,7 +260,7 @@
     /**
      * Set the object id field for the CommonObjectData record.
      */
-    public void setObjectId(short field_2_objectId)
+    public void setObjectId(int field_2_objectId)
     {
         this.field_2_objectId = field_2_objectId;
     }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/EscherAggregate.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/EscherAggregate.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/EscherAggregate.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/EscherAggregate.java Sun Jun  7 15:39:51 2009
@@ -812,7 +812,7 @@
 		ObjRecord obj = new ObjRecord();
 		CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
 		cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP );
-		cmo.setObjectId( (short) ( shapeId ) );
+		cmo.setObjectId( shapeId );
 		cmo.setLocked( true );
 		cmo.setPrintable( true );
 		cmo.setAutofill( true );

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/FooterRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/FooterRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/FooterRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/FooterRecord.java Sun Jun  7 15:39:51 2009
@@ -27,48 +27,30 @@
  *
  */
 public final class FooterRecord extends HeaderFooterBase {
-    public final static short sid = 0x0015;
+	public final static short sid = 0x0015;
 
-    public FooterRecord(String text) {
-    	super(text);
-    }
+	public FooterRecord(String text) {
+		super(text);
+	}
 
-    public FooterRecord(RecordInputStream in) {
+	public FooterRecord(RecordInputStream in) {
 		super(in);
 	}
 
-     /**
-     * set the footer string
-     *
-     * @param footer string to display
-     */
-    public void setFooter(String footer) {
-        setText(footer);
-    }
-
-    /**
-     * get the footer string
-     *
-     * @return footer string to display
-     */
-    public String getFooter() {
-        return getText();
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[FOOTER]\n");
-        buffer.append("    .footer = ").append(getText()).append("\n");
-        buffer.append("[/FOOTER]\n");
-        return buffer.toString();
-    }
-
-    public short getSid() {
-        return sid;
-    }
-
-    public Object clone() {
-        return new FooterRecord(getText());
-    }
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[FOOTER]\n");
+		buffer.append("    .footer = ").append(getText()).append("\n");
+		buffer.append("[/FOOTER]\n");
+		return buffer.toString();
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	public Object clone() {
+		return new FooterRecord(getText());
+	}
 }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java Sun Jun  7 15:39:51 2009
@@ -25,7 +25,7 @@
  *
  * @author Josh Micich
  */
-abstract class HeaderFooterBase extends StandardRecord {
+public abstract class HeaderFooterBase extends StandardRecord {
 	private boolean field_2_hasMultibyte;
 	private String field_3_text;
 
@@ -44,7 +44,8 @@
 				field_3_text = in.readCompressedUnicode(field_1_footer_len);
 			}
 		} else {
-			// Note - this is unusual: when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
+			// Note - this is unusual for BIFF records in general, but normal for header / footer records:
+			// when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
 			field_3_text = "";
 		}
 	}
@@ -62,16 +63,9 @@
 		field_3_text = text;
 
 		// Check it'll fit into the space in the record
-		if (field_2_hasMultibyte) {
-			if (field_3_text.length() > 127) {
-				throw new IllegalArgumentException(
-						"Footer string too long (limit is 127 for unicode strings)");
-			}
-		} else {
-			if (field_3_text.length() > 255) {
-				throw new IllegalArgumentException(
-						"Footer string too long (limit is 255 for non-unicode strings)");
-			}
+		if (getDataSize() > RecordInputStream.MAX_RECORD_DATA_SIZE) {
+			throw new IllegalArgumentException("Header/Footer string too long (limit is "
+					+ RecordInputStream.MAX_RECORD_DATA_SIZE + " bytes)");
 		}
 	}
 

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/HeaderRecord.java Sun Jun  7 15:39:51 2009
@@ -17,7 +17,6 @@
 
 package org.apache.poi.hssf.record;
 
-
 /**
  * Title:        Header Record<P>
  * Description:  Specifies a header for a sheet<P>
@@ -27,49 +26,30 @@
  * @author Jason Height (jheight at chariot dot net dot au)
  */
 public final class HeaderRecord extends HeaderFooterBase {
-    public final static short sid = 0x0014;
+	public final static short sid = 0x0014;
 
-    public HeaderRecord(String text) {
-    	super(text);
-    }
-
-    public HeaderRecord(RecordInputStream in) {
-    	super(in);
-    }
-
-    /**
-     * set the header string
-     *
-     * @param header string to display
-     */
-    public void setHeader(String header) {
-    	setText(header);
-    }
-
-    /**
-     * get the header string
-     *
-     * @return header string to display
-     */
-    public String getHeader() {
-        return getText();
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[HEADER]\n");
-        buffer.append("    .header = ").append(getText()).append("\n");
-        buffer.append("[/HEADER]\n");
-        return buffer.toString();
-    }
-
-
-    public short getSid() {
-        return sid;
-    }
-
-    public Object clone() {
-      return new HeaderRecord(getText());
-    }
+	public HeaderRecord(String text) {
+		super(text);
+	}
+
+	public HeaderRecord(RecordInputStream in) {
+		super(in);
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[HEADER]\n");
+		buffer.append("    .header = ").append(getText()).append("\n");
+		buffer.append("[/HEADER]\n");
+		return buffer.toString();
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	public Object clone() {
+		return new HeaderRecord(getText());
+	}
 }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/MulBlankRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/MulBlankRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/MulBlankRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/MulBlankRecord.java Sun Jun  7 15:39:51 2009
@@ -22,128 +22,114 @@
 /**
  * Title:        Multiple Blank cell record(0x00BE) <P/>
  * Description:  Represents a  set of columns in a row with no value but with styling.
- *               In this release we have read-only support for this record type.
- *               The RecordFactory converts this to a set of BlankRecord objects.<P/>
+ * <p/>
  * REFERENCE:  PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P/>
  * @author Andrew C. Oliver (acoliver at apache dot org)
  * @author Glen Stampoultzis (glens at apache.org)
  * @see BlankRecord
  */
 public final class MulBlankRecord extends StandardRecord {
-    public final static short sid = 0x00BE;
-    
-    private int               field_1_row;
-    private short             field_2_first_col;
-    private short[]           field_3_xfs;
-    private short             field_4_last_col;
-
-    public MulBlankRecord(int row, int firstCol, short[] xfs) {
-        field_1_row = row;
-        field_2_first_col = (short)firstCol;
-        field_3_xfs = xfs;
-        field_4_last_col = (short) (firstCol + xfs.length - 1);
-    }
-
-    /**
-     * get the row number of the cells this represents
-     *
-     * @return row number
-     */
-    public int getRow()
-    {
-        return field_1_row;
-    }
-
-    /**
-     * starting column (first cell this holds in the row)
-     * @return first column number
-     */
-    public short getFirstColumn()
-    {
-        return field_2_first_col;
-    }
-
-    /**
-     * ending column (last cell this holds in the row)
-     * @return first column number
-     */
-    public short getLastColumn()
-    {
-        return field_4_last_col;
-    }
-
-    /**
-     * get the number of columns this contains (last-first +1)
-     * @return number of columns (last - first +1)
-     */
-    public int getNumColumns()
-    {
-        return field_4_last_col - field_2_first_col + 1;
-    }
-
-    /**
-     * returns the xf index for column (coffset = column - field_2_first_col)
-     * @param coffset  the column (coffset = column - field_2_first_col)
-     * @return the XF index for the column
-     */
-    public short getXFAt(int coffset)
-    {
-        return field_3_xfs[ coffset ];
-    }
-
-    /**
-     * @param in the RecordInputstream to read the record from
-     */
-    public MulBlankRecord(RecordInputStream in) {
-        field_1_row       = in.readUShort();
-        field_2_first_col = in.readShort();
-        field_3_xfs       = parseXFs(in);
-        field_4_last_col  = in.readShort();
-    }
-
-    private static short [] parseXFs(RecordInputStream in)
-    {
-        short[] retval = new short[ (in.remaining() - 2) / 2 ];
-
-        for (int idx = 0; idx < retval.length;idx++)
-        {
-          retval[idx] = in.readShort();
-        }
-        return retval;
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[MULBLANK]\n");
-        buffer.append("row  = ").append(Integer.toHexString(getRow())).append("\n");
-        buffer.append("firstcol  = ").append(Integer.toHexString(getFirstColumn())).append("\n");
-        buffer.append(" lastcol  = ").append(Integer.toHexString(getLastColumn())).append("\n");
-        for (int k = 0; k < getNumColumns(); k++) {
-            buffer.append("xf").append(k).append("        = ").append(
-                    Integer.toHexString(getXFAt(k))).append("\n");
-        }
-        buffer.append("[/MULBLANK]\n");
-        return buffer.toString();
-    }
-
-    public short getSid()
-    {
-        return sid;
-    }
-
-    public void serialize(LittleEndianOutput out) {
-        out.writeShort(field_1_row);
-        out.writeShort(field_2_first_col);
-        int nItems = field_3_xfs.length;
-        for (int i = 0; i < nItems; i++) {
-            out.writeShort(field_3_xfs[i]);
-        }
-        out.writeShort(field_4_last_col);
-    }
-
-    protected int getDataSize() {
-        // 3 short fields + array of shorts
-        return 6 + field_3_xfs.length * 2; 
-    }
+	public final static short sid = 0x00BE;
+
+	private final int _row;
+	private final int _firstCol;
+	private final short[] _xfs;
+	private final int _lastCol;
+
+	public MulBlankRecord(int row, int firstCol, short[] xfs) {
+		_row = row;
+		_firstCol = firstCol;
+		_xfs = xfs;
+		_lastCol = firstCol + xfs.length - 1;
+	}
+
+	/**
+	 * @return the row number of the cells this represents
+	 */
+	public int getRow() {
+		return _row;
+	}
+
+	/**
+	 * @return starting column (first cell this holds in the row). Zero based
+	 */
+	public int getFirstColumn() {
+		return _firstCol;
+	}
+
+	/**
+	 * get the number of columns this contains (last-first +1)
+	 * @return number of columns (last - first +1)
+	 */
+	public int getNumColumns() {
+		return _lastCol - _firstCol + 1;
+	}
+
+	/**
+	 * returns the xf index for column (coffset = column - field_2_first_col)
+	 * @param coffset  the column (coffset = column - field_2_first_col)
+	 * @return the XF index for the column
+	 */
+	public short getXFAt(int coffset) {
+		return _xfs[coffset];
+	}
+
+	/**
+	 * @param in the RecordInputstream to read the record from
+	 */
+	public MulBlankRecord(RecordInputStream in) {
+		_row	   = in.readUShort();
+		_firstCol = in.readShort();
+		_xfs	   = parseXFs(in);
+		_lastCol  = in.readShort();
+	}
+
+	private static short [] parseXFs(RecordInputStream in) {
+		short[] retval = new short[(in.remaining() - 2) / 2];
+
+		for (int idx = 0; idx < retval.length;idx++) {
+		  retval[idx] = in.readShort();
+		}
+		return retval;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[MULBLANK]\n");
+		buffer.append("row  = ").append(Integer.toHexString(getRow())).append("\n");
+		buffer.append("firstcol  = ").append(Integer.toHexString(getFirstColumn())).append("\n");
+		buffer.append(" lastcol  = ").append(Integer.toHexString(_lastCol)).append("\n");
+		for (int k = 0; k < getNumColumns(); k++) {
+			buffer.append("xf").append(k).append("		= ").append(
+					Integer.toHexString(getXFAt(k))).append("\n");
+		}
+		buffer.append("[/MULBLANK]\n");
+		return buffer.toString();
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	public void serialize(LittleEndianOutput out) {
+		out.writeShort(_row);
+		out.writeShort(_firstCol);
+		int nItems = _xfs.length;
+		for (int i = 0; i < nItems; i++) {
+			out.writeShort(_xfs[i]);
+		}
+		out.writeShort(_lastCol);
+	}
+
+	protected int getDataSize() {
+		// 3 short fields + array of shorts
+		return 6 + _xfs.length * 2;
+	}
+
+	@Override
+	public Object clone() {
+		// immutable - so OK to return this
+		return this;
+	}
 }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/NoteRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/NoteRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/NoteRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/NoteRecord.java Sun Jun  7 15:39:51 2009
@@ -45,7 +45,7 @@
 	private int field_1_row;
 	private int field_2_col;
 	private short field_3_flags;
-	private short field_4_shapeid;
+	private int field_4_shapeid;
 	private boolean field_5_hasMultibyte;
 	private String field_6_author;
 	/**
@@ -77,10 +77,10 @@
 	 * Read the record data from the supplied <code>RecordInputStream</code>
 	 */
 	public NoteRecord(RecordInputStream in) {
-		field_1_row = in.readShort();
+		field_1_row = in.readUShort();
 		field_2_col = in.readShort();
 		field_3_flags = in.readShort();
-		field_4_shapeid = in.readShort();
+		field_4_shapeid = in.readUShort();
 		int length = in.readShort();
 		field_5_hasMultibyte = in.readByte() != 0x00;
 		if (field_5_hasMultibyte) {
@@ -194,14 +194,14 @@
 	/**
 	 * Object id for OBJ record that contains the comment
 	 */
-	public short getShapeId() {
+	public int getShapeId() {
 		return field_4_shapeid;
 	}
 
 	/**
 	 * Object id for OBJ record that contains the comment
 	 */
-	public void setShapeId(short id) {
+	public void setShapeId(int id) {
 		field_4_shapeid = id;
 	}
 

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/SSTRecord.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/SSTRecord.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/SSTRecord.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/SSTRecord.java Sun Jun  7 15:39:51 2009
@@ -177,28 +177,6 @@
     }
 
     /**
-     * @return hashcode
-     */
-    public int hashCode()
-    {
-        return field_2_num_unique_strings;
-    }
-
-    public boolean equals( Object o )
-    {
-        if ( ( o == null ) || ( o.getClass() != this.getClass() ) )
-        {
-            return false;
-        }
-        SSTRecord other = (SSTRecord) o;
-
-        return ( ( field_1_num_strings == other
-                .field_1_num_strings ) && ( field_2_num_unique_strings == other
-                .field_2_num_unique_strings ) && field_3_strings
-                .equals( other.field_3_strings ) );
-    }
-
-    /**
      * Fill the fields from the data
      * <P>
      * The data consists of sets of string data. This string data is

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java Sun Jun  7 15:39:51 2009
@@ -125,36 +125,47 @@
 	private boolean readARecord(RecordStream rs) {
 		switch (rs.peekNextSid()) {
 			case HorizontalPageBreakRecord.sid:
+				checkNotPresent(_rowBreaksRecord);
 				_rowBreaksRecord = (PageBreakRecord) rs.getNext();
 				break;
 			case VerticalPageBreakRecord.sid:
+				checkNotPresent(_columnBreaksRecord);
 				_columnBreaksRecord = (PageBreakRecord) rs.getNext();
 				break;
 			case HeaderRecord.sid:
+				checkNotPresent(_header);
 				_header = (HeaderRecord) rs.getNext();
 				break;
 			case FooterRecord.sid:
+				checkNotPresent(_footer);
 				_footer = (FooterRecord) rs.getNext();
 				break;
 			case HCenterRecord.sid:
+				checkNotPresent(_hCenter);
 				_hCenter = (HCenterRecord) rs.getNext();
 				break;
 			case VCenterRecord.sid:
+				checkNotPresent(_vCenter);
 				_vCenter = (VCenterRecord) rs.getNext();
 				break;
 			case LeftMarginRecord.sid:
+				checkNotPresent(_leftMargin);
 				_leftMargin = (LeftMarginRecord) rs.getNext();
 				break;
 			case RightMarginRecord.sid:
+				checkNotPresent(_rightMargin);
 				_rightMargin = (RightMarginRecord) rs.getNext();
 				break;
 			case TopMarginRecord.sid:
+				checkNotPresent(_topMargin);
 				_topMargin = (TopMarginRecord) rs.getNext();
 				break;
 			case BottomMarginRecord.sid:
+				checkNotPresent(_bottomMargin);
 				_bottomMargin = (BottomMarginRecord) rs.getNext();
 				break;
 			case UnknownRecord.PLS_004D:
+				checkNotPresent(_pls);
 				_pls = rs.getNext();
 				while (rs.peekNextSid()==ContinueRecord.sid) {
 					if (_plsContinues==null) {
@@ -164,15 +175,19 @@
 				}
 				break;
 			case PrintSetupRecord.sid:
+				checkNotPresent(_printSetup);
 				_printSetup = (PrintSetupRecord)rs.getNext();
 				break;
 			case UnknownRecord.BITMAP_00E9:
+				checkNotPresent(_bitmap);
 				_bitmap = rs.getNext();
 				break;
 			case UnknownRecord.PRINTSIZE_0033:
+				checkNotPresent(_printSize);
 				_printSize = rs.getNext();
 				break;
 			case UnknownRecord.HEADER_FOOTER_089C:
+				checkNotPresent(_headerFooter);
 				_headerFooter = rs.getNext();
 				break;
 			default:
@@ -182,6 +197,13 @@
 		return true;
 	}
 
+	private void checkNotPresent(Record rec) {
+		if (rec != null) {
+			throw new RecordFormatException("Duplicate PageSettingsBlock record (sid=0x"
+					+ Integer.toHexString(rec.getSid()) + ")");
+		}
+	}
+
 	private PageBreakRecord getRowBreaksRecord() {
 		if (_rowBreaksRecord == null) {
 			_rowBreaksRecord = new HorizontalPageBreakRecord();
@@ -217,10 +239,21 @@
 
 
 	public void visitContainedRecords(RecordVisitor rv) {
+		// Replicates record order from Excel 2007, though this is not critical
+
 		visitIfPresent(_rowBreaksRecord, rv);
 		visitIfPresent(_columnBreaksRecord, rv);
-		visitIfPresent(_header, rv);
-		visitIfPresent(_footer, rv);
+		// Write out empty header / footer records if these are missing 
+		if (_header == null) {
+			rv.visitRecord(new HeaderRecord(""));
+		} else {
+			rv.visitRecord(_header);
+		}
+		if (_footer == null) {
+			rv.visitRecord(new FooterRecord(""));
+		} else {
+			rv.visitRecord(_footer);
+		}
 		visitIfPresent(_hCenter, rv);
 		visitIfPresent(_vCenter, rv);
 		visitIfPresent(_leftMargin, rv);
@@ -551,4 +584,40 @@
 		}
 		_headerFooter = rec;
 	}
+
+	/**
+	 * This method reads PageSettingsBlock records from the supplied RecordStream until the first
+	 * non-PageSettingsBlock record is encountered.  As each record is read, it is incorporated
+	 * into this PageSettingsBlock.
+	 * <p/>
+	 * The latest Excel version seems to write the PageSettingsBlock uninterrupted. However there
+	 * are several examples (that Excel reads OK) where these records are not written together:
+	 * <ul>
+	 * <li><b>HEADER_FOOTER(0x089C) after WINDOW2</b> - This record is new in 2007.  Some apps
+	 * seem to have scattered this record long after the PageSettingsBlock where it belongs
+	 * test samples: SharedFormulaTest.xls, ex44921-21902.xls, ex42570-20305.xls</li>
+	 * <li><b>PLS, WSBOOL, PageSettingsBlock</b> - WSBOOL is not a PSB record. 
+	 * This happens in the test sample file "NoGutsRecords.xls" and "WORKBOOK_in_capitals.xls"</li>
+	 * <li><b>Margins after DIMENSION</b> - All of PSB should be before DIMENSION. (Bug-47199)</li>
+	 * </ul>
+	 * These were probably written by other applications (or earlier versions of Excel). It was 
+	 * decided to not write specific code for detecting each of these cases.  POI now tolerates
+	 * PageSettingsBlock records scattered all over the sheet record stream, and in any order, but
+	 * does not allow duplicates of any of those records.
+	 * 
+	 * <p/>
+	 * <b>Note</b> - when POI writes out this PageSettingsBlock, the records will always be written
+	 * in one consolidated block (in the standard ordering) regardless of how scattered the records
+	 * were when they were originally read. 
+	 * 
+	 * @throws  RecordFormatException if any PSB record encountered has the same type (sid) as 
+	 * a record that is already part of this PageSettingsBlock
+	 */
+	public void addLateRecords(RecordStream rs) {
+		while(true) {
+			if (!readARecord(rs)) {
+				break;
+			}
+		}
+	}
 }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java Sun Jun  7 15:39:51 2009
@@ -19,11 +19,7 @@
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 
 import org.apache.poi.hssf.model.HSSFFormulaParser;
 import org.apache.poi.hssf.model.Sheet;
@@ -56,6 +52,8 @@
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.ss.formula.FormulaType;
 import org.apache.poi.ss.SpreadsheetVersion;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.POILogFactory;
 
 /**
  * High level representation of a cell in a row of a spreadsheet.
@@ -75,6 +73,7 @@
  * @author  Yegor Kozlov cell comments support
  */
 public class HSSFCell implements Cell {
+    private static POILogger log = POILogFactory.getLogger(HSSFCell.class);
 
     private static final String FILE_FORMAT_NAME  = "BIFF8";
     /**
@@ -980,7 +979,7 @@
             return;
         }
 
-        comment.setRow((short)_record.getRow());
+        comment.setRow(_record.getRow());
         comment.setColumn(_record.getColumn());
         _comment = (HSSFComment)comment;
     }
@@ -1047,45 +1046,51 @@
      *
      * @return cell comment or <code>null</code> if not found
      */
-    protected static HSSFComment findCellComment(Sheet sheet, int row, int column){
+    protected static HSSFComment findCellComment(Sheet sheet, int row, int column) {
         // TODO - optimise this code by searching backwards, find NoteRecord first, quit if not found. Find one TXO by id
         HSSFComment comment = null;
-        HashMap<Integer, TextObjectRecord> txshapesByShapeId = new HashMap<Integer, TextObjectRecord>(); 
-        for (Iterator<RecordBase> it = sheet.getRecords().iterator(); it.hasNext(); ) {
-           RecordBase rec = it.next();
-           if (rec instanceof NoteRecord){
-               NoteRecord note = (NoteRecord)rec;
-               if (note.getRow() == row && note.getColumn() == column){
-                   TextObjectRecord txo = txshapesByShapeId.get(new Integer(note.getShapeId()));
-                   comment = new HSSFComment(note, txo);
-                   comment.setRow(note.getRow());
-                   comment.setColumn((short)note.getColumn());
-                   comment.setAuthor(note.getAuthor());
-                   comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
-                   comment.setString(txo.getStr());
-                   break;
-               }
-           } else if (rec instanceof ObjRecord){
-               ObjRecord obj = (ObjRecord)rec;
-               SubRecord sub = obj.getSubRecords().get(0);
-               if (sub instanceof CommonObjectDataSubRecord){
-                   CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)sub;
-                   if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT){
-                       //find the nearest TextObjectRecord which holds comment's text and map it to its shapeId
-                       while(it.hasNext()) {
-                           rec = it.next();
-                           if (rec instanceof TextObjectRecord) {
-                               txshapesByShapeId.put(new Integer(cmo.getObjectId()), (TextObjectRecord)rec);
-                               break;
-                           }
-                       }
-
-                   }
-               }
-           }
+        ArrayList<TextObjectRecord> noteTxo = new ArrayList<TextObjectRecord>();
+        int i = 0;
+        for (Iterator<RecordBase> it = sheet.getRecords().iterator(); it.hasNext();) {
+            RecordBase rec = it.next();
+            if (rec instanceof NoteRecord) {
+                NoteRecord note = (NoteRecord) rec;
+                if (note.getRow() == row && note.getColumn() == column) {
+                    if(i < noteTxo.size()) {
+                        TextObjectRecord txo = noteTxo.get(i);
+                        comment = new HSSFComment(note, txo);
+                        comment.setRow(note.getRow());
+                        comment.setColumn((short) note.getColumn());
+                        comment.setAuthor(note.getAuthor());
+                        comment.setVisible(note.getFlags() == NoteRecord.NOTE_VISIBLE);
+                        comment.setString(txo.getStr());
+                    } else {
+                        log.log(POILogger.WARN, "Failed to match NoteRecord and TextObjectRecord, row: " + row + ", column: " + column);
+                    }
+                    break;
+                }
+                i++;
+            } else if (rec instanceof ObjRecord) {
+                ObjRecord obj = (ObjRecord) rec;
+                SubRecord sub = obj.getSubRecords().get(0);
+                if (sub instanceof CommonObjectDataSubRecord) {
+                    CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) sub;
+                    if (cmo.getObjectType() == CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT) {
+                        //find the next TextObjectRecord which holds the comment's text
+                        //the order of TXO matches the order of NoteRecords: i-th TXO record corresponds to the i-th NoteRecord
+                        while (it.hasNext()) {
+                            rec = it.next();
+                            if (rec instanceof TextObjectRecord) {
+                                noteTxo.add((TextObjectRecord) rec);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
         }
         return comment;
-   }
+    }
 
     /**
      * @return hyperlink associated with this cell or <code>null</code> if not found

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java Sun Jun  7 15:39:51 2009
@@ -15,10 +15,10 @@
    limitations under the License.
 ==================================================================== */
 
-
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.FooterRecord;
+import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.ss.usermodel.Footer;
 
 /**
@@ -33,59 +33,29 @@
  * <P>
  * @author Shawn Laubach (slaubach at apache dot org)
  */
-public class HSSFFooter extends HeaderFooter implements Footer {
-    private FooterRecord footerRecord;
+public final class HSSFFooter extends HeaderFooter implements Footer {
+	private final PageSettingsBlock _psb;
 
-    /**
-     * Constructor.  Creates a new footer interface from a footer record
-     * @param footerRecord Footer record to create the footer with
-     */
-    protected HSSFFooter(FooterRecord footerRecord) {
-    	super(footerRecord.getFooter());
-    	this.footerRecord = footerRecord;
-    }
-
-    /**
-     * Sets the left string.
-     * @param newLeft The string to set as the left side.
-     */
-    public void setLeft(String newLeft) {
-	left = newLeft;
-	createFooterString();
-    }
-
-    /**
-     * Sets the center string.
-     * @param newCenter The string to set as the center.
-     */
-    public void setCenter(String newCenter) {
-	center = newCenter;
-	createFooterString();
-    }
-
-    /**
-     * Sets the right string.
-     * @param newRight The string to set as the right side.
-     */
-    public void setRight(String newRight) {
-	right = newRight;
-	createFooterString();
-    }
-    
-    protected String getRawFooter() {
-    	return footerRecord.getFooter();
-    }
-
-
-    /**
-     * Creates the complete footer string based on the left, center, and middle
-     * strings.
-     */
-    private void createFooterString() {
-	footerRecord.setFooter(
-			       "&C" + (center == null ? "" : center) +
-			       "&L" + (left == null ? "" : left) +
-			       "&R" + (right == null ? "" : right));
-    }
+	protected HSSFFooter(PageSettingsBlock psb) {
+		_psb = psb;
+	}
+
+	protected String getRawText() {
+		FooterRecord hf = _psb.getFooter();
+		if (hf == null) {
+			return "";
+		}
+		return hf.getText();
+	}
+
+	@Override
+	protected void setHeaderFooterText(String text) {
+		FooterRecord hfr = _psb.getFooter();
+		if (hfr == null) {
+			hfr = new FooterRecord(text);
+			_psb.setFooter(hfr);
+		} else {
+			hfr.setText(text);
+		}
+	}
 }
-

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java Sun Jun  7 15:39:51 2009
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.HeaderRecord;
+import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.ss.usermodel.Header;
 
 /**
@@ -33,66 +34,30 @@
  *
  * @author Shawn Laubach (slaubach at apache dot org)
  */
-public class HSSFHeader extends HeaderFooter implements Header {
-	private HeaderRecord headerRecord;
+public final class HSSFHeader extends HeaderFooter implements Header {
 
-    /**
-     * Constructor.  Creates a new header interface from a header record
-     *
-     * @param headerRecord Header record to create the header with
-     */
-    protected HSSFHeader( HeaderRecord headerRecord ) {
-    	super(headerRecord.getHeader());
-        this.headerRecord = headerRecord;
-    }
-
-    /**
-     * Sets the left string.
-     *
-     * @param newLeft The string to set as the left side.
-     */
-    public void setLeft( String newLeft )
-    {
-        left = newLeft;
-        createHeaderString();
-    }
-
-    /**
-     * Sets the center string.
-     *
-     * @param newCenter The string to set as the center.
-     */
-    public void setCenter( String newCenter )
-    {
-        center = newCenter;
-        createHeaderString();
-    }
-
-    /**
-     * Sets the right string.
-     *
-     * @param newRight The string to set as the right side.
-     */
-    public void setRight( String newRight )
-    {
-        right = newRight;
-        createHeaderString();
-    }
-    
-    protected String getRawHeader() {
-    	return headerRecord.getHeader();
-    }
-
-    /**
-     * Creates the complete header string based on the left, center, and middle
-     * strings.
-     */
-    private void createHeaderString()
-    {
-        headerRecord.setHeader( "&C" + ( center == null ? "" : center ) +
-                "&L" + ( left == null ? "" : left ) +
-                "&R" + ( right == null ? "" : right ) );
-    }
+	private final PageSettingsBlock _psb;
 
+	protected HSSFHeader(PageSettingsBlock psb) {
+		_psb = psb;
+	}
+
+	protected String getRawText() {
+		HeaderRecord hf = _psb.getHeader();
+		if (hf == null) {
+			return "";
+		}
+		return hf.getText();
+	}
+
+	@Override
+	protected void setHeaderFooterText(String text) {
+		HeaderRecord hfr = _psb.getHeader();
+		if (hfr == null) {
+			hfr = new HeaderRecord(text);
+			_psb.setHeader(hfr);
+		} else {
+			hfr.setText(text);
+		}
+	}
 }
-

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Sun Jun  7 15:39:51 2009
@@ -913,20 +913,12 @@
         return new HSSFPrintSetup(_sheet.getPageSettings().getPrintSetup());
     }
 
-    /**
-     * Gets the user model for the document header.
-     * @return The Document header.
-     */
     public HSSFHeader getHeader() {
-        return new HSSFHeader(_sheet.getPageSettings().getHeader());
+        return new HSSFHeader(_sheet.getPageSettings());
     }
 
-    /**
-     * Gets the user model for the document footer.
-     * @return The Document footer.
-     */
     public HSSFFooter getFooter() {
-        return new HSSFFooter(_sheet.getPageSettings().getFooter());
+        return new HSSFFooter(_sheet.getPageSettings());
     }
 
     /**

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java Sun Jun  7 15:39:51 2009
@@ -14,318 +14,325 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
+
 package org.apache.poi.hssf.usermodel;
 
-import java.util.ArrayList;
 
 /**
- * Common class for {@link HSSFHeader} and
- *  {@link HSSFFooter}.
+ * Common class for {@link HSSFHeader} and {@link HSSFFooter}.
  */
 public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.HeaderFooter {
-	protected String left;
-	protected String center;
-	protected String right;
+
+	protected HeaderFooter() {
+		//
+	}
 	
-	private boolean stripFields = false;
+	/**
+	 * @return the internal text representation (combining center, left and right parts).
+	 * Possibly empty string if no header or footer is set.  Never <code>null</code>.
+	 */
+	protected abstract String getRawText(); 
 	
-	protected HeaderFooter(String text) {
-		while (text != null && text.length() > 1) {
-		    int pos = text.length();
-		    switch (text.substring(1, 2).charAt(0)) {
-			    case 'L' :
+	private String[] splitParts() {
+		String text = getRawText();
+		// default values
+		String _left = "";
+		String _center = "";
+		String _right = "";
+
+		while (text.length() > 1) {
+			int pos = text.length();
+			switch (text.charAt(1)) {
+			case 'L':
 				if (text.indexOf("&C") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&C"));
-				} 
+					pos = Math.min(pos, text.indexOf("&C"));
+				}
 				if (text.indexOf("&R") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&R"));
-				} 
-				left = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&R"));
+				}
+				_left = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    case 'C' : 
+			case 'C':
 				if (text.indexOf("&L") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&L"));
-				} 
+					pos = Math.min(pos, text.indexOf("&L"));
+				}
 				if (text.indexOf("&R") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&R"));
-				} 
-				center = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&R"));
+				}
+				_center = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    case 'R' : 
+			case 'R':
 				if (text.indexOf("&C") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&C"));
-				} 
+					pos = Math.min(pos, text.indexOf("&C"));
+				}
 				if (text.indexOf("&L") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&L"));
-				} 
-				right = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&L"));
+				}
+				_right = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    default: 
-		    	text = null;
-		    }
+			default:
+				throw new IllegalStateException("bad text '" + getRawText() + "'.");
+			}
 		}
+		return new String[] { _left, _center, _right, };
+	}
+
+	/**
+	 * @return the left side of the header or footer.
+	 */
+	public final String getLeft() {
+		return splitParts()[0];
+	}
+
+	/**
+	 * @param newLeft The string to set as the left side.
+	 */
+	public final void setLeft(String newLeft) {
+		updatePart(0, newLeft); 
+	}
+
+	/**
+	 * @return the center of the header or footer.
+	 */
+	public final String getCenter() {
+		return splitParts()[1];
+	}
+
+	/**
+	 * @param newCenter The string to set as the center.
+	 */
+	public final void setCenter(String newCenter) {
+		updatePart(1, newCenter); 
+	}
+
+	/**
+	 * @return The right side of the header or footer.
+	 */
+	public final String getRight() {
+		return splitParts()[2];
+	}
+
+	/**
+	 * @param newRight The string to set as the right side.
+	 */
+	public final void setRight(String newRight) {
+		updatePart(2, newRight); 
 	}
 	
-    /**
-     * Get the left side of the header or footer.
-     * @return The string representing the left side.
-     */
-    public String getLeft() {
-    	if(stripFields)
-    		return stripFields(left);
-		return left;
-	}
-    public abstract void setLeft( String newLeft );
-
-    /**
-     * Get the center of the header or footer.
-     * @return The string representing the center.
-     */
-    public String getCenter() {
-    	if(stripFields)
-    		return stripFields(center);
-    	return center;
-    }
-    public abstract void setCenter( String newCenter );
-
-    /**
-     * Get the right side of the header or footer.
-     * @return The string representing the right side.
-     */
-    public String getRight() {
-    	if(stripFields)
-    		return stripFields(right);
-    	return right;
-    }
-    public abstract void setRight( String newRight );
-
-
-    /**
-     * Returns the string that represents the change in font size.
-     *
-     * @param size the new font size
-     * @return The special string to represent a new font size
-     */
-    public static String fontSize( short size )
-    {
-        return "&" + size;
-    }
-
-    /**
-     * Returns the string that represents the change in font.
-     *
-     * @param font  the new font
-     * @param style the fonts style, one of regular, italic, bold, italic bold or bold italic
-     * @return The special string to represent a new font size
-     */
-    public static String font( String font, String style )
-    {
-        return "&\"" + font + "," + style + "\"";
-    }
-
-    /**
-     * Returns the string representing the current page number
-     *
-     * @return The special string for page number
-     */
-    public static String page() {
-    	return PAGE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the number of pages.
-     *
-     * @return The special string for the number of pages
-     */
-    public static String numPages() {
-    	return NUM_PAGES_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current date
-     *
-     * @return The special string for the date
-     */
-    public static String date() {
-    	return DATE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current time
-     *
-     * @return The special string for the time
-     */
-    public static String time() {
-    	return TIME_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current file name
-     *
-     * @return The special string for the file name
-     */
-    public static String file() {
-    	return FILE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current tab (sheet) name
-     *
-     * @return The special string for tab name
-     */
-    public static String tab() {
-    	return SHEET_NAME_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start bold
-     *
-     * @return The special string for start bold
-     */
-    public static String startBold() {
-    	return BOLD_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end bold
-     *
-     * @return The special string for end bold
-     */
-    public static String endBold() {
-    	return BOLD_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start underline
-     *
-     * @return The special string for start underline
-     */
-    public static String startUnderline() {
-    	return UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end underline
-     *
-     * @return The special string for end underline
-     */
-    public static String endUnderline() {
-    	return UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start double underline
-     *
-     * @return The special string for start double underline
-     */
-    public static String startDoubleUnderline() {
-    	return DOUBLE_UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end double underline
-     *
-     * @return The special string for end double underline
-     */
-    public static String endDoubleUnderline() {
-    	return DOUBLE_UNDERLINE_FIELD.sequence;
-    }
-    
-    
-    /**
-     * Removes any fields (eg macros, page markers etc)
-     *  from the string.
-     * Normally used to make some text suitable for showing
-     *  to humans, and the resultant text should not normally
-     *  be saved back into the document!
-     */
-    public static String stripFields(String text) {
-    	int pos;
-    	
-    	// Check we really got something to work on
-    	if(text == null || text.length() == 0) {
-    		return text;
-    	}
-    	
-    	// Firstly, do the easy ones which are static
-    	for(int i=0; i<Field.ALL_FIELDS.size(); i++) {
-    		String seq = ((Field)Field.ALL_FIELDS.get(i)).sequence;
-    		while((pos = text.indexOf(seq)) > -1) {
-    			text = text.substring(0, pos) +
-    				text.substring(pos+seq.length());
-    		}
-    	}
-    	
-    	// Now do the tricky, dynamic ones
-    	// These are things like font sizes and font names
-    	text = text.replaceAll("\\&\\d+", "");
-    	text = text.replaceAll("\\&\".*?,.*?\"", "");
-    	
-    	// All done
-    	return text;
-    }
-    
-	
+	private void updatePart(int partIndex, String newValue) {
+		String[] parts = splitParts();
+		parts[partIndex] = newValue == null ? "" : newValue;
+		updateHeaderFooterText(parts);
+	}
+	/**
+	 * Creates the complete footer string based on the left, center, and middle
+	 * strings.
+	 */
+	private void updateHeaderFooterText(String[] parts) {
+		String _left = parts[0];
+		String _center = parts[1];
+		String _right = parts[2];
+		
+		if (_center.length() < 1 && _left.length() < 1 && _right.length() < 1) {
+			setHeaderFooterText("");
+			return;
+		}
+		StringBuilder sb = new StringBuilder(64);
+		sb.append("&C");
+		sb.append(_center);
+		sb.append("&L");
+		sb.append(_left);
+		sb.append("&R");
+		sb.append(_right);
+		String text = sb.toString();
+		setHeaderFooterText(text);
+	}
+
+	/**
+	 * @param text the new header footer text (contains mark-up tags). Possibly
+	 *            empty string never <code>null</code>
+	 */
+	protected abstract void setHeaderFooterText(String text);
+
+	/**
+	 * @param size
+	 *            the new font size
+	 * @return The mark-up tag representing a new font size
+	 */
+	public static String fontSize(short size) {
+		return "&" + size;
+	}
+
+	/**
+	 * @param font
+	 *            the new font
+	 * @param style
+	 *            the fonts style, one of regular, italic, bold, italic bold or
+	 *            bold italic
+	 * @return The mark-up tag representing a new font size
+	 */
+	public static String font(String font, String style) {
+		return "&\"" + font + "," + style + "\"";
+	}
+
+	/**
+	 * @return The mark-up tag representing the current page number
+	 */
+	public static String page() {
+		return MarkupTag.PAGE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the number of pages
+	 */
+	public static String numPages() {
+		return MarkupTag.NUM_PAGES_FIELD.getRepresentation();
+	}
+
 	/**
-	 * Are fields currently being stripped from
-	 *  the text that this {@link HeaderFooter} returns?
-	 *  Default is false, but can be changed
-	 */
-	public boolean areFieldsStripped() {
-		return stripFields;
-	}
-	/**
-	 * Should fields (eg macros) be stripped from
-	 *  the text that this class returns?
-	 * Default is not to strip.
-	 * @param stripFields
-	 */
-	public void setAreFieldsStripped(boolean stripFields) {
-		this.stripFields = stripFields;
-	}
-
-    
-    public static final Field SHEET_NAME_FIELD = new Field("&A");
-    public static final Field DATE_FIELD = new Field("&D");
-    public static final Field FILE_FIELD = new Field("&F");
-    public static final Field FULL_FILE_FIELD = new Field("&Z");
-    public static final Field PAGE_FIELD = new Field("&P");
-    public static final Field TIME_FIELD = new Field("&T");
-    public static final Field NUM_PAGES_FIELD = new Field("&N");
-    
-    public static final Field PICTURE_FIELD = new Field("&G");
-    
-    public static final PairField BOLD_FIELD = new PairField("&B");
-    public static final PairField ITALIC_FIELD = new PairField("&I");
-    public static final PairField STRIKETHROUGH_FIELD = new PairField("&S");
-    public static final PairField SUBSCRIPT_FIELD = new PairField("&Y");
-    public static final PairField SUPERSCRIPT_FIELD = new PairField("&X");
-    public static final PairField UNDERLINE_FIELD = new PairField("&U");
-    public static final PairField DOUBLE_UNDERLINE_FIELD = new PairField("&E");
-    
-    /**
-     * Represents a special field in a header or footer,
-     *  eg the page number
-     */
-    public static class Field {
-    	private static ArrayList ALL_FIELDS = new ArrayList();
-    	/** The character sequence that marks this field */
-    	public final String sequence;
-    	private Field(String sequence) {
-    		this.sequence = sequence;
-    		ALL_FIELDS.add(this);
-    	}
-    }
-    /**
-     * A special field that normally comes in a pair, eg
-     *  turn on underline / turn off underline
-     */
-    public static class PairField extends Field {
-    	private PairField(String sequence) {
-    		super(sequence);
-    	}
-    }
+	 * @return The mark-up tag representing the current date date
+	 */
+	public static String date() {
+		return MarkupTag.DATE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing current time
+	 */
+	public static String time() {
+		return MarkupTag.TIME_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the current file name
+	 */
+	public static String file() {
+		return MarkupTag.FILE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the current tab (sheet) name
+	 */
+	public static String tab() {
+		return MarkupTag.SHEET_NAME_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start bold
+	 */
+	public static String startBold() {
+		return MarkupTag.BOLD_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end bold
+	 */
+	public static String endBold() {
+		return MarkupTag.BOLD_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start underline
+	 */
+	public static String startUnderline() {
+		return MarkupTag.UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end underline
+	 */
+	public static String endUnderline() {
+		return MarkupTag.UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start double underline
+	 */
+	public static String startDoubleUnderline() {
+		return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end double underline
+	 */
+	public static String endDoubleUnderline() {
+		return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * Removes any fields (eg macros, page markers etc) from the string.
+	 * Normally used to make some text suitable for showing to humans, and the
+	 * resultant text should not normally be saved back into the document!
+	 */
+	public static String stripFields(String pText) {
+		int pos;
+
+		// Check we really got something to work on
+		if (pText == null || pText.length() == 0) {
+			return pText;
+		}
+
+		String text = pText;
+
+		// Firstly, do the easy ones which are static
+		for (MarkupTag mt : MarkupTag.values()) {
+			String seq = mt.getRepresentation();
+			while ((pos = text.indexOf(seq)) > -1) {
+				text = text.substring(0, pos) + text.substring(pos + seq.length());
+			}
+		}
+
+		// Now do the tricky, dynamic ones
+		// These are things like font sizes and font names
+		text = text.replaceAll("\\&\\d+", "");
+		text = text.replaceAll("\\&\".*?,.*?\"", "");
+
+		// All done
+		return text;
+	}
+
+	private enum MarkupTag {
+		SHEET_NAME_FIELD ("&A", false),
+		DATE_FIELD       ("&D", false),
+		FILE_FIELD       ("&F", false),
+		FULL_FILE_FIELD  ("&Z", false),
+		PAGE_FIELD       ("&P", false),
+		TIME_FIELD       ("&T", false),
+		NUM_PAGES_FIELD  ("&N", false),
+
+		PICTURE_FIELD    ("&G", false),
+
+		BOLD_FIELD             ("&B", true),
+		ITALIC_FIELD           ("&I", true),
+		STRIKETHROUGH_FIELD    ("&S", true),
+		SUBSCRIPT_FIELD        ("&Y", true),
+		SUPERSCRIPT_FIELD      ("&X", true),
+		UNDERLINE_FIELD        ("&U", true),
+		DOUBLE_UNDERLINE_FIELD ("&E", true),
+		;
+		
+		private final String _representation;
+		private final boolean _occursInPairs;
+		private MarkupTag(String sequence, boolean occursInPairs) {
+			_representation = sequence;
+			_occursInPairs = occursInPairs;
+		}
+		/**
+		 * @return The character sequence that marks this field
+		 */
+		public String getRepresentation() {
+			return _representation;
+		}
+
+		/**
+		 * @return true if this markup tag normally comes in a pair, eg turn on
+		 *         underline / turn off underline
+		 */
+		public boolean occursPairs() {
+			return _occursInPairs;
+		}
+	}
 }

Modified: poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/ss/formula/package.html
URL: http://svn.apache.org/viewvc/poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/ss/formula/package.html?rev=782402&r1=782401&r2=782402&view=diff
==============================================================================
--- poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/ss/formula/package.html (original)
+++ poi/tags/REL_3_5_BETA6/src/java/org/apache/poi/ss/formula/package.html Sun Jun  7 15:39:51 2009
@@ -1,29 +1,29 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<!--
-   ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-   ====================================================================
--->
-<html>
-<head>
-</head>
-<body bgcolor="white">
-
-This package contains common internal POI code for manipulating formulas.
-Client applications should not refer to these classes directly.
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+   ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+   ====================================================================
+-->
+<html>
+<head>
+</head>
+<body bgcolor="white">
+
+This package contains common internal POI code for manipulating formulas.
+Client applications should not refer to these classes directly.
+
+</body>
+</html>



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