You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/10/25 03:47:28 UTC
svn commit: r707807 [1/3] - in /poi/branches/ooxml: ./
src/documentation/content/xdocs/ src/java/org/apache/poi/hssf/dev/
src/java/org/apache/poi/hssf/model/ src/java/org/apache/poi/hssf/record/
src/java/org/apache/poi/hssf/record/formula/ src/java/org...
Author: josh
Date: Fri Oct 24 18:47:25 2008
New Revision: 707807
URL: http://svn.apache.org/viewvc?rev=707807&view=rev
Log:
Merged revisions 703100,703197,703302,703596,703620,703645,703651,706540 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk
........
r703100 | josh | 2008-10-09 01:33:54 -0700 (Thu, 09 Oct 2008) | 1 line
Removed last occurrences of storing Ptg arrays in Stacks. Some related clean-up.
........
r703197 | josh | 2008-10-09 09:10:39 -0700 (Thu, 09 Oct 2008) | 1 line
Should have been submitted with r703100 (changes to Ptg)
........
r703302 | josh | 2008-10-09 17:40:58 -0700 (Thu, 09 Oct 2008) | 1 line
Fix for bug 45964 - support for link formulas in Text Objects
........
r703596 | josh | 2008-10-10 15:59:14 -0700 (Fri, 10 Oct 2008) | 1 line
Made RecordInputStream final (major clean-up in test cases and BiffViewer)
........
r703620 | josh | 2008-10-10 18:11:05 -0700 (Fri, 10 Oct 2008) | 2 lines
fix for bug 45866 - allowed for change of unicode compression across Continue records
........
r703645 | yegor | 2008-10-11 03:31:24 -0700 (Sat, 11 Oct 2008) | 1 line
fixed error in eval.xml: use < instead of '<'
........
r703651 | yegor | 2008-10-11 05:01:42 -0700 (Sat, 11 Oct 2008) | 1 line
set trunk version.id=3.3-alpha1
........
r706540 | yegor | 2008-10-20 23:47:35 -0700 (Mon, 20 Oct 2008) | 1 line
updated release version on the index page, started a new section in the change log
........
Added:
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java
- copied unchanged from r706540, poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java
Removed:
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/CustomField.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectBaseRecord.java
Modified:
poi/branches/ooxml/ (props changed)
poi/branches/ooxml/src/documentation/content/xdocs/changes.xml
poi/branches/ooxml/src/documentation/content/xdocs/index.xml
poi/branches/ooxml/src/documentation/content/xdocs/status.xml
poi/branches/ooxml/src/java/org/apache/poi/hssf/dev/BiffViewer.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/model/TextboxShape.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ContinueRecord.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordFactory.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/TextObjectRecord.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/record/formula/Ptg.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
poi/branches/ooxml/src/java/org/apache/poi/hssf/usermodel/HSSFRichTextString.java
poi/branches/ooxml/src/java/org/apache/poi/ss/formula/SheetRefEvaluator.java (props changed)
poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/usermodel/HSSFChart.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/eventmodel/TestEventRecordFactory.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAreaFormatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAreaRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAxisLineFormatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAxisOptionsRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAxisParentRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAxisRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestAxisUsedRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestBarRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestBoundSheetRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestCategorySeriesAxisRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestChartRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestCommonObjectDataSubRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestDatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestDataFormatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestDefaultDataLabelTextPropertiesRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestEmbeddedObjectRefSubRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestEndSubRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestExtendedFormatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestExternalNameRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFontBasisRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFontIndexRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFontRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFormulaRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestFrameRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestHyperlinkRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestLegendRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestLineFormatRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestLinkedDataRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestNameRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestNoteRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestNoteStructureSubRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestNumberFormatIndexRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestObjRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestObjectLinkRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestPaneRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestPlotAreaRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestPlotGrowthRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestRecordFactory.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSCLRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSSTDeserializer.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesChartGroupIndexRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesIndexRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesLabelsRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesListRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesTextRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSeriesToChartGroupRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSheetPropertiesRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestStringRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestSupBookRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTableRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTextObjectBaseRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTextObjectRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTextRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestTickRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestUnicodeString.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestUnitsRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestValueRangeRecord.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/TestcaseRecordInputStream.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/constant/TestConstantValueParser.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestFuncPtg.java
poi/branches/ooxml/src/testcases/org/apache/poi/hssf/record/formula/TestReferencePtg.java
Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Oct 24 18:47:25 2008
@@ -1 +1 @@
-/poi/trunk:693591-694881,695264-695420,695621,695649-703092
+/poi/trunk:693591-694881,695264-695420,695621,695649-706540
Propchange: poi/branches/ooxml/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Oct 24 18:47:25 2008
@@ -1 +1 @@
-/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-703092
+/poi/trunk:1-638784,638786-639486,639488-639601,639603-640056,640058-642562,642564-642566,642568-642574,642576-642736,642739-650914,650916-706540
Modified: poi/branches/ooxml/src/documentation/content/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/documentation/content/xdocs/changes.xml?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/documentation/content/xdocs/changes.xml (original)
+++ poi/branches/ooxml/src/documentation/content/xdocs/changes.xml Fri Oct 24 18:47:25 2008
@@ -66,7 +66,12 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
- <release version="3.2-alpha1" date="2008-??-??">
+ <release version="3.5-beta4" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">YK: remove me. required to keep Forrest DTD compiler quiet</action>
+ </release>
+ <release version="3.2-FINAL" date="2008-10-19">
+ <action dev="POI-DEVELOPERS" type="fix">45866 - allowed for change of unicode compression across Continue records</action>
+ <action dev="POI-DEVELOPERS" type="fix">45964 - support for link formulas in Text Objects</action>
<action dev="POI-DEVELOPERS" type="fix">43354 - support for evalating formulas with missing args</action>
<action dev="POI-DEVELOPERS" type="fix">45912 - fixed ArrayIndexOutOfBoundsException in EmbeddedObjectRefSubRecord</action>
<action dev="POI-DEVELOPERS" type="fix">45889 - fixed ArrayIndexOutOfBoundsException when constructing HSLF Table with a single row </action>
Modified: poi/branches/ooxml/src/documentation/content/xdocs/index.xml
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/documentation/content/xdocs/index.xml?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/documentation/content/xdocs/index.xml (original)
+++ poi/branches/ooxml/src/documentation/content/xdocs/index.xml Fri Oct 24 18:47:25 2008
@@ -44,10 +44,10 @@
People interested should also follow the
<link href="mailinglists.html">dev list</link> to track progress.</p>
</section>
- <section><title>POI 3.1-FINAL Released (2008-06-29)</title>
+ <section><title>POI 3.2-FINAL Released (2008-10-19)</title>
<p>
- The POI team is pleased to announce the release of 3.1 FINAL, the latest release of Apache POI.
- There have been many important bug fixes since the 3.0.2 release and a lot of new features.
+ The POI team is pleased to announce the release of 3.2 FINAL, the latest release of Apache POI.
+ There have been many important bug fixes since the 3.1 release and a lot of new features.
</p><p> A full list of changes is available in
<link href="./changes.html">the changelog</link>, and
<link href="http://www.apache.org/dyn/closer.cgi/poi/release/">download</link>
@@ -56,7 +56,7 @@
</p>
<p>
The release is also available from the central Maven repository
- under Group ID "org.apache.poi" and Version "3.1-FINAL".
+ under Group ID "org.apache.poi" and Version "3.2-FINAL".
</p>
</section>
Modified: poi/branches/ooxml/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/documentation/content/xdocs/status.xml?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/documentation/content/xdocs/status.xml (original)
+++ poi/branches/ooxml/src/documentation/content/xdocs/status.xml Fri Oct 24 18:47:25 2008
@@ -63,7 +63,12 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling PowerPoint files, irrespective of if they are .ppt or .pptx</action>
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
- <release version="3.2-alpha1" date="2008-??-??">
+ <release version="3.5-beta4" date="2008-??-??">
+ <action dev="POI-DEVELOPERS" type="fix">YK: remove me. required to keep Forrest DTD compiler quiet</action>
+ </release>
+ <release version="3.2-FINAL" date="2008-10-19">
+ <action dev="POI-DEVELOPERS" type="fix">45866 - allowed for change of unicode compression across Continue records</action>
+ <action dev="POI-DEVELOPERS" type="fix">45964 - support for link formulas in Text Objects</action>
<action dev="POI-DEVELOPERS" type="fix">43354 - support for evalating formulas with missing args</action>
<action dev="POI-DEVELOPERS" type="fix">45912 - fixed ArrayIndexOutOfBoundsException in EmbeddedObjectRefSubRecord</action>
<action dev="POI-DEVELOPERS" type="fix">45889 - fixed ArrayIndexOutOfBoundsException when constructing HSLF Table with a single row </action>
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/dev/BiffViewer.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/dev/BiffViewer.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/dev/BiffViewer.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/dev/BiffViewer.java Fri Oct 24 18:47:25 2008
@@ -17,17 +17,23 @@
package org.apache.poi.hssf.dev;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.PrintStream;
+import java.io.Writer;
import java.util.ArrayList;
+import java.util.List;
import org.apache.poi.hssf.record.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.HexDump;
+import org.apache.poi.util.LittleEndian;
/**
* Utillity for reading in BIFF8 records and displaying data from them.
@@ -37,333 +43,488 @@
*@see #main
*/
public final class BiffViewer {
- private final File _inputFile;
- private boolean dump;
- private final PrintStream _ps;
-
-
- public BiffViewer(File inFile, PrintStream ps) {
- _inputFile = inFile;
- _ps = ps;
- }
-
-
- /**
- * Method run starts up BiffViewer...
- */
- public void run() {
- try {
- POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(_inputFile));
- InputStream stream = fs.createDocumentInputStream("Workbook");
- createRecords(stream, dump, _ps);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
- /**
- * Create an array of records from an input stream
- *
- *@param in the InputStream from which the records
- * will be obtained
- *@param dump
- *@return an array of Records created from the
- * InputStream
- *@exception RecordFormatException on error processing the InputStream
- */
- public static Record[] createRecords(InputStream in, boolean dump, PrintStream ps)
- throws RecordFormatException {
- ArrayList records = new ArrayList();
- RecordDetails activeRecord = null;
-
- BiffviewRecordInputStream recStream = new BiffviewRecordInputStream(in);
- while (recStream.hasNextRecord()) {
- recStream.nextRecord();
- if (recStream.getSid() != 0) {
- Record record = createRecord (recStream);
- if (record.getSid() != ContinueRecord.sid)
- {
- records.add(record);
- if (activeRecord != null)
- activeRecord.dump(ps);
- int startPos = (int)(recStream.getPos()-recStream.getLength() - 4);
- activeRecord = new RecordDetails(recStream.getSid(), recStream.getLength(), startPos, record);
- }
- if (dump) {
- recStream.dumpBytes(ps);
- }
- }
- }
- if (activeRecord != null) {
- activeRecord.dump(ps);
- }
- Record[] retval = new Record[records.size()];
- records.toArray(retval);
- return retval;
- }
-
-
- /**
- * Essentially a duplicate of RecordFactory. Kept separate as not to screw
- * up non-debug operations.
- *
- */
- private static Record createRecord( RecordInputStream in )
- {
- switch ( in.getSid() )
- {
- case AreaFormatRecord.sid: return new AreaFormatRecord(in);
- case AreaRecord.sid: return new AreaRecord(in);
- case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in);
- case AxisOptionsRecord.sid: return new AxisOptionsRecord(in);
- case AxisParentRecord.sid: return new AxisParentRecord(in);
- case AxisRecord.sid: return new AxisRecord(in);
- case AxisUsedRecord.sid: return new AxisUsedRecord(in);
- case BOFRecord.sid: return new BOFRecord(in);
- case BackupRecord.sid: return new BackupRecord(in);
- case BarRecord.sid: return new BarRecord(in);
- case BeginRecord.sid: return new BeginRecord(in);
- case BlankRecord.sid: return new BlankRecord(in);
- case BookBoolRecord.sid: return new BookBoolRecord(in);
- case BoolErrRecord.sid: return new BoolErrRecord(in);
- case BottomMarginRecord.sid: return new BottomMarginRecord(in);
- case BoundSheetRecord.sid: return new BoundSheetRecord(in);
- case CFHeaderRecord.sid: return new CFHeaderRecord(in);
- case CFRuleRecord.sid: return new CFRuleRecord(in);
- case CalcCountRecord.sid: return new CalcCountRecord(in);
- case CalcModeRecord.sid: return new CalcModeRecord(in);
- case CategorySeriesAxisRecord.sid: return new CategorySeriesAxisRecord(in);
- case ChartFormatRecord.sid: return new ChartFormatRecord(in);
- case ChartRecord.sid: return new ChartRecord(in);
- case CodepageRecord.sid: return new CodepageRecord(in);
- case ColumnInfoRecord.sid: return new ColumnInfoRecord(in);
- case ContinueRecord.sid: return new ContinueRecord(in);
- case CountryRecord.sid: return new CountryRecord(in);
- case DBCellRecord.sid: return new DBCellRecord(in);
- case DSFRecord.sid: return new DSFRecord(in);
- case DatRecord.sid: return new DatRecord(in);
- case DataFormatRecord.sid: return new DataFormatRecord(in);
- case DateWindow1904Record.sid: return new DateWindow1904Record(in);
- case DefaultColWidthRecord.sid:return new DefaultColWidthRecord(in);
- case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in);
- case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in);
- case DeltaRecord.sid: return new DeltaRecord(in);
- case DimensionsRecord.sid: return new DimensionsRecord(in);
- case DrawingGroupRecord.sid: return new DrawingGroupRecord(in);
- case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in);
- case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in);
- case DVRecord.sid: return new DVRecord(in);
- case DVALRecord.sid: return new DVALRecord(in);
- case EOFRecord.sid: return new EOFRecord(in);
- case EndRecord.sid: return new EndRecord(in);
- case ExtSSTRecord.sid: return new ExtSSTRecord(in);
- case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
- case ExternSheetRecord.sid: return new ExternSheetRecord(in);
- case FilePassRecord.sid: return new FilePassRecord(in);
- case FileSharingRecord.sid: return new FileSharingRecord(in);
- case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);
- case FontBasisRecord.sid: return new FontBasisRecord(in);
- case FontIndexRecord.sid: return new FontIndexRecord(in);
- case FontRecord.sid: return new FontRecord(in);
- case FooterRecord.sid: return new FooterRecord(in);
- case FormatRecord.sid: return new FormatRecord(in);
- case FormulaRecord.sid: return new FormulaRecord(in);
- case FrameRecord.sid: return new FrameRecord(in);
- case GridsetRecord.sid: return new GridsetRecord(in);
- case GutsRecord.sid: return new GutsRecord(in);
- case HCenterRecord.sid: return new HCenterRecord(in);
- case HeaderRecord.sid: return new HeaderRecord(in);
- case HideObjRecord.sid: return new HideObjRecord(in);
- case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in);
- case HyperlinkRecord.sid: return new HyperlinkRecord(in);
- case IndexRecord.sid: return new IndexRecord(in);
- case InterfaceEndRecord.sid: return new InterfaceEndRecord(in);
- case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in);
- case IterationRecord.sid: return new IterationRecord(in);
- case LabelRecord.sid: return new LabelRecord(in);
- case LabelSSTRecord.sid: return new LabelSSTRecord(in);
- case LeftMarginRecord.sid: return new LeftMarginRecord(in);
- case LegendRecord.sid: return new LegendRecord(in);
- case LineFormatRecord.sid: return new LineFormatRecord(in);
- case LinkedDataRecord.sid: return new LinkedDataRecord(in);
- case MMSRecord.sid: return new MMSRecord(in);
- case MergeCellsRecord.sid: return new MergeCellsRecord(in);
- case MulBlankRecord.sid: return new MulBlankRecord(in);
- case MulRKRecord.sid: return new MulRKRecord(in);
- case NameRecord.sid: return new NameRecord(in);
- case NoteRecord.sid: return new NoteRecord(in);
- case NumberRecord.sid: return new NumberRecord(in);
- case ObjRecord.sid: return new ObjRecord(in);
- case ObjectLinkRecord.sid: return new ObjectLinkRecord(in);
- case PaletteRecord.sid: return new PaletteRecord(in);
- case PaneRecord.sid: return new PaneRecord(in);
- case PasswordRecord.sid: return new PasswordRecord(in);
- case PasswordRev4Record.sid: return new PasswordRev4Record(in);
- case PlotAreaRecord.sid: return new PlotAreaRecord(in);
- case PlotGrowthRecord.sid: return new PlotGrowthRecord(in);
- case PrecisionRecord.sid: return new PrecisionRecord(in);
- case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in);
- case PrintHeadersRecord.sid: return new PrintHeadersRecord(in);
- case PrintSetupRecord.sid: return new PrintSetupRecord(in);
- case ProtectRecord.sid: return new ProtectRecord(in);
- case ProtectionRev4Record.sid: return new ProtectionRev4Record(in);
- case RKRecord.sid: return new RKRecord(in);
- case RefModeRecord.sid: return new RefModeRecord(in);
- case RefreshAllRecord.sid: return new RefreshAllRecord(in);
- case RightMarginRecord.sid: return new RightMarginRecord(in);
- case RowRecord.sid: return new RowRecord(in);
- case SCLRecord.sid: return new SCLRecord(in);
- case SSTRecord.sid: return new SSTRecord(in);
- case SaveRecalcRecord.sid: return new SaveRecalcRecord(in);
- case SelectionRecord.sid: return new SelectionRecord(in);
- case SeriesIndexRecord.sid: return new SeriesIndexRecord(in);
- case SeriesListRecord.sid: return new SeriesListRecord(in);
- case SeriesRecord.sid: return new SeriesRecord(in);
- case SeriesTextRecord.sid: return new SeriesTextRecord(in);
- case SeriesToChartGroupRecord.sid: return new SeriesToChartGroupRecord(in);
- case SharedFormulaRecord.sid: return new SharedFormulaRecord(in);
- case SheetPropertiesRecord.sid:return new SheetPropertiesRecord(in);
- case StringRecord.sid: return new StringRecord(in);
- case StyleRecord.sid: return new StyleRecord(in);
- case SupBookRecord.sid: return new SupBookRecord(in);
- case TabIdRecord.sid: return new TabIdRecord(in);
- case TableRecord.sid: return new TableRecord(in);
- case TextObjectRecord.sid: return new TextObjectRecord(in);
- case TextRecord.sid: return new TextRecord(in);
- case TickRecord.sid: return new TickRecord(in);
- case TopMarginRecord.sid: return new TopMarginRecord(in);
- case UnitsRecord.sid: return new UnitsRecord(in);
- case UseSelFSRecord.sid: return new UseSelFSRecord(in);
- case VCenterRecord.sid: return new VCenterRecord(in);
- case ValueRangeRecord.sid: return new ValueRangeRecord(in);
- case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in);
- case WSBoolRecord.sid: return new WSBoolRecord(in);
- case WindowOneRecord.sid: return new WindowOneRecord(in);
- case WindowProtectRecord.sid: return new WindowProtectRecord(in);
- case WindowTwoRecord.sid: return new WindowTwoRecord(in);
- case WriteAccessRecord.sid: return new WriteAccessRecord(in);
- case WriteProtectRecord.sid: return new WriteProtectRecord(in);
-
- }
- return new UnknownRecord(in);
- }
-
-
- /**
- * Method setDump - hex dump out data or not.
- */
- public void setDump(boolean dump) {
- this.dump = dump;
- }
-
-
- /**
- * Method main with 1 argument just run straight biffview against given
- * file<P>
- *
- * with 2 arguments where the second argument is "on" - run biffviewer<P>
- *
- * with hex dumps of records <P>
- *
- * with 2 arguments where the second argument is "bfd" just run a big fat
- * hex dump of the file...don't worry about biffviewing it at all
- * <p>
- * Define the system property <code>poi.deserialize.escher</code> to turn on
- * deserialization of escher records.
- *
- */
- public static void main(String[] args) {
-
- System.setProperty("poi.deserialize.escher", "true");
-
- if (args.length == 0) {
- System.out.println( "Biff viewer needs a filename" );
- return;
- }
-
- try {
- String inFileName = args[0];
- File inputFile = new File(inFileName);
- if(!inputFile.exists()) {
- throw new RuntimeException("specified inputFile '" + inFileName + "' does not exist");
- }
- PrintStream ps;
- if (false) { // set to true to output to file
- OutputStream os = new FileOutputStream(inFileName + ".out");
- ps = new PrintStream(os);
- } else {
- ps = System.out;
- }
- BiffViewer viewer = new BiffViewer(inputFile, ps);
-
- if (args.length > 1 && args[1].equals("on")) {
- viewer.setDump(true);
- }
- if (args.length > 1 && args[1].equals("bfd")) {
- POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(inputFile));
- InputStream stream = fs.createDocumentInputStream("Workbook");
- int size = stream.available();
- byte[] data = new byte[size];
-
- stream.read(data);
- HexDump.dump(data, 0, System.out, 0);
- } else {
- viewer.run();
- }
- ps.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * This record supports dumping of completed continue records.
- */
- private static final class RecordDetails
- {
- short rectype, recsize;
- int startloc;
- Record record;
-
- public RecordDetails( short rectype, short recsize, int startloc, Record record )
- {
- this.rectype = rectype;
- this.recsize = recsize;
- this.startloc = startloc;
- this.record = record;
- }
-
- public short getRectype()
- {
- return rectype;
- }
-
- public short getRecsize()
- {
- return recsize;
- }
-
- public Record getRecord()
- {
- return record;
- }
-
- public void dump(PrintStream ps) {
- ps.println("Offset 0x" + Integer.toHexString(startloc) + " (" + startloc + ")");
- ps.println( "recordid = 0x" + Integer.toHexString( rectype ) + ", size = " + recsize );
- ps.println( record.toString() );
- }
- }
-
- private static final class BiffviewRecordInputStream extends RecordInputStream {
- public BiffviewRecordInputStream(InputStream in) {
- super(in);
- }
- public void dumpBytes(PrintStream ps) {
- ps.println(HexDump.dump(this.data, 0, this.currentLength));
- }
- }
+ static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray();
+ private BiffViewer() {
+ // no instances of this class
+ }
+
+ /**
+ * Create an array of records from an input stream
+ *
+ *@param in the InputStream from which the records will be obtained
+ *@return an array of Records created from the InputStream
+ *@exception RecordFormatException on error processing the InputStream
+ */
+ public static Record[] createRecords(InputStream is, PrintStream ps, BiffRecordListener recListener, boolean dumpInterpretedRecords)
+ throws RecordFormatException {
+ ArrayList temp = new ArrayList();
+
+ RecordInputStream recStream = new RecordInputStream(is);
+ while (recStream.hasNextRecord()) {
+ recStream.nextRecord();
+ if (recStream.getSid() == 0) {
+ continue;
+ }
+ Record record = createRecord (recStream);
+ if (record.getSid() == ContinueRecord.sid) {
+ continue;
+ }
+ temp.add(record);
+ if (dumpInterpretedRecords) {
+ String[] headers = recListener.getRecentHeaders();
+ for (int i = 0; i < headers.length; i++) {
+ ps.println(headers[i]);
+ }
+ ps.print(record.toString());
+ }
+ ps.println();
+ }
+ Record[] result = new Record[temp.size()];
+ temp.toArray(result);
+ return result;
+ }
+
+
+ /**
+ * Essentially a duplicate of RecordFactory. Kept separate as not to screw
+ * up non-debug operations.
+ *
+ */
+ private static Record createRecord(RecordInputStream in) {
+ switch (in.getSid()) {
+ case AreaFormatRecord.sid: return new AreaFormatRecord(in);
+ case AreaRecord.sid: return new AreaRecord(in);
+ case ArrayRecord.sid: return new ArrayRecord(in);
+ case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in);
+ case AxisOptionsRecord.sid: return new AxisOptionsRecord(in);
+ case AxisParentRecord.sid: return new AxisParentRecord(in);
+ case AxisRecord.sid: return new AxisRecord(in);
+ case AxisUsedRecord.sid: return new AxisUsedRecord(in);
+ case BOFRecord.sid: return new BOFRecord(in);
+ case BackupRecord.sid: return new BackupRecord(in);
+ case BarRecord.sid: return new BarRecord(in);
+ case BeginRecord.sid: return new BeginRecord(in);
+ case BlankRecord.sid: return new BlankRecord(in);
+ case BookBoolRecord.sid: return new BookBoolRecord(in);
+ case BoolErrRecord.sid: return new BoolErrRecord(in);
+ case BottomMarginRecord.sid: return new BottomMarginRecord(in);
+ case BoundSheetRecord.sid: return new BoundSheetRecord(in);
+ case CFHeaderRecord.sid: return new CFHeaderRecord(in);
+ case CFRuleRecord.sid: return new CFRuleRecord(in);
+ case CalcCountRecord.sid: return new CalcCountRecord(in);
+ case CalcModeRecord.sid: return new CalcModeRecord(in);
+ case CategorySeriesAxisRecord.sid: return new CategorySeriesAxisRecord(in);
+ case ChartFormatRecord.sid: return new ChartFormatRecord(in);
+ case ChartRecord.sid: return new ChartRecord(in);
+ case CodepageRecord.sid: return new CodepageRecord(in);
+ case ColumnInfoRecord.sid: return new ColumnInfoRecord(in);
+ case ContinueRecord.sid: return new ContinueRecord(in);
+ case CountryRecord.sid: return new CountryRecord(in);
+ case DBCellRecord.sid: return new DBCellRecord(in);
+ case DSFRecord.sid: return new DSFRecord(in);
+ case DatRecord.sid: return new DatRecord(in);
+ case DataFormatRecord.sid: return new DataFormatRecord(in);
+ case DateWindow1904Record.sid: return new DateWindow1904Record(in);
+ case DefaultColWidthRecord.sid:return new DefaultColWidthRecord(in);
+ case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in);
+ case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in);
+ case DeltaRecord.sid: return new DeltaRecord(in);
+ case DimensionsRecord.sid: return new DimensionsRecord(in);
+ case DrawingGroupRecord.sid: return new DrawingGroupRecord(in);
+ case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in);
+ case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in);
+ case DVRecord.sid: return new DVRecord(in);
+ case DVALRecord.sid: return new DVALRecord(in);
+ case EOFRecord.sid: return new EOFRecord(in);
+ case EndRecord.sid: return new EndRecord(in);
+ case ExtSSTRecord.sid: return new ExtSSTRecord(in);
+ case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in);
+ case ExternSheetRecord.sid: return new ExternSheetRecord(in);
+ case FilePassRecord.sid: return new FilePassRecord(in);
+ case FileSharingRecord.sid: return new FileSharingRecord(in);
+ case FnGroupCountRecord.sid: return new FnGroupCountRecord(in);
+ case FontBasisRecord.sid: return new FontBasisRecord(in);
+ case FontIndexRecord.sid: return new FontIndexRecord(in);
+ case FontRecord.sid: return new FontRecord(in);
+ case FooterRecord.sid: return new FooterRecord(in);
+ case FormatRecord.sid: return new FormatRecord(in);
+ case FormulaRecord.sid: return new FormulaRecord(in);
+ case FrameRecord.sid: return new FrameRecord(in);
+ case GridsetRecord.sid: return new GridsetRecord(in);
+ case GutsRecord.sid: return new GutsRecord(in);
+ case HCenterRecord.sid: return new HCenterRecord(in);
+ case HeaderRecord.sid: return new HeaderRecord(in);
+ case HideObjRecord.sid: return new HideObjRecord(in);
+ case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in);
+ case HyperlinkRecord.sid: return new HyperlinkRecord(in);
+ case IndexRecord.sid: return new IndexRecord(in);
+ case InterfaceEndRecord.sid: return new InterfaceEndRecord(in);
+ case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in);
+ case IterationRecord.sid: return new IterationRecord(in);
+ case LabelRecord.sid: return new LabelRecord(in);
+ case LabelSSTRecord.sid: return new LabelSSTRecord(in);
+ case LeftMarginRecord.sid: return new LeftMarginRecord(in);
+ case LegendRecord.sid: return new LegendRecord(in);
+ case LineFormatRecord.sid: return new LineFormatRecord(in);
+ case LinkedDataRecord.sid: return new LinkedDataRecord(in);
+ case MMSRecord.sid: return new MMSRecord(in);
+ case MergeCellsRecord.sid: return new MergeCellsRecord(in);
+ case MulBlankRecord.sid: return new MulBlankRecord(in);
+ case MulRKRecord.sid: return new MulRKRecord(in);
+ case NameRecord.sid: return new NameRecord(in);
+ case NoteRecord.sid: return new NoteRecord(in);
+ case NumberRecord.sid: return new NumberRecord(in);
+ case ObjRecord.sid: return new ObjRecord(in);
+ case ObjectLinkRecord.sid: return new ObjectLinkRecord(in);
+ case PaletteRecord.sid: return new PaletteRecord(in);
+ case PaneRecord.sid: return new PaneRecord(in);
+ case PasswordRecord.sid: return new PasswordRecord(in);
+ case PasswordRev4Record.sid: return new PasswordRev4Record(in);
+ case PlotAreaRecord.sid: return new PlotAreaRecord(in);
+ case PlotGrowthRecord.sid: return new PlotGrowthRecord(in);
+ case PrecisionRecord.sid: return new PrecisionRecord(in);
+ case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in);
+ case PrintHeadersRecord.sid: return new PrintHeadersRecord(in);
+ case PrintSetupRecord.sid: return new PrintSetupRecord(in);
+ case ProtectRecord.sid: return new ProtectRecord(in);
+ case ProtectionRev4Record.sid: return new ProtectionRev4Record(in);
+ case RKRecord.sid: return new RKRecord(in);
+ case RefModeRecord.sid: return new RefModeRecord(in);
+ case RefreshAllRecord.sid: return new RefreshAllRecord(in);
+ case RightMarginRecord.sid: return new RightMarginRecord(in);
+ case RowRecord.sid: return new RowRecord(in);
+ case SCLRecord.sid: return new SCLRecord(in);
+ case SSTRecord.sid: return new SSTRecord(in);
+ case SaveRecalcRecord.sid: return new SaveRecalcRecord(in);
+ case SelectionRecord.sid: return new SelectionRecord(in);
+ case SeriesIndexRecord.sid: return new SeriesIndexRecord(in);
+ case SeriesListRecord.sid: return new SeriesListRecord(in);
+ case SeriesRecord.sid: return new SeriesRecord(in);
+ case SeriesTextRecord.sid: return new SeriesTextRecord(in);
+ case SeriesToChartGroupRecord.sid: return new SeriesToChartGroupRecord(in);
+ case SharedFormulaRecord.sid: return new SharedFormulaRecord(in);
+ case SheetPropertiesRecord.sid:return new SheetPropertiesRecord(in);
+ case StringRecord.sid: return new StringRecord(in);
+ case StyleRecord.sid: return new StyleRecord(in);
+ case SupBookRecord.sid: return new SupBookRecord(in);
+ case TabIdRecord.sid: return new TabIdRecord(in);
+ case TableRecord.sid: return new TableRecord(in);
+ case TextObjectRecord.sid: return new TextObjectRecord(in);
+ case TextRecord.sid: return new TextRecord(in);
+ case TickRecord.sid: return new TickRecord(in);
+ case TopMarginRecord.sid: return new TopMarginRecord(in);
+ case UnitsRecord.sid: return new UnitsRecord(in);
+ case UseSelFSRecord.sid: return new UseSelFSRecord(in);
+ case VCenterRecord.sid: return new VCenterRecord(in);
+ case ValueRangeRecord.sid: return new ValueRangeRecord(in);
+ case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in);
+ case WSBoolRecord.sid: return new WSBoolRecord(in);
+ case WindowOneRecord.sid: return new WindowOneRecord(in);
+ case WindowProtectRecord.sid: return new WindowProtectRecord(in);
+ case WindowTwoRecord.sid: return new WindowTwoRecord(in);
+ case WriteAccessRecord.sid: return new WriteAccessRecord(in);
+ case WriteProtectRecord.sid: return new WriteProtectRecord(in);
+
+ }
+ return new UnknownRecord(in);
+ }
+
+ /**
+ * Method main with 1 argument just run straight biffview against given
+ * file<P>
+ *
+ * with 2 arguments where the second argument is "on" - run biffviewer<P>
+ *
+ * with hex dumps of records <P>
+ *
+ * with 2 arguments where the second argument is "bfd" just run a big fat
+ * hex dump of the file...don't worry about biffviewing it at all
+ * <p>
+ * Define the system property <code>poi.deserialize.escher</code> to turn on
+ * deserialization of escher records.
+ *
+ */
+ public static void main(String[] args) {
+
+ System.setProperty("poi.deserialize.escher", "true");
+
+ if (args.length == 0) {
+ System.out.println( "Biff viewer needs a filename" );
+ return;
+ }
+
+ try {
+ String inFileName = args[0];
+ File inputFile = new File(inFileName);
+ if(!inputFile.exists()) {
+ throw new RuntimeException("specified inputFile '" + inFileName + "' does not exist");
+ }
+ PrintStream ps;
+ if (false) { // set to true to output to file
+ OutputStream os = new FileOutputStream(inFileName + ".out");
+ ps = new PrintStream(os);
+ } else {
+ ps = System.out;
+ }
+
+ if (args.length > 1 && args[1].equals("bfd")) {
+ POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(inputFile));
+ InputStream stream = fs.createDocumentInputStream("Workbook");
+ int size = stream.available();
+ byte[] data = new byte[size];
+
+ stream.read(data);
+ HexDump.dump(data, 0, System.out, 0);
+ } else {
+ boolean dumpInterpretedRecords = true;
+ boolean dumpHex = args.length > 1 && args[1].equals("on");
+
+ POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(inputFile));
+ InputStream is = fs.createDocumentInputStream("Workbook");
+ BiffRecordListener recListener = new BiffRecordListener(dumpHex ? new OutputStreamWriter(ps) : null);
+ is = new BiffDumpingStream(is, recListener);
+ createRecords(is, ps, recListener, dumpInterpretedRecords);
+ }
+ ps.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static final class BiffRecordListener implements IBiffRecordListener {
+ private final Writer _hexDumpWriter;
+ private final List _headers;
+ public BiffRecordListener(Writer hexDumpWriter) {
+ _hexDumpWriter = hexDumpWriter;
+ _headers = new ArrayList();
+ }
+
+ public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
+ byte[] data) {
+ String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
+ _headers.add(header);
+ Writer w = _hexDumpWriter;
+ if (w != null) {
+ try {
+ w.write(header);
+ w.write(NEW_LINE_CHARS);
+ hexDumpAligned(w, data, 0, dataSize+4, globalOffset);
+ w.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ public String[] getRecentHeaders() {
+ String[] result = new String[_headers.size()];
+ _headers.toArray(result);
+ _headers.clear();
+ return result;
+ }
+ private static String formatRecordDetails(int globalOffset, int sid, int size, int recordCounter) {
+ StringBuffer sb = new StringBuffer(64);
+ sb.append("Offset=").append(HexDump.intToHex(globalOffset)).append("(").append(globalOffset).append(")");
+ sb.append(" recno=").append(recordCounter);
+ sb.append( " sid=").append(HexDump.shortToHex(sid));
+ sb.append( " size=").append(HexDump.shortToHex(size)).append("(").append(size).append(")");
+ return sb.toString();
+ }
+ }
+
+ private static interface IBiffRecordListener {
+
+ void processRecord(int globalOffset, int recordCounter, int sid, int dataSize, byte[] data);
+
+ }
+
+ /**
+ * Wraps a plain {@link InputStream} and allows BIFF record information to be tapped off
+ *
+ */
+ private static final class BiffDumpingStream extends InputStream {
+ private final DataInputStream _is;
+ private final IBiffRecordListener _listener;
+ private final byte[] _data;
+ private int _recordCounter;
+ private int _overallStreamPos;
+ private int _currentPos;
+ private int _currentSize;
+ private boolean _innerHasReachedEOF;
+
+ public BiffDumpingStream(InputStream is, IBiffRecordListener listener) {
+ _is = new DataInputStream(is);
+ _listener = listener;
+ _data = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE + 4];
+ _recordCounter = 0;
+ _overallStreamPos = 0;
+ _currentSize = 0;
+ _currentPos = 0;
+ }
+
+ public int read() throws IOException {
+ if (_currentPos >= _currentSize) {
+ fillNextBuffer();
+ }
+ if (_currentPos >= _currentSize) {
+ return -1;
+ }
+ int result = _data[_currentPos] & 0x00FF;
+ _currentPos ++;
+ _overallStreamPos ++;
+ formatBufferIfAtEndOfRec();
+ return result;
+ }
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (_currentPos >= _currentSize) {
+ fillNextBuffer();
+ }
+ if (_currentPos >= _currentSize) {
+ return -1;
+ }
+ int availSize = _currentSize - _currentPos;
+ int result;
+ if (len > availSize) {
+ System.err.println("Unexpected request to read past end of current biff record");
+ result = availSize;
+ } else {
+ result = len;
+ }
+ System.arraycopy(_data, _currentPos, b, off, result);
+ _currentPos += result;
+ _overallStreamPos += result;
+ formatBufferIfAtEndOfRec();
+ return result;
+ }
+
+ public int available() throws IOException {
+ return _currentSize - _currentPos + _is.available();
+ }
+ private void fillNextBuffer() throws IOException {
+ if (_innerHasReachedEOF) {
+ return;
+ }
+ int b0 = _is.read();
+ if (b0 == -1) {
+ _innerHasReachedEOF = true;
+ return;
+ }
+ _data[0] = (byte) b0;
+ _is.readFully(_data, 1, 3);
+ int len = LittleEndian.getShort(_data, 2);
+ _is.readFully(_data, 4, len);
+ _currentPos = 0;
+ _currentSize = len + 4;
+ _recordCounter++;
+ }
+ private void formatBufferIfAtEndOfRec() {
+ if (_currentPos != _currentSize) {
+ return;
+ }
+ int dataSize = _currentSize-4;
+ int sid = LittleEndian.getShort(_data, 0);
+ int globalOffset = _overallStreamPos-_currentSize;
+ _listener.processRecord(globalOffset, _recordCounter, sid, dataSize, _data);
+ }
+ public void close() throws IOException {
+ _is.close();
+ }
+ }
+
+ private static final int DUMP_LINE_LEN = 16;
+ private static final char[] COLUMN_SEPARATOR = " | ".toCharArray();
+ /**
+ * Hex-dumps a portion of a byte array in typical format, also preserving dump-line alignment
+ * @param globalOffset (somewhat arbitrary) used to calculate the addresses printed at the
+ * start of each line
+ */
+ static void hexDumpAligned(Writer w, byte[] data, int baseDataOffset, int dumpLen, int globalOffset) {
+ // perhaps this code should be moved to HexDump
+ int globalStart = globalOffset + baseDataOffset;
+ int globalEnd = globalOffset + baseDataOffset + dumpLen;
+ int startDelta = globalStart % DUMP_LINE_LEN;
+ int endDelta = globalEnd % DUMP_LINE_LEN;
+ int startLineAddr = globalStart - startDelta;
+ int endLineAddr = globalEnd - endDelta;
+
+ int lineDataOffset = baseDataOffset - startDelta;
+ int lineAddr = startLineAddr;
+
+ // output (possibly incomplete) first line
+ if (startLineAddr == endLineAddr) {
+ hexDumpLine(w, data, lineAddr, lineDataOffset, startDelta, endDelta);
+ return;
+ }
+ hexDumpLine(w, data, lineAddr, lineDataOffset, startDelta, DUMP_LINE_LEN);
+
+ // output all full lines in the middle
+ while (true) {
+ lineAddr += DUMP_LINE_LEN;
+ lineDataOffset += DUMP_LINE_LEN;
+ if (lineAddr >= endLineAddr) {
+ break;
+ }
+ hexDumpLine(w, data, lineAddr, lineDataOffset, 0, DUMP_LINE_LEN);
+ }
+
+
+ // output (possibly incomplete) last line
+ if (endDelta != 0) {
+ hexDumpLine(w, data, lineAddr, lineDataOffset, 0, endDelta);
+ }
+ }
+
+ private static void hexDumpLine(Writer w, byte[] data, int lineStartAddress, int lineDataOffset, int startDelta, int endDelta) {
+ if (startDelta >= endDelta) {
+ throw new IllegalArgumentException("Bad start/end delta");
+ }
+ try {
+ writeHex(w, lineStartAddress, 8);
+ w.write(COLUMN_SEPARATOR);
+ // raw hex data
+ for (int i=0; i< DUMP_LINE_LEN; i++) {
+ if (i>0) {
+ w.write(" ");
+ }
+ if (i >= startDelta && i < endDelta) {
+ writeHex(w, data[lineDataOffset+i], 2);
+ } else {
+ w.write(" ");
+ }
+ }
+ w.write(COLUMN_SEPARATOR);
+
+ // interpreted ascii
+ for (int i=0; i< DUMP_LINE_LEN; i++) {
+ if (i >= startDelta && i < endDelta) {
+ w.write(getPrintableChar(data[lineDataOffset+i]));
+ } else {
+ w.write(" ");
+ }
+ }
+ w.write(NEW_LINE_CHARS);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static char getPrintableChar(byte b) {
+ char ib = (char) (b & 0x00FF);
+ if (ib < 32 || ib > 126) {
+ return '.';
+ }
+ return ib;
+ }
+
+ private static void writeHex(Writer w, int value, int nDigits) throws IOException {
+ char[] buf = new char[nDigits];
+ int acc = value;
+ for(int i=nDigits-1; i>=0; i--) {
+ int digit = acc & 0x0F;
+ buf[i] = (char) (digit < 10 ? ('0' + digit) : ('A' + digit - 10));
+ acc >>= 4;
+ }
+ w.write(buf);
+ }
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/model/TextboxShape.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/model/TextboxShape.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/model/TextboxShape.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/model/TextboxShape.java Fri Oct 24 18:47:25 2008
@@ -138,15 +138,11 @@
HSSFTextbox shape = hssfShape;
TextObjectRecord obj = new TextObjectRecord();
- obj.setHorizontalTextAlignment( hssfShape.getHorizontalAlignment() );
- obj.setVerticalTextAlignment( hssfShape.getVerticalAlignment());
- obj.setTextLocked( true );
- obj.setTextOrientation( TextObjectRecord.TEXT_ORIENTATION_NONE );
- int frLength = ( shape.getString().numFormattingRuns() + 1 ) * 8;
- obj.setFormattingRunLength( (short) frLength );
- obj.setTextLength( (short) shape.getString().length() );
- obj.setStr( shape.getString() );
- obj.setReserved7( 0 );
+ obj.setHorizontalTextAlignment(hssfShape.getHorizontalAlignment());
+ obj.setVerticalTextAlignment(hssfShape.getVerticalAlignment());
+ obj.setTextLocked(true);
+ obj.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_NONE);
+ obj.setStr(shape.getString());
return obj;
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ContinueRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ContinueRecord.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ContinueRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ContinueRecord.java Fri Oct 24 18:47:25 2008
@@ -22,76 +22,44 @@
import org.apache.poi.util.LittleEndian;
/**
- * Title: Continue Record - Helper class used primarily for SST Records <P>
+ * Title: Continue Record(0x003C) - Helper class used primarily for SST Records <P>
* Description: handles overflow for prior record in the input
* stream; content is tailored to that prior record<P>
* @author Marc Johnson (mjohnson at apache dot org)
* @author Andrew C. Oliver (acoliver at apache dot org)
* @author Csaba Nagy (ncsaba at yahoo dot com)
- * @version 2.0-pre
*/
-
-public class ContinueRecord
- extends Record
-{
+public final class ContinueRecord extends Record {
public final static short sid = 0x003C;
- private byte[] field_1_data;
-
- /**
- * default constructor
- */
+ private byte[] _data;
- public ContinueRecord()
- {
+ public ContinueRecord(byte[] data) {
+ _data = data;
}
/**
* USE ONLY within "processContinue"
*/
-
public byte [] serialize()
{
- byte[] retval = new byte[ field_1_data.length + 4 ];
+ byte[] retval = new byte[ _data.length + 4 ];
serialize(0, retval);
return retval;
}
- public int serialize(int offset, byte [] data)
- {
-
- LittleEndian.putShort(data, offset, sid);
- LittleEndian.putShort(data, offset + 2, ( short ) field_1_data.length);
- System.arraycopy(field_1_data, 0, data, offset + 4, field_1_data.length);
- return field_1_data.length + 4;
- // throw new RecordFormatException(
- // "You're not supposed to serialize Continue records like this directly");
- }
-
- /*
- * @param data raw data
- */
-
- public void setData(byte [] data)
- {
- field_1_data = data;
+ public int serialize(int offset, byte[] data) {
+ return write(data, offset, null, _data);
}
/**
* get the data for continuation
* @return byte array containing all of the continued data
*/
-
public byte [] getData()
{
- return field_1_data;
+ return _data;
}
- /**
- * Debugging toString
- *
- * @return string representation
- */
-
public String toString()
{
StringBuffer buffer = new StringBuffer();
@@ -113,19 +81,36 @@
*
* @param in the RecordInputstream to read the record from
*/
-
public ContinueRecord(RecordInputStream in)
{
- field_1_data = in.readRemainder();
+ _data = in.readRemainder();
}
- /**
- * Clone this record.
- */
public Object clone() {
- ContinueRecord clone = new ContinueRecord();
- clone.setData(field_1_data);
- return clone;
+ return new ContinueRecord(_data);
}
+ /**
+ * Writes the full encoding of a Continue record without making an instance
+ */
+ public static int write(byte[] destBuf, int destOffset, Byte initialDataByte, byte[] srcData) {
+ return write(destBuf, destOffset, initialDataByte, srcData, 0, srcData.length);
+ }
+ /**
+ * @param initialDataByte (optional - often used for unicode flag).
+ * If supplied, this will be written before srcData
+ * @return the total number of bytes written
+ */
+ public static int write(byte[] destBuf, int destOffset, Byte initialDataByte, byte[] srcData, int srcOffset, int len) {
+ int totalLen = len + (initialDataByte == null ? 0 : 1);
+ LittleEndian.putUShort(destBuf, destOffset, sid);
+ LittleEndian.putUShort(destBuf, destOffset + 2, totalLen);
+ int pos = destOffset + 4;
+ if (initialDataByte != null) {
+ LittleEndian.putByte(destBuf, pos, initialDataByte.byteValue());
+ pos += 1;
+ }
+ System.arraycopy(srcData, srcOffset, destBuf, pos, len);
+ return 4 + totalLen;
+ }
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java Fri Oct 24 18:47:25 2008
@@ -17,8 +17,6 @@
package org.apache.poi.hssf.record;
-import java.util.Stack;
-
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.StringUtil;
@@ -124,11 +122,7 @@
}
private int getNameDefinitionSize() {
- int result = 0;
- for (int i = 0; i < field_5_name_definition.length; i++) {
- result += field_5_name_definition[i].getSize();
- }
- return result;
+ return Ptg.getEncodedSize(field_5_name_definition);
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataFormulaField.java Fri Oct 24 18:47:25 2008
@@ -20,47 +20,38 @@
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.util.LittleEndian;
-import java.util.Stack;
-import java.util.Iterator;
-
/**
* Not implemented yet. May commit it anyway just so people can see
* where I'm heading.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
-public final class LinkedDataFormulaField implements CustomField {
- Stack formulaTokens = new Stack();
+public final class LinkedDataFormulaField {
+ private Ptg[] formulaTokens;
public int getSize()
{
- int size = 0;
- for ( Iterator iterator = formulaTokens.iterator(); iterator.hasNext(); )
- {
- Ptg token = (Ptg) iterator.next();
- size += token.getSize();
- }
- return size + 2;
+ return 2 + Ptg.getEncodedSize(formulaTokens);
}
public int fillField( RecordInputStream in )
{
- short tokenSize = in.readShort();
- formulaTokens = Ptg.createParsedExpressionTokens(tokenSize, in);
-
+ int tokenSize = in.readUShort();
+ formulaTokens = Ptg.readTokens(tokenSize, in);
return tokenSize + 2;
}
public void toString( StringBuffer buffer )
{
- for ( int k = 0; k < formulaTokens.size(); k++ )
+ for ( int k = 0; k < formulaTokens.length; k++ )
{
+ Ptg ptg = formulaTokens[k];
buffer.append( "Formula " )
.append( k )
.append( "=" )
- .append( formulaTokens.get( k ).toString() )
+ .append(ptg.toString() )
.append( "\n" )
- .append( ( (Ptg) formulaTokens.get( k ) ).toDebugString() )
+ .append(ptg.toDebugString() )
.append( "\n" );
}
}
@@ -75,34 +66,26 @@
public int serializeField( int offset, byte[] data )
{
int size = getSize();
- LittleEndian.putShort(data, offset, (short)(size - 2));
+ LittleEndian.putUShort(data, offset, size - 2);
int pos = offset + 2;
- pos += Ptg.serializePtgStack(formulaTokens, data, pos);
+ pos += Ptg.serializePtgs(formulaTokens, data, pos);
return size;
}
- public Object clone()
- {
- try
- {
- // todo: clone tokens? or are they immutable?
- return super.clone();
- }
- catch ( CloneNotSupportedException e )
- {
- // should not happen
- return null;
- }
- }
-
- public void setFormulaTokens( Stack formulaTokens )
+ public void setFormulaTokens(Ptg[] ptgs)
{
- this.formulaTokens = (Stack) formulaTokens.clone();
+ this.formulaTokens = (Ptg[])ptgs.clone();
}
- public Stack getFormulaTokens()
+ public Ptg[] getFormulaTokens()
{
- return (Stack)this.formulaTokens.clone();
+ return (Ptg[])this.formulaTokens.clone();
}
+ public LinkedDataFormulaField copy() {
+ LinkedDataFormulaField result = new LinkedDataFormulaField();
+
+ result.formulaTokens = getFormulaTokens();
+ return result;
+ }
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/LinkedDataRecord.java Fri Oct 24 18:47:25 2008
@@ -125,7 +125,7 @@
rec.field_2_referenceType = field_2_referenceType;
rec.field_3_options = field_3_options;
rec.field_4_indexNumberFmtRecord = field_4_indexNumberFmtRecord;
- rec.field_5_formulaOfLink = ((LinkedDataFormulaField)field_5_formulaOfLink.clone());
+ rec.field_5_formulaOfLink = field_5_formulaOfLink.copy();
return rec;
}
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordFactory.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordFactory.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordFactory.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordFactory.java Fri Oct 24 18:47:25 2008
@@ -321,51 +321,54 @@
Record lastRecord = null;
while (recStream.hasNextRecord()) {
recStream.nextRecord();
- if (recStream.getSid() != 0) {
- Record[] recs = createRecord(recStream); // handle MulRK records
+ if (recStream.getSid() == 0) {
+ // After EOF, Excel seems to pad block with zeros
+ continue;
+ }
+ Record[] recs = createRecord(recStream); // handle MulRK records
- if (recs.length > 1) {
- for (int k = 0; k < recs.length; k++) {
- records.add(recs[ k ]); // these will be number records
- }
- } else {
- Record record = recs[ 0 ];
+ if (recs.length > 1) {
+ for (int k = 0; k < recs.length; k++) {
+ records.add(recs[ k ]); // these will be number records
+ }
+ continue;
+ }
+ Record record = recs[ 0 ];
- if (record != null) {
- if (record.getSid() == DrawingGroupRecord.sid
- && lastRecord instanceof DrawingGroupRecord) {
- DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord;
- lastDGRecord.join((AbstractEscherHolderRecord) record);
- } else if (record.getSid() == ContinueRecord.sid &&
- ((lastRecord instanceof ObjRecord) || (lastRecord instanceof TextObjectRecord))) {
- // Drawing records have a very strange continue behaviour.
- //There can actually be OBJ records mixed between the continues.
- lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() );
- //we must remember the position of the continue record.
- //in the serialization procedure the original structure of records must be preserved
- records.add(record);
- } else if (record.getSid() == ContinueRecord.sid &&
- (lastRecord instanceof DrawingGroupRecord)) {
- ((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
- } else if (record.getSid() == ContinueRecord.sid &&
- (lastRecord instanceof StringRecord)) {
- ((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
- } else if (record.getSid() == ContinueRecord.sid) {
- if (lastRecord instanceof UnknownRecord) {
- //Gracefully handle records that we dont know about,
- //that happen to be continued
- records.add(record);
- } else
- throw new RecordFormatException("Unhandled Continue Record");
- } else {
- lastRecord = record;
- if (record instanceof DrawingRecord) {
- lastDrawingRecord = (DrawingRecord) record;
- }
- records.add(record);
- }
- }
+ if (record == null) {
+ continue;
+ }
+ if (record.getSid() == DrawingGroupRecord.sid
+ && lastRecord instanceof DrawingGroupRecord) {
+ DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord;
+ lastDGRecord.join((AbstractEscherHolderRecord) record);
+ } else if (record.getSid() == ContinueRecord.sid) {
+ ContinueRecord contRec = (ContinueRecord)record;
+
+ if (lastRecord instanceof ObjRecord || lastRecord instanceof TextObjectRecord) {
+ // Drawing records have a very strange continue behaviour.
+ //There can actually be OBJ records mixed between the continues.
+ lastDrawingRecord.processContinueRecord(contRec.getData() );
+ //we must remember the position of the continue record.
+ //in the serialization procedure the original structure of records must be preserved
+ records.add(record);
+ } else if (lastRecord instanceof DrawingGroupRecord) {
+ ((DrawingGroupRecord)lastRecord).processContinueRecord(contRec.getData());
+ } else if (lastRecord instanceof StringRecord) {
+ ((StringRecord)lastRecord).processContinueRecord(contRec.getData());
+ } else if (lastRecord instanceof UnknownRecord) {
+ //Gracefully handle records that we don't know about,
+ //that happen to be continued
+ records.add(record);
+ } else {
+ throw new RecordFormatException("Unhandled Continue Record");
+ }
+ } else {
+ lastRecord = record;
+ if (record instanceof DrawingRecord) {
+ lastDrawingRecord = (DrawingRecord) record;
}
+ records.add(record);
}
}
return records;
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=707807&r1=707806&r2=707807&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/record/RecordInputStream.java Fri Oct 24 18:47:25 2008
@@ -29,19 +29,19 @@
*
* @author Jason Height (jheight @ apache dot org)
*/
-public class RecordInputStream extends InputStream {
- /** Maximum size of a single record (minus the 4 byte header) without a continue*/
- public final static short MAX_RECORD_DATA_SIZE = 8224;
- private static final int INVALID_SID_VALUE = -1;
-
- private InputStream in;
- protected short currentSid;
- protected short currentLength = -1;
- protected short nextSid;
-
- protected byte[] data = new byte[MAX_RECORD_DATA_SIZE];
- protected short recordOffset;
- protected long pos;
+public final class RecordInputStream extends InputStream {
+ /** Maximum size of a single record (minus the 4 byte header) without a continue*/
+ public final static short MAX_RECORD_DATA_SIZE = 8224;
+ private static final int INVALID_SID_VALUE = -1;
+
+ private InputStream in;
+ private short currentSid;
+ private short currentLength = -1;
+ private short nextSid;
+
+ private final byte[] data = new byte[MAX_RECORD_DATA_SIZE];
+ private short recordOffset;
+ private long pos;
private boolean autoContinue = true;
@@ -218,54 +218,81 @@
return result;
}
- /**
- * given a byte array of 16-bit unicode characters, compress to 8-bit and
- * return a string
- *
- * { 0x16, 0x00 } -0x16
- *
- * @param length the length of the final string
- * @return the converted string
- * @exception IllegalArgumentException if len is too large (i.e.,
- * there is not enough data in string to create a String of that
- * length)
- */
- public String readUnicodeLEString(int length) {
- if ((length < 0) || (((remaining() / 2) < length) && !isContinueNext())) {
- throw new IllegalArgumentException("Illegal length - asked for " + length + " but only " + (remaining()/2) + " left!");
- }
-
- StringBuffer buf = new StringBuffer(length);
- for (int i=0;i<length;i++) {
- if ((remaining() == 0) && (isContinueNext())){
- nextRecord();
- int compressByte = readByte();
- if(compressByte != 1) throw new IllegalArgumentException("compressByte in continue records must be 1 while reading unicode LE string");
- }
- char ch = (char)readShort();
- buf.append(ch);
- }
- return buf.toString();
- }
+ public String readString() {
+ int requestedLength = readUShort();
+ byte compressFlag = readByte();
+ return readStringCommon(requestedLength, compressFlag == 0);
+ }
+ /**
+ * given a byte array of 16-bit unicode characters, compress to 8-bit and
+ * return a string
+ *
+ * { 0x16, 0x00 } -0x16
+ *
+ * @param requestedLength the length of the final string
+ * @return the converted string
+ * @exception IllegalArgumentException if len is too large (i.e.,
+ * there is not enough data in string to create a String of that
+ * length)
+ */
+ public String readUnicodeLEString(int requestedLength) {
+ return readStringCommon(requestedLength, false);
+ }
- public String readCompressedUnicode(int length) {
- if ((length < 0) || ((remaining() < length) && !isContinueNext())) {
- throw new IllegalArgumentException("Illegal length " + length);
- }
+ public String readCompressedUnicode(int requestedLength) {
+ return readStringCommon(requestedLength, true);
+ }
- StringBuffer buf = new StringBuffer(length);
- for (int i=0;i<length;i++) {
- if ((remaining() == 0) && (isContinueNext())) {
- nextRecord();
- int compressByte = readByte();
- if(compressByte != 0) throw new IllegalArgumentException("compressByte in continue records must be 0 while reading compressed unicode");
- }
- byte b = readByte();
- char ch = (char)(0x00FF & b); // avoid sex
- buf.append(ch);
- }
- return buf.toString();
- }
+ private String readStringCommon(int requestedLength, boolean pIsCompressedEncoding) {
+ // Sanity check to detect garbage string lengths
+ if (requestedLength < 0 || requestedLength > 0x100000) { // 16 million chars?
+ throw new IllegalArgumentException("Bad requested string length (" + requestedLength + ")");
+ }
+ char[] buf = new char[requestedLength];
+ boolean isCompressedEncoding = pIsCompressedEncoding;
+ int curLen = 0;
+ while(true) {
+ int availableChars =isCompressedEncoding ? remaining() : remaining() / LittleEndian.SHORT_SIZE;
+ if (requestedLength - curLen <= availableChars) {
+ // enough space in current record, so just read it out
+ while(curLen < requestedLength) {
+ char ch;
+ if (isCompressedEncoding) {
+ ch = (char)readUByte();
+ } else {
+ ch = (char)readShort();
+ }
+ buf[curLen] = ch;
+ curLen++;
+ }
+ return new String(buf);
+ }
+ // else string has been spilled into next continue record
+ // so read what's left of the current record
+ while(availableChars > 0) {
+ char ch;
+ if (isCompressedEncoding) {
+ ch = (char)readUByte();
+ } else {
+ ch = (char)readShort();
+ }
+ buf[curLen] = ch;
+ curLen++;
+ availableChars--;
+ }
+ if (!isContinueNext()) {
+ throw new RecordFormatException("Expected to find a ContinueRecord in order to read remaining "
+ + (requestedLength-curLen) + " of " + requestedLength + " chars");
+ }
+ if(remaining() != 0) {
+ throw new RecordFormatException("Odd number of bytes(" + remaining() + ") left behind");
+ }
+ nextRecord();
+ // note - the compressed flag may change on the fly
+ byte compressFlag = readByte();
+ isCompressedEncoding = (compressFlag == 0);
+ }
+ }
/** Returns an excel style unicode string from the bytes reminaing in the record.
* <i>Note:</i> Unicode strings differ from <b>normal</b> strings due to the addition of
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org