<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>
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>
</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>
<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>
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.
*@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);
+ }
}
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;
}
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();
*
* @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;
+ }
}
+++ /dev/null
-/* ====================================================================
- 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.
-==================================================================== */
-
-package org.apache.poi.hssf.record;
-
-public interface CustomField
- extends Cloneable
-{
- /**
- * @return The size of this field in bytes. This operation is not valid
- * until after the call to <code>fillField()</code>
- */
- int getSize();
-
- /**
- * Populates this fields data from the byte array passed in.
- * @param in the RecordInputstream to read the record from
- */
- int fillField(RecordInputStream in);
-
- /**
- * Appends the string representation of this field to the supplied
- * StringBuffer.
- *
- * @param str The string buffer to append to.
- */
- void toString(StringBuffer str);
-
- /**
- * Converts this field to it's byte array form.
- * @param offset The offset into the byte array to start writing to.
- * @param data The data array to write to.
- * @return The number of bytes written.
- */
- int serializeField(int offset, byte[] data);
-
-
-}
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;
}
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);
}
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" );
}
}
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;
+ }
}
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;
}
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;
*
* @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;
+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;
- protected short currentSid;
- protected short currentLength = -1;
- protected short nextSid;
+ private InputStream in;
+ private short currentSid;
+ private short currentLength = -1;
+ private short nextSid;
- protected byte[] data = new byte[MAX_RECORD_DATA_SIZE];
- protected short recordOffset;
- protected long pos;
+ private final byte[] data = new byte[MAX_RECORD_DATA_SIZE];
+ private short recordOffset;
+ private long pos;
private boolean autoContinue = true;
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
+++ /dev/null
-
-/* ====================================================================
- 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.
-==================================================================== */
-
-
-package org.apache.poi.hssf.record;
-
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
-import org.apache.poi.util.HexDump;
-import org.apache.poi.util.LittleEndian;
-
-/**
- * The TXO record is used to define the properties of a text box. It is followed
- * by two continue records unless there is no actual text. The first continue record contains
- * the text data and the next continue record contains the formatting runs.<p/>
- *
- * @author Glen Stampoultzis (glens at apache.org)
- */
-public class TextObjectBaseRecord extends Record {
- // TODO - don't instantiate superclass
- public final static short sid = 0x01B6;
-
- private static final BitField reserved1 = BitFieldFactory.getInstance(0x0001);
- private static final BitField HorizontalTextAlignment = BitFieldFactory.getInstance(0x000E);
- private static final BitField VerticalTextAlignment = BitFieldFactory.getInstance(0x0070);
- private static final BitField reserved2 = BitFieldFactory.getInstance(0x0180);
- private static final BitField textLocked = BitFieldFactory.getInstance(0x0200);
- private static final BitField reserved3 = BitFieldFactory.getInstance(0xFC00);
-
- private short field_1_options;
- public final static short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1;
- public final static short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2;
- public final static short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3;
- public final static short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4;
- public final static short VERTICAL_TEXT_ALIGNMENT_TOP = 1;
- public final static short VERTICAL_TEXT_ALIGNMENT_CENTER = 2;
- public final static short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3;
- public final static short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4;
- private short field_2_textOrientation;
- public final static short TEXT_ORIENTATION_NONE = 0;
- public final static short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1;
- public final static short TEXT_ORIENTATION_ROT_RIGHT = 2;
- public final static short TEXT_ORIENTATION_ROT_LEFT = 3;
- private short field_3_reserved4;
- private short field_4_reserved5;
- private short field_5_reserved6;
- private short field_6_textLength;
- private short field_7_formattingRunLength;
- private int field_8_reserved7;
-
-
- public TextObjectBaseRecord()
- {
-
- }
-
- public TextObjectBaseRecord(RecordInputStream in)
- {
- field_1_options = in.readShort();
- field_2_textOrientation = in.readShort();
- field_3_reserved4 = in.readShort();
- field_4_reserved5 = in.readShort();
- field_5_reserved6 = in.readShort();
- field_6_textLength = in.readShort();
- field_7_formattingRunLength = in.readShort();
- field_8_reserved7 = in.readInt();
-
- }
-
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[TXO]\n");
- buffer.append(" .options = ")
- .append("0x").append(HexDump.toHex( getOptions ()))
- .append(" (").append( getOptions() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .reserved1 = ").append(isReserved1()).append('\n');
- buffer.append(" .HorizontalTextAlignment = ").append(getHorizontalTextAlignment()).append('\n');
- buffer.append(" .VerticalTextAlignment = ").append(getVerticalTextAlignment()).append('\n');
- buffer.append(" .reserved2 = ").append(getReserved2()).append('\n');
- buffer.append(" .textLocked = ").append(isTextLocked()).append('\n');
- buffer.append(" .reserved3 = ").append(getReserved3()).append('\n');
- buffer.append(" .textOrientation = ")
- .append("0x").append(HexDump.toHex( getTextOrientation ()))
- .append(" (").append( getTextOrientation() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .reserved4 = ")
- .append("0x").append(HexDump.toHex( getReserved4 ()))
- .append(" (").append( getReserved4() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .reserved5 = ")
- .append("0x").append(HexDump.toHex( getReserved5 ()))
- .append(" (").append( getReserved5() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .reserved6 = ")
- .append("0x").append(HexDump.toHex( getReserved6 ()))
- .append(" (").append( getReserved6() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .textLength = ")
- .append("0x").append(HexDump.toHex( getTextLength ()))
- .append(" (").append( getTextLength() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .formattingRunLength = ")
- .append("0x").append(HexDump.toHex( getFormattingRunLength ()))
- .append(" (").append( getFormattingRunLength() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
- buffer.append(" .reserved7 = ")
- .append("0x").append(HexDump.toHex( getReserved7 ()))
- .append(" (").append( getReserved7() ).append(" )");
- buffer.append(System.getProperty("line.separator"));
-
- buffer.append("[/TXO]\n");
- return buffer.toString();
- }
-
- public int serialize(int offset, byte[] data)
- {
- int pos = 0;
-
- LittleEndian.putShort(data, 0 + offset, sid);
- LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
-
- LittleEndian.putShort(data, 4 + offset + pos, field_1_options);
- LittleEndian.putShort(data, 6 + offset + pos, field_2_textOrientation);
- LittleEndian.putShort(data, 8 + offset + pos, field_3_reserved4);
- LittleEndian.putShort(data, 10 + offset + pos, field_4_reserved5);
- LittleEndian.putShort(data, 12 + offset + pos, field_5_reserved6);
- LittleEndian.putShort(data, 14 + offset + pos, field_6_textLength);
- LittleEndian.putShort(data, 16 + offset + pos, field_7_formattingRunLength);
- LittleEndian.putInt(data, 18 + offset + pos, field_8_reserved7);
-
- return getRecordSize();
- }
-
- public int getRecordSize()
- {
- return 4 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4;
- }
-
- public short getSid()
- {
- return sid;
- }
-
- public Object clone() {
- TextObjectBaseRecord rec = new TextObjectBaseRecord();
-
- rec.field_1_options = field_1_options;
- rec.field_2_textOrientation = field_2_textOrientation;
- rec.field_3_reserved4 = field_3_reserved4;
- rec.field_4_reserved5 = field_4_reserved5;
- rec.field_5_reserved6 = field_5_reserved6;
- rec.field_6_textLength = field_6_textLength;
- rec.field_7_formattingRunLength = field_7_formattingRunLength;
- rec.field_8_reserved7 = field_8_reserved7;
- return rec;
- }
-
-
-
-
- /**
- * Get the options field for the TextObjectBase record.
- */
- public short getOptions()
- {
- return field_1_options;
- }
-
- /**
- * Set the options field for the TextObjectBase record.
- */
- public void setOptions(short field_1_options)
- {
- this.field_1_options = field_1_options;
- }
-
- /**
- * Get the text orientation field for the TextObjectBase record.
- *
- * @return One of
- * TEXT_ORIENTATION_NONE
- * TEXT_ORIENTATION_TOP_TO_BOTTOM
- * TEXT_ORIENTATION_ROT_RIGHT
- * TEXT_ORIENTATION_ROT_LEFT
- */
- public short getTextOrientation()
- {
- return field_2_textOrientation;
- }
-
- /**
- * Set the text orientation field for the TextObjectBase record.
- *
- * @param field_2_textOrientation
- * One of
- * TEXT_ORIENTATION_NONE
- * TEXT_ORIENTATION_TOP_TO_BOTTOM
- * TEXT_ORIENTATION_ROT_RIGHT
- * TEXT_ORIENTATION_ROT_LEFT
- */
- public void setTextOrientation(short field_2_textOrientation)
- {
- this.field_2_textOrientation = field_2_textOrientation;
- }
-
- /**
- * Get the reserved4 field for the TextObjectBase record.
- */
- public short getReserved4()
- {
- return field_3_reserved4;
- }
-
- /**
- * Set the reserved4 field for the TextObjectBase record.
- */
- public void setReserved4(short field_3_reserved4)
- {
- this.field_3_reserved4 = field_3_reserved4;
- }
-
- /**
- * Get the reserved5 field for the TextObjectBase record.
- */
- public short getReserved5()
- {
- return field_4_reserved5;
- }
-
- /**
- * Set the reserved5 field for the TextObjectBase record.
- */
- public void setReserved5(short field_4_reserved5)
- {
- this.field_4_reserved5 = field_4_reserved5;
- }
-
- /**
- * Get the reserved6 field for the TextObjectBase record.
- */
- public short getReserved6()
- {
- return field_5_reserved6;
- }
-
- /**
- * Set the reserved6 field for the TextObjectBase record.
- */
- public void setReserved6(short field_5_reserved6)
- {
- this.field_5_reserved6 = field_5_reserved6;
- }
-
- /**
- * Get the text length field for the TextObjectBase record.
- */
- public short getTextLength()
- {
- return field_6_textLength;
- }
-
- /**
- * Set the text length field for the TextObjectBase record.
- */
- public void setTextLength(short field_6_textLength)
- {
- this.field_6_textLength = field_6_textLength;
- }
-
- /**
- * Get the formatting run length field for the TextObjectBase record.
- */
- public short getFormattingRunLength()
- {
- return field_7_formattingRunLength;
- }
-
- /**
- * Set the formatting run length field for the TextObjectBase record.
- */
- public void setFormattingRunLength(short field_7_formattingRunLength)
- {
- this.field_7_formattingRunLength = field_7_formattingRunLength;
- }
-
- /**
- * Get the reserved7 field for the TextObjectBase record.
- */
- public int getReserved7()
- {
- return field_8_reserved7;
- }
-
- /**
- * Set the reserved7 field for the TextObjectBase record.
- */
- public void setReserved7(int field_8_reserved7)
- {
- this.field_8_reserved7 = field_8_reserved7;
- }
-
- /**
- * Sets the reserved1 field value.
- * reserved field
- */
- public void setReserved1(boolean value)
- {
- field_1_options = reserved1.setShortBoolean(field_1_options, value);
- }
-
- /**
- * reserved field
- * @return the reserved1 field value.
- */
- public boolean isReserved1()
- {
- return reserved1.isSet(field_1_options);
- }
-
- /**
- * Sets the Horizontal text alignment field value.
- *
- */
- public void setHorizontalTextAlignment(short value)
- {
- field_1_options = HorizontalTextAlignment.setShortValue(field_1_options, value);
- }
-
- /**
- *
- * @return the Horizontal text alignment field value.
- */
- public short getHorizontalTextAlignment()
- {
- return HorizontalTextAlignment.getShortValue(field_1_options);
- }
-
- /**
- * Sets the Vertical text alignment field value.
- *
- */
- public void setVerticalTextAlignment(short value)
- {
- field_1_options = VerticalTextAlignment.setShortValue(field_1_options, value);
- }
-
- /**
- *
- * @return the Vertical text alignment field value.
- */
- public short getVerticalTextAlignment()
- {
- return VerticalTextAlignment.getShortValue(field_1_options);
- }
-
- /**
- * Sets the reserved2 field value.
- *
- */
- public void setReserved2(short value)
- {
- field_1_options = reserved2.setShortValue(field_1_options, value);
- }
-
- /**
- *
- * @return the reserved2 field value.
- */
- public short getReserved2()
- {
- return reserved2.getShortValue(field_1_options);
- }
-
- /**
- * Sets the text locked field value.
- * Text has been locked
- */
- public void setTextLocked(boolean value)
- {
- field_1_options = textLocked.setShortBoolean(field_1_options, value);
- }
-
- /**
- * Text has been locked
- * @return the text locked field value.
- */
- public boolean isTextLocked()
- {
- return textLocked.isSet(field_1_options);
- }
-
- /**
- * Sets the reserved3 field value.
- *
- */
- public void setReserved3(short value)
- {
- field_1_options = reserved3.setShortValue(field_1_options, value);
- }
-
- /**
- *
- * @return the reserved3 field value.
- */
- public short getReserved3()
- {
- return reserved3.getShortValue(field_1_options);
- }
-}
import java.io.UnsupportedEncodingException;
+import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
+import org.apache.poi.util.BitField;
+import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
-public class TextObjectRecord
- extends TextObjectBaseRecord
-{
- HSSFRichTextString str;
-
- public TextObjectRecord()
- {
- }
-
- public TextObjectRecord( RecordInputStream in )
- {
- super( in );
-
- if (getTextLength() > 0) {
- if (in.isContinueNext() && in.remaining() == 0) {
- //1st Continue
- in.nextRecord();
- processRawString(in);
- } else
- throw new RecordFormatException("Expected Continue record to hold string data for TextObjectRecord");
- }
- if (getFormattingRunLength() > 0) {
- if (in.isContinueNext() && in.remaining() == 0) {
- in.nextRecord();
- processFontRuns(in);
- } else throw new RecordFormatException("Expected Continue Record to hold font runs for TextObjectRecord");
- }
- if (str == null)
- str = new HSSFRichTextString("");
- }
-
-
- public int getRecordSize()
- {
- int continue1Size = 0;
- int continue2Size = 0;
- if (str.length() != 0)
- {
- int length = str.length() * 2;
- while(length > 0){
- int chunkSize = Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE-2, length);
- length -= chunkSize;
-
- continue1Size += chunkSize;
- continue1Size += 1 + 4;
- }
-
- continue2Size = (str.numFormattingRuns() + 1) * 8 + 4;
- }
- return super.getRecordSize() + continue1Size + continue2Size;
- }
-
-
-
- public int serialize( int offset, byte[] data )
- {
- // Temporarily blank out str so that record size is calculated without the continue records.
- HSSFRichTextString temp = str;
- str = new HSSFRichTextString("");
- int bytesWritten1 = super.serialize( offset, data );
- str = temp;
-
- int pos = offset + bytesWritten1;
- if ( str.getString().equals( "" ) == false )
- {
- ContinueRecord c2 = createContinue2();
- int bytesWritten2 = 0;
-
- try
- {
- byte[] c1Data = str.getString().getBytes( "UTF-16LE" );
- int length = c1Data.length;
-
- int charsWritten = 0;
- int spos = pos;
- while(length > 0){
- int chunkSize = Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE-2 , length);
- length -= chunkSize;
-
- //continue header
- LittleEndian.putShort(data, spos, ContinueRecord.sid);
- spos += LittleEndian.SHORT_SIZE;
- LittleEndian.putShort(data, spos, (short)(chunkSize+1));
- spos += LittleEndian.SHORT_SIZE;
-
- //The first byte specifies if the text is compressed unicode or unicode.
- //(regardless what was read, we always serialize double-byte unicode characters (UTF-16LE).
- data[spos] = 1;
- spos += LittleEndian.BYTE_SIZE;
-
- //copy characters data
- System.arraycopy(c1Data, charsWritten, data, spos, chunkSize);
- spos += chunkSize;
- charsWritten += chunkSize;
- }
-
- bytesWritten2 = (spos-pos);
- }
- catch ( UnsupportedEncodingException e )
- {
- throw new RuntimeException( e.getMessage(), e );
- }
-
- pos += bytesWritten2;
- int bytesWritten3 = c2.serialize( pos, data );
- pos += bytesWritten3;
-
- int size = bytesWritten1 + bytesWritten2 + bytesWritten3;
- if ( size != getRecordSize() )
- throw new RecordFormatException(size + " bytes written but getRecordSize() reports " + getRecordSize());
- return size;
- }
- if ( bytesWritten1 != getRecordSize() )
- throw new RecordFormatException(bytesWritten1 + " bytes written but getRecordSize() reports " + getRecordSize());
- return bytesWritten1;
- }
-
- private ContinueRecord createContinue2()
- {
- ContinueRecord c2 = new ContinueRecord();
- byte[] c2Data = new byte[str.numFormattingRuns() * 8 + 8];
- int pos = 0;
- for ( int i = 0; i < str.numFormattingRuns(); i++ )
- {
- LittleEndian.putShort( c2Data, pos, (short) str.getIndexOfFormattingRun( i ) );
- pos += 2;
- LittleEndian.putShort( c2Data, pos, str.getFontOfFormattingRun( i ) == str.NO_FONT ? 0 : str.getFontOfFormattingRun( i ) );
- pos += 2;
- pos += 4; // skip reserved
- }
- LittleEndian.putShort( c2Data, pos, (short) str.length() );
- pos += 2;
- LittleEndian.putShort( c2Data, pos, (short) 0 );
- pos += 2;
- pos += 4; // skip reserved
-
- c2.setData( c2Data );
-
- return c2;
- }
-
- private void processFontRuns( RecordInputStream in )
- {
- while (in.remaining() > 0)
- {
- short index = in.readShort();
- short iFont = in.readShort();
- in.readInt(); // skip reserved.
-
- str.applyFont( index, str.length(), iFont );
- }
- }
-
- private void processRawString( RecordInputStream in )
- {
- String s;
- byte compressByte = in.readByte();
- boolean isCompressed = compressByte == 0;
- if ( isCompressed )
- {
- s = in.readCompressedUnicode(getTextLength());
- }
- else
- {
- s = in.readUnicodeLEString(getTextLength());
- }
- str = new HSSFRichTextString( s );
- }
-
- public HSSFRichTextString getStr()
- {
- return str;
- }
-
- public void setStr( HSSFRichTextString str )
- {
- this.str = str;
- }
-
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append( "[TXO]\n" );
- buffer.append( " .options = " )
- .append( "0x" ).append( HexDump.toHex( getOptions() ) )
- .append( " (" ).append( getOptions() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .reserved1 = " ).append( isReserved1() ).append( '\n' );
- buffer.append( " .HorizontalTextAlignment = " ).append( getHorizontalTextAlignment() ).append( '\n' );
- buffer.append( " .VerticalTextAlignment = " ).append( getVerticalTextAlignment() ).append( '\n' );
- buffer.append( " .reserved2 = " ).append( getReserved2() ).append( '\n' );
- buffer.append( " .textLocked = " ).append( isTextLocked() ).append( '\n' );
- buffer.append( " .reserved3 = " ).append( getReserved3() ).append( '\n' );
- buffer.append( " .textOrientation = " )
- .append( "0x" ).append( HexDump.toHex( getTextOrientation() ) )
- .append( " (" ).append( getTextOrientation() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .reserved4 = " )
- .append( "0x" ).append( HexDump.toHex( getReserved4() ) )
- .append( " (" ).append( getReserved4() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .reserved5 = " )
- .append( "0x" ).append( HexDump.toHex( getReserved5() ) )
- .append( " (" ).append( getReserved5() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .reserved6 = " )
- .append( "0x" ).append( HexDump.toHex( getReserved6() ) )
- .append( " (" ).append( getReserved6() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .textLength = " )
- .append( "0x" ).append( HexDump.toHex( getTextLength() ) )
- .append( " (" ).append( getTextLength() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
- buffer.append( " .reserved7 = " )
- .append( "0x" ).append( HexDump.toHex( getReserved7() ) )
- .append( " (" ).append( getReserved7() ).append( " )" );
- buffer.append( System.getProperty( "line.separator" ) );
-
- buffer.append( " .string = " ).append(str).append('\n');
-
- for (int i = 0; i < str.numFormattingRuns(); i++) {
- buffer.append( " .textrun = " ).append(str.getFontOfFormattingRun(i)).append('\n');
-
- }
- buffer.append( "[/TXO]\n" );
- return buffer.toString();
- }
-
- public Object clone() {
-
- TextObjectRecord rec = new TextObjectRecord();
- rec.str = str;
-
- rec.setOptions(getOptions());
- rec.setTextOrientation(getTextOrientation());
- rec.setReserved4(getReserved4());
- rec.setReserved5(getReserved5());
- rec.setReserved6(getReserved6());
- rec.setTextLength(getTextLength());
- rec.setFormattingRunLength(getFormattingRunLength());
- rec.setReserved7(getReserved7());
- return rec;
- }
-
+/**
+ * The TXO record (0x01B6) is used to define the properties of a text box. It is
+ * followed by two or more continue records unless there is no actual text. The
+ * first continue records contain the text data and the last continue record
+ * contains the formatting runs.<p/>
+ *
+ * @author Glen Stampoultzis (glens at apache.org)
+ */
+public final class TextObjectRecord extends Record {
+ public final static short sid = 0x01B6;
+
+ private static final int FORMAT_RUN_ENCODED_SIZE = 8; // 2 shorts and 4 bytes reserved
+
+ private static final BitField HorizontalTextAlignment = BitFieldFactory.getInstance(0x000E);
+ private static final BitField VerticalTextAlignment = BitFieldFactory.getInstance(0x0070);
+ private static final BitField textLocked = BitFieldFactory.getInstance(0x0200);
+
+ public final static short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1;
+ public final static short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2;
+ public final static short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3;
+ public final static short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4;
+ public final static short VERTICAL_TEXT_ALIGNMENT_TOP = 1;
+ public final static short VERTICAL_TEXT_ALIGNMENT_CENTER = 2;
+ public final static short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3;
+ public final static short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4;
+
+ public final static short TEXT_ORIENTATION_NONE = 0;
+ public final static short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1;
+ public final static short TEXT_ORIENTATION_ROT_RIGHT = 2;
+ public final static short TEXT_ORIENTATION_ROT_LEFT = 3;
+
+ private int field_1_options;
+ private int field_2_textOrientation;
+ private int field_3_reserved4;
+ private int field_4_reserved5;
+ private int field_5_reserved6;
+ private int field_8_reserved7;
+
+ private HSSFRichTextString _text;
+
+ /*
+ * Note - the next three fields are very similar to those on
+ * EmbededObjectRefSubRecord(ftPictFmla 0x0009)
+ *
+ * some observed values for the 4 bytes preceding the formula: C0 5E 86 03
+ * C0 11 AC 02 80 F1 8A 03 D4 F0 8A 03
+ */
+ private int _unknownPreFormulaInt;
+ /** expect tRef, tRef3D, tArea, tArea3D or tName */
+ private Ptg _linkRefPtg;
+ /**
+ * Not clear if needed . Excel seems to be OK if this byte is not present.
+ * Value is often the same as the earlier firstColumn byte. */
+ private Byte _unknownPostFormulaByte;
+
+ public TextObjectRecord() {
+ }
+
+ public TextObjectRecord(RecordInputStream in) {
+ field_1_options = in.readUShort();
+ field_2_textOrientation = in.readUShort();
+ field_3_reserved4 = in.readUShort();
+ field_4_reserved5 = in.readUShort();
+ field_5_reserved6 = in.readUShort();
+ int field_6_textLength = in.readUShort();
+ int field_7_formattingDataLength = in.readUShort();
+ field_8_reserved7 = in.readInt();
+
+ if (in.remaining() > 0) {
+ // Text Objects can have simple reference formulas
+ // (This bit not mentioned in the MS document)
+ if (in.remaining() < 11) {
+ throw new RecordFormatException("Not enough remaining data for a link formula");
+ }
+ int formulaSize = in.readUShort();
+ _unknownPreFormulaInt = in.readInt();
+ Ptg[] ptgs = Ptg.readTokens(formulaSize, in);
+ if (ptgs.length != 1) {
+ throw new RecordFormatException("Read " + ptgs.length
+ + " tokens but expected exactly 1");
+ }
+ _linkRefPtg = ptgs[0];
+ if (in.remaining() > 0) {
+ _unknownPostFormulaByte = new Byte(in.readByte());
+ } else {
+ _unknownPostFormulaByte = null;
+ }
+ } else {
+ _linkRefPtg = null;
+ }
+ if (in.remaining() > 0) {
+ throw new RecordFormatException("Unused " + in.remaining() + " bytes at end of record");
+ }
+
+ String text;
+ if (field_6_textLength > 0) {
+ text = readRawString(in, field_6_textLength);
+ } else {
+ text = "";
+ }
+ _text = new HSSFRichTextString(text);
+
+ if (field_7_formattingDataLength > 0) {
+ if (in.isContinueNext() && in.remaining() == 0) {
+ in.nextRecord();
+ processFontRuns(in, _text, field_7_formattingDataLength);
+ } else {
+ throw new RecordFormatException(
+ "Expected Continue Record to hold font runs for TextObjectRecord");
+ }
+ }
+ }
+
+ private static String readRawString(RecordInputStream in, int textLength) {
+ byte compressByte = in.readByte();
+ boolean isCompressed = (compressByte & 0x01) == 0;
+ if (isCompressed) {
+ return in.readCompressedUnicode(textLength);
+ }
+ return in.readUnicodeLEString(textLength);
+ }
+
+ private static void processFontRuns(RecordInputStream in, HSSFRichTextString str,
+ int formattingRunDataLength) {
+ if (formattingRunDataLength % FORMAT_RUN_ENCODED_SIZE != 0) {
+ throw new RecordFormatException("Bad format run data length " + formattingRunDataLength
+ + ")");
+ }
+ if (in.remaining() != formattingRunDataLength) {
+ throw new RecordFormatException("Expected " + formattingRunDataLength
+ + " bytes but got " + in.remaining());
+ }
+ int nRuns = formattingRunDataLength / FORMAT_RUN_ENCODED_SIZE;
+ for (int i = 0; i < nRuns; i++) {
+ short index = in.readShort();
+ short iFont = in.readShort();
+ in.readInt(); // skip reserved.
+ str.applyFont(index, str.length(), iFont);
+ }
+ }
+
+ public short getSid() {
+ return sid;
+ }
+
+ /**
+ * Only for the current record. does not include any subsequent Continue
+ * records
+ */
+ private int getDataSize() {
+ int result = 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4;
+ if (_linkRefPtg != null) {
+ result += 2 // formula size
+ + 4 // unknownInt
+ +_linkRefPtg.getSize();
+ if (_unknownPostFormulaByte != null) {
+ result += 1;
+ }
+ }
+ return result;
+ }
+
+ private int serializeTXORecord(int offset, byte[] data) {
+ int dataSize = getDataSize();
+
+ LittleEndian.putUShort(data, 0 + offset, TextObjectRecord.sid);
+ LittleEndian.putUShort(data, 2 + offset, dataSize);
+
+
+ LittleEndian.putUShort(data, 4 + offset, field_1_options);
+ LittleEndian.putUShort(data, 6 + offset, field_2_textOrientation);
+ LittleEndian.putUShort(data, 8 + offset, field_3_reserved4);
+ LittleEndian.putUShort(data, 10 + offset, field_4_reserved5);
+ LittleEndian.putUShort(data, 12 + offset, field_5_reserved6);
+ LittleEndian.putUShort(data, 14 + offset, _text.length());
+ LittleEndian.putUShort(data, 16 + offset, getFormattingDataLength());
+ LittleEndian.putInt(data, 18 + offset, field_8_reserved7);
+
+ if (_linkRefPtg != null) {
+ int pos = offset+22;
+ int formulaSize = _linkRefPtg.getSize();
+ LittleEndian.putUShort(data, pos, formulaSize);
+ pos += LittleEndian.SHORT_SIZE;
+ LittleEndian.putInt(data, pos, _unknownPreFormulaInt);
+ pos += LittleEndian.INT_SIZE;
+ _linkRefPtg.writeBytes(data, pos);
+ pos += formulaSize;
+ if (_unknownPostFormulaByte != null) {
+ LittleEndian.putByte(data, pos, _unknownPostFormulaByte.byteValue());
+ pos += LittleEndian.BYTE_SIZE;
+ }
+ }
+
+ return 4 + dataSize;
+ }
+
+ private int serializeTrailingRecords(int offset, byte[] data) {
+ byte[] textBytes;
+ try {
+ textBytes = _text.getString().getBytes("UTF-16LE");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ int remainingLength = textBytes.length;
+
+ int countTextBytesWritten = 0;
+ int pos = offset;
+ // (regardless what was read, we always serialize double-byte
+ // unicode characters (UTF-16LE).
+ Byte unicodeFlag = new Byte((byte)1);
+ while (remainingLength > 0) {
+ int chunkSize = Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE - 2, remainingLength);
+ remainingLength -= chunkSize;
+ pos += ContinueRecord.write(data, pos, unicodeFlag, textBytes, countTextBytesWritten, chunkSize);
+ countTextBytesWritten += chunkSize;
+ }
+
+ byte[] formatData = createFormatData(_text);
+ pos += ContinueRecord.write(data, pos, null, formatData);
+ return pos - offset;
+ }
+
+ private int getTrailingRecordsSize() {
+ if (_text.length() < 1) {
+ return 0;
+ }
+ int encodedTextSize = 0;
+ int textBytesLength = _text.length() * LittleEndian.SHORT_SIZE;
+ while (textBytesLength > 0) {
+ int chunkSize = Math.min(RecordInputStream.MAX_RECORD_DATA_SIZE - 2, textBytesLength);
+ textBytesLength -= chunkSize;
+
+ encodedTextSize += 4; // +4 for ContinueRecord sid+size
+ encodedTextSize += 1+chunkSize; // +1 for compressed unicode flag,
+ }
+
+ int encodedFormatSize = (_text.numFormattingRuns() + 1) * FORMAT_RUN_ENCODED_SIZE
+ + 4; // +4 for ContinueRecord sid+size
+ return encodedTextSize + encodedFormatSize;
+ }
+
+
+ public int serialize(int offset, byte[] data) {
+
+ int expectedTotalSize = getRecordSize();
+ int totalSize = serializeTXORecord(offset, data);
+
+ if (_text.getString().length() > 0) {
+ totalSize += serializeTrailingRecords(offset+totalSize, data);
+ }
+
+ if (totalSize != expectedTotalSize)
+ throw new RecordFormatException(totalSize
+ + " bytes written but getRecordSize() reports " + expectedTotalSize);
+ return totalSize;
+ }
+
+ /**
+ * Note - this total size includes all potential {@link ContinueRecord}s written
+ */
+ public int getRecordSize() {
+ int baseSize = 4 + getDataSize();
+ return baseSize + getTrailingRecordsSize();
+ }
+
+
+ private int getFormattingDataLength() {
+ if (_text.length() < 1) {
+ // important - no formatting data if text is empty
+ return 0;
+ }
+ return (_text.numFormattingRuns() + 1) * FORMAT_RUN_ENCODED_SIZE;
+ }
+
+ private static byte[] createFormatData(HSSFRichTextString str) {
+ int nRuns = str.numFormattingRuns();
+ byte[] result = new byte[(nRuns + 1) * FORMAT_RUN_ENCODED_SIZE];
+ int pos = 0;
+ for (int i = 0; i < nRuns; i++) {
+ LittleEndian.putUShort(result, pos, str.getIndexOfFormattingRun(i));
+ pos += 2;
+ int fontIndex = str.getFontOfFormattingRun(i);
+ LittleEndian.putUShort(result, pos, fontIndex == str.NO_FONT ? 0 : fontIndex);
+ pos += 2;
+ pos += 4; // skip reserved
+ }
+ LittleEndian.putUShort(result, pos, str.length());
+ pos += 2;
+ LittleEndian.putUShort(result, pos, 0);
+ pos += 2;
+ pos += 4; // skip reserved
+
+ return result;
+ }
+
+ /**
+ * Sets the Horizontal text alignment field value.
+ */
+ public void setHorizontalTextAlignment(int value) {
+ field_1_options = HorizontalTextAlignment.setValue(field_1_options, value);
+ }
+
+ /**
+ * @return the Horizontal text alignment field value.
+ */
+ public int getHorizontalTextAlignment() {
+ return HorizontalTextAlignment.getValue(field_1_options);
+ }
+
+ /**
+ * Sets the Vertical text alignment field value.
+ */
+ public void setVerticalTextAlignment(int value) {
+ field_1_options = VerticalTextAlignment.setValue(field_1_options, value);
+ }
+
+ /**
+ * @return the Vertical text alignment field value.
+ */
+ public int getVerticalTextAlignment() {
+ return VerticalTextAlignment.getValue(field_1_options);
+ }
+
+ /**
+ * Sets the text locked field value.
+ */
+ public void setTextLocked(boolean value) {
+ field_1_options = textLocked.setBoolean(field_1_options, value);
+ }
+
+ /**
+ * @return the text locked field value.
+ */
+ public boolean isTextLocked() {
+ return textLocked.isSet(field_1_options);
+ }
+
+ /**
+ * Get the text orientation field for the TextObjectBase record.
+ *
+ * @return One of TEXT_ORIENTATION_NONE TEXT_ORIENTATION_TOP_TO_BOTTOM
+ * TEXT_ORIENTATION_ROT_RIGHT TEXT_ORIENTATION_ROT_LEFT
+ */
+ public int getTextOrientation() {
+ return field_2_textOrientation;
+ }
+
+ /**
+ * Set the text orientation field for the TextObjectBase record.
+ *
+ * @param textOrientation
+ * One of TEXT_ORIENTATION_NONE TEXT_ORIENTATION_TOP_TO_BOTTOM
+ * TEXT_ORIENTATION_ROT_RIGHT TEXT_ORIENTATION_ROT_LEFT
+ */
+ public void setTextOrientation(int textOrientation) {
+ this.field_2_textOrientation = textOrientation;
+ }
+
+ public HSSFRichTextString getStr() {
+ return _text;
+ }
+
+ public void setStr(HSSFRichTextString str) {
+ _text = str;
+ }
+
+ public Ptg getLinkRefPtg() {
+ return _linkRefPtg;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+
+ sb.append("[TXO]\n");
+ sb.append(" .options = ").append(HexDump.shortToHex(field_1_options)).append("\n");
+ sb.append(" .isHorizontal = ").append(getHorizontalTextAlignment()).append('\n');
+ sb.append(" .isVertical = ").append(getVerticalTextAlignment()).append('\n');
+ sb.append(" .textLocked = ").append(isTextLocked()).append('\n');
+ sb.append(" .textOrientation= ").append(HexDump.shortToHex(getTextOrientation())).append("\n");
+ sb.append(" .reserved4 = ").append(HexDump.shortToHex(field_3_reserved4)).append("\n");
+ sb.append(" .reserved5 = ").append(HexDump.shortToHex(field_4_reserved5)).append("\n");
+ sb.append(" .reserved6 = ").append(HexDump.shortToHex(field_5_reserved6)).append("\n");
+ sb.append(" .textLength = ").append(HexDump.shortToHex(_text.length())).append("\n");
+ sb.append(" .reserved7 = ").append(HexDump.intToHex(field_8_reserved7)).append("\n");
+
+ sb.append(" .string = ").append(_text).append('\n');
+
+ for (int i = 0; i < _text.numFormattingRuns(); i++) {
+ sb.append(" .textrun = ").append(_text.getFontOfFormattingRun(i)).append('\n');
+
+ }
+ sb.append("[/TXO]\n");
+ return sb.toString();
+ }
+
+ public Object clone() {
+
+ TextObjectRecord rec = new TextObjectRecord();
+ rec._text = _text;
+
+ rec.field_1_options = field_1_options;
+ rec.field_2_textOrientation = field_2_textOrientation;
+ rec.field_3_reserved4 = field_3_reserved4;
+ rec.field_4_reserved5 = field_4_reserved5;
+ rec.field_5_reserved6 = field_5_reserved6;
+ rec.field_8_reserved7 = field_8_reserved7;
+
+ rec._text = _text; // clone needed?
+
+ if (_linkRefPtg != null) {
+ rec._unknownPreFormulaInt = _unknownPreFormulaInt;
+ rec._linkRefPtg = _linkRefPtg.copy();
+ rec._unknownPostFormulaByte = rec._unknownPostFormulaByte;
+ }
+ return rec;
+ }
}
import java.util.ArrayList;
import java.util.List;
-import java.util.Stack;
import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
/**
* <tt>Ptg</tt> represents a syntactic token in a formula. 'PTG' is an acronym for
* Extra data (beyond <tt>size</tt>) may be read if and <tt>ArrayPtg</tt>s are present.
*/
public static Ptg[] readTokens(int size, RecordInputStream in) {
- Stack temp = createParsedExpressionTokens((short)size, in);
- return toPtgArray(temp);
- }
-
- /**
- * @deprecated - use readTokens()
- */
- public static Stack createParsedExpressionTokens(short size, RecordInputStream in) {
- Stack stack = new Stack();
+ List temp = new ArrayList(4 + size / 2);
int pos = 0;
List arrayPtgs = null;
while (pos < size) {
} else {
pos += ptg.getSize();
}
- stack.push( ptg );
+ temp.add( ptg );
}
if(pos != size) {
throw new RuntimeException("Ptg array size mismatch");
p.readTokenValues(in);
}
}
- return stack;
+ return toPtgArray(temp);
}
public static Ptg createPtg(RecordInputStream in) {
l.toArray(result);
return result;
}
- private static Stack createStack(Ptg[] formulaTokens) {
- Stack result = new Stack();
- for (int i = 0; i < formulaTokens.length; i++) {
- result.add(formulaTokens[i]);
- }
- return result;
- }
/**
* This method will return the same result as {@link #getEncodedSizeWithoutArrayData(Ptg[])}
* if there are no array tokens present.
* @return the full size taken to encode the specified <tt>Ptg</tt>s
*/
- // TODO - several duplicates of this code should be refactored here
public static int getEncodedSize(Ptg[] ptgs) {
int result = 0;
for (int i = 0; i < ptgs.length; i++) {
* The 2 byte encode length field is <b>not</b> written by this method.
* @return number of bytes written
*/
- public static int serializePtgs(Ptg[] ptgs, byte[] data, int offset) {
- return serializePtgStack(createStack(ptgs), data, offset);
- }
-
- /**
- * @deprecated use serializePtgs()
- */
- public static int serializePtgStack(Stack expression, byte[] array, int offset) {
+ public static int serializePtgs(Ptg[] ptgs, byte[] array, int offset) {
int pos = 0;
- int size = 0;
- if (expression != null)
- size = expression.size();
+ int size = ptgs.length;
List arrayPtgs = null;
for (int k = 0; k < size; k++) {
- Ptg ptg = ( Ptg ) expression.get(k);
+ Ptg ptg = ptgs[k];
ptg.writeBytes(array, pos + offset);
if (ptg instanceof ArrayPtg) {
if (hstring.numFormattingRuns() == 0) hstring.applyFont((short)0);
if (txo != null) {
- int frLength = ( hstring.numFormattingRuns() + 1 ) * 8;
- txo.setFormattingRunLength( (short) frLength );
- txo.setTextLength( (short) hstring.length() );
- txo.setStr( hstring );
+ txo.setStr(hstring);
}
super.setString(string);
}
/**
- * @return the number of characters in the font.
+ * @return the number of characters in the text.
*/
public int length()
{
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import java.util.Stack;
import org.apache.poi.hssf.record.AreaFormatRecord;
import org.apache.poi.hssf.record.AxisLineFormatRecord;
import org.apache.poi.hssf.record.VCenterRecord;
import org.apache.poi.hssf.record.ValueRangeRecord;
import org.apache.poi.hssf.record.formula.Area3DPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
/**
* Has methods for construction of a chart object.
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
LinkedDataFormulaField formula = new LinkedDataFormulaField();
- Stack tokens = new Stack();
Area3DPtg p = new Area3DPtg(0, 31, 1, 1,
false, false, false, false, 0);
- tokens.add( p );
- formula.setFormulaTokens( tokens );
+ formula.setFormulaTokens(new Ptg[] { p, });
r.setFormulaOfLink( formula );
return r;
}
r.setCustomNumberFormat( false );
r.setIndexNumberFmtRecord( (short) 0 );
LinkedDataFormulaField formula = new LinkedDataFormulaField();
- Stack tokens = new Stack();
Area3DPtg p = new Area3DPtg(0, 31, 0, 0,
false, false, false, false, 0);
- tokens.add( p );
- formula.setFormulaTokens( tokens );
+ formula.setFormulaTokens(new Ptg[] { p, });
r.setFormulaOfLink( formula );
return r;
}
bof.setHistoryBitMask(BOFRecord.HISTORY_MASK);
byte[] bytes = bof.serialize();
- byte[] nbytes = new byte[bytes.length - 4];
- System.arraycopy(bytes,4,nbytes,0,nbytes.length);
- Record[] records = RecordFactory.createRecord(new TestcaseRecordInputStream(bof.getSid(),(short)nbytes.length,nbytes));
+ Record[] records = RecordFactory.createRecord(TestcaseRecordInputStream.create(bytes));
assertTrue("record.length must be 1, was ="+records.length,records.length == 1);
assertTrue("record is the same", compareRec(bof,records[0]));
result.addTestSuite(TestPaneRecord.class);
result.addTestSuite(TestPlotAreaRecord.class);
result.addTestSuite(TestPlotGrowthRecord.class);
+ result.addTestSuite(TestRecordInputStream.class);
result.addTestSuite(TestRecordFactory.class);
result.addTestSuite(TestSCLRecord.class);
result.addTestSuite(TestSSTDeserializer.class);
public void testLoad() {
- AreaFormatRecord record = new AreaFormatRecord(new TestcaseRecordInputStream((short)0x100a, (short)data.length, data));
+ AreaFormatRecord record = new AreaFormatRecord(TestcaseRecordInputStream.create(0x100a, data));
assertEquals( 0xFFFFFF, record.getForegroundColor());
assertEquals( 0x000000, record.getBackgroundColor());
assertEquals( 1, record.getPattern());
public void testLoad() {
- AreaRecord record = new AreaRecord(new TestcaseRecordInputStream((short)0x101A, (short)data.length, data));
+ AreaRecord record = new AreaRecord(TestcaseRecordInputStream.create(0x101A, data));
assertEquals( 2, record.getFormatFlags());
assertEquals( false, record.isStacked() );
assertEquals( true, record.isDisplayAsPercentage() );
};
public void testLoad() {
- AxisLineFormatRecord record = new AxisLineFormatRecord(new TestcaseRecordInputStream((short)0x1021, (short)data.length, data));
+ AxisLineFormatRecord record = new AxisLineFormatRecord(TestcaseRecordInputStream.create(0x1021, data));
assertEquals( AxisLineFormatRecord.AXIS_TYPE_MAJOR_GRID_LINE, record.getAxisType());
assertEquals( 6, record.getRecordSize() );
};
public void testLoad() {
- AxisOptionsRecord record = new AxisOptionsRecord(new TestcaseRecordInputStream((short)0x1062, (short)data.length, data));
+ AxisOptionsRecord record = new AxisOptionsRecord(TestcaseRecordInputStream.create(0x1062, data));
assertEquals( 0, record.getMinimumCategory());
assertEquals( 0, record.getMaximumCategory());
assertEquals( 1, record.getMajorUnitValue());
};
public void testLoad() {
- AxisParentRecord record = new AxisParentRecord(new TestcaseRecordInputStream((short)0x1041, (short)data.length, data));
+ AxisParentRecord record = new AxisParentRecord(TestcaseRecordInputStream.create(0x1041, data));
assertEquals( AxisParentRecord.AXIS_TYPE_MAIN, record.getAxisType());
assertEquals( 0x021d, record.getX());
assertEquals( 0xdd, record.getY());
public void testLoad() {
- AxisRecord record = new AxisRecord(new TestcaseRecordInputStream((short)0x101d, (short)data.length, data));
+ AxisRecord record = new AxisRecord(TestcaseRecordInputStream.create(0x101d, data));
assertEquals( AxisRecord.AXIS_TYPE_CATEGORY_OR_X_AXIS, record.getAxisType());
assertEquals( 0, record.getReserved1());
assertEquals( 0, record.getReserved2());
};
public void testLoad() {
- AxisUsedRecord record = new AxisUsedRecord(new TestcaseRecordInputStream((short)0x1046, (short)data.length, data));
+ AxisUsedRecord record = new AxisUsedRecord(TestcaseRecordInputStream.create(0x1046, data));
assertEquals( 1, record.getNumAxis());
assertEquals( 6, record.getRecordSize() );
public void testLoad() {
- BarRecord record = new BarRecord(new TestcaseRecordInputStream((short)0x1017, (short)data.length, data));
+ BarRecord record = new BarRecord(TestcaseRecordInputStream.create(0x1017, data));
assertEquals( 0, record.getBarSpace());
assertEquals( 0x96, record.getCategorySpace());
assertEquals( 0, record.getFormatFlags());
// </str>
};
- RecordInputStream in = new TestcaseRecordInputStream(BoundSheetRecord.sid, data);
+ RecordInputStream in = TestcaseRecordInputStream.create(BoundSheetRecord.sid, data);
BoundSheetRecord bsr = new BoundSheetRecord(in);
// sheet name is unicode Russian for 'minor page'
assertEquals("\u0421\u0442\u0440\u0430\u043D\u0438\u0447\u043A\u0430", bsr.getSheetname());
(byte)0x03, (byte)0x00,
};
- CFHeaderRecord record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
+ CFHeaderRecord record = new CFHeaderRecord(TestcaseRecordInputStream.create(CFHeaderRecord.sid, recordData));
assertEquals("#CFRULES", 3, record.getNumberOfConditionalFormats());
assertTrue(record.getNeedRecalculation());
CFHeaderRecord record;
try {
- record = new CFHeaderRecord(new TestcaseRecordInputStream(CFHeaderRecord.sid, (short)recordData.length, recordData));
+ record = new CFHeaderRecord(TestcaseRecordInputStream.create(CFHeaderRecord.sid, recordData));
} catch (IllegalArgumentException e) {
if(e.getMessage().equals("invalid cell range (-25536, 2, -15536, 2)")) {
throw new AssertionFailedError("Identified bug 44739b");
System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length);
// Deserialize
- record = new CFRuleRecord(new TestcaseRecordInputStream(CFRuleRecord.sid, (short)recordData.length, recordData));
+ record = new CFRuleRecord(TestcaseRecordInputStream.create(CFRuleRecord.sid, recordData));
// Serialize again
byte[] output = record.serialize();
*/
public void testReserializeRefNTokens() {
- RecordInputStream is = new TestcaseRecordInputStream(CFRuleRecord.sid, DATA_REFN);
+ RecordInputStream is = TestcaseRecordInputStream.create(CFRuleRecord.sid, DATA_REFN);
CFRuleRecord rr = new CFRuleRecord(is);
Ptg[] ptgs = rr.getParsedExpression1();
assertEquals(3, ptgs.length);
public void testLoad() {
- CategorySeriesAxisRecord record = new CategorySeriesAxisRecord(new TestcaseRecordInputStream((short)0x1020, (short)data.length, data));
+ CategorySeriesAxisRecord record = new CategorySeriesAxisRecord(TestcaseRecordInputStream.create(0x1020, data));
assertEquals( 1, record.getCrossingPoint());
assertEquals( 1, record.getLabelFrequency());
assertEquals( 1, record.getTickMarkFrequency());
public void testLoad() {
- ChartRecord record = new ChartRecord(new TestcaseRecordInputStream((short)0x1002, (short)data.length, data));
+ ChartRecord record = new ChartRecord(TestcaseRecordInputStream.create(0x1002, data));
assertEquals( 0, record.getX());
assertEquals( 0, record.getY());
assertEquals( 30474216, record.getWidth());
};
public void testLoad() {
- CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(new TestcaseRecordInputStream((short)0x15, (short)data.length, data));
+ CommonObjectDataSubRecord record = new CommonObjectDataSubRecord(TestcaseRecordInputStream.create(0x15, data));
assertEquals( CommonObjectDataSubRecord.OBJECT_TYPE_LIST_BOX, record.getObjectType());
assertEquals( (short)1, record.getObjectId());
public void testLoad() {
- DatRecord record = new DatRecord(new TestcaseRecordInputStream((short)0x1063, (short)data.length, data));
+ DatRecord record = new DatRecord(TestcaseRecordInputStream.create(0x1063, data));
assertEquals( 0xD, record.getOptions());
assertEquals( true, record.isHorizontalBorder() );
assertEquals( false, record.isVerticalBorder() );
public void testLoad() {
- DataFormatRecord record = new DataFormatRecord(new TestcaseRecordInputStream((short)0x1006, (short)data.length, data));
+ DataFormatRecord record = new DataFormatRecord(TestcaseRecordInputStream.create(0x1006, data));
assertEquals( (short)0xFFFF, record.getPointNumber());
assertEquals( 0, record.getSeriesIndex());
assertEquals( 0, record.getSeriesNumber());
public void testLoad() {
- DefaultDataLabelTextPropertiesRecord record = new DefaultDataLabelTextPropertiesRecord(new TestcaseRecordInputStream((short)0x1024, (short)data.length, data));
+ DefaultDataLabelTextPropertiesRecord record = new DefaultDataLabelTextPropertiesRecord(TestcaseRecordInputStream.create(0x1024, data));
assertEquals( 2, record.getCategoryDataType());
assertEquals( 6, record.getRecordSize() );
}\r
\r
private static void confirmRead(byte[] data, int i) {\r
- RecordInputStream in = new TestcaseRecordInputStream(EmbeddedObjectRefSubRecord.sid, (short)data.length, data);\r
+ RecordInputStream in = TestcaseRecordInputStream.create(EmbeddedObjectRefSubRecord.sid, data);\r
\r
EmbeddedObjectRefSubRecord rec = new EmbeddedObjectRefSubRecord(in);\r
byte[] ser2 = rec.serialize();\r
};
public void testLoad() {
- EndSubRecord record = new EndSubRecord(new TestcaseRecordInputStream((short)0x00, (short)data.length, data));
+ EndSubRecord record = new EndSubRecord(TestcaseRecordInputStream.create(0x00, data));
assertEquals( 4, record.getRecordSize() );
}
};
public void testLoad() {
- ExtendedFormatRecord record = new ExtendedFormatRecord(new TestcaseRecordInputStream((short)0xe0, (short)data.length, data));
+ ExtendedFormatRecord record = new ExtendedFormatRecord(TestcaseRecordInputStream.create(0xe0, data));
assertEquals(0, record.getFontIndex());
assertEquals(0, record.getFormatIndex());
assertEquals(0xF5-256, record.getCellOptions());
}
public void testCloneOnto() throws Exception {
- ExtendedFormatRecord base = new ExtendedFormatRecord(new TestcaseRecordInputStream((short)0xe0, (short)data.length, data));
+ ExtendedFormatRecord base = new ExtendedFormatRecord(TestcaseRecordInputStream.create(0xe0, data));
ExtendedFormatRecord other = new ExtendedFormatRecord();
other.cloneStyleFrom(base);
};\r
\r
private static ExternalNameRecord createSimpleENR(byte[] data) {\r
- return new ExternalNameRecord(new TestcaseRecordInputStream((short)0x0023, data));\r
+ return new ExternalNameRecord(TestcaseRecordInputStream.create(0x0023, data));\r
}\r
public void testBasicDeserializeReserialize() {\r
\r
public void testLoad() {
- FontBasisRecord record = new FontBasisRecord(new TestcaseRecordInputStream((short)0x1060, (short)data.length, data));
+ FontBasisRecord record = new FontBasisRecord(TestcaseRecordInputStream.create(0x1060, data));
assertEquals( 0x1a28, record.getXBasis());
assertEquals( 0x0f9c, record.getYBasis());
assertEquals( 0xc8, record.getHeightBasis());
public void testLoad() {
- FontIndexRecord record = new FontIndexRecord(new TestcaseRecordInputStream((short)0x1026, (short)data.length, data));
+ FontIndexRecord record = new FontIndexRecord(TestcaseRecordInputStream.create(0x1026, data));
assertEquals( 5, record.getFontIndex());
assertEquals( 6, record.getRecordSize() );
public void testLoad() {
- FontRecord record = new FontRecord(new TestcaseRecordInputStream((short)0x31, (short)data.length, data));
+ FontRecord record = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
assertEquals( 0xc8, record.getFontHeight());
assertEquals( 0x00, record.getAttributes());
assertFalse( record.isItalic());
}
public void testCloneOnto() throws Exception {
- FontRecord base = new FontRecord(new TestcaseRecordInputStream((short)0x31, (short)data.length, data));
+ FontRecord base = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
FontRecord other = new FontRecord();
other.cloneStyleFrom(base);
}
public void testSameProperties() throws Exception {
- FontRecord f1 = new FontRecord(new TestcaseRecordInputStream((short)0x31, (short)data.length, data));
- FontRecord f2 = new FontRecord(new TestcaseRecordInputStream((short)0x31, (short)data.length, data));
+ FontRecord f1 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
+ FontRecord f2 = new FontRecord(TestcaseRecordInputStream.create(0x31, data));
assertTrue(f1.sameProperties(f2));
};
- FormulaRecord record = new FormulaRecord(new TestcaseRecordInputStream(FormulaRecord.sid, (short)29, formulaByte));
+ FormulaRecord record = new FormulaRecord(TestcaseRecordInputStream.create(FormulaRecord.sid, formulaByte));
assertEquals("Row", 0, record.getRow());
assertEquals("Column", 0, record.getColumn());
assertEquals(HSSFCell.CELL_TYPE_ERROR, record.getCachedResultType());
formulaByte[19]=(byte)0xFD;
formulaByte[20]=(byte)0x05;
formulaByte[22]=(byte)0x01;
- FormulaRecord record = new FormulaRecord(new TestcaseRecordInputStream(FormulaRecord.sid, (short)27, formulaByte));
+ FormulaRecord record = new FormulaRecord(TestcaseRecordInputStream.create(FormulaRecord.sid, formulaByte));
assertEquals("Row", 0, record.getRow());
assertEquals("Column", 0, record.getColumn());
byte[] output = record.serialize();
public void testLoad() {
- FrameRecord record = new FrameRecord(new TestcaseRecordInputStream((short)0x1032, (short)data.length, data));
+ FrameRecord record = new FrameRecord(TestcaseRecordInputStream.create(0x1032, data));
assertEquals( FrameRecord.BORDER_TYPE_REGULAR, record.getBorderType());
assertEquals( 2, record.getOptions());
assertEquals( false, record.isAutoSize() );
package org.apache.poi.hssf.record;
import java.io.ByteArrayInputStream;
-import java.net.URL;
import java.util.Arrays;
import junit.framework.TestCase;
* @author Nick Burch
* @author Yegor Kozlov
*/
-public class TestHyperlinkRecord extends TestCase {
+public final class TestHyperlinkRecord extends TestCase {
//link to http://www.lakings.com/
byte[] data1 = { 0x02, 0x00, //First row of the hyperlink
0x00, 0x41, 0x00, 0x31, 0x00, 0x00, 0x00};
public void testReadURLLink(){
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data1.length, data1);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data1);
HyperlinkRecord link = new HyperlinkRecord(is);
assertEquals(2, link.getFirstRow());
assertEquals(2, link.getLastRow());
}
public void testReadFileLink(){
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data2.length, data2);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data2);
HyperlinkRecord link = new HyperlinkRecord(is);
assertEquals(0, link.getFirstRow());
assertEquals(0, link.getLastRow());
}
public void testReadEmailLink(){
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data3.length, data3);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data3);
HyperlinkRecord link = new HyperlinkRecord(is);
assertEquals(1, link.getFirstRow());
assertEquals(1, link.getLastRow());
}
public void testReadDocumentLink(){
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data4.length, data4);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data4);
HyperlinkRecord link = new HyperlinkRecord(is);
assertEquals(3, link.getFirstRow());
assertEquals(3, link.getLastRow());
}
private void serialize(byte[] data){
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data.length, data);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data);
HyperlinkRecord link = new HyperlinkRecord(is);
byte[] bytes1 = link.serialize();
is = new RecordInputStream(new ByteArrayInputStream(bytes1));
public void testClone() throws Exception {
byte[][] data = {data1, data2, data3, data4};
for (int i = 0; i < data.length; i++) {
- RecordInputStream is = new TestcaseRecordInputStream((short)HyperlinkRecord.sid, (short)data[i].length, data[i]);
+ RecordInputStream is = TestcaseRecordInputStream.create(HyperlinkRecord.sid, data[i]);
HyperlinkRecord link = new HyperlinkRecord(is);
HyperlinkRecord clone = (HyperlinkRecord)link.clone();
assertTrue(Arrays.equals(link.serialize(), clone.serialize()));
package org.apache.poi.hssf.record;
-
import junit.framework.TestCase;
/**
- * Tests the serialization and deserialization of the LegendRecord
- * class works correctly. Test data taken directly from a real
- * Excel file.
- *
-
+ * Tests the serialization and deserialization of the LegendRecord class works
+ * correctly. Test data taken directly from a real Excel file.
+ *
+ *
* @author Andrew C. Oliver (acoliver at apache.org)
*/
-public class TestLegendRecord extends TestCase {
- byte[] data = new byte[] {
- (byte)0x76,(byte)0x0E,(byte)0x00,(byte)0x00,(byte)0x86,(byte)0x07,(byte)0x00,(byte)0x00,(byte)0x19,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x8B,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x01,(byte)0x1F,(byte)0x00
- };
-
- public void testLoad() {
- LegendRecord record = new LegendRecord(new TestcaseRecordInputStream((short)0x1015, (short)data.length, data));
-
-
- assertEquals( (int)0xe76, record.getXAxisUpperLeft());
-
- assertEquals( (int)0x786, record.getYAxisUpperLeft());
-
- assertEquals( (int)0x119, record.getXSize());
+public final class TestLegendRecord extends TestCase {
+ byte[] data = new byte[] { (byte) 0x76, (byte) 0x0E, (byte) 0x00, (byte) 0x00, (byte) 0x86,
+ (byte) 0x07, (byte) 0x00, (byte) 0x00, (byte) 0x19, (byte) 0x01, (byte) 0x00,
+ (byte) 0x00, (byte) 0x8B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03,
+ (byte) 0x01, (byte) 0x1F, (byte) 0x00 };
- assertEquals( (int)0x8b, record.getYSize());
+ public void testLoad() {
+ LegendRecord record = new LegendRecord(TestcaseRecordInputStream.create(0x1015, data));
- assertEquals( (byte)0x3, record.getType());
+ assertEquals(0xe76, record.getXAxisUpperLeft());
- assertEquals( (byte)0x1, record.getSpacing());
+ assertEquals(0x786, record.getYAxisUpperLeft());
- assertEquals( (short)0x1f, record.getOptions());
- assertEquals( true, record.isAutoPosition() );
- assertEquals( true, record.isAutoSeries() );
- assertEquals( true, record.isAutoXPositioning() );
- assertEquals( true, record.isAutoYPositioning() );
- assertEquals( true, record.isVertical() );
- assertEquals( false, record.isDataTable() );
+ assertEquals(0x119, record.getXSize());
+ assertEquals(0x8b, record.getYSize());
- assertEquals( 24, record.getRecordSize() );
- }
+ assertEquals((byte) 0x3, record.getType());
- public void testStore()
- {
- LegendRecord record = new LegendRecord();
+ assertEquals((byte) 0x1, record.getSpacing());
+ assertEquals((short) 0x1f, record.getOptions());
+ assertEquals(true, record.isAutoPosition());
+ assertEquals(true, record.isAutoSeries());
+ assertEquals(true, record.isAutoXPositioning());
+ assertEquals(true, record.isAutoYPositioning());
+ assertEquals(true, record.isVertical());
+ assertEquals(false, record.isDataTable());
+ assertEquals(24, record.getRecordSize());
+ }
- record.setXAxisUpperLeft( (int)0xe76 );
+ public void testStore() {
+ LegendRecord record = new LegendRecord();
- record.setYAxisUpperLeft( (int)0x786 );
+ record.setXAxisUpperLeft(0xe76);
- record.setXSize( (int)0x119 );
+ record.setYAxisUpperLeft(0x786);
- record.setYSize( (int)0x8b );
+ record.setXSize(0x119);
- record.setType( (byte)0x3 );
+ record.setYSize(0x8b);
- record.setSpacing( (byte)0x1 );
+ record.setType((byte) 0x3);
- record.setOptions( (short)0x1f );
- record.setAutoPosition( true );
- record.setAutoSeries( true );
- record.setAutoXPositioning( true );
- record.setAutoYPositioning( true );
- record.setVertical( true );
- record.setDataTable( false );
+ record.setSpacing((byte) 0x1);
+ record.setOptions((short) 0x1f);
+ record.setAutoPosition(true);
+ record.setAutoSeries(true);
+ record.setAutoXPositioning(true);
+ record.setAutoYPositioning(true);
+ record.setVertical(true);
+ record.setDataTable(false);
- byte [] recordBytes = record.serialize();
- assertEquals(recordBytes.length - 4, data.length);
- for (int i = 0; i < data.length; i++)
- assertEquals("At offset " + i, data[i], recordBytes[i+4]);
- }
+ byte[] recordBytes = record.serialize();
+ assertEquals(recordBytes.length - 4, data.length);
+ for (int i = 0; i < data.length; i++)
+ assertEquals("At offset " + i, data[i], recordBytes[i + 4]);
+ }
}
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class TestLineFormatRecord extends TestCase {
+public final class TestLineFormatRecord extends TestCase {
byte[] data = new byte[] {
(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, // colour
(byte)0x00,(byte)0x00, // pattern
};
public void testLoad() {
- LineFormatRecord record = new LineFormatRecord(new TestcaseRecordInputStream((short)0x1007, (short)data.length, data));
+ LineFormatRecord record = new LineFormatRecord(TestcaseRecordInputStream.create(0x1007, data));
assertEquals( 0, record.getLineColor());
assertEquals( 0, record.getLinePattern());
assertEquals( 0, record.getWeight());
import junit.framework.TestCase;
-import org.apache.poi.hssf.record.formula.Area3DPtg;
-import java.util.Stack;
+import org.apache.poi.hssf.record.formula.Area3DPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
/**
* Tests the serialization and deserialization of the LinkedDataRecord
public void testLoad() {
- LinkedDataRecord record = new LinkedDataRecord(new TestcaseRecordInputStream((short)0x1051, (short)data.length, data));
+ LinkedDataRecord record = new LinkedDataRecord(TestcaseRecordInputStream.create(0x1051, data));
assertEquals( LinkedDataRecord.LINK_TYPE_VALUES, record.getLinkType());
assertEquals( LinkedDataRecord.REFERENCE_TYPE_WORKSHEET, record.getReferenceType());
assertEquals( 0, record.getOptions());
Area3DPtg ptgExpected = new Area3DPtg(0, 7936, 0, 0,
false, false, false, false, 0);
- Object ptgActual = record.getFormulaOfLink().getFormulaTokens().get(0);
+ Object ptgActual = record.getFormulaOfLink().getFormulaTokens()[0];
assertEquals(ptgExpected.toString(), ptgActual.toString());
assertEquals( data.length + 4, record.getRecordSize() );
record.setIndexNumberFmtRecord( (short)0 );
Area3DPtg ptg = new Area3DPtg(0, 7936, 0, 0,
false, false, false, false, 0);
- Stack s = new Stack();
- s.push(ptg);
LinkedDataFormulaField formulaOfLink = new LinkedDataFormulaField();
- formulaOfLink.setFormulaTokens(s);
+ formulaOfLink.setFormulaTokens(new Ptg[] { ptg, });
record.setFormulaOfLink(formulaOfLink );
byte [] recordBytes = record.serialize();
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
*
* @author Danny Mui (dmui at apache dot org)
*/
-public class TestNameRecord
- extends TestCase
-{
+public final class TestNameRecord extends TestCase {
/**
* Makes sure that additional name information is parsed properly such as menu/description
};
- NameRecord name = new NameRecord(new TestcaseRecordInputStream(NameRecord.sid, (short) examples.length, examples));
+ NameRecord name = new NameRecord(TestcaseRecordInputStream.create(NameRecord.sid, examples));
String description = name.getDescriptionText();
assertNotNull( description );
assertTrue( "text contains ALLWOR", description.indexOf( "ALLWOR" ) > 0 );
-
}
-
}
*
* @author Yegor Kozlov
*/
-public class TestNoteRecord
- extends TestCase
-{
+public final class TestNoteRecord extends TestCase {
private byte[] data = new byte[] {
0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x04, 0x1A, 0x00,
0x00, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x53, 0x6F,
public void testRead() {
- NoteRecord record = new NoteRecord(new TestcaseRecordInputStream(NoteRecord.sid, (short)data.length, data));
+ NoteRecord record = new NoteRecord(TestcaseRecordInputStream.create(NoteRecord.sid, data));
assertEquals(NoteRecord.sid, record.getSid());
assertEquals(6, record.getRow());
public void testRead() {
- NoteStructureSubRecord record = new NoteStructureSubRecord(new TestcaseRecordInputStream(NoteStructureSubRecord.sid, (short)data.length, data));
+ NoteStructureSubRecord record = new NoteStructureSubRecord(TestcaseRecordInputStream.create(NoteStructureSubRecord.sid, data));
assertEquals(NoteStructureSubRecord.sid, record.getSid());
assertEquals(data.length + 4, record.getRecordSize());
public void testLoad() {
- NumberFormatIndexRecord record = new NumberFormatIndexRecord(new TestcaseRecordInputStream((short)0x104e, (short)data.length, data));
+ NumberFormatIndexRecord record = new NumberFormatIndexRecord(TestcaseRecordInputStream.create(0x104e, data));
assertEquals( 5, record.getFormatIndex());
assertEquals( 6, record.getRecordSize() );
};
public void testLoad() {
- ObjRecord record = new ObjRecord(new TestcaseRecordInputStream(ObjRecord.sid, (short)recdata.length, recdata));
+ ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
assertEquals(28, record.getRecordSize() - 4);
}
public void testStore() {
- ObjRecord record = new ObjRecord(new TestcaseRecordInputStream(ObjRecord.sid, (short)recdata.length, recdata));
+ ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdata));
byte [] recordBytes = record.serialize();
assertEquals(28, recordBytes.length - 4);
byte [] bytes = new byte[recordBytes.length-4];
System.arraycopy(recordBytes, 4, bytes, 0, bytes.length);
- record = new ObjRecord(new TestcaseRecordInputStream(ObjRecord.sid, (short)bytes.length, bytes));
+ record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, bytes));
List subrecords = record.getSubRecords();
assertEquals( 2, subrecords.size() );
assertTrue( subrecords.get(0) instanceof CommonObjectDataSubRecord);
}
public void testReadWriteWithPadding_bug45133() {
- ObjRecord record = new ObjRecord(new TestcaseRecordInputStream(ObjRecord.sid, (short)recdataNeedingPadding.length, recdataNeedingPadding));
+ ObjRecord record = new ObjRecord(TestcaseRecordInputStream.create(ObjRecord.sid, recdataNeedingPadding));
if (record.getRecordSize() == 34) {
throw new AssertionFailedError("Identified bug 45133");
};
public void testLoad() {
- ObjectLinkRecord record = new ObjectLinkRecord(new TestcaseRecordInputStream((short)0x1027, (short)data.length, data));
+ ObjectLinkRecord record = new ObjectLinkRecord(TestcaseRecordInputStream.create(0x1027, data));
assertEquals( (short)3, record.getAnchorId());
assertEquals( (short)0x00, record.getLink1());
};
public void testLoad() {
- PaneRecord record = new PaneRecord(new TestcaseRecordInputStream((short)0x41, (short)data.length, data));
+ PaneRecord record = new PaneRecord(TestcaseRecordInputStream.create(0x41, data));
assertEquals( (short)1, record.getX());
assertEquals( (short)2, record.getY());
};
public void testLoad() {
- PlotAreaRecord record = new PlotAreaRecord(new TestcaseRecordInputStream((short)0x1035, (short)data.length, data));
+ PlotAreaRecord record = new PlotAreaRecord(TestcaseRecordInputStream.create(0x1035, data));
assertEquals( 4, record.getRecordSize() );
}
public void testLoad() {
- PlotGrowthRecord record = new PlotGrowthRecord(new TestcaseRecordInputStream((short)0x1064, (short)data.length, data));
+ PlotGrowthRecord record = new PlotGrowthRecord(TestcaseRecordInputStream.create(0x1064, data));
assertEquals( 65536, record.getHorizontalScale());
assertEquals( 65536, record.getVerticalScale());
0, 6, 5, 0, -2, 28, -51, 7, -55, 64, 0, 0, 6, 1, 0, 0
};
short size = 16;
- Record[] record = RecordFactory.createRecord(new TestcaseRecordInputStream(recType, size, data));
+ Record[] record = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));
assertEquals(BOFRecord.class.getName(),
record[ 0 ].getClass().getName());
{
0, 0
};
- record = RecordFactory.createRecord(new TestcaseRecordInputStream(recType, size, data));
+ record = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));
assertEquals(MMSRecord.class.getName(),
record[ 0 ].getClass().getName());
MMSRecord mmsRecord = ( MMSRecord ) record[ 0 ];
0, 0, 0, 0, 21, 0, 0, 0, 0, 0
};
short size = 10;
- Record[] record = RecordFactory.createRecord(new TestcaseRecordInputStream(recType, size, data));
+ Record[] record = RecordFactory.createRecord(TestcaseRecordInputStream.create(recType, data));
assertEquals(NumberRecord.class.getName(),
record[ 0 ].getClass().getName());
--- /dev/null
+/* ====================================================================
+ 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.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import org.apache.poi.util.HexRead;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link RecordInputStream}
+ *
+ * @author Josh Micich
+ */
+public final class TestRecordInputStream extends TestCase {
+
+ /**
+ * Data inspired by attachment 22626 of bug 45866<br/>
+ * A unicode string of 18 chars, with a continue record where the compression flag changes
+ */
+ private static final String HED_DUMP1 = ""
+ + "1A 59 00 8A 9E 8A " // 3 uncompressed unicode chars
+ + "3C 00 " // Continue sid
+ + "10 00 " // rec size 16 (1+15)
+ + "00" // next chunk is compressed
+ + "20 2D 20 4D 75 6C 74 69 6C 69 6E 67 75 61 6C " // 15 chars
+ ;
+ /**
+ * same string re-arranged
+ */
+ private static final String HED_DUMP2 = ""
+ // 15 chars at end of current record
+ + "4D 75 6C 74 69 6C 69 6E 67 75 61 6C 20 2D 20"
+ + "3C 00 " // Continue sid
+ + "07 00 " // rec size 7 (1+6)
+ + "01" // this bit uncompressed
+ + "1A 59 00 8A 9E 8A " // 3 uncompressed unicode chars
+ ;
+ public void testChangeOfCompressionFlag_bug25866() {
+ byte[] changingFlagSimpleData = HexRead.readFromString(""
+ + "AA AA " // fake SID
+ + "06 00 " // first rec len 6
+ + HED_DUMP1
+ );
+ RecordInputStream in = TestcaseRecordInputStream.create(changingFlagSimpleData);
+ String actual;
+ try {
+ actual = in.readUnicodeLEString(18);
+ } catch (IllegalArgumentException e) {
+ if ("compressByte in continue records must be 1 while reading unicode LE string".equals(e.getMessage())) {
+ throw new AssertionFailedError("Identified bug 45866");
+ }
+
+ throw e;
+ }
+ assertEquals("\u591A\u8A00\u8A9E - Multilingual", actual);
+ }
+
+ public void testChangeFromUnCompressedToCompressed() {
+ byte[] changingFlagSimpleData = HexRead.readFromString(""
+ + "AA AA " // fake SID
+ + "0F 00 " // first rec len 15
+ + HED_DUMP2
+ );
+ RecordInputStream in = TestcaseRecordInputStream.create(changingFlagSimpleData);
+ String actual = in.readCompressedUnicode(18);
+ assertEquals("Multilingual - \u591A\u8A00\u8A9E", actual);
+ }
+
+ public void testReadString() {
+ byte[] changingFlagFullData = HexRead.readFromString(""
+ + "AA AA " // fake SID
+ + "12 00 " // first rec len 18 (15 + next 3 bytes)
+ + "12 00 " // total chars 18
+ + "00 " // this bit compressed
+ + HED_DUMP2
+ );
+ RecordInputStream in = TestcaseRecordInputStream.create(changingFlagFullData);
+ String actual = in.readString();
+ assertEquals("Multilingual - \u591A\u8A00\u8A9E", actual);
+ }
+}
};
public void testLoad() {
- SCLRecord record = new SCLRecord(new TestcaseRecordInputStream((short)0xa0, (short)data.length, data));
+ SCLRecord record = new SCLRecord(TestcaseRecordInputStream.create(0xa0, data));
assertEquals( 3, record.getNumerator());
assertEquals( 4, record.getDenominator());
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class TestSSTDeserializer extends TestCase {
+ private static final int FAKE_SID = -5555;
-
- private byte[] joinArray(byte[] array1, byte[] array2) {
- byte[] bigArray = new byte[array1.length + array2.length];
- System.arraycopy(array1, 0, bigArray, 0, array1.length);
- System.arraycopy(array2, 0, bigArray, array1.length, array2.length);
- return bigArray;
+ private static byte[] concat(byte[] a, byte[] b) {
+ byte[] result = new byte[a.length + b.length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ System.arraycopy(b, 0, result, a.length, b.length);
+ return result;
}
- private static byte[] readSampleHexData(String sampleFileName, String sectionName) {
+ private static byte[] readSampleHexData(String sampleFileName, String sectionName, int recSid) {
InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleFileName);
+ byte[] data;
try {
- return HexRead.readData(is, sectionName);
+ data = HexRead.readData(is, sectionName);
} catch (IOException e) {
throw new RuntimeException(e);
}
+ return TestcaseRecordInputStream.mergeDataAndSid(recSid, data.length, data);
}
- public void testSpanRichTextToPlainText()
- throws Exception
- {
- byte[] header = readSampleHexData("richtextdata.txt", "header" );
- byte[] continueBytes = readSampleHexData("richtextdata.txt", "continue1" );
- continueBytes = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continueBytes.length, continueBytes);
- TestcaseRecordInputStream in = new TestcaseRecordInputStream((short)0, (short)header.length, joinArray(header, continueBytes));
+ public void testSpanRichTextToPlainText() {
+ byte[] header = readSampleHexData("richtextdata.txt", "header", FAKE_SID);
+ byte[] continueBytes = readSampleHexData("richtextdata.txt", "continue1", ContinueRecord.sid);
+ RecordInputStream in = TestcaseRecordInputStream.create(concat(header, continueBytes));
IntMapper strings = new IntMapper();
assertEquals( "At a dinner party orAt At At ", strings.get( 0 ) + "" );
}
- public void testContinuationWithNoOverlap()
- throws Exception
- {
- byte[] header = readSampleHexData("evencontinuation.txt", "header" );
- byte[] continueBytes = readSampleHexData("evencontinuation.txt", "continue1" );
- continueBytes = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continueBytes.length, continueBytes);
- TestcaseRecordInputStream in = new TestcaseRecordInputStream((short)0, (short)header.length, joinArray(header, continueBytes));
+ public void testContinuationWithNoOverlap() {
+ byte[] header = readSampleHexData("evencontinuation.txt", "header", FAKE_SID);
+ byte[] continueBytes = readSampleHexData("evencontinuation.txt", "continue1", ContinueRecord.sid);
+ RecordInputStream in = TestcaseRecordInputStream.create(concat(header, continueBytes));
IntMapper strings = new IntMapper();
SSTDeserializer deserializer = new SSTDeserializer( strings );
/**
* Strings can actually span across more than one continuation.
*/
- public void testStringAcross2Continuations()
- throws Exception
- {
- byte[] header = readSampleHexData("stringacross2continuations.txt", "header" );
- byte[] continue1 = readSampleHexData("stringacross2continuations.txt", "continue1" );
- continue1 = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continue1.length, continue1);
- byte[] continue2 = readSampleHexData("stringacross2continuations.txt", "continue2" );
- continue2 = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continue2.length, continue2);
+ public void testStringAcross2Continuations() {
+ byte[] header = readSampleHexData("stringacross2continuations.txt", "header", FAKE_SID);
+ byte[] continue1 = readSampleHexData("stringacross2continuations.txt", "continue1", ContinueRecord.sid);
+ byte[] continue2 = readSampleHexData("stringacross2continuations.txt", "continue2", ContinueRecord.sid);
- byte[] bytes = joinArray(header, continue1);
- bytes = joinArray(bytes, continue2);
- TestcaseRecordInputStream in = new TestcaseRecordInputStream((short)0, (short)header.length, bytes);
+ RecordInputStream in = TestcaseRecordInputStream.create(concat(header, concat(continue1, continue2)));
IntMapper strings = new IntMapper();
SSTDeserializer deserializer = new SSTDeserializer( strings );
}
public void testExtendedStrings() {
- byte[] header = readSampleHexData("extendedtextstrings.txt", "rich-header" );
- byte[] continueBytes = readSampleHexData("extendedtextstrings.txt", "rich-continue1" );
- continueBytes = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continueBytes.length, continueBytes);
- TestcaseRecordInputStream in = new TestcaseRecordInputStream((short)0, (short)header.length, joinArray(header, continueBytes));
+ byte[] header = readSampleHexData("extendedtextstrings.txt", "rich-header", FAKE_SID);
+ byte[] continueBytes = readSampleHexData("extendedtextstrings.txt", "rich-continue1", ContinueRecord.sid);
+ RecordInputStream in = TestcaseRecordInputStream.create(concat(header, continueBytes));
IntMapper strings = new IntMapper();
SSTDeserializer deserializer = new SSTDeserializer( strings );
assertEquals( "At a dinner party orAt At At ", strings.get( 0 ) + "" );
- header = readSampleHexData("extendedtextstrings.txt", "norich-header" );
- continueBytes = readSampleHexData("extendedtextstrings.txt", "norich-continue1" );
- continueBytes = TestcaseRecordInputStream.mergeDataAndSid(ContinueRecord.sid, (short)continueBytes.length, continueBytes);
- in = new TestcaseRecordInputStream((short)0, (short)header.length, joinArray(header, continueBytes));
+ header = readSampleHexData("extendedtextstrings.txt", "norich-header", FAKE_SID);
+ continueBytes = readSampleHexData("extendedtextstrings.txt", "norich-continue1", ContinueRecord.sid);
+ in = TestcaseRecordInputStream.create(concat(header, continueBytes));
strings = new IntMapper();
deserializer = new SSTDeserializer( strings );
};
public void testLoad() {
- SeriesChartGroupIndexRecord record = new SeriesChartGroupIndexRecord(new TestcaseRecordInputStream((short)0x1045, (short)data.length, data));
+ SeriesChartGroupIndexRecord record = new SeriesChartGroupIndexRecord(TestcaseRecordInputStream.create(0x1045, data));
assertEquals( 0, record.getChartGroupIndex());
assertEquals( 6, record.getRecordSize() );
};
public void testLoad() {
- SeriesIndexRecord record = new SeriesIndexRecord(new TestcaseRecordInputStream((short)0x1065, (short)data.length, data));
+ SeriesIndexRecord record = new SeriesIndexRecord(TestcaseRecordInputStream.create(0x1065, data));
assertEquals( (short)3, record.getIndex());
assertEquals( 6, record.getRecordSize() );
};
public void testLoad() {
- SeriesLabelsRecord record = new SeriesLabelsRecord(new TestcaseRecordInputStream((short)0x100c, (short)data.length, data));
+ SeriesLabelsRecord record = new SeriesLabelsRecord(TestcaseRecordInputStream.create(0x100c, data));
assertEquals( 3, record.getFormatFlags());
assertEquals( true, record.isShowActual() );
assertEquals( true, record.isShowPercent() );
public void testLoad() {
- SeriesListRecord record = new SeriesListRecord(new TestcaseRecordInputStream((short)0x1016, (short)data.length, data));
+ SeriesListRecord record = new SeriesListRecord(TestcaseRecordInputStream.create(0x1016, data));
assertEquals( (short)0x2001, record.getSeriesNumbers()[0]);
assertEquals( (short)0xf0ff, record.getSeriesNumbers()[1]);
assertEquals( 2, record.getSeriesNumbers().length);
public void testLoad() {
- SeriesRecord record = new SeriesRecord(new TestcaseRecordInputStream((short)0x1003, (short)data.length, data));
+ SeriesRecord record = new SeriesRecord(TestcaseRecordInputStream.create(0x1003, data));
assertEquals( SeriesRecord.CATEGORY_DATA_TYPE_NUMERIC, record.getCategoryDataType());
assertEquals( SeriesRecord.VALUES_DATA_TYPE_NUMERIC, record.getValuesDataType());
assertEquals( 27, record.getNumCategories());
};
public void testLoad() {
- SeriesTextRecord record = new SeriesTextRecord(new TestcaseRecordInputStream((short)0x100d, (short)data.length, data));
+ SeriesTextRecord record = new SeriesTextRecord(TestcaseRecordInputStream.create(0x100d, data));
assertEquals( (short)0, record.getId());
assertEquals( (byte)0x0C, record.getTextLength());
};
public void testLoad() {
- SeriesToChartGroupRecord record = new SeriesToChartGroupRecord(new TestcaseRecordInputStream((short)0x1045, (short)data.length, data));
+ SeriesToChartGroupRecord record = new SeriesToChartGroupRecord(TestcaseRecordInputStream.create(0x1045, data));
assertEquals( 0x0, record.getChartGroupIndex());
assertEquals( 0x6, record.getRecordSize() );
*/
public void testConvertSharedFormulasOperandClasses_bug45123() {
- TestcaseRecordInputStream in = new TestcaseRecordInputStream(0, SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
+ RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
int encodedLen = in.readUShort();
Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in);
};
public void testLoad() {
- SheetPropertiesRecord record = new SheetPropertiesRecord(new TestcaseRecordInputStream((short)0x1044, (short)data.length, data));
+ SheetPropertiesRecord record = new SheetPropertiesRecord(TestcaseRecordInputStream.create(0x1044, data));
assertEquals( 10, record.getFlags());
assertEquals( false, record.isChartTypeManuallyFormatted() );
assertEquals( true, record.isPlotVisibleOnly() );
*
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class TestStringRecord extends TestCase {
+public final class TestStringRecord extends TestCase {
byte[] data = new byte[] {
(byte)0x0B,(byte)0x00, // length
(byte)0x00, // option
public void testLoad() {
- StringRecord record = new StringRecord(new TestcaseRecordInputStream((short)0x207, (short)data.length, data));
+ StringRecord record = new StringRecord(TestcaseRecordInputStream.create(0x207, data));
assertEquals( "Fahrzeugtyp", record.getString());
assertEquals( 18, record.getRecordSize() );
*/
public void testLoadIR() {
- SupBookRecord record = new SupBookRecord(new TestcaseRecordInputStream((short)0x01AE, dataIR));
+ SupBookRecord record = new SupBookRecord(TestcaseRecordInputStream.create(0x01AE, dataIR));
assertTrue( record.isInternalReferences() ); //expected flag
assertEquals( 0x4, record.getNumberOfSheets() ); //expected # of sheets
*/
public void testLoadER() {
- SupBookRecord record = new SupBookRecord(new TestcaseRecordInputStream((short)0x01AE, dataER));
+ SupBookRecord record = new SupBookRecord(TestcaseRecordInputStream.create(0x01AE, dataER));
assertTrue( record.isExternalReferences() ); //expected flag
assertEquals( 0x2, record.getNumberOfSheets() ); //expected # of sheets
*/
public void testLoadAIF() {
- SupBookRecord record = new SupBookRecord(new TestcaseRecordInputStream((short)0x01AE, dataAIF));
+ SupBookRecord record = new SupBookRecord(TestcaseRecordInputStream.create(0x01AE, dataAIF));
assertTrue( record.isAddInFunctions() ); //expected flag
assertEquals( 0x1, record.getNumberOfSheets() ); //expected # of sheets
assertEquals( 8, record.getRecordSize() ); //sid+size+data
public void testLoad() {
- TableRecord record = new TableRecord(new TestcaseRecordInputStream((short)0x236, (short)data.length, data));
+ TableRecord record = new TableRecord(TestcaseRecordInputStream.create(0x236, data));
CellRangeAddress8Bit range = record.getRange();
assertEquals(3, range.getFirstRow());
package org.apache.poi.hssf.record;
+import java.io.ByteArrayInputStream;
+
+import org.apache.poi.hssf.usermodel.HSSFRichTextString;
+import org.apache.poi.util.HexRead;
+
import junit.framework.TestCase;
/**
* class works correctly. Test data taken directly from a real
* Excel file.
*
-
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class TestTextObjectBaseRecord extends TestCase {
- byte[] data = new byte[] {
- 0x44, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00,
- };
+public final class TestTextObjectBaseRecord extends TestCase {
+ /** data for one TXO rec and two continue recs */
+ private static final byte[] data = HexRead.readFromString(
+ "B6 01 " + // TextObjectRecord.sid
+ "12 00 " + // size 18
+ "44 02 02 00 00 00 00 00" +
+ "00 00 " +
+ "02 00 " + // strLen 2
+ "10 00 " + // 16 bytes for 2 format runs
+ "00 00" +
+ "00 00 " +
+ "3C 00 " + // ContinueRecord.sid
+ "05 00 " + // size 5
+ "01 " + // unicode uncompressed
+ "41 00 42 00 " + // 'AB'
+ "3C 00 " + // ContinueRecord.sid
+ "10 00 " + // size 16
+ "00 00 18 00 00 00 00 00 " +
+ "02 00 00 00 00 00 00 00 "
+ );
+
public void testLoad() {
- TextObjectBaseRecord record = new TextObjectBaseRecord(new TestcaseRecordInputStream((short)0x1B6, (short)data.length, data));
-
-
-// assertEquals( (short), record.getOptions());
- assertEquals( false, record.isReserved1() );
- assertEquals( TextObjectBaseRecord.HORIZONTAL_TEXT_ALIGNMENT_CENTERED, record.getHorizontalTextAlignment() );
- assertEquals( TextObjectBaseRecord.VERTICAL_TEXT_ALIGNMENT_JUSTIFY, record.getVerticalTextAlignment() );
- assertEquals( 0, record.getReserved2() );
- assertEquals( true, record.isTextLocked() );
- assertEquals( 0, record.getReserved3() );
- assertEquals( TextObjectBaseRecord.TEXT_ORIENTATION_ROT_RIGHT, record.getTextOrientation());
- assertEquals( 0, record.getReserved4());
- assertEquals( 0, record.getReserved5());
- assertEquals( 0, record.getReserved6());
- assertEquals( 2, record.getTextLength());
- assertEquals( 2, record.getFormattingRunLength());
- assertEquals( 0, record.getReserved7());
-
-
- assertEquals( 22, record.getRecordSize() );
+ RecordInputStream in = new RecordInputStream(new ByteArrayInputStream(data));
+ in.nextRecord();
+ TextObjectRecord record = new TextObjectRecord(in);
+
+
+ assertEquals(TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_CENTERED, record.getHorizontalTextAlignment());
+ assertEquals(TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_JUSTIFY, record.getVerticalTextAlignment());
+ assertEquals(true, record.isTextLocked());
+ assertEquals(TextObjectRecord.TEXT_ORIENTATION_ROT_RIGHT, record.getTextOrientation());
+
+ assertEquals(51, record.getRecordSize() );
}
public void testStore()
{
- TextObjectBaseRecord record = new TextObjectBaseRecord();
+ TextObjectRecord record = new TextObjectRecord();
+ HSSFRichTextString str = new HSSFRichTextString("AB");
+ str.applyFont(0, 2, (short)0x0018);
+ str.applyFont(2, 2, (short)0x0320);
-// record.setOptions( (short) 0x0000);
- record.setReserved1( false );
- record.setHorizontalTextAlignment( TextObjectBaseRecord.HORIZONTAL_TEXT_ALIGNMENT_CENTERED );
- record.setVerticalTextAlignment( TextObjectBaseRecord.VERTICAL_TEXT_ALIGNMENT_JUSTIFY );
- record.setReserved2( (short)0 );
- record.setTextLocked( true );
- record.setReserved3( (short)0 );
- record.setTextOrientation( TextObjectBaseRecord.TEXT_ORIENTATION_ROT_RIGHT );
- record.setReserved4( (short)0 );
- record.setReserved5( (short)0 );
- record.setReserved6( (short)0 );
- record.setTextLength( (short)2 );
- record.setFormattingRunLength( (short)2 );
- record.setReserved7( 0 );
+ record.setHorizontalTextAlignment(TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_CENTERED);
+ record.setVerticalTextAlignment(TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_JUSTIFY);
+ record.setTextLocked(true);
+ record.setTextOrientation(TextObjectRecord.TEXT_ORIENTATION_ROT_RIGHT);
+ record.setStr(str);
byte [] recordBytes = record.serialize();
- assertEquals(recordBytes.length - 4, data.length);
+ assertEquals(recordBytes.length, data.length);
for (int i = 0; i < data.length; i++)
- assertEquals("At offset " + i, data[i], recordBytes[i+4]);
+ assertEquals("At offset " + i, data[i], recordBytes[i]);
}
}
\r
import junit.framework.TestCase;\r
\r
+import org.apache.poi.hssf.record.formula.Ptg;\r
+import org.apache.poi.hssf.record.formula.RefPtg;\r
import org.apache.poi.hssf.usermodel.HSSFRichTextString;\r
+import org.apache.poi.util.HexRead;\r
+import org.apache.poi.util.LittleEndian;\r
\r
/**\r
* Tests that serialization and deserialization of the TextObjectRecord .\r
*/\r
public final class TestTextObjectRecord extends TestCase {\r
\r
- byte[] data = {(byte)0xB6, 0x01, 0x12, 0x00, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x3C, 0x00, 0x1B, 0x00, 0x01, 0x48, 0x00, 0x65, 0x00, 0x6C,\r
- 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x57, 0x00,\r
- 0x6F, 0x00, 0x72, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x21, 0x00, 0x3C,\r
- 0x00, 0x08, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };\r
+ private static final byte[] simpleData = HexRead.readFromString(\r
+ "B6 01 12 00 " +\r
+ "12 02 00 00 00 00 00 00" +\r
+ "00 00 0D 00 08 00 00 00" +\r
+ "00 00 " +\r
+ "3C 00 1B 00 " +\r
+ "01 48 00 65 00 6C 00 6C 00 6F 00 " +\r
+ "2C 00 20 00 57 00 6F 00 72 00 6C " +\r
+ "00 64 00 21 00 " + \r
+ "3C 00 08 " +\r
+ "00 0D 00 00 00 00 00 00 00"\r
+ );\r
\r
\r
public void testRead() {\r
\r
- RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(data));\r
+ RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(simpleData));\r
is.nextRecord();\r
TextObjectRecord record = new TextObjectRecord(is);\r
\r
assertEquals(TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED, record.getHorizontalTextAlignment());\r
assertEquals(TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_TOP, record.getVerticalTextAlignment());\r
assertEquals(TextObjectRecord.TEXT_ORIENTATION_NONE, record.getTextOrientation());\r
- assertEquals(0, record.getReserved7());\r
assertEquals("Hello, World!", record.getStr().getString());\r
-\r
}\r
\r
- public void testWrite()\r
- {\r
+ public void testWrite() {\r
HSSFRichTextString str = new HSSFRichTextString("Hello, World!");\r
\r
TextObjectRecord record = new TextObjectRecord();\r
- int frLength = ( str.numFormattingRuns() + 1 ) * 8;\r
- record.setFormattingRunLength( (short) frLength );\r
- record.setTextLength( (short) str.length() );\r
- record.setStr( str );\r
+ record.setStr(str);\r
record.setHorizontalTextAlignment( TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED );\r
record.setVerticalTextAlignment( TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_TOP );\r
record.setTextLocked( true );\r
record.setTextOrientation( TextObjectRecord.TEXT_ORIENTATION_NONE );\r
- record.setReserved7( 0 );\r
\r
byte [] ser = record.serialize();\r
- //assertEquals(ser.length , data.length);\r
+ assertEquals(ser.length , simpleData.length);\r
\r
- //assertTrue(Arrays.equals(data, ser));\r
+ assertTrue(Arrays.equals(simpleData, ser));\r
\r
//read again\r
- RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(data));\r
+ RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(simpleData));\r
is.nextRecord();\r
record = new TextObjectRecord(is);\r
+ }\r
+\r
+ /**\r
+ * Zero {@link ContinueRecord}s follow a {@link TextObjectRecord} if the text is empty\r
+ */\r
+ public void testWriteEmpty() {\r
+ HSSFRichTextString str = new HSSFRichTextString("");\r
+\r
+ TextObjectRecord record = new TextObjectRecord();\r
+ record.setStr(str);\r
\r
+ byte [] ser = record.serialize();\r
+ \r
+ int formatDataLen = LittleEndian.getUShort(ser, 16);\r
+ assertEquals("formatDataLength", 0, formatDataLen);\r
+\r
+ assertEquals(22, ser.length); // just the TXO record\r
+ \r
+ //read again\r
+ RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(ser));\r
+ is.nextRecord();\r
+ record = new TextObjectRecord(is);\r
+ assertEquals(0, record.getStr().length());\r
}\r
\r
/**\r
HSSFRichTextString str = new HSSFRichTextString(buff.toString());\r
\r
TextObjectRecord obj = new TextObjectRecord();\r
- int frLength = ( str.numFormattingRuns() + 1 ) * 8;\r
- obj.setFormattingRunLength( (short) frLength );\r
- obj.setTextLength( (short) str.length() );\r
- obj.setStr( str );\r
+ obj.setStr(str);\r
\r
byte [] data = obj.serialize();\r
RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(data));\r
HSSFRichTextString str = new HSSFRichTextString(text);\r
\r
TextObjectRecord obj = new TextObjectRecord();\r
- int frLength = ( str.numFormattingRuns() + 1 ) * 8;\r
- obj.setFormattingRunLength( (short) frLength );\r
- obj.setTextLength( (short) str.length() );\r
- obj.setReserved1(true);\r
- obj.setReserved2((short)2);\r
- obj.setReserved3((short)3);\r
- obj.setReserved4((short)4);\r
- obj.setReserved5((short)5);\r
- obj.setReserved6((short)6);\r
- obj.setReserved7((short)7);\r
obj.setStr( str );\r
\r
\r
TextObjectRecord cloned = (TextObjectRecord)obj.clone();\r
- assertEquals(obj.getReserved2(), cloned.getReserved2());\r
- assertEquals(obj.getReserved3(), cloned.getReserved3());\r
- assertEquals(obj.getReserved4(), cloned.getReserved4());\r
- assertEquals(obj.getReserved5(), cloned.getReserved5());\r
- assertEquals(obj.getReserved6(), cloned.getReserved6());\r
- assertEquals(obj.getReserved7(), cloned.getReserved7());\r
assertEquals(obj.getRecordSize(), cloned.getRecordSize());\r
- assertEquals(obj.getOptions(), cloned.getOptions());\r
assertEquals(obj.getHorizontalTextAlignment(), cloned.getHorizontalTextAlignment());\r
- assertEquals(obj.getFormattingRunLength(), cloned.getFormattingRunLength());\r
assertEquals(obj.getStr().getString(), cloned.getStr().getString());\r
\r
//finally check that the serialized data is the same\r
byte[] cln = cloned.serialize();\r
assertTrue(Arrays.equals(src, cln));\r
}\r
+ \r
+ /** similar to {@link #simpleData} but with link formula at end of TXO rec*/ \r
+ private static final byte[] linkData = HexRead.readFromString(\r
+ "B6 01 " + // TextObjectRecord.sid\r
+ "1E 00 " + // size 18\r
+ "44 02 02 00 00 00 00 00" +\r
+ "00 00 " +\r
+ "02 00 " + // strLen 2\r
+ "10 00 " + // 16 bytes for 2 format runs\r
+ "00 00 00 00 " +\r
+\r
+ "05 00 " + // formula size\r
+ "D4 F0 8A 03 " + // unknownInt\r
+ "24 01 00 13 C0 " + //tRef(T2)\r
+ "13 " + // ??\r
+\r
+ "3C 00 " + // ContinueRecord.sid\r
+ "05 00 " + // size 5\r
+ "01 " + // unicode uncompressed\r
+ "41 00 42 00 " + // 'AB'\r
+ "3C 00 " + // ContinueRecord.sid\r
+ "10 00 " + // size 16 \r
+ "00 00 18 00 00 00 00 00 " +\r
+ "02 00 00 00 00 00 00 00 " \r
+ );\r
+ \r
+ \r
+ public void testLinkFormula() {\r
+ RecordInputStream is = new RecordInputStream(new ByteArrayInputStream(linkData));\r
+ is.nextRecord();\r
+ TextObjectRecord rec = new TextObjectRecord(is);\r
+ \r
+ Ptg ptg = rec.getLinkRefPtg();\r
+ assertNotNull(ptg);\r
+ assertEquals(RefPtg.class, ptg.getClass());\r
+ RefPtg rptg = (RefPtg) ptg;\r
+ assertEquals("T2", rptg.toFormulaString());\r
+\r
+ byte [] data2 = rec.serialize();\r
+ assertEquals(linkData.length, data2.length);\r
+ assertTrue(Arrays.equals(linkData, data2));\r
+ }\r
+ \r
}\r
*
* @author Glen Stampoultzis (glens at apache.org)
*/
-public class TestTextRecord extends TestCase {
+public final class TestTextRecord extends TestCase {
byte[] data = new byte[] {
(byte)0x02, // horiz align
(byte)0x02, // vert align
public void testLoad() {
- TextRecord record = new TextRecord(new TestcaseRecordInputStream((short)0x1025, (short)data.length, data));
+ TextRecord record = new TextRecord(TestcaseRecordInputStream.create(0x1025, data));
assertEquals( TextRecord.HORIZONTAL_ALIGNMENT_CENTER, record.getHorizontalAlignment());
assertEquals( TextRecord.VERTICAL_ALIGNMENT_CENTER, record.getVerticalAlignment());
assertEquals( TextRecord.DISPLAY_MODE_TRANSPARENT, record.getDisplayMode());
};
public void testLoad() {
- TickRecord record = new TickRecord(new TestcaseRecordInputStream((short)0x101e, (short)data.length, data));
+ TickRecord record = new TickRecord(TestcaseRecordInputStream.create(0x101e, data));
assertEquals( (byte)2, record.getMajorTickType());
assertEquals( (byte)0, record.getMinorTickType());
assertEquals( (byte)3, record.getLabelPosition());
-
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
package org.apache.poi.hssf.record;
+import org.apache.poi.util.HexRead;
+
import junit.framework.TestCase;
/**
*
* @author Jason Height (jheight at apache.org)
*/
-public class TestUnicodeString
- extends TestCase
-{
+public final class TestUnicodeString extends TestCase {
- public TestUnicodeString( String s )
- {
- super( s );
- }
- public void testSmallStringSize()
- throws Exception
- {
+ public void testSmallStringSize() {
//Test a basic string
UnicodeString s = makeUnicodeString("Test");
UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
assertEquals(30, stats.recordSize);
}
- public void testPerfectStringSize()
- throws Exception
- {
+ public void testPerfectStringSize() {
//Test a basic string
UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1);
UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
assertEquals(SSTRecord.MAX_RECORD_SIZE-1, stats.recordSize);
}
- public void testPerfectRichStringSize()
- throws Exception
- {
+ public void testPerfectRichStringSize() {
//Test a rich text string
UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1-8-2);
s.addFormatRun(new UnicodeString.FormatRun((short)1,(short)0));
assertEquals(SSTRecord.MAX_RECORD_SIZE-1, stats.recordSize);
}
- public void testContinuedStringSize() throws Exception {
+ public void testContinuedStringSize() {
//Test a basic string
UnicodeString s = makeUnicodeString(SSTRecord.MAX_RECORD_SIZE-2-1+20);
UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
}
/** Tests that a string size calculation that fits neatly in two records, the second being a continue*/
- public void testPerfectContinuedStringSize() throws Exception {
+ public void testPerfectContinuedStringSize() {
//Test a basic string
int strSize = SSTRecord.MAX_RECORD_SIZE*2;
//String overhead
- private UnicodeString makeUnicodeString( String s )
+ private static UnicodeString makeUnicodeString( String s )
{
UnicodeString st = new UnicodeString(s);
st.setOptionFlags((byte)0);
return st;
}
- private UnicodeString makeUnicodeString( int numChars) {
+ private static UnicodeString makeUnicodeString( int numChars) {
StringBuffer b = new StringBuffer(numChars);
for (int i=0;i<numChars;i++) {
b.append(i%10);
}
return makeUnicodeString(b.toString());
}
-
}
public void testLoad() {
- UnitsRecord record = new UnitsRecord(new TestcaseRecordInputStream((short)0x1001, (short)data.length, data));
+ UnitsRecord record = new UnitsRecord(TestcaseRecordInputStream.create(0x1001, data));
assertEquals( 0, record.getUnits());
assertEquals( 6, record.getRecordSize() );
public void testLoad() {
- ValueRangeRecord record = new ValueRangeRecord(new TestcaseRecordInputStream((short)0x101f, (short)data.length, data));
+ ValueRangeRecord record = new ValueRangeRecord(TestcaseRecordInputStream.create(0x101f, data));
assertEquals( 0.0, record.getMinimumAxisValue(), 0.001);
assertEquals( 0.0, record.getMaximumAxisValue(), 0.001);
assertEquals( 0.0, record.getMajorIncrement(), 0.001);
package org.apache.poi.hssf.record;
import java.io.ByteArrayInputStream;
+import java.io.InputStream;
import junit.framework.Assert;
*
* @author Jason Height (jheight at apache.org)
*/
-public class TestcaseRecordInputStream
- extends RecordInputStream
-{
+public final class TestcaseRecordInputStream {
+
+ private TestcaseRecordInputStream() {
+ // no instances of this class
+ }
+
+ /**
+ * Prepends a mock record identifier to the supplied data and opens a record input stream
+ */
+ public static RecordInputStream createWithFakeSid(byte[] data) {
+ return create(-5555, data);
+
+ }
+ public static RecordInputStream create(int sid, byte[] data) {
+ return create(mergeDataAndSid(sid, data.length, data));
+ }
+ /**
+ * First 4 bytes of <tt>data</tt> are assumed to be record identifier and length. The supplied
+ * <tt>data</tt> can contain multiple records (sequentially encoded in the same way)
+ */
+ public static RecordInputStream create(byte[] data) {
+ InputStream is = new ByteArrayInputStream(data);
+ RecordInputStream result = new RecordInputStream(is);
+ result.nextRecord();
+ return result;
+ }
+
/**
* Convenience constructor
*/
- public TestcaseRecordInputStream(int sid, byte[] data)
- {
- super(new ByteArrayInputStream(mergeDataAndSid((short)sid, (short)data.length, data)));
- nextRecord();
- }
- public TestcaseRecordInputStream(short sid, short length, byte[] data)
- {
- super(new ByteArrayInputStream(mergeDataAndSid(sid, length, data)));
- nextRecord();
- }
+// public TestcaseRecordInputStream(int sid, byte[] data)
+// {
+// super(new ByteArrayInputStream(mergeDataAndSid(sid, data.length, data)));
+// nextRecord();
+// }
+// public TestcaseRecordInputStream(short sid, short length, byte[] data)
+// {
+// super(new ByteArrayInputStream(mergeDataAndSid(sid, length, data)));
+// nextRecord();
+// }
- public static byte[] mergeDataAndSid(short sid, short length, byte[] data) {
+ public static byte[] mergeDataAndSid(int sid, int length, byte[] data) {
byte[] result = new byte[data.length + 4];
- LittleEndian.putShort(result, 0, sid);
- LittleEndian.putShort(result, 2, length);
+ LittleEndian.putUShort(result, 0, sid);
+ LittleEndian.putUShort(result, 2, length);
System.arraycopy(data, 0, result, 4, data.length);
return result;
}
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.record.UnicodeString;
import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+import org.apache.poi.util.HexRead;
/**
*
* @author Josh Micich
new UnicodeString("Sample text"),
ErrorConstant.valueOf(HSSFErrorConstants.ERROR_DIV_0),
};
- private static final byte[] SAMPLE_ENCODING = {
- 4, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, -102, -103, -103, -103, -103, -103, -15, 63,
- 2, 11, 0, 0, 83, 97, 109, 112, 108, 101, 32, 116, 101, 120, 116,
- 16, 7, 0, 0, 0, 0, 0, 0, 0,
- };
+ private static final byte[] SAMPLE_ENCODING = HexRead.readFromString(
+ "04 01 00 00 00 00 00 00 00 " +
+ "00 00 00 00 00 00 00 00 00 " +
+ "01 9A 99 99 99 99 99 F1 3F " +
+ "02 0B 00 00 53 61 6D 70 6C 65 20 74 65 78 74 " +
+ "10 07 00 00 00 00 00 00 00");
public void testGetEncodedSize() {
int actual = ConstantValueParser.getEncodedSize(SAMPLE_VALUES);
}
}
public void testDecode() {
- RecordInputStream in = new TestcaseRecordInputStream(0x0001, SAMPLE_ENCODING);
+ RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(SAMPLE_ENCODING);
Object[] values = ConstantValueParser.parse(in, 4);
for (int i = 0; i < values.length; i++) {
*/
public void testReadWriteTokenValueBytes() {
- ArrayPtg ptg = new ArrayPtg(new TestcaseRecordInputStream(ArrayPtg.sid, ENCODED_PTG_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
- ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
Object[][] values = ptg.getTokenArrayValues();
* Excel stores array elements column by column. This test makes sure POI does the same.
*/
public void testElementOrdering() {
- ArrayPtg ptg = new ArrayPtg(new TestcaseRecordInputStream(ArrayPtg.sid, ENCODED_PTG_DATA));
- ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
assertEquals(3, ptg.getColumnCount());
assertEquals(2, ptg.getRowCount());
}
public void testToFormulaString() {
- ArrayPtg ptg = new ArrayPtg(new TestcaseRecordInputStream(ArrayPtg.sid, ENCODED_PTG_DATA));
+ ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createWithFakeSid(ENCODED_PTG_DATA));
- ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
+ ptg.readTokenValues(TestcaseRecordInputStream.createWithFakeSid(ENCODED_CONSTANT_DATA));
String actualFormula;
try {
// Force encoded operand class for tArray
fullData[0] = (byte) (ArrayPtg.sid + operandClass);
- RecordInputStream in = new TestcaseRecordInputStream(ArrayPtg.sid, fullData);
+ RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(fullData);
Ptg[] ptgs = Ptg.readTokens(ENCODED_PTG_DATA.length, in);
assertEquals(1, ptgs.length);
0,
};
- FuncPtg ptg = new FuncPtg( new TestcaseRecordInputStream((short)0, (short)fakeData.length, fakeData) );
+ FuncPtg ptg = new FuncPtg(TestcaseRecordInputStream.createWithFakeSid(fakeData) );
assertEquals( "Len formula index is not 32(20H)", 0x20, ptg.getFunctionIndex() );
assertEquals( "Number of operands in the len formula", 1, ptg.getNumberOfOperands() );
assertEquals( "Function Name", "LEN", ptg.getName() );
package org.apache.poi.hssf.record.formula;
import java.util.Arrays;
-import java.util.Stack;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
0x2C, 33, 44, 55, 66,
};
public void testReadWrite_tRefN_bug45091() {
- TestcaseRecordInputStream in = new TestcaseRecordInputStream(-1, tRefN_data);
- Stack ptgs = Ptg.createParsedExpressionTokens((short)tRefN_data.length, in);
+ RecordInputStream in = TestcaseRecordInputStream.createWithFakeSid(tRefN_data);
+ Ptg[] ptgs = Ptg.readTokens(tRefN_data.length, in);
byte[] outData = new byte[5];
- Ptg.serializePtgStack(ptgs, outData, 0);
+ Ptg.serializePtgs(ptgs, outData, 0);
if (outData[0] == 0x24) {
throw new AssertionFailedError("Identified bug 45091");
}