summaryrefslogtreecommitdiff
path: root/xmerge/source/pexcel/java/org/openoffice/xmerge
diff options
context:
space:
mode:
Diffstat (limited to 'xmerge/source/pexcel/java/org/openoffice/xmerge')
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java113
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java130
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java67
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java438
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java289
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java129
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java130
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html43
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java61
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java116
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java115
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java125
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java136
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java136
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java107
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java157
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java94
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java96
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java226
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java70
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java384
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java120
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java286
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java257
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java139
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java93
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java218
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java138
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java142
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java124
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java41
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java115
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java154
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java539
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java319
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java271
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java152
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java561
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java41
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java204
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java62
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java73
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java42
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java85
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java81
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java151
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java203
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java497
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java559
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java118
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java40
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html42
-rw-r--r--xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html47
53 files changed, 9076 insertions, 0 deletions
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java
new file mode 100644
index 000000000000..c39b95a173ad
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java
@@ -0,0 +1,113 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+
+
+/**
+ * <p>Pocket Excel implementation of <code>ConverterCapabilities</code> for
+ * the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.pexcel.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>Used with StarCalc SXC to/from Pocket Excel conversions. The
+ * <code>ConverterCapibilies</code> specify which &quot;Office&quot;
+ * <code>Document</code> tags and attributes are supported on the
+ * &quot;Device&quot; <code>Document</code> format.</p>
+ */
+public final class ConverterCapabilitiesImpl
+ implements ConverterCapabilities {
+
+ public boolean canConvertTag(String tag) {
+
+ if (OfficeConstants.TAG_OFFICE_BODY.equals(tag))
+ return true;
+ else if (OfficeConstants.TAG_PARAGRAPH.equals(tag))
+ return true;
+ else if (OfficeConstants.TAG_TABLE.equals(tag))
+ return true;
+ else if (OfficeConstants.TAG_TABLE_ROW.equals(tag))
+ return true;
+ else if (OfficeConstants.TAG_TABLE_COLUMN.equals(tag))
+ return false;
+ // TODO - we currently do not handle the table column tag
+ else if (OfficeConstants.TAG_TABLE_SCENARIO.equals(tag))
+ return false;
+ // TODO - we currently do not handle the table scenario tag
+ else if (OfficeConstants.TAG_TABLE_CELL.equals(tag))
+ return true;
+
+ return false;
+ }
+
+ public boolean canConvertAttribute(String tag,
+ String attribute) {
+
+ if (OfficeConstants.TAG_TABLE.equals(tag)) {
+
+ if (OfficeConstants.ATTRIBUTE_TABLE_NAME.equals(attribute))
+ return true;
+
+ } else if (OfficeConstants.TAG_TABLE_CELL.equals(tag)) {
+
+ if (OfficeConstants.ATTRIBUTE_TABLE_VALUE_TYPE.equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_FORMULA.
+ equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_VALUE.equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_BOOLEAN_VALUE.
+ equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_CURRENCY.
+ equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_TIME_VALUE.
+ equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_DATE_VALUE.
+ equals(attribute))
+ return true;
+ else if (OfficeConstants.ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED.
+ equals(attribute))
+ return true;
+
+ } else if (OfficeConstants.TAG_TABLE_ROW.equals(tag)) {
+
+ if (OfficeConstants.ATTRIBUTE_TABLE_NUM_ROWS_REPEATED.
+ equals(attribute))
+ return true;
+ }
+
+ return false;
+ }
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java
new file mode 100644
index 000000000000..3b45b2bf680c
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.DocumentSerializer;
+import org.openoffice.xmerge.DocumentSerializerFactory;
+import org.openoffice.xmerge.DocumentDeserializer;
+import org.openoffice.xmerge.DocumentDeserializerFactory;
+import org.openoffice.xmerge.DocumentMerger;
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.sxc.DocumentMergerImpl;
+import org.openoffice.xmerge.converter.xml.sxc.SxcPluginFactory;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.util.registry.ConverterInfo;
+
+/**
+ * <p>Pocket Excel implementation of the <code>PluginFactory</code>.
+ * This encapsulates conversion of StarCalc XML format to and from
+ * Pocket Excel format.</p>
+ *
+ * <p>The superclass produces a particular
+ * {@link org.openoffice.xmerge.Document Document}
+ * object, i.e. {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcDocument
+ * SxcDocument} that the converters in this class works with. Thus,
+ * this class only implements the methods that produces the converters,
+ * i.e. {@link
+ * org.openoffice.xmerge.DocumentSerializer
+ * DocumentSerializer} and {@link
+ * org.openoffice.xmerge.DocumentDeserializer
+ * DocumentDeserializer};
+ * as well as the {@link
+ * org.openoffice.xmerge.ConverterCapabilities
+ * ConverterCapabilities} object that is specific to this format
+ * conversion. That superclass also produces a {@link
+ * org.openoffice.xmerge.DocumentMerger DocumentMerger}
+ * object, i.e. {@link
+ * org.openoffice.xmerge.converter.xml.sxc.DocumentMergerImpl
+ * DocumentMergerImpl} which this class derives the functionality.</p>
+ */
+public final class PluginFactoryImpl extends SxcPluginFactory
+ implements DocumentDeserializerFactory, DocumentSerializerFactory {
+
+ /** ConverterCapabilities object for this type of conversion. */
+ private final static ConverterCapabilities converterCap =
+ new ConverterCapabilitiesImpl();
+
+
+ public PluginFactoryImpl(ConverterInfo ci) {
+ super(ci);
+ }
+
+
+ /**
+ * Returns an instance of <code>DocumentSerializerImpl</code>,
+ * which is an implementation of <code>DocumentSerializer</code>
+ * interface.
+ *
+ * @param doc <code>Document</code> object to be
+ * converted/serialized.
+ *
+ * @return A <code>DocumentSerializerImpl</code> object.
+ */
+ public DocumentSerializer createDocumentSerializer(Document doc) {
+
+ return new SxcDocumentSerializerImpl(doc);
+ }
+
+
+ /**
+ * Returns an instance of <code>DocumentDeserializerImpl</code>,
+ * which is an implementation of <code>DocumentDeserializer</code>
+ * interface.
+ *
+ * @param cd <code>ConvertData</code> object for reading data
+ * which will be converted back to a
+ * <code>Document</code> object.
+ *
+ * @return A <code>DocumentDeserializerImpl</code> object.
+ */
+ public DocumentDeserializer createDocumentDeserializer(ConvertData cd) {
+
+ return new SxcDocumentDeserializerImpl(cd);
+ }
+
+
+ public Document createDeviceDocument(String name, InputStream is)
+ throws IOException {
+
+ Workbook wb = new Workbook(name, is);
+ return wb;
+ }
+
+ public DocumentMerger createDocumentMerger(Document doc) {
+
+ DocumentMergerImpl merger = new DocumentMergerImpl(doc, converterCap);
+ return merger;
+ }
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java
new file mode 100644
index 000000000000..13f73f18fdae
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java
@@ -0,0 +1,67 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+
+/**
+ * Interface defining constants for Pocket Excel attributes.
+ *
+ * @author Martin Maher
+ */
+public interface PocketExcelConstants {
+ /** File extension for Pocket Word files. */
+ public static final String FILE_EXTENSION = ".pxl";
+
+ /** Constants for pexcel BIFF records */
+ public static final int BLANK_CELL = 0x01;
+ public static final int NUMBER_CELL = 0x03;
+ public static final int LABEL_CELL = 0x04;
+ public static final int BOOLERR_CELL = 0x05;
+ public static final int FORMULA_CELL = 0x06;
+ public static final int FORMULA_STRING = 0x07;
+ public static final int ROW_DESCRIPTION = 0x08;
+ public static final int BOF_RECORD = 0x09;
+ public static final int EOF_MARKER = 0x0A;
+ public static final int DEFINED_NAME = 0x18;
+ public static final int CURRENT_SELECTION = 0x1D;
+ public static final int NUMBER_FORMAT = 0x1E;
+ public static final int DEFAULT_ROW_HEIGHT = 0x25;
+ public static final int FONT_DESCRIPTION = 0x31;
+ public static final int WINDOW_INFO = 0x3D;
+ public static final int SHEET_WINDOW_INFO = 0x3E;
+ public static final int PANE_INFO = 0x41;
+ public static final int CODEPAGE = 0x42;
+ public static final int DEF_COL_WIDTH = 0x55;
+ public static final int COLINFO = 0x7D;
+ public static final int BOUND_SHEET = 0x85;
+ public static final int EXTENDED_FORMAT = 0xE0;
+
+ /** Colour lookup table for mapping pexcel color values
+ (See util/ColourConverter.java */
+ public short cLookup[] = { 0, 14, 15, 1, 2, 3, 4, 7, 6, 5, 8, 9, 10, 13, 12, 11 };
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java
new file mode 100644
index 000000000000..dbfc43a64cd6
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java
@@ -0,0 +1,438 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.BookSettings;
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetDecoder;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.sxc.ColumnRowInfo;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.*;
+
+/**
+ * This class is used by {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializerImpl}
+ * SxcDocumentDeserializerImpl} to decode the Pocket Excel format.
+ *
+ * @author Paul Rank
+ */
+final class PocketExcelDecoder extends SpreadsheetDecoder {
+
+ private Workbook wb;
+ private Worksheet ws;
+ private CellValue cell;
+ private int maxRows = 0;
+ private int maxCols = 0;
+ private int wsIndex;
+ private Enumeration cellValue;
+ private Format fmt = null;
+
+ /**
+ * Constructor creates a Pocket Excel WorkBook.
+ *
+ * @param name The name of the WorkBook.
+ * @param worksheetNames set of Strings equivalent to the worksheets
+ * contained in the workbook
+ * @param password The password for the workBook.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ PocketExcelDecoder(String name, String[] worksheetNames, String password) throws IOException {
+ super(name, password);
+
+ fmt = new Format();
+ }
+
+
+ /**
+ * This method takes a <code>ConvertData</code> as input and
+ * converts it into a PocketWord WorkSheet. The WorkSheet is then
+ * added to the WorkBook.
+ *
+ * @param InputStream An <code>ConvertData</code> containing a
+ * Pocket Excel WorkSheet.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void addDeviceContent(ConvertData cd) throws IOException {
+
+ Enumeration e = cd.getDocumentEnumeration();
+ wb = (Workbook) e.nextElement();
+ }
+
+
+ /**
+ * This method returns the number of spreadsheets
+ * stored in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public int getNumberOfSheets() {
+
+ Vector v = wb.getWorksheetNames();
+ Debug.log(Debug.TRACE,"Total Number of Sheets : " + v.size());
+ return (v.size());
+ }
+
+ /**
+ * This method returns the number of spreadsheets
+ * stored in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public Enumeration getNameDefinitions() {
+
+ Enumeration e = wb.getDefinedNames();
+ Vector nameDefinitionVector = new Vector();
+ while(e.hasMoreElements()) {
+ DefinedName dn = (DefinedName)e.nextElement();
+ NameDefinition nameDefinitionEntry = dn.getNameDefinition();
+ nameDefinitionVector.add(nameDefinitionEntry);
+ }
+ Debug.log(Debug.TRACE,"Getting " + nameDefinitionVector.size() + " DefinedName records");
+ return (nameDefinitionVector.elements());
+ }
+
+ /**
+ * This method returns an enumeration of Settings object(s),
+ * one for each worksheet
+ *
+ * @return An enumerattion of <code>Settings</code>
+ */
+ public BookSettings getSettings() {
+
+ return (wb.getSettings());
+ }
+ /**
+ * This method returns the number of spreadsheets
+ * stored in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public Enumeration getColumnRowInfos() {
+
+ Vector colRowVector = new Vector();
+
+ // Collect Columns from worksheet and add them to the vector
+ for(Enumeration e = ws.getColInfos();e.hasMoreElements();) {
+ ColInfo ci = (ColInfo)e.nextElement();
+ int repeated = ci.getLast() - ci.getFirst() + 1;
+ ColumnRowInfo colInfo = new ColumnRowInfo( ci.getColWidth(),
+ repeated,
+ ColumnRowInfo.COLUMN);
+ colRowVector.add(colInfo);
+ }
+
+ // Collect Rows from worksheet and add them to the vector
+ for(Enumeration e = ws.getRows();e.hasMoreElements();) {
+ Row rw = (Row)e.nextElement();
+ // We will use the repeat field for number (unlike columns rows
+ // cannot be repeated, we have unique record for each row in pxl
+ int repeated = rw.getRowNumber();
+ ColumnRowInfo rowInfo = new ColumnRowInfo( rw.getRowHeight(),
+ repeated,
+ ColumnRowInfo.ROW);
+ colRowVector.add(rowInfo);
+ }
+ Debug.log(Debug.TRACE,"Getting " + colRowVector.size() + " ColRowInfo records");
+ return (colRowVector.elements());
+ }
+
+ /**
+ * This method gets the requested WorkSheet from the
+ * WorkBook and sets it as the selected WorkSheet. All
+ * other "get" methods will now get data from this WorkSheet.
+ *
+ * @param sheetIndex The index number of the sheet to open.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void setWorksheet(int sheetIndex) throws IOException {
+ Debug.log(Debug.TRACE,"Setting to worksheet : " + sheetIndex);
+ ws = wb.getWorksheet(sheetIndex);
+ cellValue = ws.getCellEnumerator();
+ wsIndex = sheetIndex;
+ while(goToNextCell()) {
+ maxRows = Math.max(maxRows, cell.getRow());
+ maxCols = Math.max(maxCols, cell.getCol());
+ }
+ cellValue = ws.getCellEnumerator();
+ Debug.log(Debug.TRACE,"Max Cols : " + maxCols + " MaxRows : " + maxRows);
+ }
+
+
+ /**
+ * This method returns the name of the current spreadsheet.
+ *
+ * @return The name of the current WorkSheet.
+ */
+ public String getSheetName() {
+
+ String wsName = wb.getSheetName(wsIndex);
+ Debug.log(Debug.TRACE,"The name of the current Worksheet is : " + wsName);
+ return wsName;
+ }
+
+
+ /**
+ * This method gets the next cell from the WorkSheet
+ * and sets it as the selected cell. All other "get"
+ * methods will now get data from this cell.
+ *
+ * @return True if we were able to go to another cell
+ * in the sheet, false if there were no cells
+ * left.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public boolean goToNextCell() throws IOException {
+
+ boolean success = false;
+
+ try {
+ cell = (CellValue) cellValue.nextElement();
+ Debug.log(Debug.TRACE,"Current Cell : " + cell.getString());
+ readCellFormat();
+ success = true;
+ } catch (NoSuchElementException e) {
+ Debug.log(Debug.TRACE,"Could't find current cell");
+ }
+
+ return success;
+ }
+
+
+ /**
+ * This method returns the row number of the current cell.
+ *
+ * @return The row number of the current cell. Returns
+ * -1 if no cell is currently selected.
+ */
+ public int getRowNumber() {
+
+ int row = -1;
+
+ if (cell != null) {
+ row = cell.getRow();
+ Debug.log(Debug.TRACE,"cell row is " + row);
+ }
+ return (row);
+ }
+
+ /**
+ * This method returns the number of rows in the current sheet.
+ *
+ * @return The number of rows in the current sheet.
+ */
+ public int getNumberOfRows() {
+ return maxRows;
+ }
+
+ /**
+ * This method returns the number of columns in the current sheet.
+ *
+ * @return The number of columns in the current sheet.
+ */
+ public int getNumberOfColumns() {
+ return maxCols;
+ }
+
+
+ /**
+ * This method returns the col number of the current cell.
+ *
+ * @return The col number of the current cell. Returns
+ * -1 if no cell is currently selected.
+ */
+ public int getColNumber() {
+
+ int col = -1;
+
+ if (cell != null) {
+ col = cell.getCol();
+ Debug.log(Debug.TRACE,"cell col is " + col);
+ }
+ return (col);
+ }
+
+ /**
+ * This method returns the contents of the current cell.
+ *
+ * @return The contents of the current cell. Returns
+ * null if no cell is currently selected.
+ */
+ public String getCellContents() {
+
+ String contents = new String("");
+
+ if (cell != null) {
+ try {
+ contents = cell.getString();
+ if (contents.startsWith("=")) {
+ contents = parseFormula(contents);
+ }
+ }
+ catch (IOException e) {
+ System.err.println("Could Not retrieve Cell contents");
+ System.err.println("Setting contents of cell(" + cell.getRow()
+ + "," + cell.getCol() + ") to an empty string");
+ System.err.println("Error msg: " + e.getMessage());
+ }
+ }
+
+ return contents;
+ }
+
+ /**
+ * <p>This method takes a formula and parses it into
+ * StarOffice XML formula format.</p>
+ *
+ * <p>Many spreadsheets use ',' as a separator.
+ * StarOffice XML format uses ';' as a separator instead.</p>
+ *
+ * <p>Many spreadsheets use '!' as a separator when refencing
+ * a cell in a different sheet.</p>
+ *
+ * <blockquote>
+ * Example: =sheet1!A1
+ * </blockquote>
+ *
+ * <p>StarOffice XML format uses '.' as a separator instead.</p>
+ *
+ * <blockquote>
+ * Example: =sheet1.A1
+ * </blockquote>
+ *
+ * @param formula A formula string.
+ *
+ * @return A StarOffice XML format formula string.
+ */
+ protected String parseFormula(String formula) {
+
+ formula = formula.replace(',', ';');
+ formula = formula.replace('!', '.');
+
+ return formula;
+ }
+
+ /**
+ * This method returns the contents of the current cell.
+ *
+ * @return The contents of the current cell. Returns
+ * null if no cell is currently selected.
+ */
+ public String getCellValue() {
+
+ String contents = new String("");
+
+ if (cell != null) {
+ try {
+ contents = ((Formula)cell).getValue();
+ }
+ catch (IOException e) {
+ System.err.println("Could Not retrieve Cell value");
+ System.err.println("Setting value of cell(" + cell.getRow()
+ + "," + cell.getCol() + ") to an empty string");
+ System.err.println("Error msg: " + e.getMessage());
+ }
+ }
+ return contents;
+ }
+
+ /**
+ * <p>This method returns the type of the data in the current cell.
+ * Currently the only type supported is String.</p>
+ *
+ * @return The type of the data in the current cell.
+ */
+ public String getCellDataType() {
+
+ String type = OfficeConstants.CELLTYPE_STRING;
+
+ if(cell instanceof FloatNumber)
+ type = OfficeConstants.CELLTYPE_FLOAT;
+ if(cell instanceof Formula)
+ type = OfficeConstants.CELLTYPE_FLOAT;
+
+ return type;
+ }
+
+
+ /**
+ * Return the Format object describing the active cell formatting.
+ *
+ * @return The Format object describing the active cell formatting.
+ */
+ public Format getCellFormat() {
+ return new Format(fmt);
+ }
+
+
+ /**
+ * Create the format data for the new cell.
+ */
+ private void readCellFormat() throws IOException {
+
+ fmt.clearFormatting();
+
+ Debug.log(Debug.TRACE," ixfe for Current Cell " + cell.getIxfe());
+ ExtendedFormat xf = wb.getExtendedFormat(cell.getIxfe());
+ Debug.log(Debug.TRACE," ixfnt for Current Cell " + xf.getFontIndex());
+ FontDescription fd = wb.getFontDescription(xf.getFontIndex());
+
+ fmt.setAttribute(Format.ITALIC, fd.isItalic());
+ fmt.setAttribute(Format.BOLD, fd.isBold());
+ fmt.setAttribute(Format.UNDERLINE, fd.isUnderline());
+ fmt.setForeground(fd.getForeground());
+
+ fmt.setBackground(xf.getBackground());
+ fmt.setAlign(xf.getAlign());
+ fmt.setVertAlign(xf.getVertAlign());
+ fmt.setAttribute(Format.WORD_WRAP, xf.isWordWrap());
+
+ fmt.setAttribute(Format.TOP_BORDER, xf.isBorder(ExtendedFormat.TOP_BORDER));
+ fmt.setAttribute(Format.BOTTOM_BORDER, xf.isBorder(ExtendedFormat.BOTTOM_BORDER));
+ fmt.setAttribute(Format.RIGHT_BORDER, xf.isBorder(ExtendedFormat.RIGHT_BORDER));
+ fmt.setAttribute(Format.LEFT_BORDER, xf.isBorder(ExtendedFormat.LEFT_BORDER));
+
+ fmt.setFontName(fd.getFont());
+ fmt.setFontSize(fd.getFontSize());
+
+ fmt.setCategory(getCellDataType());
+
+ }
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java
new file mode 100644
index 000000000000..52ef18d252f0
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java
@@ -0,0 +1,289 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import java.io.IOException;
+import java.util.Vector;
+
+import org.openoffice.xmerge.util.Debug;
+
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetEncoder;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.BookSettings;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+
+/**
+ * This class is used by {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializerImpl
+ * SxcDocumentSerializerImpl} to encode the Pocket Excel format.
+ *
+ * @author Martin Maher
+ */
+final class PocketExcelEncoder extends SpreadsheetEncoder {
+
+ private Workbook wb;
+
+ /**
+ * Constructor creates a Pocket Excel WorkBook.
+ *
+ * @param name The name of the WorkBook.
+ * @param password The password for the WorkBook.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ PocketExcelEncoder(String name, String password) throws IOException {
+
+ super(name, password);
+ wb = new Workbook(name);
+
+ }
+
+
+ /**
+ * This method creates a WorkSheet belonging to the
+ * WorkBook.
+ *
+ * @param sheetName The name of the WorkSheet.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void createWorksheet(String sheetName) throws IOException {
+
+ wb.addWorksheet(sheetName);
+ }
+
+
+ /**
+ * This method gets the number of sheets in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public int getNumberOfSheets() {
+
+ Vector v = wb.getWorksheetNames();
+ return (v.size());
+ }
+
+
+ /**
+ * This method returns the Workbook created.
+ *
+ * @return Returns a <code>Workbook</code>
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public Workbook getWorkbook() throws IOException {
+
+ return wb;
+ }
+
+ /**
+ * This method converts a String containing a formula in infix notation
+ * to a String in Reverse Polish Notation (RPN)
+ *
+ * @return a parsed pexcel formula in RPN
+ */
+ protected String parseFormula(String formula) {
+
+ Debug.log(Debug.TRACE,"Strip Formula (Before) : " + formula);
+
+ StringBuffer inFormula = new StringBuffer(formula);
+ StringBuffer outFormula = new StringBuffer();
+
+ boolean inBrace = false;
+ boolean firstCharAfterBrace = false;
+ boolean firstCharAfterColon = false;
+
+ int len = inFormula.length();
+
+ for (int in = 0; in < len; in++) {
+ switch (inFormula.charAt(in)) {
+ case '[':
+ // We are now inside a StarOffice cell reference.
+ // We also need to strip out the '['
+ Debug.log(Debug.TRACE,"brace Found");
+ inBrace = true;
+
+ // If the next character is a '.', we want to strip it out
+ firstCharAfterBrace = true;
+ break;
+
+ case ']':
+ // We are exiting a StarOffice cell reference
+ // We are stripping out the ']'
+ inBrace = false;
+ break;
+ case '.':
+ if (inBrace == true && (firstCharAfterBrace == true ||
+ firstCharAfterColon == true) ) {
+
+ Debug.log(Debug.TRACE,"dot Found and in brace");
+ // Since we are in a StarOffice cell reference,
+ // and we are the first character, we need to
+ // strip out the '.'
+ firstCharAfterBrace = false;
+ firstCharAfterColon = false;
+
+ } else if(firstCharAfterColon == true) {
+ firstCharAfterColon = false;
+ } else {
+ outFormula.append(inFormula.charAt(in));
+ }
+ break;
+
+ case ':':
+ // We have a cell range reference.
+ // May need to strip out the leading '.'
+ firstCharAfterColon = true;
+ outFormula.append(inFormula.charAt(in));
+ break;
+
+ case ';':
+ // StarOffice XML format uses ';' as a separator. MiniCalc (and
+ // many spreadsheets) use ',' as a separator instead.
+ outFormula.append(',');
+ break;
+
+ default:
+ // We hit valid data, lets add it to the formula string
+ outFormula.append(inFormula.charAt(in));
+
+ // Need to make sure that firstCharAfterBrace is not true.
+ firstCharAfterBrace = false;
+ break;
+ }
+ }
+
+ Debug.log(Debug.TRACE,"Strip Formula (After) : " + outFormula);
+ return outFormula.toString();
+ }
+
+ /**
+ * Add a cell to the current WorkSheet.
+ *
+ * @param row The row number of the cell.
+ * @param column The column number of the cell.
+ * @param fmt The <code>Format</code> object describing
+ * the appearance of this cell.
+ * @param cellContents The text or formula of the cell's contents.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void addCell(int row, int column, Format fmt, String cellContents) throws IOException {
+
+ if (cellContents.startsWith("=")) {
+ cellContents = parseFormula(cellContents);
+ Debug.log(Debug.TRACE,"Parsing Formula " + cellContents);
+ }
+ wb.addCell(row, column, fmt, cellContents);
+ }
+
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public void setColumnRows(Vector columnRows) throws IOException {
+
+ wb.addColInfo(columnRows);
+ }
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public void setNameDefinition(NameDefinition nd) throws IOException {
+
+ String parsedName = nd.getDefinition();
+ nd.setDefinition(parseFormula(parsedName));
+
+ wb.addNameDefinition(nd);
+ }
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public void addSettings(BookSettings s) throws IOException {
+
+ wb.addSettings(s);
+ }
+
+ /**
+ * This method sets the format of a cell to <i>string</i>.
+ *
+ * @param format The cell format-may already contain display info,
+ * such as alignment or font type.
+ *
+ * @return The updated format of the cell.
+ */
+ private long setFormatString(long format) {
+
+ return 0;
+ }
+
+
+ /**
+ * Set a cell's formatting options via a separately create
+ * <code>Format</code> object.
+ *
+ * @param row The row number of the cell to be changed.
+ * @param column The column number of the cell to be changed.
+ * @param fmt Object containing formatting settings for
+ * this cell.
+ */
+ public void setCellFormat(int row, int column, Format fmt) {
+ Debug.log(Debug.TRACE,"bold : " + fmt.getAttribute(Format.BOLD) +
+ ",Italic : " + fmt.getAttribute(Format.ITALIC) +
+ ",Underline : " + fmt.getAttribute(Format.UNDERLINE));
+ }
+
+
+ /**
+ * Get the names of the sheets in the WorkBook.
+ *
+ * @param sheet The required sheet.
+ */
+ public String getSheetName(int sheet) {
+
+ Vector v = wb.getWorksheetNames();
+ String wsName = (String) (v.elementAt(sheet));
+
+ return wsName;
+ }
+
+
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java
new file mode 100644
index 000000000000..e95a6aa41e19
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java
@@ -0,0 +1,129 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetDecoder;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializer;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelDecoder;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+
+
+/**
+ * <p>Pocket Excel implementation of <code>DocumentDeserializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.pexcel.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>This converts a set of files in Pocket Excel PXL format to a StarOffice DOM.</p>
+ *
+ * @author Mark Murnane
+ */
+public final class SxcDocumentDeserializerImpl extends SxcDocumentDeserializer {
+
+ /**
+ * Creates new <code>SxcDocumentDeserializerImpl</code>.
+ *
+ * @param cd <code>ConvertData</code> Input data to convert.
+ */
+ public SxcDocumentDeserializerImpl(ConvertData cd) {
+ super(cd);
+ }
+
+
+ /**
+ * This method will be implemented by concrete subclasses and will
+ * return an application-specific decoder.
+ *
+ * @param workbook The WorkBook name.
+ * @param worksheetNames An array of WorkSheet names.
+ * @param password The password.
+ *
+ * @return An application-specific <code>SpreadsheetDecoder</code>.
+ */
+ public SpreadsheetDecoder createDecoder(String workbook,
+ String[] worksheetNames, String password) throws IOException {
+
+ return new PocketExcelDecoder(workbook, worksheetNames, password);
+ }
+
+
+ /**
+ * This method will return the name of the WorkBook from the
+ * <code>ConvertData</code>. Allows for situations where the
+ * WorkBook name differs from the PDB name.
+ *
+ * Implemented in the Deserializer as the Decoder's constructor
+ * requires a name.
+ *
+ * @param cd The <code>ConvertData</code>.
+ *
+ * @return The name of the WorkBook.
+ */
+ protected String getWorkbookName(ConvertData cd)
+ throws IOException {
+
+ Enumeration e = cd.getDocumentEnumeration();
+ Workbook wb = (Workbook) e.nextElement();
+
+ String workbookName = wb.getName();
+ return workbookName;
+ }
+
+
+ /**
+ * This method will return an array of WorkSheet names from the
+ * <code>ConvertData</code>.
+ *
+ * @param cd The <code>ConvertData</code>.
+ *
+ * @return The name of the WorkSheet.
+ */
+ protected String[] getWorksheetNames(ConvertData cd)
+ throws IOException {
+
+ Enumeration e = cd.getDocumentEnumeration();
+ Workbook wb = (Workbook) e.nextElement();
+ Vector v = wb.getWorksheetNames();
+ e = v.elements();
+ String worksheetNames[] = new String[v.size()];
+ int i = 0;
+ while(e.hasMoreElements()) {
+ worksheetNames[i] = (String) e.nextElement();
+ Debug.log(Debug.TRACE,"Worksheet Name : " + worksheetNames[i]);
+ i++;
+ }
+ return worksheetNames;
+ }
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java
new file mode 100644
index 000000000000..26d4546bd369
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java
@@ -0,0 +1,130 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+
+import java.io.IOException;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.ConvertException;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializer;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+
+/**
+ * <p>Pocket Excel implementation of <code>SxcDocumentDeserializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.pexcel.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>This converts StarOffice XML format to a set of files in
+ * Pocket Excel PXL format.</p>
+ *
+ * @author Paul Rank
+ * @author Mark Murnane
+ */
+public final class SxcDocumentSerializerImpl extends SxcDocumentSerializer {
+
+
+ /**
+ * Constructor.
+ *
+ * @param document The <code>Document</code> to convert.
+ */
+ public SxcDocumentSerializerImpl(Document document) {
+ super(document);
+ }
+
+
+ public ConvertData serialize() throws ConvertException, IOException {
+
+ // Get the server side document name. This value should not
+ // contain a path or the file extension.
+ String docName = sxcDoc.getName();
+
+ // TODO - get real values for password when implemnted in XML
+ // Passwords are not currently stored in StarCalc XML format.
+ String password = null;
+
+ encoder = new PocketExcelEncoder(docName, password);
+
+ // get dom document
+ org.w3c.dom.Document domDoc = sxcDoc.getContentDOM();
+
+ // load the styles
+ loadStyles(sxcDoc);
+ // Traverse to the office:body element.
+ // There should only be one.
+ NodeList list = domDoc.getElementsByTagName(TAG_OFFICE_BODY);
+ int len = list.getLength();
+
+ if (len > 0) {
+ Node node = list.item(0);
+ traverseBody(node);
+ }
+
+ // get settings for this document
+ org.w3c.dom.Document settingsDoc = sxcDoc.getSettingsDOM();
+ if(settingsDoc!=null) {
+ NodeList settingsList = settingsDoc.getElementsByTagName(TAG_OFFICE_SETTINGS);
+ int slen = settingsList.getLength();
+
+ if (slen > 0) {
+ Node settingsNode = settingsList.item(0);
+ traverseSettings(settingsNode);
+ }
+ }
+
+ // Get the number of sheets in the workbook
+ // This will equal the number of PDBs we need
+ ConvertData cd = new ConvertData();
+ Workbook wb = ((PocketExcelEncoder) encoder).getWorkbook();
+ cd.addDocument(wb);
+
+ return cd;
+ }
+
+
+ /**
+ * A cell reference in a StarOffice formula looks like
+ * [.C2] (for cell C2). MiniCalc is expecting cell references
+ * to look like C2. This method strips out the braces and
+ * the period.
+ *
+ * @param formula A StarOffice formula <code>String</code>.
+ *
+ * @return A MiniCalc formula <code>String</code>.
+ */
+ protected String parseFormula(String formula) {
+
+ return null;
+ }
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html
new file mode 100644
index 000000000000..61c1f3f0a79d
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+ #*************************************************************************
+ #
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2000, 2010 Oracle and/or its affiliates.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ This file is part of OpenOffice.org.
+
+ OpenOffice.org is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ OpenOffice.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details
+ (a copy is included in the LICENSE file that accompanied this code).
+
+ You should have received a copy of the GNU Lesser General Public License
+ version 3 along with OpenOffice.org. If not, see
+ <http://www.openoffice.org/license.html>
+ for a copy of the LGPLv3 License.
+
+ #*************************************************************************
+ -->
+<html>
+<head>
+<title>org.openoffice.xmerge.converter.xml.sxc.pexcel package</title>
+</head>
+
+<body bgcolor="white">
+
+<p>Provides the tools for doing the conversion of StarWriter XML to
+and from Pocket Excel format.</p>
+
+<p>It follows the {@link org.openoffice.xmerge} framework for the conversion process.</p>
+
+</body>
+</html>
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java
new file mode 100644
index 000000000000..190cb0925c21
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+ public interface BIFFRecord {
+
+ /**
+ * Get the type of the record. In the BIFF file format each record has a type
+ * designated with a byte value. See @link PocketExcelBiffConstants
+ * for a list of the BIFF constants and what they mean.
+ *
+ * @return byte The BIFF record value.
+ */
+ public short getBiffType();
+
+ /**
+ * Read from the input stream <b>NB</b>The input stream is assumed to be in
+ * Little Endian format. The Biff identifier is expected to be in the stream.
+ *
+ * @param input The InputStream to read from.
+ * @return The number of bytes that were read in.
+ */
+ public int read(InputStream input) throws IOException;
+
+ /**
+ * Writes the record, including the BIFF record byte to the outputstream
+ * @param output The output stream to write to in LittleEndian format.
+ */
+ public void write(OutputStream output) throws IOException;
+
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java
new file mode 100644
index 000000000000..df45b708d89c
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * This class describes the beginning of file. It is the
+ * the Biff record that marks the beginning of a a worbook
+ * or the beginning of worksheets in the workbook
+ *
+ */
+public class BeginningOfFile implements BIFFRecord {
+
+ private byte[] version = new byte[2];
+ private byte[] subStream = new byte[2];
+
+ /**
+ * Constructor that initializes the member values.
+ *
+ * @param ver Version Number
+ * Substream type (workbook = 0x05, worksheet = 0x10)
+ */
+ public BeginningOfFile(boolean global) {
+ setVersion((short) 271);
+ if(global)
+ setSubStreamWBGlobal();
+ else
+ setSubStreamWorkSheet();
+ // this.subStream = EndianConverter.writeShort(dt);
+ }
+
+ public BeginningOfFile(InputStream is) throws IOException {
+ read(is);
+ }
+
+ private void setVersion(short version) {
+ this.version = EndianConverter.writeShort(version);
+ }
+
+ int getVersion() {
+ return EndianConverter.readShort(version);
+ }
+
+ private void setSubStreamWBGlobal() {
+ // subStream = new byte[] {0x05};
+ subStream = EndianConverter.writeShort((short) 0x05);
+ }
+
+ private void setSubStreamWorkSheet() {
+ // subStream = new byte[] {0x10};
+ subStream = EndianConverter.writeShort((short) 0x10);
+ }
+
+ int getSubStreamType() {
+ return EndianConverter.readShort(subStream);
+ }
+
+ public int read(InputStream input) throws IOException {
+ int numBytesRead = input.read(version);
+ numBytesRead += input.read(subStream);
+ Debug.log(Debug.TRACE,"\tVersion : "+ EndianConverter.readShort(version) +
+ " Stream : " + EndianConverter.readShort(subStream));
+
+ return numBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(version);
+ output.write(subStream);
+
+ Debug.log(Debug.TRACE, "Writing BeginningOfFile record");
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BeginningOfFile</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.BOF_RECORD;
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java
new file mode 100644
index 000000000000..da826a8d9058
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record that describes a blank cell
+ */
+public class BlankCell extends CellValue {
+
+ /**
+ * Constructs a BlankCell <code>InputStream</code>
+ *
+ * @param is InputStream containing a BlankCell.
+ */
+ public BlankCell(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Constructs a <code>BlankCell</code> using specified attributes
+ *
+ * @param row row number
+ * @param col column number
+ * @param cellContents contents of the cell
+ * @param ixfe font index
+ */
+ public BlankCell(int row, int column, int ixfe) throws IOException {
+
+ setRow(row);
+ setCol(column);
+ setIxfe(ixfe);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BlankCell</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.BLANK_CELL;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(rw);
+ output.write(col);
+ output.write(ixfe);
+
+ Debug.log(Debug.TRACE, "Writing BlankCell record");
+
+ }
+
+ /**
+ * Reads a BlankCell <code>InputStream</code>
+ *
+ * @param is InputStream containing a BlankCell.
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(rw);
+ numOfBytesRead++;
+ col += input.read();
+ numOfBytesRead += input.read(ixfe);
+
+ Debug.log(Debug.TRACE, "\tRow : "+ EndianConverter.readShort(rw) +
+ " Column : " + col +
+ " ixfe : " + EndianConverter.readShort(ixfe));
+
+ return numOfBytesRead;
+ }
+
+ /**
+ * Gets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ public String getString() throws IOException {
+
+ return (new String(""));
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java
new file mode 100644
index 000000000000..9a370ccd8a59
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java
@@ -0,0 +1,125 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record that describes a Boolean or Error value
+ */
+public class BoolErrCell extends CellValue {
+
+ private byte bBoolErr;
+ private byte fError;
+
+ /**
+ * Constructs a BoolErrCell from arguments
+ *
+ * @param row row number
+ * @param col column number
+ * @param ixfe font index
+ * @param bBoolErr Boolean value or error value
+ * @param fError Boolean error flag
+ */
+ public BoolErrCell(int row, int column, int ixfe, int bBoolErr, int fError) throws IOException {
+
+ setIxfe(ixfe);
+ this.bBoolErr = (byte)bBoolErr;
+ this.fError = (byte)fError;
+ setRow(row);
+ setCol(column);
+ }
+
+ /**
+ * Constructs a BoolErrCell from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a BoolErrCell
+ */
+ public BoolErrCell(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BoolErrCEll</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.BOOLERR_CELL;
+ }
+
+ /**
+ * Writes a <code>BoolErrCell</code> to the specified <code>Outputstream</code>
+ *
+ * @param os the <code>OutputStream</code> to write to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+
+ super.write(output);
+
+ output.write(bBoolErr);
+ output.write(fError);
+
+ Debug.log(Debug.TRACE,"Writing BoolErrCell record");
+ }
+
+ /**
+ * Reads a BoolErrCell from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a BoolErrCell
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = super.read(input);
+
+ bBoolErr = (byte) input.read();
+ fError = (byte) input.read();
+ numOfBytesRead += 2;
+
+ Debug.log(Debug.TRACE, " bBoolErr : " + bBoolErr +
+ " fError : " + fError);
+ return numOfBytesRead;
+ }
+
+ /**
+ * Gets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ public String getString() throws IOException {
+ return ("Error Cell");
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java
new file mode 100644
index 000000000000..679224634bfa
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.OutputStream;
+import java.io.InputStream;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BoundSheet Record which describes the name of a worksheet
+ */
+public class BoundSheet implements BIFFRecord {
+
+ private byte reserved;
+ private byte cch;
+ private byte[] sheetName;
+
+ /**
+ * Constructs a pocket Excel Document assigns it the document name passed in
+ *
+ * @param name name of the worksheet represented
+ */
+ public BoundSheet(String name) throws IOException {
+ setSheetName(name);
+ reserved = 0;
+ }
+
+ /**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public BoundSheet(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Sets the worksheet name. The sheetname length must be doubled as the
+ * String is stored in unicode format.
+ *
+ * @param sheetname worksheet name
+ */
+ void setSheetName(String sheetName) throws IOException {
+ this.cch = (byte) sheetName.length();
+ this.sheetName = new byte[cch*2];
+ this.sheetName = sheetName.getBytes("UTF-16LE");
+ }
+
+ public String getSheetName() {
+ String name;
+
+ try {
+ name = new String(sheetName, "UTF-16LE");
+ } catch (UnsupportedEncodingException e){
+ name = "unknown";
+ }
+ return name;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BoundSheet</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.BOUND_SHEET;
+ }
+
+ /**
+ * Write this particular <code>BIFFRecord</code> to the <code>OutputStream</code>
+ *
+ * @param ouput the <code>OutputStream</code>
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(reserved);
+ output.write(cch);
+ output.write(sheetName);
+
+ Debug.log(Debug.TRACE,"Writing BoundSheet record");
+ }
+
+ /**
+ * Reads a BoundSheet from the <code>InputStream</code> The byte array
+ * must be twice the size of the String as it uses unicode.
+ *
+ * @param is InputStream containing the record data
+ */
+ public int read(InputStream input) throws IOException {
+
+ reserved = (byte) input.read();
+ cch = (byte) input.read();
+ int numOfBytesRead = 2;
+ int strLen = cch*2;
+ sheetName = new byte[strLen];
+ numOfBytesRead += input.read(sheetName, 0, strLen);
+
+ Debug.log(Debug.TRACE,"\tReserved : "+ reserved +
+ " cch : " + cch +
+ " sheetName : " + new String(sheetName,"UTF-16LE"));
+
+ return numOfBytesRead;
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java
new file mode 100644
index 000000000000..c09cde5a32c1
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+
+public abstract class CellValue implements BIFFRecord {
+
+ protected byte[] rw = new byte[2];
+ protected byte col;
+ protected byte[] ixfe = new byte[2];
+
+ /**
+ * Get the row number of this cell
+ *
+ * @return the row number of this cell
+ */
+ public int getRow() {
+ return EndianConverter.readShort(rw) + 1;
+ }
+
+ /**
+ * Set the row number of this cell
+ *
+ * @param row sets the row number for this cell
+ */
+ public void setRow(int row) {
+ this.rw = EndianConverter.writeShort((short) (row - 1));
+ }
+ /**
+ * Get the Index to the <code>ExtendedFormat</code>
+ *
+ * @return the index number of this cell's <code>ExtendedFormat</code>
+ */
+ public int getIxfe() {
+ return EndianConverter.readShort(ixfe);
+ }
+
+ /**
+ * Sets the Index to the <code>ExtendedFormat</code>
+ *
+ * @param ixfe sets the index number for this cell's <code>ExtendedFormat</code>
+ */
+ public void setIxfe(int ixfe) {
+ this.ixfe = EndianConverter.writeShort((short) (ixfe));
+ }
+
+ /**
+ * Get the column number of this cell
+ *
+ * @return the column number of this cell
+ */
+ public int getCol() {
+ return col + 1; // The cols start at 1
+ }
+
+ /**
+ * Set the row number of this cell
+ *
+ * @param col sets the row number for this cell
+ */
+ public void setCol(int col) {
+ this.col = (byte) (col - 1); // The cols start at 1
+ }
+
+ /**
+ * Writes basic cell value attributes to the specified <code>Outputstream</code>
+ *
+ * @param os the <code>OutputStream</code> to write to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(rw);
+ output.write(col);
+ output.write(ixfe);
+ }
+
+ /**
+ * Writes a<code>LabelCell</code> to the specified <code>Outputstream</code>
+ *
+ * @param os the <code>OutputStream</code> to write to
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(rw);
+ col += input.read();
+ numOfBytesRead++;
+ numOfBytesRead += input.read(ixfe);
+
+ Debug.log(Debug.TRACE, "\tRow : "+ EndianConverter.readShort(rw) +
+ " Column : " + col +
+ " ixfe : " + EndianConverter.readShort(ixfe));
+
+ return numOfBytesRead;
+ }
+
+
+ /**
+ * Returns the contents of the cell as a String
+ *
+ * @return the contents of the cell
+ */
+ abstract public String getString() throws IOException;
+
+}
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java
new file mode 100644
index 000000000000..91186fa27c3c
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents the codepage for the document. There is a number of unknown
+ * fields which are hardcoded at construction
+ */
+public class CodePage implements BIFFRecord {
+
+ private byte[] codepage = new byte[2];
+ private byte[] unknown1 = new byte[2];
+ private byte[] unknown2 = new byte[2];
+ private byte unknown3;
+
+ /**
+ * Constructs a pocket Excel Codepage
+ */
+ public CodePage() {
+ codepage = new byte[] {(byte)0xE4, (byte)0x04};
+ unknown1 = new byte[] {(byte)0x8C, (byte)0x01};
+ unknown2 = new byte[] {(byte)0x00, (byte)0x01};
+ unknown3 = 0x00;
+ }
+
+ /**
+ * Constructs a pocket Excel Codepage from the<code>InputStream</code>
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public CodePage(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BoundSheet</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.CODEPAGE;
+ }
+
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(codepage);
+ numOfBytesRead += input.read(unknown1);
+ numOfBytesRead += input.read(unknown2);
+ // numOfBytesRead += input.read(unknown3);
+ unknown3 = (byte) input.read();
+ numOfBytesRead++;
+
+ Debug.log(Debug.TRACE,"\tcodepage : "+ EndianConverter.readShort(codepage) +
+ " unknown1 : " + EndianConverter.readShort(unknown1) +
+ " unknown2 : " + EndianConverter.readShort(unknown2) +
+ " unknown3 : " + unknown3);
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(codepage);
+ output.write(unknown1);
+ output.write(unknown2);
+ output.write(unknown3);
+
+ Debug.log(Debug.TRACE,"Writing CodePage record");
+
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java
new file mode 100644
index 000000000000..6ce59c7ca72c
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java
@@ -0,0 +1,157 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * ColInfo describes the formatting for a column
+ *
+ */
+public class ColInfo implements BIFFRecord {
+
+ private byte[] colFirst = new byte[2]; // first column this formatting applies to
+ private byte[] colLast = new byte[2]; // last column this formatting applies to
+ private byte[] colDX = new byte[2]; // column width
+ private byte[] ixfe = new byte[2]; // index for formatting
+ private byte grbit; // options flags
+ private float scale = (float) 2.5; // 1.798;
+
+ /**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param colFirst the first column this formatting applies to
+ * @param colLast last column this formatting applies to
+ * @param coldx column width
+ * @param grbit options flags
+ */
+ public ColInfo(int colFirst, int colLast, int colDX, int ixfe) {
+ this.colFirst = EndianConverter.writeShort((short)colFirst);
+ this.colLast = EndianConverter.writeShort((short)colLast);
+ colDX *= scale;
+ this.colDX = EndianConverter.writeShort((short)colDX);
+ this.ixfe = EndianConverter.writeShort((short)ixfe);
+ this.grbit = 0x00;
+ }
+
+ /**
+ * Construct a ColInfo from the InputStream
+ *
+ * @param is the <code>Inputstream</code> to read from
+ */
+ public ColInfo(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Reads ColInfo record from the InputStream
+ *
+ * @param input the InputStream to read from
+ * @return the number of bytes read
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(colFirst);
+ numOfBytesRead += input.read(colLast);
+ numOfBytesRead += input.read(colDX);
+ short scaledDX = (short) (EndianConverter.readShort(colDX) / scale);
+ colDX = EndianConverter.writeShort(scaledDX);
+ numOfBytesRead += input.read(ixfe);
+ grbit = (byte) input.read();
+ numOfBytesRead ++;
+
+ Debug.log(Debug.TRACE,"\tcolFirst : "+ EndianConverter.readShort(colFirst) +
+ " colLast : " + EndianConverter.readShort(colLast) +
+ " colDX : " + EndianConverter.readShort(colDX) +
+ " ixfe : " + EndianConverter.readShort(ixfe) +
+ " grbit : " + grbit);
+
+ return numOfBytesRead;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>ColInfo</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.COLINFO;
+ }
+ /**
+ * Get the width of this column
+ *
+ * @return the width of this column
+ */
+ public short getColWidth() {
+ return EndianConverter.readShort(colDX);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>ColInfo</code>
+ */
+ public short getFirst() {
+ return EndianConverter.readShort(colFirst);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>ColInfo</code>
+ */
+ public short getLast() {
+ return EndianConverter.readShort(colLast);
+ }
+
+ /**
+ * Writes a ColInfo to the specified <code>Outputstream</code>
+ *
+ * @param os the <code>OutputStream</code> to write to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(colFirst);
+ output.write(colLast);
+ output.write(colDX);
+ output.write(ixfe);
+ output.write(grbit);
+
+ Debug.log(Debug.TRACE,"Writing ColInfo record");
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java
new file mode 100644
index 000000000000..b3e3a8e6b0e3
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java
@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF record defiuning the defualt column width
+ */
+public class DefColWidth implements BIFFRecord {
+
+ private byte[] grbit = new byte[2];
+ private byte[] coldx = new byte[2];
+ private byte[] ixfe = new byte[2];
+
+/**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public DefColWidth() {
+ grbit = new byte[] {0x00, 0x00};
+ coldx = new byte[] {0x00, 0x09};
+ ixfe = new byte[] {0x00, 0x00};
+ }
+
+ public DefColWidth(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>DefColWidth</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.DEF_COL_WIDTH;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(grbit);
+ output.write(coldx);
+ output.write(ixfe);
+
+ Debug.log(Debug.TRACE, "Writing DefColWidth record");
+ }
+
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(grbit);
+ numOfBytesRead += input.read(coldx);
+ numOfBytesRead += input.read(ixfe);
+
+ Debug.log(Debug.TRACE,"\tgrbit : "+ EndianConverter.readShort(grbit) +
+ " coldx : " + EndianConverter.readShort(coldx) +
+ " ixfe : " + EndianConverter.readShort(ixfe));
+ return 0;
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java
new file mode 100644
index 000000000000..454a5ed87520
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF record defiuning the default row height
+ */
+public class DefRowHeight implements BIFFRecord {
+
+ private byte[] unknown1 = new byte[2];
+ private byte[] unknown2 = new byte[2];
+
+ /**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public DefRowHeight() {
+ unknown1 = new byte[] {(byte)0x00, (byte)0x00};
+ unknown2 = new byte[] {(byte)0xFF, (byte)0x00};
+ }
+
+ /**
+ * Constructs a DefRowHeight from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public DefRowHeight(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>DefRowHeight</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.DEFAULT_ROW_HEIGHT;
+ }
+
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(unknown1);
+ numOfBytesRead += input.read(unknown2);
+
+ Debug.log(Debug.TRACE,"\tunknown1 : "+ EndianConverter.readShort(unknown1) +
+ " unknown2 : " + EndianConverter.readShort(unknown2));
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(unknown1);
+ output.write(unknown2);
+
+ Debug.log(Debug.TRACE,"Writing DefRowHeight record");
+
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java
new file mode 100644
index 000000000000..0f8c535a9b92
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java
@@ -0,0 +1,226 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula.FormulaHelper;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record representing a defined name in the workbook
+ */
+public class DefinedName implements BIFFRecord {
+
+ private byte[] grbit = new byte[2];
+ private byte cch;
+ private byte[] cce = new byte[2];
+ private byte[] ixals = new byte[2];
+ private byte[] rgch;
+ private byte[] rgce;
+ private FormulaHelper fh = new FormulaHelper();
+ private String definition = new String("");
+ private Workbook wb;
+
+ /**
+ * Constructs a Defined Name from the <code>InputStream</code>
+ *
+ * @param is InputStream containing the record data
+ */
+ public DefinedName(NameDefinition nd, Workbook wb) throws IOException {
+
+ fh.setWorkbook(wb);
+ this.wb = wb;
+ String name = nd.getName();
+
+ // we have to insert an = to stop the formulaParser throwing an exception
+ definition = "=" + nd.getDefinition();
+
+ cch = (byte)name.length();
+ rgch = new byte[cch*2];
+ rgch = name.getBytes("UTF-16LE");
+ grbit = EndianConverter.writeShort((short)0);
+ ixals[0] = (byte)0xFF;ixals[1] = (byte)0xFF;
+ }
+ /**
+ * Constructs a Defined Name from the <code>InputStream</code>
+ *
+ * @param is InputStream containing the record data
+ */
+ public DefinedName(InputStream is, Workbook wb) throws IOException {
+
+ read(is);
+ fh.setWorkbook(wb);
+ this.wb = wb;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>DefinedName</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.DEFINED_NAME;
+ }
+
+ /**
+ * Reads a Defined Name from the <code>InputStream</code> The byte array
+ * must be twice the size of the String as it uses unicode.
+ *
+ * @param is InputStream containing the record data
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(grbit);
+ cch = (byte) input.read();
+ numOfBytesRead++;
+ numOfBytesRead += input.read(cce);
+ numOfBytesRead += input.read(ixals);
+
+ rgch = new byte[cch*2];
+ input.read(rgch, 0, cch*2);
+
+ rgce = new byte[EndianConverter.readShort(cce)];
+ input.read(rgce, 0, EndianConverter.readShort(cce));
+
+
+
+ Debug.log(Debug.TRACE, "\tgrbit : "+ EndianConverter.readShort(grbit) +
+ " cch : " + cch +
+ " cce : " + EndianConverter.readShort(cce) +
+ " ixals : " + EndianConverter.readShort(ixals) +
+ "\n\trgch : " + rgch +
+ " rgce : " + rgce);
+
+ return numOfBytesRead;
+ }
+
+ /**
+ * Write this particular <code>BIFFRecord</code> to the <code>OutputStream</code>
+ *
+ * @param ouput the <code>OutputStream</code>
+ */
+ public void write(OutputStream output) throws IOException {
+
+ try {
+ Debug.log(Debug.TRACE,"Writing out " + definition);
+ rgce = fh.convertCalcToPXL(definition);
+ cce = EndianConverter.writeShort((short) rgce.length);
+ } catch(Exception e) {
+ Debug.log(Debug.TRACE,"Error in Parsing Name Definition");
+ cce = EndianConverter.writeShort((short) 0);
+ }
+
+
+ output.write(getBiffType());
+ output.write(grbit);
+ output.write(cch);
+ output.write(cce);
+ output.write(ixals);
+ output.write(rgch);
+ if(rgce.length!=0)
+ output.write(rgce);
+
+ Debug.log(Debug.TRACE,"Writing DefinedName record");
+ }
+
+ /**
+ * Returns definition name. This is public because the
+ * <code>TokenDecoder</code> has to substitue the Name token with this
+ * String when writing out to sxc
+ *
+ * @return the <code>String</code> containing the name
+ */
+ public String getName() {
+ String name;
+
+ try {
+ name = new String(rgch, "UTF-16LE");
+ } catch (UnsupportedEncodingException e){
+ name = "unknown";
+ }
+ return name;
+ }
+
+ /**
+ * Returns a definition table which can be used by the pocket excel
+ * decoder to build a complete definitions table for writing to the sxc
+ * document
+ */
+ public NameDefinition getNameDefinition() {
+
+ String baseCellAddress;
+ getDefinition(); // This must be called first so we know the type
+
+ baseCellAddress = "$" + wb.getSheetName(0) + ".A1";
+
+ NameDefinition nd = new NameDefinition(getName(),definition, baseCellAddress, isRangeType(), isExpressionType());
+ return nd;
+ }
+
+ /**
+ * Returns the definition
+ *
+ * @return the <code>String</code> containing the definition
+ */
+ private String getDefinition() {
+ // pexcel sometimes creates Name definition with no defintion, bug??
+ if(EndianConverter.readShort(cce)!=0) {
+ definition = fh.convertPXLToCalc(rgce);
+ definition = definition.substring(1); // remove the '='
+ definition = definition.replace(',', ';');
+ }
+ return definition;
+ }
+
+ /**
+ * Returns the defintion
+ *
+ * @return the <code>String</code> containing the definition
+ */
+ private boolean isRangeType() {
+
+ return fh.isRangeType();
+ }
+ /**
+ * Returns the defintion
+ *
+ * @return the <code>String</code> containing the definition
+ */
+ private boolean isExpressionType() {
+
+ return fh.isExpressionType();
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java
new file mode 100644
index 000000000000..d0a2fec3e90e
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record used to mark the end of a section of file
+ */
+public class Eof implements BIFFRecord {
+
+ /**
+ * Constructor
+ */
+ public Eof() {
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>BeginningOfFile</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.EOF_MARKER;
+ }
+
+ public int read(InputStream input) throws IOException {
+ return 0;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+
+ Debug.log(Debug.TRACE,"Writing Eof record");
+
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java
new file mode 100644
index 000000000000..5165efd84460
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java
@@ -0,0 +1,384 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.awt.Color;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.util.ColourConverter;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record descibing extended formatting information
+ *
+ */
+public class ExtendedFormat implements BIFFRecord,
+org.openoffice.xmerge.converter.xml.OfficeConstants {
+
+ private byte[] ixfnt = new byte[2]; // Index to Font Record
+ private byte[] ixnf = new byte[2];
+ private byte[] fattributes = new byte[4];
+ private byte[] fBaseAttr = new byte[2]; // base attribute flags
+ private byte[] fTextAttr = new byte[2]; // text attribute flags
+ private byte[] icvFore = new byte[2]; // Background colour of the cell
+ private byte[] icvFill = new byte[2];
+ private byte bRight; // Right border Style
+ private byte bTop; // Top border style
+ private byte bLeft; // Left border style
+ private byte bBottom; // Bottom border style
+ private byte backstyle;
+ private byte borderstyle;
+
+ public static final int TOP_BORDER = 0x01;
+ public static final int LEFT_BORDER = 0x02;
+ public static final int BOTTOM_BORDER = 0x04;
+ public static final int RIGHT_BORDER = 0x08;
+
+ // Horizontal Alignment Styles
+ public static final int NORMAL_ALIGN = 0x00;
+ public static final int LEFT_ALIGN = 0x01;
+ public static final int CENTER_ALIGN = 0x02;
+ public static final int RIGHT_ALIGN = 0x03;
+
+ // Vertical Alignment Styles
+ public static final int TOP_ALIGN = 0x10;
+ public static final int MIDDLE_ALIGN = 0x20;
+ public static final int BOTTOM_ALIGN = 0x30;
+
+ public static final int WORD_WRAP = 0x08;
+
+ /**
+ * Constructs an <code>ExtendedFormat</code> from the
+ * <code>InputStream</code>
+ *
+ * @param is <code>InputStream</code> to read from
+ */
+ public ExtendedFormat(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Constructs a pocket Excel Document using defualt values and sets the
+ * font index using the specified attribute
+ *
+ * @param ixfnt index of the font this format should use
+ */
+ public ExtendedFormat(int ixfnt, Format fmt) {
+
+ this.ixfnt = EndianConverter.writeShort((short)ixfnt);
+ String category = fmt.getCategory();
+ if(category.equalsIgnoreCase(CELLTYPE_CURRENCY)) {
+ this.ixnf = EndianConverter.writeShort((short) 0);
+ } else if(category.equalsIgnoreCase(CELLTYPE_DATE)) {
+ this.ixnf = EndianConverter.writeShort((short) 0x12);
+ } else if(category.equalsIgnoreCase(CELLTYPE_TIME)) {
+ this.ixnf = EndianConverter.writeShort((short) 0x1E);
+ } else {
+ this.ixnf = EndianConverter.writeShort((short) 0);
+ }
+ this.fattributes = new byte[] {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
+ this.fBaseAttr = new byte[] {(byte)0x02,(byte)0x00};
+
+ this.fTextAttr = new byte[] {(byte)0x00, (byte)0x00};
+
+ int align = fmt.getAlign();
+
+ // Horizontal alignment
+ if(align==Format.CENTER_ALIGN) {
+ fTextAttr[0] |= CENTER_ALIGN;
+ } else if(align==Format.LEFT_ALIGN) {
+ fTextAttr[0] |= LEFT_ALIGN;
+ } else if(align==Format.RIGHT_ALIGN) {
+ fTextAttr[0] |= RIGHT_ALIGN;
+ } else {
+ fTextAttr[0] |= NORMAL_ALIGN;
+ }
+
+ int vertAlign = fmt.getVertAlign();
+
+ // Vertical alignment
+ if(vertAlign==Format.TOP_ALIGN) {
+ fTextAttr[0] |= TOP_ALIGN;
+ } else if(vertAlign==Format.BOTTOM_ALIGN) {
+ fTextAttr[0] |= BOTTOM_ALIGN;
+ } else if(vertAlign==Format.MIDDLE_ALIGN) {
+ fTextAttr[0] |= MIDDLE_ALIGN;
+ } else {
+ fTextAttr[0] |= BOTTOM_ALIGN;
+ }
+
+ if(fmt.getAttribute(Format.WORD_WRAP)) {
+ fTextAttr[0] |= WORD_WRAP;
+ }
+
+ if(fmt.getAttribute(Format.LEFT_BORDER)) {
+ fTextAttr[1] |= LEFT_BORDER;
+ }
+ if(fmt.getAttribute(Format.RIGHT_BORDER)) {
+ fTextAttr[1] |= RIGHT_BORDER;
+ }
+ if(fmt.getAttribute(Format.TOP_BORDER)) {
+ fTextAttr[1] |= TOP_BORDER;
+ }
+ if(fmt.getAttribute(Format.BOTTOM_BORDER)) {
+ fTextAttr[1] |= BOTTOM_BORDER;
+ }
+
+ Color background = fmt.getBackground();
+ if( background != null ) {
+ ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
+ icvFill = EndianConverter.writeShort(cc.convertFromRGB(background));
+ } else {
+ icvFill = new byte[] {(byte)0xFF,(byte)0x00};
+ }
+
+ icvFore = new byte[] {(byte)0xFF,(byte)0x00};
+
+ bRight = (byte) 0xFF;
+ bTop = (byte) 0xFF;
+ bLeft = (byte) 0xFF;
+ bBottom = (byte) 0xFF;
+ backstyle = (byte) 0x00;
+ borderstyle = (byte) 0x00;
+
+ }
+
+ /**
+ * Get the font index this format uses
+ *
+ * @return the font index
+ */
+ public int getFontIndex() {
+ return EndianConverter.readShort(ixfnt);
+ }
+
+ /**
+ * Get the font index this format uses
+ *
+ * @return the font index
+ */
+ public int getFormatIndex() {
+ return EndianConverter.readShort(ixnf);
+ }
+
+ /**
+ * Get the font index this format uses
+ *
+ * @return the font index
+ */
+ public int getTextAttr() {
+ return EndianConverter.readShort(fTextAttr);
+ }
+
+ /**
+ * Get the background color this format uses
+ *
+ * @return the background color
+ */
+ public Color getBackground() {
+ short rgb = EndianConverter.readShort(icvFill);
+ Color c = null;
+ if(rgb!=0xFF) {
+ ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
+ c = cc.convertToRGB(rgb);
+ }
+ return c;
+ }
+
+ /**
+ * Get the Vertical alignment for this Format
+ *
+ * @return the alignment
+ */
+ public int getVertAlign() {
+
+ int mask = MIDDLE_ALIGN | BOTTOM_ALIGN | TOP_ALIGN;
+ int masked = fTextAttr[0] & mask;
+
+ if(masked == MIDDLE_ALIGN)
+ return Format.MIDDLE_ALIGN;
+
+ if(masked == BOTTOM_ALIGN)
+ return Format.BOTTOM_ALIGN;
+
+ if(masked == TOP_ALIGN)
+ return Format.TOP_ALIGN;
+
+ return Format.BOTTOM_ALIGN;
+ }
+
+ /**
+ * Get the alignment for this Format
+ *
+ * @return the alignment
+ */
+ public int getAlign() {
+
+ int mask = LEFT_ALIGN | CENTER_ALIGN | RIGHT_ALIGN;
+ int masked = fTextAttr[0] & mask;
+
+ if(masked == MIDDLE_ALIGN)
+ return Format.LEFT_ALIGN;
+
+ if(masked == CENTER_ALIGN)
+ return Format.CENTER_ALIGN;
+
+ if(masked == RIGHT_ALIGN)
+ return Format.RIGHT_ALIGN;
+
+ return Format.LEFT_ALIGN;
+ }
+
+ /**
+ * Is the word wrap set
+ *
+ * @return true if it is selected
+ */
+ public boolean isWordWrap() {
+ return (!((fTextAttr[0] & WORD_WRAP) == 0));
+ }
+ /**
+ * Get the border style
+ *
+ * @param side the side to test
+ * @return true if it is selected
+ */
+ public boolean isBorder(int side) {
+ return (!((fTextAttr[1] & side) == 0));
+ }
+
+ /**
+ * Compare two ExtendedFormat to see if the font index is the same
+ *
+ * @param the ExtendedFormat to be used in the comaprison
+ * @return boolean if the two are the same otherwise false
+ */
+ public boolean compareTo(ExtendedFormat rhs) {
+
+ if(EndianConverter.readShort(icvFill) !=
+ EndianConverter.readShort(rhs.icvFill))
+ return false;
+
+ if(this.getTextAttr() != rhs.getTextAttr())
+ return false;
+
+ if(this.getVertAlign() != rhs.getVertAlign())
+ return false;
+
+ if(this.getAlign() != rhs.getAlign())
+ return false;
+
+ if (this.getFontIndex() != rhs.getFontIndex())
+ return false;
+
+ if (this.getFormatIndex() != rhs.getFormatIndex())
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>ExtendedFormat</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.EXTENDED_FORMAT;
+ }
+
+ /**
+ * Reads the extended format from the <code>Inputstream</code>
+ *
+ * @param input the <code>Inputstream</code>to read
+ * @return toal number of bytes read
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(ixfnt);
+ numOfBytesRead += input.read(ixnf);
+ numOfBytesRead += input.read(fattributes);
+ numOfBytesRead += input.read(fBaseAttr);
+ numOfBytesRead += input.read(fTextAttr);
+ numOfBytesRead += input.read(icvFore);
+ numOfBytesRead += input.read(icvFill);
+ bRight = (byte) input.read();
+ bTop = (byte) input.read();
+ bLeft = (byte) input.read();
+ bBottom = (byte) input.read();
+ backstyle = (byte) input.read();
+ borderstyle = (byte) input.read();
+ numOfBytesRead += 6;
+
+ Debug.log(Debug.TRACE,"\tixfnt : "+ EndianConverter.readShort(ixfnt) +
+ " ixnf : " + EndianConverter.readShort(ixnf) +
+ " fattributes : " + EndianConverter.readInt(fattributes) +
+ " fBaseAttr : " + EndianConverter.readShort(fBaseAttr) +
+ "\n\tfTextAttr : " + EndianConverter.readShort(fTextAttr) +
+ " icvFore : " + EndianConverter.readShort(icvFore) +
+ " icvFill : " + EndianConverter.readShort(icvFill) +
+ " bRight : " + bRight +
+ "\n\tbTop : " + bTop +
+ " bLeft : " + bLeft +
+ " bBottom : " + bBottom +
+ " backstyle : " + backstyle +
+ " borderstyle : " + borderstyle);
+ return numOfBytesRead;
+ }
+
+ /**
+ * Writes the ExtendedFormat to the <code>Outputstream<code>
+ *
+ * @param output the <code>Outputstream</code>to write to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(ixfnt);
+ output.write(ixnf);
+ output.write(fattributes);
+ output.write(fBaseAttr);
+ output.write(fTextAttr);
+ output.write(icvFore);
+ output.write(icvFill);
+ output.write(bRight);
+ output.write(bTop);
+ output.write(bLeft);
+ output.write(bBottom);
+ output.write(backstyle);
+ output.write(borderstyle);
+
+ Debug.log(Debug.TRACE,"Writing ExtendedFormat record");
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java
new file mode 100644
index 000000000000..8d702640a500
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+/**
+ * Represents a BIFF Record describing a floating point
+ */
+public class FloatNumber extends CellValue {
+
+ protected byte[] num = new byte[8];
+
+ /**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public FloatNumber(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Constructs a <code>FloatNumber</code> using specified attributes
+ *
+ * @param row row number
+ * @param col column number
+ * @param cellContents contents of the cell
+ * @param ixfe font index
+ */
+ public FloatNumber(int row, int column, String cellContents, int ixfe) throws IOException {
+
+ setIxfe(ixfe);
+ setRow(row);
+ setCol(column);
+ double cellLong = (double) Double.parseDouble(cellContents);
+ num = EndianConverter.writeDouble(cellLong);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>FloatNumber</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.NUMBER_CELL;
+ }
+
+ /**
+ * Reads a<code>FloatNumber</code> from the specified <code>InputStream</code>
+ *
+ * @param input the <code>InputStram</code> to read from
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = super.read(input);
+
+ numOfBytesRead += input.read(num);
+
+ Debug.log(Debug.TRACE," num : " + getString());
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+
+ super.write(output);
+
+ output.write(num);
+
+ Debug.log(Debug.TRACE,"Writing FloatNumber record");
+ }
+
+
+ /**
+ * Gets the numerical value the cell represents
+ *
+ * @return the <code>String</code> representing a double value
+ */
+ public String getString() throws IOException {
+
+ double value = EndianConverter.readDouble(num);
+ Double myDo = new Double(value);
+ return myDo.toString();
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java
new file mode 100644
index 000000000000..61d9746c80d3
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java
@@ -0,0 +1,286 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.awt.Color;
+
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.util.ColourConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF Record descibing a font used
+ */
+public class FontDescription implements BIFFRecord {
+
+ private byte[] dwHeight = new byte[2];
+ private byte[] grbit = new byte[2];
+ private byte[] icvFore = new byte[2];
+ private byte[] bls = new byte[2];
+ private byte[] Reserved2 = new byte[2];
+ private byte uls;
+ private byte bFamily;
+ private byte bCharSet;
+ private byte Reserved3;
+ private byte cch;
+ private byte[] rgch;
+
+ public static final int UNDERLINE = 0x01;
+ public static final int ITALIC = 0x02;
+
+ /**
+ * Constructs a FontDescription from the bold italic and undelrine attributes
+ *
+ * @param italic Italic attribute
+ * @param bold Bold attribute
+ * @param underline Underline attribute
+ */
+ public FontDescription(Format fmt) throws IOException {
+
+ Debug.log(Debug.TRACE,"Building FontDescriptor based on Format : " + fmt);
+
+ this.dwHeight = EndianConverter.writeShort((short) (fmt.getFontSize()*20));
+
+ grbit = new byte[] {(byte)0x00, (byte)0x00};
+ bls = EndianConverter.writeShort((short) 400);
+ uls = 0;
+
+ if (fmt.getAttribute(Format.ITALIC))
+ grbit[0] |= ITALIC;
+
+ if (fmt.getAttribute(Format.BOLD))
+ bls = EndianConverter.writeShort((short) 700);
+
+ if (fmt.getAttribute(Format.UNDERLINE))
+ uls |= UNDERLINE;
+
+
+ bFamily = 0;
+ bCharSet = 0;
+
+ String fontName = fmt.getFontName();
+ if( !fontName.equals("Tahoma") &&
+ !fontName.equals("Courier New")) {
+ // We will set our default font to be Tahoma
+ fontName = new String("Tahoma");
+ }
+
+ cch = (byte) fontName.length();
+ rgch = fontName.getBytes("UTF-16LE");
+
+ Color foreground = fmt.getForeground();
+ if( foreground != null ) {
+ ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
+ icvFore = EndianConverter.writeShort(cc.convertFromRGB(foreground));
+ } else {
+ icvFore = new byte[] {(byte)0xFF,(byte)0x00};
+ }
+
+ Reserved2 = EndianConverter.writeShort((short) 0);
+ Reserved3 = 0;
+
+ }
+
+ /**
+ * Tests if this font descriptor defines italic
+ *
+ * @return true if italic otherwise false
+ */
+ public boolean isItalic() {
+
+ return (EndianConverter.readShort(grbit) == 2);
+ }
+
+ /**
+ * Tests if this font descriptor defines underline
+ *
+ * @return true if underline otherwise false
+ */
+ public boolean isUnderline() {
+
+ return (uls == 1);
+ }
+
+ /**
+ * Tests if this font descriptor defines bold
+ *
+ * @return true if bold otherwise false
+ */
+ public boolean isBold() {
+
+ return (EndianConverter.readShort(bls) == 700);
+ }
+
+ /**
+ * Get the background color this format uses
+ *
+ * @return the background color
+ */
+ public Color getForeground() {
+ short rgb = EndianConverter.readShort(icvFore);
+ Color c = null;
+ if(rgb!=0xFF) {
+ ColourConverter cc = new ColourConverter(PocketExcelConstants.cLookup);
+ c = cc.convertToRGB(rgb);
+ }
+ return c;
+ }
+
+ /**
+ * Compares current font descriptor against one passed in
+ *
+ * @return true if attrbitues are the same
+ */
+ public boolean compareTo(FontDescription rhs) {
+
+ if(EndianConverter.readShort(icvFore) !=
+ EndianConverter.readShort(rhs.icvFore))
+ return false;
+
+ if (EndianConverter.readShort(dwHeight) !=
+ EndianConverter.readShort(dwHeight))
+ return false;
+
+ if (this.getFont() != rhs.getFont())
+ return false;
+
+ if (this.isBold() != rhs.isBold())
+ return false;
+
+ if (this.isUnderline() != rhs.isUnderline())
+ return false;
+
+ if (this.isItalic() != rhs.isItalic())
+ return false;
+
+ return true;
+ }
+
+
+ /**
+ * Constructs a Font Description from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a <code>FontDescription</code>
+ */
+ public FontDescription(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>FontDescription</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.FONT_DESCRIPTION;
+ }
+
+ /**
+ * Get the Font size
+ *
+ */
+ public int getFontSize() {
+ return EndianConverter.readShort(dwHeight)/20;
+ }
+
+ /**
+ * Get the font name
+ *
+ */
+ public String getFont() {
+
+ String name;
+
+ try {
+ name = new String(rgch, "UTF-16LE");
+ } catch (UnsupportedEncodingException e){
+ name = "Tahoma";
+ }
+ return name;
+ }
+
+ /**
+ * Constructs a Font Description from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a <code>FontDescription</code>
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(dwHeight);
+ numOfBytesRead += input.read(grbit);
+ numOfBytesRead += input.read(icvFore);
+ numOfBytesRead += input.read(bls);
+ numOfBytesRead += input.read(Reserved2);
+ uls = (byte) input.read();
+ bFamily = (byte) input.read();
+ bCharSet = (byte) input.read();
+ Reserved3 = (byte) input.read();
+ cch = (byte) input.read();
+ numOfBytesRead += 5;
+
+ rgch = new byte[cch*2];
+ input.read(rgch, 0, cch*2);
+
+ Debug.log(Debug.TRACE,"\tdwHeight : "+ EndianConverter.readShort(dwHeight) +
+ " grbit : " + EndianConverter.readShort(grbit) +
+ " bls : " + EndianConverter.readShort(bls) +
+ " uls : " + uls +
+ "\n\tFamily : " + bFamily +
+ " bCharSet : " + bCharSet +
+ " cch : " + cch +
+ " rgch : " + new String(rgch,"UTF-16LE"));
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(dwHeight);
+ output.write(grbit);
+ output.write(icvFore);
+ output.write(bls);
+ output.write(Reserved2);
+ output.write(uls);
+ output.write(bFamily);
+ output.write(bCharSet);
+ output.write(Reserved3);
+ output.write(cch);
+ output.write(rgch);
+
+ Debug.log(Debug.TRACE,"Writing FontDescription record");
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java
new file mode 100644
index 000000000000..a073883b2e8e
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java
@@ -0,0 +1,257 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula.FormulaHelper;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF Record describing a formula
+ */
+public class Formula extends CellValue implements OfficeConstants {
+
+ private byte[] num = new byte[8];
+ private byte grbit;
+ private byte[] cce = new byte[2];
+ private byte[] rgce;
+ private FormulaHelper fh = new FormulaHelper();
+
+ /**
+ * Constructs a <code>Formula</code> using specified attributes
+ *
+ * @param row row number
+ * @param col column number
+ * @param cellContents contents of the cell
+ * @param ixfe font index
+ * @param value the value of the cell
+ */
+ public Formula(int row, int column, String cellContents, int ixfe, Format fmt, Workbook wb)
+ throws Exception {
+
+ fh.setWorkbook(wb);
+
+ setRow(row);
+ setCol(column);
+ setIxfe(ixfe);
+ setFormula(cellContents);
+
+ String category = fmt.getCategory();
+ String value = fmt.getValue();
+
+ if(category.equalsIgnoreCase(CELLTYPE_BOOLEAN)) {
+ num[0]=(byte)0x01;
+ num[1]=(byte)0x00;
+ if(value.equalsIgnoreCase("true")) {
+ num[2]=(byte)0x01;
+ } else {
+ num[2]=(byte)0x00;
+ }
+ num[3]=(byte)0x00;num[4]=(byte)0x00;num[5]=(byte)0x00;
+ num[6]=(byte)0xFF;num[7]=(byte)0xFF;
+ } else if(category.equalsIgnoreCase(CELLTYPE_DATE)) {
+ Debug.log(Debug.TRACE,"Date Formula");
+ num = EndianConverter.writeDouble(toExcelSerialDate(fmt.getValue()));
+ } else if(category.equalsIgnoreCase(CELLTYPE_TIME)) {
+ Debug.log(Debug.TRACE,"Time Formula");
+ num = EndianConverter.writeDouble(toExcelSerialTime(fmt.getValue()));
+ } else if(category.equalsIgnoreCase(CELLTYPE_PERCENT)) {
+ Debug.log(Debug.TRACE,"Percent Formula");
+ double percent = (double) Double.parseDouble(fmt.getValue());
+ num = EndianConverter.writeDouble(percent);
+ } else if(category.equalsIgnoreCase(CELLTYPE_CURRENCY)) {
+ Debug.log(Debug.TRACE,"Currency Formula");
+ } else if(category.equalsIgnoreCase(CELLTYPE_STRING)) {
+ Debug.log(Debug.TRACE,"String Formula");
+ num[0]=(byte)0x00;
+ num[1]=(byte)0x00;
+ num[2]=(byte)0x00;
+ num[3]=(byte)0x00;
+ num[4]=(byte)0x00;
+ num[5]=(byte)0x00;
+ num[6]=(byte)0xFF;
+ num[7]=(byte)0xFF;
+ } else {
+ Debug.log(Debug.TRACE,"Float Formula");
+ double cellLong = (double) Double.parseDouble(fmt.getValue());
+ num = EndianConverter.writeDouble(cellLong);
+ }
+ }
+
+ /**
+ * Translates a <code>String</code> written in infix which represents a
+ * formula into a byte[] what can be written to pocket excel file.
+ *
+ * @param formula string
+ */
+ public void setFormula(String inFormula) throws Exception {
+
+ rgce = fh.convertCalcToPXL(inFormula);
+ cce = EndianConverter.writeShort((short) rgce.length);
+ }
+
+ /**
+ * Constructs a pocket Excel formula from the
+ * <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public Formula(InputStream is, Workbook wb) throws IOException {
+ read(is);
+ fh.setWorkbook(wb);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Formula</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.FORMULA_CELL;
+ }
+
+ /**
+ * Reads the formula data members from the stream. Byte arrays for Strings
+ * are doubled as they are stored as unicode
+ *
+ * @return total number of bytes read
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = super.read(input);
+
+ numOfBytesRead += input.read(num);
+ grbit = (byte) input.read();
+ numOfBytesRead ++;
+ numOfBytesRead += input.read(cce);
+
+ int strLen = EndianConverter.readShort(cce);
+ rgce = new byte[strLen];
+ input.read(rgce, 0, strLen);
+
+ Debug.log(Debug.TRACE, " num : " + num +
+ "\n\tgrbit : " + grbit +
+ " cce : " + EndianConverter.readShort(cce) +
+ " rgce : " + new String(rgce,"UTF-16LE") +
+ "\n" + numOfBytesRead + " Bytes Read");
+
+ return numOfBytesRead;
+ }
+
+ /**
+ * Writes the Formula record to the <code>OutputStream</code>
+ *
+ * @param the <code>OutputStream</code> being written to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+
+ super.write(output);
+
+ output.write(num);
+ output.write(grbit);
+ output.write(cce);
+ output.write(rgce);
+
+ Debug.log(Debug.TRACE,"Writing Formula record");
+ }
+
+ /**
+ * Gets the <code>String</code> representing the cell value
+ *
+ * @return the <code>String</code> representing the cell value
+ */
+ public String getValue() throws IOException {
+
+ double value = EndianConverter.readDouble(num);
+ Double myDo = new Double(value);
+ return myDo.toString();
+ }
+
+ /**
+ * Gets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ public String getString() throws IOException {
+
+ return fh.convertPXLToCalc(rgce);
+ }
+
+ /**
+ * Excel dates are the number of days since 1/1/1900. This method converts
+ * to this date.
+ *
+ * @param s String representing a date in the form YYYY-MM-DD
+ * @return The excel serial date
+ */
+ public long toExcelSerialDate(String s) throws IOException {
+
+ int year = Integer.parseInt(s.substring(0,4));
+ int month = Integer.parseInt(s.substring(5,7));
+ int day = Integer.parseInt(s.substring(8,10));
+
+ long serialDate = (1461 * (year + 4800 + (month - 14) / 12)) / 4 +
+ (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 -
+ (3 * ((year + 4900 + (month - 14) / 12)) / 100) / 4 +
+ day - 2415019 - 32075;
+
+ return serialDate;
+ }
+
+ /**
+ * Excel times are a fraction of a 24 hour day expressed in seconds. This method converts
+ * to this time.
+ *
+ * @param s String representing a time in the form ??HH?MM?SS?
+ * @return The excel serial time
+ */
+ public double toExcelSerialTime(String s) throws IOException {
+
+ int hours = Integer.parseInt(s.substring(2,4));
+ int mins = Integer.parseInt(s.substring(5,7));
+ int secs = Integer.parseInt(s.substring(8,10));
+
+ int timeSecs = (hours*3600) + (mins*60) + (secs);
+
+ double d = (double) timeSecs / (24 * 3600);
+
+ return d;
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java
new file mode 100644
index 000000000000..d4ad28cc7e2b
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Reperesent a BIFF Record descibing a cell containing a string
+ */
+public class LabelCell extends CellValue {
+
+ private byte[] cch = new byte[2];
+ private byte[] rgch;
+
+ /**
+ * Constructs a <code>LabelCell</code> using specified attributes
+ *
+ * @param row row number
+ * @param col column number
+ * @param cellContents contents of the cell
+ * @param ixfe font index
+ */
+ public LabelCell(int row, int column, String cellContents, int ixfe)
+ throws IOException {
+
+ setLabel(cellContents);
+ setRow(row);
+ setCol(column);
+ setIxfe(ixfe);
+ }
+
+ /**
+ * Reads a LabelCell from the <code>InputStream</code>
+ *
+ * @param is the <code>Inputstream</code> to read from
+ */
+ public LabelCell(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Writes a <code>LabelCell</code> to the specified <code>Outputstream</code>
+ *
+ * @param os the <code>OutputStream</code> to write to
+ */
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+
+ super.write(output);
+
+ output.write(cch);
+ output.write(rgch);
+
+ Debug.log(Debug.TRACE,"Writing Label record");
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>LabelCell</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.LABEL_CELL;
+ }
+
+ /**
+ * Reads a<code>LabelCell</code> from the specified <code>InputStream</code>
+ *
+ * @param input the <code>InputStram</code> to read from
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = super.read(input);
+
+ numOfBytesRead += input.read(cch);
+
+ int strLen = EndianConverter.readShort(cch)*2;
+ rgch = new byte[strLen];
+ input.read(rgch, 0, strLen);
+
+ Debug.log(Debug.TRACE, " cch : " + EndianConverter.readShort(cch) +
+ " rgch : " + new String(rgch, "UTF-16LE"));
+
+ return numOfBytesRead;
+ }
+
+
+ /**
+ * Gets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ public String getString() throws IOException {
+ return (new String(rgch,"UTF-16LE"));
+ }
+
+ /**
+ * Sets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ private void setLabel(String cellContents) throws IOException {
+ rgch = cellContents.getBytes("UTF-16LE");
+ cch = EndianConverter.writeShort((short)cellContents.length());
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java
new file mode 100644
index 000000000000..342d9b676bcd
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java
@@ -0,0 +1,93 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF Record describing a number format
+ */
+public class NumberFormat implements BIFFRecord {
+
+ private byte cce;
+ private byte[] rgch;
+
+ /**
+ * Constructs a NumberFormat Record from the <code>InputStream</code>
+ *
+ * @param is InputStream containing the record data
+ */
+ public NumberFormat(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>NumberFormat</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.NUMBER_FORMAT;
+ }
+
+ /**
+ * Reads the NumberFormat from the <code>InputStream</code> Byte array
+ * containg strings are doubled in length becuse they use unicode
+ *
+ * @return the total number of bytes read
+ */
+ public int read(InputStream input) throws IOException {
+
+ cce = (byte) input.read();
+ int numOfBytesRead = 1;
+
+ rgch = new byte[cce*2];
+ numOfBytesRead += input.read(rgch, 0, cce*2);
+
+ Debug.log(Debug.TRACE, "\tcce : "+ cce +
+ " rgch : " + new String(rgch,"UTF-16LE"));
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(cce);
+ output.write(rgch);
+
+ Debug.log(Debug.TRACE,"Writing NumberFormat record");
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java
new file mode 100644
index 000000000000..b65d1027f969
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java
@@ -0,0 +1,218 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.awt.Point;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+import org.openoffice.xmerge.converter.xml.sxc.SheetSettings;
+
+/**
+ * Represents a BIFF Record that describes the number and position of unfrozen
+ * panes.
+ */
+public class Pane implements BIFFRecord {
+
+ private byte[] x = new byte[2];
+ private byte[] y = new byte[2];
+ private byte[] rwTop = new byte[2];
+ private byte[] colLeft = new byte[2];
+ private byte pnnAcct;
+
+ /**
+ * Default Constructor
+ */
+ public Pane() {
+ pnnAcct = (byte) 0x02; // Default setting
+ }
+
+ /**
+ * Constructs a Pane Record from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pane record
+ */
+ public Pane(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Pane</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.PANE_INFO;
+ }
+
+ /**
+ * Gets the split point for this pane, in the case of splits this will be
+ * in twips.
+ *
+ * @return the split point
+ */
+ public Point getSplitPoint() {
+
+ int xTwips = EndianConverter.readShort(x)/11;
+ int yTwips = EndianConverter.readShort(y)/15;
+ return (new Point(xTwips, yTwips));
+ }
+
+ /**
+ * Gets the freeze point for this pane, in the case of freezes this will
+ * be a zero-based index to either the column or row.
+ *
+ * @return the freeze point
+ */
+ public Point getFreezePoint() {
+
+ return (new Point(EndianConverter.readShort(x),
+ EndianConverter.readShort(y)));
+ }
+
+ /**
+ * Sets the split point for this pane, coordinates are in column row units
+ * if the split type is freeze or twips if split type is split.
+ *
+ * @param splitType contains the X and Y split types (freeze or split)
+ * @param p the split point
+ */
+ public void setSplitPoint(Point splitType, Point p) {
+
+ if(splitType.getX()==SheetSettings.SPLIT
+ || splitType.getY()==SheetSettings.SPLIT) {
+ int yTwips = (int) p.getY();
+ short yPxl = (short) (yTwips * 15);
+ y = EndianConverter.writeShort(yPxl);
+ int xTwips = (int) p.getX();
+ short xPxl = (short) (xTwips * 11);
+ x = EndianConverter.writeShort(xPxl);
+ } else {
+ y = EndianConverter.writeShort((short) p.getY());
+ x = EndianConverter.writeShort((short) p.getX());
+ }
+
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Pane</code>
+ */
+ public void setPaneNumber(int paneNumber) {
+ pnnAcct = (byte) paneNumber;
+ }
+
+ /**
+ * Get the pane number of the active pane
+ * 0 - bottom right, 1 - top right
+ * 2 - bottom left, 3 - top left
+ *
+ * @return the hex code for <code>Pane</code>
+ */
+ public int getPaneNumber() {
+ return pnnAcct;
+ }
+
+ /**
+ * Set the top row visible in the lower pane
+ *
+ * @param top 0-based inex of the top row
+ */
+ public void setTop(int top) {
+ rwTop = EndianConverter.writeShort((short)top);
+ }
+
+ /**
+ * Set leftmost column visible in the right pane
+ *
+ * @param left 0-based index of the leftmost column
+ */
+ public void setLeft(int left) {
+ colLeft = EndianConverter.writeShort((short)left);
+ }
+
+ /**
+ * Get the top row visible in the lower pane
+ *
+ * @return the hex code for <code>Pane</code>
+ */
+ public int getTop() {
+ return EndianConverter.readShort(rwTop);
+ }
+
+ /**
+ * Get leftmost column visible in the right pane
+ *
+ * @return 0-based index of the column
+ */
+ public int getLeft() {
+ return EndianConverter.readShort(colLeft);
+ }
+
+
+ /**
+ * Reads a <code>Pane</code> record from the <code>InputStream</code>
+ *
+ * @param input <code>InputStream</code> to read from
+ * @return the total number of bytes read
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(x);
+ numOfBytesRead += input.read(y);
+ numOfBytesRead += input.read(rwTop);
+ numOfBytesRead += input.read(colLeft);
+ pnnAcct = (byte) input.read();
+ numOfBytesRead++;
+
+ Debug.log(Debug.TRACE, "\tx : "+ EndianConverter.readShort(x) +
+ " y : " + EndianConverter.readShort(y) +
+ " rwTop : " + EndianConverter.readShort(rwTop) +
+ " colLeft : " + EndianConverter.readShort(colLeft) +
+ " pnnAcct : " + pnnAcct);
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(x);
+ output.write(y);
+ output.write(rwTop);
+ output.write(colLeft);
+ output.write(pnnAcct);
+
+ Debug.log(Debug.TRACE,"Writing Pane record");
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java
new file mode 100644
index 000000000000..8e3067d26c6b
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java
@@ -0,0 +1,138 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents s BIFF Record that describes the format of a column
+ */
+public class Row implements BIFFRecord {
+
+ private byte[] rw = new byte[2];
+ private byte[] miyRw = new byte[2];
+ private byte[] grbit = new byte[2];
+ private byte[] ixfe = new byte[2];
+ private float scale = (float) 1;
+
+ /**
+ * Constructs a pocket Excel Document from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param rw Zero based row number
+ * @param miyRw row height
+ */
+ public Row(int rw, int miyRw, boolean userDefined) {
+ this.rw = EndianConverter.writeShort((short) rw);
+ miyRw *= scale;
+ this.miyRw = EndianConverter.writeShort((short) miyRw);
+ if(userDefined) {
+ grbit = EndianConverter.writeShort((short) 2);
+ } else {
+ grbit = EndianConverter.writeShort((short) 0);
+ }
+ ixfe = EndianConverter.writeShort((short) 0);
+ }
+
+ /**
+ * Constructs a Row fro man <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pane Record
+ */
+ public Row(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Row</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.ROW_DESCRIPTION;
+ }
+
+ /**
+ * Get the height of this row
+ *
+ * @return the height of this row
+ */
+ public short getRowHeight() {
+ return EndianConverter.readShort(miyRw);
+ }
+
+ /**
+ * Get the rown number for this style
+ *
+ * @return the row this style applies to
+ */
+ public short getRowNumber() {
+ return EndianConverter.readShort(rw);
+ }
+
+ /**
+ * Reads a Row from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pane Record
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(rw);
+ numOfBytesRead += input.read(miyRw);
+ short scaledHeight = (short) (EndianConverter.readShort(miyRw) / scale);
+ miyRw = EndianConverter.writeShort(scaledHeight);
+ numOfBytesRead += input.read(grbit);
+ numOfBytesRead += input.read(ixfe);
+
+ Debug.log(Debug.TRACE,"\trw : "+ EndianConverter.readShort(rw) +
+ " miyRw : " + EndianConverter.readShort(miyRw) +
+ " grbit : " + EndianConverter.readShort(grbit) +
+ " ixfe : " + EndianConverter.readShort(ixfe));
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(rw);
+ output.write(miyRw);
+ output.write(grbit);
+ output.write(ixfe);
+
+ Debug.log(Debug.TRACE,"Writing Row record");
+
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java
new file mode 100644
index 000000000000..308eae29227e
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.awt.Point;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF Record that describes the selected area of a worksheet
+ */
+public class Selection implements BIFFRecord {
+
+ private byte[] rwTop = new byte[2];
+ private byte colLeft;
+ private byte[] rwBottom = new byte[2];
+ private byte colRight;
+ private byte[] rwActive = new byte[2];
+ private byte colActive;
+
+ /**
+ * Default Constructor
+ */
+ public Selection() {
+ this.rwTop = EndianConverter.writeShort((short) 0);
+ this.colLeft = 0;
+ this.rwBottom = EndianConverter.writeShort((short) 0);
+ this.colRight = 0;
+ this.rwActive = EndianConverter.writeShort((short) 0);
+ this.colActive = 0;
+
+ }
+
+ /**
+ * Constructs a Selection Record from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public Selection(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Selection</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.CURRENT_SELECTION;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Selection</code>
+ */
+ public Point getActiveCell() {
+ Point p = new Point(colActive, EndianConverter.readShort(rwActive));
+ return p;
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Selection</code>
+ */
+ public void setActiveCell(Point p) {
+
+ colActive = (byte) p.getX();
+ rwActive = EndianConverter.writeShort((short) p.getY());
+ }
+
+ /**
+ * Reads a Selection Record from the <code>InputStream</code>
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(rwTop);
+ colLeft += (byte) input.read();
+ numOfBytesRead += input.read(rwBottom);
+ colRight += (byte) input.read();
+ numOfBytesRead += input.read(rwActive);
+ colActive += (byte) input.read();
+ numOfBytesRead += 3;
+
+ Debug.log(Debug.TRACE,"\trwTop : "+ EndianConverter.readShort(rwTop) +
+ " colLeft : " + colLeft +
+ " rwBottom : " + EndianConverter.readShort(rwBottom) +
+ " colRight : "+ colRight +
+ " rwActive : " + EndianConverter.readShort(rwActive) +
+ " colActive : " + colActive);
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(rwTop);
+ output.write(colLeft);
+ output.write(rwBottom);
+ output.write(colRight);
+ output.write(rwActive);
+ output.write(colActive);
+
+ Debug.log(Debug.TRACE,"Writing Selection record");
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java
new file mode 100644
index 000000000000..c516eca69b1b
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF Record that describes the value of a formula that
+ * evaluates to a string
+ */
+public class StringValue implements BIFFRecord {
+
+ private byte[] cch = new byte[2];
+ private byte[] rgch;
+
+ /**
+ * Constructs a StringValue Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a StringValue Record
+ */
+ public StringValue(String str) throws IOException {
+ cch = EndianConverter.writeShort((short) str.length());
+ rgch = new byte[str.length()];
+ rgch = str.getBytes("UTF-16LE");
+ }
+
+ /**
+ * Constructs a StringValue Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a StringValue Record
+ */
+ public StringValue(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>StringValue</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.FORMULA_STRING;
+ }
+
+ /**
+ * Reads a StringVlaue Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a StringValue Record
+ */
+ public int read(InputStream input) throws IOException {
+
+ cch[0] = (byte) input.read();
+ cch[1] = (byte) input.read();
+ int numOfBytesRead = 1;
+
+ int strlen = EndianConverter.readShort(cch)*2;
+ rgch = new byte[strlen];
+ numOfBytesRead += input.read(rgch, 0, strlen);
+
+ Debug.log(Debug.TRACE,"\tcch : "+ cch +
+ " rgch : " + rgch);
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(cch);
+ output.write(rgch);
+
+ Debug.log(Debug.TRACE,"Writing StringValue record");
+ }
+
+ /**
+ * Gets the <code>String</code> representing the cells contents
+ *
+ * @return the <code>String</code> representing the cells contents
+ */
+ public String getString() throws IOException {
+ String name;
+
+ try {
+ name = new String(rgch, "UTF-16LE");
+ } catch (UnsupportedEncodingException e){
+ name = "unknown";
+ }
+ return name;
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java
new file mode 100644
index 000000000000..e6f941d46556
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.lang.Exception;
+
+/**
+ * At the moment any functions within a formula will result in this exception
+ * being thrown.
+ */
+public class UnsupportedFormulaException extends Exception {
+
+ public UnsupportedFormulaException(String message){
+ super(message);
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java
new file mode 100644
index 000000000000..c060db90d60d
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * Represents a BIFF REcord that describes workbook window attributes
+ */
+public class Window1 implements BIFFRecord {
+
+ private byte[] grbit = new byte[2];
+ private byte[] itabCur = new byte[2]; // index of selected worksheet
+
+ /**
+ * Constructor
+ */
+ public Window1() {
+ grbit = EndianConverter.writeShort((short) 0);
+ itabCur = EndianConverter.writeShort((short) 0);
+ }
+
+ /**
+ * Constructs a Window1 Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a Window1 Record
+ */
+ public Window1(InputStream is) throws IOException{
+ read(is);
+ }
+
+ /**
+ * Set the number of the active sheet
+ *
+ * @param activeSheet number of the active sheet
+ */
+ public void setActiveSheet(int activeSheet) {
+ itabCur = EndianConverter.writeShort((short) activeSheet);
+ }
+
+ /**
+ * Get the number of the active sheet
+ *
+ * @return number of the active sheet
+ */
+ public int getActiveSheet() {
+ return EndianConverter.readShort(itabCur);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Window1</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.WINDOW_INFO;
+ }
+
+ /**
+ * Reads a Window1 Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a Window1 Record
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(grbit);
+ numOfBytesRead += input.read(itabCur);
+
+ Debug.log(Debug.TRACE,"\tgrbit : "+ EndianConverter.readShort(grbit) +
+ " itabCur : " + EndianConverter.readShort(itabCur));
+
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(grbit);
+ output.write(itabCur);
+
+ Debug.log(Debug.TRACE,"Writing Window1 record");
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java
new file mode 100644
index 000000000000..4c49a941219c
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java
@@ -0,0 +1,154 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.awt.Point;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+import org.openoffice.xmerge.converter.xml.sxc.SheetSettings;
+
+
+/**
+ * Represents a BIFF Record that describes worksheet window attributes
+ */
+public class Window2 implements BIFFRecord {
+
+ private final static int FROZEN = 0x08;
+ private final static int NOSPLIT = 0x01;
+
+ private byte[] rwTop = new byte[2];
+ private byte colLeft;
+ private byte[] grbit = new byte[2];
+
+ /**
+ * Constructor
+ */
+ public Window2() {
+ this.rwTop = EndianConverter.writeShort((short) 0);
+ this.colLeft = 0;
+ this.grbit = EndianConverter.writeShort((short) 0);
+ }
+
+ /**
+ * Constructs a Window2 Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a Window2 Record
+ */
+ public Window2(InputStream is) throws IOException {
+ read(is);
+ }
+
+ /**
+ * Get the hex code for this particular <code>BIFFRecord</code>
+ *
+ * @return the hex code for <code>Window2</code>
+ */
+ public short getBiffType() {
+ return PocketExcelConstants.SHEET_WINDOW_INFO;
+ }
+
+ /**
+ * Sets the split type for this pane, the split type is the same for both
+ * x and y so we only test against one.
+ *
+ * @param splitType the split type based on types defined in
+ * <code>sheetSettings</code>
+ */
+ public void setSplitType(Point splitType) {
+ if(splitType.getX()==SheetSettings.SPLIT) {
+ grbit[0] &= ~FROZEN;
+ grbit[1] &= ~NOSPLIT;
+ } else {
+ grbit[0] |= FROZEN;
+ grbit[1] |= NOSPLIT;
+ }
+ }
+
+ /**
+ * This method tests if this object describes a freeze
+ *
+ * @return true if freeze otherwise false
+ */
+ public boolean isFrozen() {
+ if((grbit[0] & FROZEN) != FROZEN)
+ return false;
+
+ if((grbit[1] & NOSPLIT) != NOSPLIT)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * This method tests if this object describes a split
+ *
+ * @return true if split otherwise false
+ */
+ public boolean isSplit() {
+ if((grbit[0] & FROZEN) == FROZEN)
+ return false;
+
+ if((grbit[1] & NOSPLIT) == NOSPLIT)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Reads a Window2 Record from an <code>InputStream</code>
+ *
+ * @param is InputStream containing a Window2 Record
+ */
+ public int read(InputStream input) throws IOException {
+
+ int numOfBytesRead = input.read(rwTop);
+ colLeft = (byte) input.read();
+ numOfBytesRead++;
+ numOfBytesRead += input.read(grbit);
+
+ Debug.log(Debug.TRACE,"\trwTop : "+ EndianConverter.readShort(rwTop) +
+ " colLeft : " + colLeft +
+ " grbit : " + EndianConverter.readShort(grbit));
+ return numOfBytesRead;
+ }
+
+ public void write(OutputStream output) throws IOException {
+
+ output.write(getBiffType());
+ output.write(rwTop);
+ output.write(colLeft);
+ output.write(grbit);
+
+ Debug.log(Debug.TRACE,"Writing Window2 record");
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java
new file mode 100644
index 000000000000..5a9f329e4667
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java
@@ -0,0 +1,539 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.sxc.BookSettings;
+import org.openoffice.xmerge.converter.xml.sxc.SheetSettings;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+import org.openoffice.xmerge.converter.xml.sxc.ColumnRowInfo;
+
+/**
+ * This class is used by <code> PxlDocument</code> to maintain pexcel
+ * workbooks.
+ *
+ * @author Martin Maher
+ */
+public class Workbook implements org.openoffice.xmerge.Document,
+OfficeConstants {
+
+ private Vector fonts = new Vector();
+ private Vector extendedFormats = new Vector();
+ private Vector worksheets = new Vector();
+ private Vector boundsheets = new Vector();
+ private Vector definedNames = new Vector();
+ private static final CodePage cp;
+ private static final Window1 win1;
+ private static final BeginningOfFile bof;;
+ private static final Eof eof;
+ private String fileName;
+
+ static {
+ cp = new CodePage();
+ win1 = new Window1();
+ bof = new BeginningOfFile(true);
+ eof = new Eof();
+ }
+
+
+ /**
+ * Constructs a pocket Excel Workbook with the name of the file passed in
+ * as an argument. Also fills out a basic header block containing the
+ * minimum number of objects that can be created at this time.
+ *
+ * @param name Name of the Pocket Excel Data file. (excluding the file
+ * extension)
+ */
+ public Workbook(String name) throws IOException {
+ fileName = name + PocketExcelConstants.FILE_EXTENSION;
+ Format defaultFormat = new Format();
+ FontDescription fd = new FontDescription(defaultFormat);
+ fonts.add(fd);
+ ExtendedFormat xf = new ExtendedFormat(0, defaultFormat);
+ extendedFormats.add(xf);
+ }
+
+ /**
+ * Constructs a pocket Excel Workbook from the
+ * <code>InputStream</code> and assigns it the document name passed in
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public Workbook(String name, InputStream is) throws IOException {
+ read(is);
+ fileName = name;
+ }
+
+ /**
+ * Writes the current workbook to the <code>Outputstream</code>
+ *
+ * @param os The destination outputstream
+ */
+ public void write(OutputStream os) throws IOException {
+ bof.write(os);
+ cp.write(os);
+ for(Enumeration e = definedNames.elements();e.hasMoreElements();) {
+ DefinedName dn = (DefinedName) e.nextElement();
+ dn.write(os);
+ }
+ win1.write(os);
+ for(Enumeration e = fonts.elements();e.hasMoreElements();) {
+ FontDescription fd = (FontDescription) e.nextElement();
+ fd.write(os);
+ }
+ for(Enumeration e = extendedFormats.elements();e.hasMoreElements();) {
+ ExtendedFormat xf = (ExtendedFormat) e.nextElement();
+ xf.write(os);
+ }
+ for(Enumeration e = boundsheets.elements();e.hasMoreElements();) {
+ BoundSheet bs = (BoundSheet) e.nextElement();
+ bs.write(os);
+ }
+ eof.write(os);
+
+ for(Enumeration e = worksheets.elements();e.hasMoreElements();) {
+ Worksheet ws = (Worksheet) e.nextElement();
+ ws.write(os);
+ }
+ }
+
+ /**
+ * Reads a workbook from the <code>InputStream</code> and contructs a
+ * workbook object from it
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public void read(InputStream is) throws IOException {
+
+ boolean done = false;
+
+ int b = 0;
+ while (!done)
+ {
+ b = is.read();
+ if (b == -1)
+ {
+ Debug.log(Debug.TRACE,"End of file reached");
+ break;
+ }
+
+ switch (b)
+ {
+ case PocketExcelConstants.DEFINED_NAME:
+ Debug.log(Debug.TRACE,"NAME: Defined Name (18h)");
+ DefinedName dn = new DefinedName(is, this);
+ definedNames.add(dn);
+ break;
+
+ case PocketExcelConstants.BOF_RECORD:
+ Debug.log(Debug.TRACE,"BOF Record");
+ bof.read(is);
+ break;
+
+ case PocketExcelConstants.EOF_MARKER:
+ Debug.log(Debug.TRACE,"EOF Marker");
+ eof.read(is);
+ Worksheet ws = new Worksheet(this);
+ while(ws.read(is)) {
+ worksheets.add(ws);
+ ws = new Worksheet(this);
+ }
+ break;
+
+ case PocketExcelConstants.FONT_DESCRIPTION:
+ Debug.log(Debug.TRACE,"FONT: Font Description (31h)");
+ FontDescription fd = new FontDescription(is);
+ fonts.add(fd);
+ break;
+
+ case PocketExcelConstants.WINDOW_INFO:
+ Debug.log(Debug.TRACE,"WINDOW1: Window Information (3Dh) [PXL 2.0]");
+ win1.read(is);
+ break;
+
+ case PocketExcelConstants.CODEPAGE:
+ Debug.log(Debug.TRACE,"CODEPAGE : Codepage and unknown fields (42h)");
+ cp.read(is);
+ break;
+
+ case PocketExcelConstants.BOUND_SHEET:
+ Debug.log(Debug.TRACE,"BOUNDSHEET: Sheet Information (85h)");
+ BoundSheet bs = new BoundSheet(is);
+ boundsheets.add(bs);
+ break;
+
+ case PocketExcelConstants.EXTENDED_FORMAT:
+ Debug.log(Debug.TRACE,"XF: Extended Format (E0h) [PXL 2.0]");
+ ExtendedFormat xf = new ExtendedFormat(is);
+ extendedFormats.add(xf);
+ break;
+
+ default:
+ b = is.read();
+ break;
+ }
+
+ }
+ is.close();
+ }
+
+ /**
+ * Adds a font recrod to the workbook
+ *
+ * @param f the font record to add
+ */
+ public int addFont(FontDescription f) {
+
+ boolean alreadyExists = false;
+ int i = 0;
+
+ for(Enumeration e = fonts.elements();e.hasMoreElements();) {
+ FontDescription fd = (FontDescription) e.nextElement();
+ if(fd.compareTo(f)) {
+ alreadyExists = true;
+ break;
+ } else {
+ i++;
+ }
+ }
+
+ if(!alreadyExists)
+ fonts.add(f);
+
+ return i;
+ }
+
+ /**
+ * Adds a ExtendedFormat record to the workbook
+ *
+ * @param f the font recrod to add
+ */
+ public int addExtendedFormat(Format fmt) throws IOException {
+
+ FontDescription fd = new FontDescription(fmt);
+ int ixfnt = addFont(fd);
+ ExtendedFormat xf = new ExtendedFormat(ixfnt, fmt);
+
+ boolean alreadyExists = false;
+ int i = 0;
+
+ for(Enumeration e = extendedFormats.elements();e.hasMoreElements();) {
+ ExtendedFormat currentXF = (ExtendedFormat) e.nextElement();
+ if(xf.compareTo(currentXF)) {
+ alreadyExists = true;
+ break;
+ } else if(!alreadyExists) {
+ i++;
+ }
+ }
+
+ if(!alreadyExists)
+ extendedFormats.add(xf);
+
+ return i;
+ }
+
+ /**
+ * Gets a worksheet at a particular index from mthe current workbook.
+ *
+ * @param index the index of the worksheet to retrieve
+ */
+ public Worksheet getWorksheet(int index) {
+
+ return ((Worksheet) worksheets.elementAt(index));
+ }
+
+ /**
+ * Returns a FontDescription indictated by the
+ * index parameter passed in to the method
+ *
+ * @param ixfnt index to the FontDescriptions, this is a 0 based index
+ * @return FontDescription indexed by ixfe
+ */
+ public FontDescription getFontDescription(int ixfnt) {
+
+ return (FontDescription) fonts.elementAt(ixfnt);
+ }
+
+ /**
+ * Returns a ExtendedFormat indictated by the
+ * index parameter passed in to the method
+ *
+ * @param ixfe index to the FontDescriptions, this is a 0 based index
+ * @return FontDescription indexed by ixfe
+ */
+ public ExtendedFormat getExtendedFormat(int ixfe) {
+
+ return (ExtendedFormat) extendedFormats.elementAt(ixfe);
+ }
+
+ /**
+ * Returns an enumeration of DefinedNames for this workbook
+ *
+ * @return Enumeration for the DefinedNames
+ */
+ public Enumeration getDefinedNames() {
+
+ return definedNames.elements();
+ }
+
+ /**
+ * Returns an enumeration of <code>Settings</code> for this workbook
+ *
+ * @return Enumeration of <code>Settings</code>
+ */
+ public BookSettings getSettings() {
+
+ Vector settingsVector = new Vector();
+ int index = 0;
+ for(Enumeration e = worksheets.elements();e.hasMoreElements();) {
+ Worksheet ws = (Worksheet) e.nextElement();
+ SheetSettings s = ws.getSettings();
+ s.setSheetName(getSheetName(index++));
+ settingsVector.add(s);
+ }
+ BookSettings bs = new BookSettings(settingsVector);
+ String activeSheetName = getSheetName(win1.getActiveSheet());
+ bs.setActiveSheet(activeSheetName);
+ return bs;
+ }
+
+ /**
+ * Returns a <code>Vector</code> containing all the worksheet Names
+ *
+ * @return a <code>Vector</code> containing all the worksheet Names
+ */
+ public Vector getWorksheetNames() {
+
+ Vector wsNames = new Vector();
+
+ for(int i = 0;i < boundsheets.size();i++) {
+ wsNames.add(getSheetName(i));
+ }
+
+ return wsNames;
+ }
+
+ /**
+ * Returns the name of the worksheet at the specified index
+ *
+ * @return a <code>String</code> containing the name of the worksheet
+ */
+ public String getSheetName(int index) {
+ BoundSheet bs = (BoundSheet) boundsheets.elementAt(index);
+
+ return bs.getSheetName();
+ }
+
+ /**
+ * Adds a <code>Worksheet</code> to the workbook.
+ *
+ * @return name the name of the <code>Worksheet</code> to be added
+ */
+ public void addWorksheet(String name) throws IOException {
+
+ BoundSheet bs = new BoundSheet(name);
+ boundsheets.add(bs);
+
+ Worksheet ws = new Worksheet();
+ worksheets.add(ws);
+ }
+
+ /**
+ * Adds a cell to the current worksheet.
+ *
+ * @return the name of the <code>Worksheet</code> to be added
+ */
+ public void addCell(int row,int col, Format fmt, String cellContents)
+ throws IOException {
+
+ Worksheet currentWS = (Worksheet) worksheets.elementAt(worksheets.size()-1);
+ int ixfe = addExtendedFormat(fmt);
+
+ String category = fmt.getCategory();
+
+ // Now the formatting is out of the way add the cell
+ Debug.log(Debug.TRACE,"Cell Format: " + fmt);
+ Debug.log(Debug.TRACE,"Row : " + row);
+ Debug.log(Debug.TRACE,"Col : " + col);
+ if(cellContents.startsWith("=")) {
+ try {
+ Formula f = new Formula(row, col, cellContents, ixfe, fmt, this);
+ currentWS.addCell(f);
+ if(category.equalsIgnoreCase(CELLTYPE_STRING)) {
+ StringValue sv = new StringValue(fmt.getValue());
+ currentWS.addCell(sv);
+ }
+ } catch(Exception e) {
+ Debug.log(Debug.TRACE, "Parsing Exception thrown : " + e.getMessage());
+ BoolErrCell errorCell = new BoolErrCell(row, col, ixfe, 0x2A, 1);
+ currentWS.addCell(errorCell);
+ }
+ } else if(category.equalsIgnoreCase(OfficeConstants.CELLTYPE_FLOAT)) {
+ try {
+ FloatNumber num = new FloatNumber(row, col, cellContents, ixfe);
+ currentWS.addCell(num);
+ } catch(Exception e) {
+ Debug.log(Debug.TRACE,"Error could not parse Float " + cellContents);
+ LabelCell lc = new LabelCell(row, col, cellContents, ixfe);
+ currentWS.addCell(lc);
+ }
+ } else {
+ if(cellContents.length()==0) {
+ Debug.log(Debug.TRACE, "Blank Cell");
+ BlankCell b = new BlankCell(row, col, ixfe);
+ currentWS.addCell(b);
+ } else {
+ Debug.log(Debug.TRACE, "Label Cell : " + cellContents);
+ LabelCell lc = new LabelCell(row, col, cellContents, ixfe);
+ currentWS.addCell(lc); // three because we assume the last three
+ // Records in any worksheet is the selection,
+ // window2 and eof Records
+ }
+ }
+ }
+
+ /**
+ * Will create a number of ColInfo records based on the column widths
+ * based in.
+ *
+ * @param columnRows <code>Vector</code> of <code>ColumnRowInfo</code>
+ */
+ public void addColInfo(Vector columnRows) throws IOException {
+
+ Worksheet currentWS = (Worksheet) worksheets.elementAt(worksheets.size()-1);
+
+ int nCols = 0;
+ int nRows = 0;
+
+ Debug.log(Debug.TRACE,"Workbook: addColInfo()");
+ for(Enumeration e = columnRows.elements();e.hasMoreElements();) {
+ ColumnRowInfo cri =(ColumnRowInfo) e.nextElement();
+ int ixfe = 0;
+ int size = cri.getSize();
+ int repeated = cri.getRepeated();
+ if(cri.isColumn()) {
+ Debug.log(Debug.TRACE,"Workbook: adding ColInfo width = " + size);
+ ColInfo newColInfo = new ColInfo( nCols,
+ nCols+repeated-1,
+ size, ixfe);
+ currentWS.addCol(newColInfo);
+ nCols += repeated;
+ } else if(cri.isRow()) {
+
+ Debug.log(Debug.TRACE,"Workbook: adding Row Height = " + size);
+ if(!cri.isDefaultSize()) {
+ for(int i=0;i<repeated;i++) {
+ Row newRow = new Row(nRows++, size, cri.isUserDefined());
+ currentWS.addRow(newRow);
+ }
+ } else {
+ // If it is the Default Row we don't need to add it
+ nRows += repeated;
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Will create a number of ColInfo recrods based on the column widths
+ * based in.
+ *
+ * @param an integer list representing the column widths
+ */
+ public void addNameDefinition(NameDefinition nameDefinition) throws IOException {
+
+ DefinedName dn = new DefinedName(nameDefinition, this);
+ definedNames.add(dn);
+ }
+
+ /**
+ * Adds the <code>BookSettings</code> for this workbook.
+ *
+ * @param book the <code>BookSettings</code> to add
+ */
+ public void addSettings(BookSettings book) throws IOException {
+
+ int index = 0;
+ Vector sheetSettings = book.getSheetSettings();
+ String activeSheetName = book.getActiveSheet();
+
+ for(Enumeration e = worksheets.elements();e.hasMoreElements();) {
+ Worksheet ws = (Worksheet) e.nextElement();
+ String name = getSheetName(index++);
+ if(activeSheetName.equals(name)) {
+ win1.setActiveSheet(index-1);
+ }
+ for(Enumeration eSettings = sheetSettings.elements();eSettings.hasMoreElements();) {
+ SheetSettings s = (SheetSettings) eSettings.nextElement();
+ if(name.equals(s.getSheetName())) {
+ ws.addSettings(s);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the filename of the pxl document without the file extension
+ *
+ * @return filename without the file extension
+ */
+ public String getName() {
+
+ // We have to strip off the file extension
+ int end = fileName.lastIndexOf(".");
+ String name;
+ if( end >= 0) // check in case the filename is already stripped
+ name = fileName.substring(0, end);
+ else
+ name = fileName;
+
+ return name;
+ }
+
+ /**
+ * Returns the filename of the pxl document with the file extension
+ *
+ * @return filename with the file extension
+ */
+ public String getFileName() {
+
+ return fileName;
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java
new file mode 100644
index 000000000000..6ab57189f39f
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java
@@ -0,0 +1,319 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.awt.Point;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.SheetSettings;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.PocketExcelConstants;
+
+
+/**
+ * This class is used by <code>PxlDocument</code> to maintain pexcel
+ * worksheets.
+ *
+ * @author Martin Maher
+ */
+public class Worksheet {
+
+ private String name;
+ private Workbook wb;
+ private Vector rows = new Vector();
+ private Vector colInfo = new Vector();
+ private Vector cells = new Vector();
+ private DefColWidth dcw = new DefColWidth();
+ private DefRowHeight drh = new DefRowHeight();
+ private Window2 win2 = new Window2();
+ private Selection sel = new Selection();
+ private Pane p = new Pane();
+ private BeginningOfFile bof;
+ private Eof eof;
+
+ /**
+ * Writes the current workbook to the <code>Outputstream</code>
+ *
+ * @param os The destination outputstream
+ */
+ public Worksheet(Workbook wb) {
+ this.wb = wb;
+ }
+
+ /**
+ * Default Contructor
+ *
+ * @param os The destination outputstream
+ */
+ public Worksheet() {
+ }
+
+ /**
+ * Writes the current workbook to the <code>Outputstream</code>
+ *
+ * @param os The destination outputstream
+ */
+ public void write(OutputStream os) throws IOException {
+
+ bof = new BeginningOfFile(false);
+ bof.write(os);
+ dcw.write(os);
+ for(Enumeration e = colInfo.elements();e.hasMoreElements();) {
+ ColInfo ci = (ColInfo) e.nextElement();
+ ci.write(os);
+ }
+ drh.write(os);
+ for(Enumeration e = rows.elements();e.hasMoreElements();) {
+ Row rw = (Row) e.nextElement();
+ rw.write(os);
+ }
+ for(Enumeration e = cells.elements();e.hasMoreElements();) {
+ BIFFRecord cv = (BIFFRecord) e.nextElement();
+ cv.write(os);
+ }
+ win2.write(os);
+ p.write(os);
+ sel.write(os);
+ eof = new Eof();
+ eof.write(os);
+ }
+
+ /**
+ * Reads a worksheet from the <code>InputStream</code> and contructs a
+ * workbook object from it
+ *
+ * @param is InputStream containing a Pocket Excel Data file.
+ */
+ public boolean read(InputStream is) throws IOException {
+
+ int b = is.read();
+
+ if (b==-1)
+ return false;
+
+ while(b!=-1) {
+ switch (b)
+ {
+ case PocketExcelConstants.BLANK_CELL:
+ Debug.log(Debug.TRACE,"Blank Cell (01h)");
+ BlankCell bc = new BlankCell(is);
+ cells.add(bc);
+ break;
+
+ case PocketExcelConstants.NUMBER_CELL:
+ Debug.log(Debug.TRACE,"NUMBER: Cell Value, Floating-Point Number (03h)");
+ FloatNumber fn = new FloatNumber(is);
+ cells.add(fn);
+ break;
+
+ case PocketExcelConstants.LABEL_CELL:
+ Debug.log(Debug.TRACE,"LABEL: Cell Value, String Constant (04h)");
+ LabelCell lc = new LabelCell(is);
+ cells.add(lc);
+ break;
+
+ case PocketExcelConstants.BOOLERR_CELL:
+ Debug.log(Debug.TRACE,"BOOLERR: Cell Value, Boolean or Error (05h)");
+ BoolErrCell bec = new BoolErrCell(is);
+ break;
+
+ case PocketExcelConstants.FORMULA_CELL:
+ Debug.log(Debug.TRACE,"FORMULA: Cell Formula (06h)");
+ Formula f = new Formula(is, wb);
+ cells.add(f);
+ break;
+
+ case PocketExcelConstants.FORMULA_STRING:
+ Debug.log(Debug.TRACE,"String Value of a Formula (07h)");
+ StringValue sv = new StringValue(is);
+ break;
+
+ case PocketExcelConstants.ROW_DESCRIPTION:
+ Debug.log(Debug.TRACE,"ROW: Describes a Row (08h)");
+ Row rw = new Row(is);
+ rows.add(rw);
+ break;
+
+ case PocketExcelConstants.BOF_RECORD:
+ Debug.log(Debug.TRACE,"BOF Record");
+ bof = new BeginningOfFile(is);
+ break;
+
+ case PocketExcelConstants.EOF_MARKER:
+ Debug.log(Debug.TRACE,"EOF Marker");
+ eof = new Eof();
+ return true;
+
+ case PocketExcelConstants.CURRENT_SELECTION:
+ Debug.log(Debug.TRACE,"SELECTION: Current Selection (1Dh)");
+ sel = new Selection(is);
+ break;
+
+ case PocketExcelConstants.NUMBER_FORMAT:
+ Debug.log(Debug.TRACE,"FORMAT: Number Format (1Eh)");
+ NumberFormat nf = new NumberFormat(is);
+ break;
+
+ case PocketExcelConstants.DEFAULT_ROW_HEIGHT:
+ Debug.log(Debug.TRACE,"DEFAULTROWHEIGHT: Default Row Height (25h)");
+ drh = new DefRowHeight(is);
+ break;
+
+ case PocketExcelConstants.SHEET_WINDOW_INFO:
+ Debug.log(Debug.TRACE,"WINDOW2: Sheet Window Information (3Eh) [PXL 2.0]");
+ win2 = new Window2(is);
+ break;
+
+ case PocketExcelConstants.PANE_INFO:
+ Debug.log(Debug.TRACE,"PANE: Number of Panes and their Position (41h) [PXL 2.0]");
+ p = new Pane(is);
+ break;
+
+ case PocketExcelConstants.DEF_COL_WIDTH:
+ Debug.log(Debug.TRACE,"DEFCOLWIDTH: Default Column Width (55h) [PXL 2.0]");
+ dcw = new DefColWidth(is);
+ break;
+
+ case PocketExcelConstants.COLINFO:
+ Debug.log(Debug.TRACE,"COLINFO: Column Formatting Information (7Dh) [PXL 2.0]");
+ ColInfo ci = new ColInfo(is);
+ colInfo.add(ci);
+ break;
+
+ default:
+ break;
+ }
+ b = is.read();
+
+ }
+ Debug.log(Debug.TRACE,"Leaving Worksheet:");
+
+ return true;
+ }
+
+ /**
+ * Returns an enumerator which will be used to access individual cells
+ *
+ * @return an enumerator to the worksheet cells
+ */
+ public Enumeration getCellEnumerator() throws IOException {
+ return (cells.elements());
+ }
+
+ /**
+ * Adds a cell to this worksheet. Current valdid celltypes are
+ * <code>FloatNumber</code>, <code>LabelCell</code> or <code>Formula</code>
+ *
+ * @param f the font recrod to add
+ */
+ public void addCell(BIFFRecord br) {
+ cells.add(br);
+ }
+
+ /**
+ * Adds a number of ColInfo Records to the worksheet base on a list of
+ * clumnwidths passed in
+ *
+ * @param list of column widths
+ */
+ public void addRow(Row r) {
+ rows.add(r);
+ }
+
+ /**
+ * Adds a number of ColInfo Records to the worksheet base on a list of
+ * clumnwidths passed in
+ *
+ * @param list of column widths
+ */
+ public void addCol(ColInfo c) {
+ colInfo.add(c);
+ }
+ /**
+ * Returns an <code>Enumeration</code> to the ColInfo's for this worksheet
+ *
+ * @return an <code>Enumeration</code> to the ColInfo's
+ */
+ public void addSettings(SheetSettings s) {
+
+ sel.setActiveCell(s.getCursor());
+ p.setLeft(s.getLeft());
+ p.setTop(s.getTop());
+ p.setPaneNumber(s.getPaneNumber());
+ Point split = s.getSplit();
+ if(split.getX()!=0 || split.getY()!=0) {
+ p.setSplitPoint(s.getSplitType(), split);
+ win2.setSplitType(s.getSplitType());
+ }
+ }
+
+ /**
+ * Returns an <code>Enumeration</code> to the ColInfo's for this worksheet
+ *
+ * @return an <code>Enumeration</code> to the ColInfo's
+ */
+ public Enumeration getColInfos() {
+
+ return (colInfo.elements());
+ }
+
+ /**
+ * Returns a <code>SheetSettings</code> object containing a collection of data
+ * contained in <code>Pane</code>, <code>Window2</code> and
+ * <code>Selection</code>
+ *
+ * @return an <code>SheetSettings</code>
+ */
+ public SheetSettings getSettings() {
+
+ SheetSettings s = new SheetSettings();
+ s.setCursor(sel.getActiveCell());
+ if(win2.isFrozen()) {
+ s.setFreeze(p.getFreezePoint());
+ } else if(win2.isSplit()) {
+ s.setSplit(p.getSplitPoint());
+ }
+ s.setPaneNumber(p.getPaneNumber());
+ s.setTopLeft(p.getTop(), p.getLeft());
+ return s;
+ }
+ /**
+ * Returns an <code>Enumeration</code> to the Rows for this worksheet
+ *
+ * @return an <code>Enumeration</code> to the Rows
+ */
+ public Enumeration getRows() {
+
+ return (rows.elements());
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java
new file mode 100644
index 000000000000..2e060ca0a148
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java
@@ -0,0 +1,271 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.util.*;
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * FormulaCompiler converts Calc formula string into PocketXL bytes
+ * and PocketXL formula bytes into Calc Formula strings
+ *
+ * For converting from infix to Reverse Polish (or Postfix) notation the string is
+ * converted into a vector of Tokens and then re-ordered based on a modified version
+ * of the standard Infix to RPN conversion algorithms.
+ * <pre>
+ * Infix2Rpn(tokens)
+ * while have more tokens
+ * if token is operand
+ * push to stack
+ * else if token is function, argument separater, or open bracket
+ * push token
+ * extract tokens to matching close bracket into param
+ * Infix2Rpn(param)
+ * else if token is close bracket
+ * pop from stack into result until close bracket or function
+ * else
+ * while stack.top.priority >= token.priority
+ * add stack.pop to result
+ * push token onto stack
+ * </pre>
+ * For converting from RPN to Infix the following algorithm is applied:
+ * <pre>
+ * while have more tokens
+ * if token is operand
+ * push token to stack
+ * else if token is function or operator
+ * pop from stack number of args required by token
+ * apply token to params to make expr
+ * push expr to stack
+ * return stack.pop
+ * </pre>
+ */
+public class FormulaCompiler {
+ /**
+ * Constructs a FormulaCompiler object
+ */
+ public FormulaCompiler() {
+ }
+
+ private boolean isPercent(Token pt) {
+ return pt.getTokenID() == TokenConstants.TPERCENT;
+ }
+
+ private boolean isOpenBrace(Token pt) {
+ return pt.getTokenID() == TokenConstants.TPAREN;
+ }
+
+ private boolean isCloseBrace(Token pt) {
+ return pt.getValue().compareTo(")") == 0;
+ }
+
+ private boolean isParamDelimiter(Token pt) {
+ return pt.getTokenID() == TokenConstants.TARGSEP;
+ }
+
+ private boolean isBinaryOperator(Token pt) {
+ return false;
+ }
+
+ /**
+ * Re-order into Infix format
+ * @param tokens The tokens in RPN form
+ * @return The vector of tokens re-ordered in Infix notation
+ */
+ public Vector RPN2Infix(Vector tokens) {
+ Vector infixExpr = new Vector(15);
+ ListIterator iter = tokens.listIterator();
+ Stack evalStack = new Stack();
+ Stack args = new Stack();
+
+ while (iter.hasNext()) {
+ Token pt = (Token)iter.next();
+ if (pt.isOperand()) {
+ Vector expr = new Vector(5);
+ expr.add(pt);
+ evalStack.push(expr);
+ } else if (pt.isOperator() || pt.isFunction()) {
+ args.clear();
+ for (int i=0; i< pt.getNumArgs(); i++) {
+ args.push(evalStack.pop());
+ }
+ evalStack.push(makeExpression(pt, args));
+ }
+ }
+ return (Vector)evalStack.elementAt(0);
+ }
+
+ /**
+ * Convert the infix expression to RPN. Note that open brackets are saved onto the stack to preserve the users bracketing.
+ * <p>Also note that the open bracket following functions is not pushed onto the stack - it is always implied when
+ * writing out results
+ *
+ * @param tokens The vector of tokens in Infix form
+ *
+ * @return A vector of tokens for the expression in Reverse Polish Notation order
+ */
+ public Vector infix2RPN(Vector tokens) {
+ Vector rpnExpr = new Vector(15);
+ Stack evalStack = new Stack();
+ ListIterator iter = tokens.listIterator();
+ while (iter.hasNext()) {
+ Token pt = (Token)iter.next();
+
+ if (pt.isOperand()) { //Operands are output immediately
+ rpnExpr.add(pt);
+ } else if (pt.isFunction() || isParamDelimiter(pt) || isOpenBrace(pt)) { //Extract parameters after afunction or comma
+ evalStack.push(pt);
+ if (pt.isFunction()) {
+ iter.next();
+ }
+ Vector param = extractParameter(iter);
+ Debug.log(Debug.TRACE, "Extracted parameter " + param);
+ rpnExpr.addAll(infix2RPN(param));
+ } else if (isCloseBrace(pt)) { //Pop off stack till you meet a function or an open bracket
+ Token tmpTok = null;
+ boolean bPop = true;
+ while (bPop) {
+ if (evalStack.isEmpty()) {
+ bPop = false;
+ } else {
+ tmpTok = (Token)evalStack.pop();
+ //if (!(isOpenBrace(tmpTok) || isParamDelimiter(tmpTok))) { //Don't output brackets and commas
+ if (!isParamDelimiter(tmpTok)) { //Don't output commas
+ rpnExpr.add(tmpTok);
+ }
+ if (tmpTok.isFunction() || isOpenBrace(tmpTok)) {
+ bPop = false;
+ }
+ }
+ }
+ } else {
+ if (!evalStack.isEmpty()) {
+ while (!evalStack.isEmpty() &&
+ (((Token)evalStack.peek()).getTokenPriority() >=pt.getTokenPriority())) {
+ Token topTok = (Token)evalStack.peek();
+ if (topTok.isFunction() || isOpenBrace(topTok)) {
+ break;
+ }
+ rpnExpr.add(evalStack.pop());
+ }
+ }
+ evalStack.push(pt);
+ }
+ }
+
+ while (!evalStack.isEmpty()) {
+ Token topTok = (Token)evalStack.peek();
+ if (!(isOpenBrace(topTok) || isParamDelimiter(topTok))) { //Don't output brackets and commas
+ rpnExpr.add(evalStack.pop());
+ }
+ else
+ {
+ evalStack.pop();
+ }
+ }
+ return rpnExpr;
+ }
+
+ /**
+ * Extract a parameter or bracketed sub-expression
+ * @param iter an iterator into the list
+ * @return A complete sub-expression
+ */
+ protected Vector extractParameter(ListIterator iter) {
+ Vector param = new Vector(5);
+ int subExprCount = 0;
+
+ while (iter.hasNext()) {
+ Token pt = (Token)iter.next();
+ Debug.log(Debug.TRACE, "Token is " + pt + " and subExprCount is " + subExprCount);
+ if (isOpenBrace(pt)) {
+ subExprCount++;
+ param.add(pt);
+ } else if (isCloseBrace(pt)) {
+ if (subExprCount == 0) {
+ iter.previous();
+ return param;
+ } else {
+ subExprCount--;
+ param.add(pt);
+ }
+ } else if (isParamDelimiter(pt) && (subExprCount == 0)) {
+ iter.previous();
+ return param;
+ } else {
+ param.add(pt);
+ }
+ }
+ return param;
+ }
+
+ /**
+ * Given the operator and it's operators
+ * @param pt The operator token
+ * @param args The arguments for this operator
+ * @return A correctly ordered expression
+ */
+ protected Vector makeExpression(Token pt, Stack args) {
+ Vector tmp = new Vector(5);
+ TokenFactory tf = new TokenFactory();
+ if (pt.isOperator()) {
+ if (pt.getNumArgs()==2) { //Binary operator
+ tmp.addAll((Vector)args.pop());
+ tmp.add(pt);
+ tmp.addAll((Vector)args.pop());
+ } else if (pt.getNumArgs() == 1) {
+ if(isPercent(pt)) {
+ tmp.addAll((Vector)args.elementAt(0));
+ tmp.add(pt);
+ } else {
+ tmp.add(pt);
+ tmp.addAll((Vector)args.elementAt(0));
+ }
+ if (isOpenBrace(pt)) {
+ tmp.add(tf.getOperatorToken(")",1));
+ }
+ }
+ } else if (pt.isFunction()) {
+ tmp.add(pt);
+ tmp.add(tf.getOperatorToken("(",1));
+ if (!args.isEmpty()) {
+ Vector v = (Vector)args.pop();
+ tmp.addAll(v);
+ }
+ while (!args.isEmpty()) {
+ tmp.add(tf.getOperatorToken(",",1));
+ Vector v = (Vector)args.pop();
+ tmp.addAll(v);
+
+ }
+ tmp.add(tf.getOperatorToken(")",1));
+ }
+
+ return tmp;
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java
new file mode 100644
index 000000000000..208feb030f36
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java
@@ -0,0 +1,152 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+
+/**
+ * This Helper class provides a simplified interface to conversion between PocketXL formula representation
+ * and Calc formula representation.<p>
+ * The class is used by {@link org.openoffice.xmerge.converter.xml.sxc.pexcel.Records.Formula}
+ */
+public class FormulaHelper {
+
+ private static FormulaParser parser;
+ private static FormulaCompiler compiler;
+ private static TokenEncoder encoder;
+ private static TokenDecoder decoder;
+ private boolean rangeType = false;
+ private boolean expressionType = false;
+
+ static {
+ parser = new FormulaParser();
+ compiler = new FormulaCompiler();
+ encoder = new TokenEncoder();
+ decoder = new TokenDecoder();
+ }
+
+ /**
+ * Sets the workbook cache so that global data such as
+ * <code>DefinedNames</code>, <code>Boundsheets</code> can be read
+ *
+ * @param wb Wrokbook object containing all the global data
+ */
+ public void setWorkbook(Workbook wb) {
+
+ encoder.setWorkbook(wb);
+ decoder.setWorkbook(wb);
+ parser.setWorkbook(wb);
+ }
+
+ /**
+ * Convertes a string representation of a calc formula into an array of PocketXL bytes
+ * @param formula The Formula String (e.g. 1+SUM(A1,B1))
+ *
+ * @throws UnsupportedFunctionException Thrown if a function in the formula is nto supported by Pocket Excel
+ * @throws FormulaParsingException Thrown when the formula is not well formed
+ *
+ */
+ public byte[] convertCalcToPXL(String formula) throws UnsupportedFunctionException, FormulaParsingException {
+
+ Vector parseTokens = parser.parse(formula);
+ Vector rpnTokens = compiler.infix2RPN(parseTokens);
+
+ ByteArrayOutputStream bytes = null;
+ try {
+ bytes = new ByteArrayOutputStream();
+ for (Enumeration e = rpnTokens.elements(); e.hasMoreElements();) {
+ Token t = (Token)e.nextElement();
+ bytes.write(encoder.getByte(t));
+ }
+ } catch (IOException e) {
+ }
+
+ return bytes.toByteArray();
+ }
+
+ /**
+ * Converts a PocketXL byte array into a Calc function string
+ * @param formula A byte array that contains the PocketXL bytes for a formula
+ *
+ */
+ public String convertPXLToCalc(byte[] formula) {
+
+ Vector parseTokens = decoder.getTokenVector(formula);
+ Vector infixTokens = compiler.RPN2Infix(parseTokens);
+
+ StringBuffer buff = new StringBuffer();
+ for (Enumeration e = infixTokens.elements();e.hasMoreElements();) {
+ Token t = (Token)e.nextElement();
+ buff.append(t.toString());
+ // If we are parsing a Name definition we need to know if it is of
+ // type range or expression
+ if(!t.isOperand()) {
+ expressionType = true;
+ }
+ }
+ if(!expressionType) {
+ rangeType = true;
+ }
+ return "=" + buff.toString();
+ }
+
+ /**
+ * Returns a boolean indicating whether or not the byte[] parsed is of
+ * type range. This means it contains only a cell reference and no
+ * operators. This is necessry because the syntax for range and expression
+ * types differs. This is only of interest when dealing with
+ * <code>DefinedNames</code> and not <code>Formula</code>
+ *
+ * @return a boolean true if of type range otherwise false
+ *
+ */
+ public boolean isRangeType() {
+
+ return rangeType;
+ }
+
+ /**
+ * Returns a boolean indicating whether or not the byte[] parsed is of
+ * type expression. This means it contains operators. This is necessry
+ * because the syntax for range and expression types differs. This is
+ * only of interest when dealing with <code>DefinedNames</code> and not
+ * <code>Formula</code>
+ *
+ * @return a boolean true if of type expression otherwise false
+ *
+ */
+ public boolean isExpressionType() {
+
+ return expressionType;
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java
new file mode 100644
index 000000000000..0ab40ec53fd2
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java
@@ -0,0 +1,561 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+
+import java.util.Vector;
+
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * This is the Formula Parser based on an article written by Jack Crenshaw. It is a
+ * top down parser with some basic error handling. It handles
+ * +,-,*,/,>,<,>=,<=,=,<>, unary + and - as well as functions.
+ * The BNF notation for this parser is
+ * <pre>
+ * &lt;expression&gt; ::= &lt;unary op&gt; &lt;term&gt; [&lt;addop&gt;|&lt;logop&gt; &lt;term&gt;]
+ * &lt;term&gt; ::= &lt;factor&gt; [&lt;mulop&gt; &lt;factor&gt;]
+ * &lt;factor&gt; ::= &lt;number&gt;[%] | &lt;CellRef&gt; | &lt;QuoteString&gt; | &lt;expression&gt;
+ * </pre>
+ */
+public class FormulaParser {
+
+ private char look;
+ private String formulaStr;
+ private int index = 1;
+ private TokenFactory tokenFactory;
+ private Vector tokenVector;
+ private Workbook wb;
+
+ /**
+ * Default constructor
+ */
+ public FormulaParser() {
+
+ Debug.log(Debug.TRACE,"Creating a Formula Parser");
+ tokenFactory = new TokenFactory();
+ tokenVector = new Vector();
+ }
+
+ /**
+ *
+ */
+ public void setWorkbook(Workbook wb) {
+
+ this.wb = wb;
+ }
+
+ /**
+ * Parse method for parsing from a String to a byte[]
+ *
+ * @param formula A <code>String</code> representation of a formula
+ * starting with the '=' character
+ * @return A <code>Vector</code> containing the parsed <code>Token</code>s
+ */
+ public Vector parse(String formula) throws FormulaParsingException {
+
+ index = 1;
+ look = ' ';
+ tokenVector.clear();
+ if(formula.startsWith("=")) {
+ formulaStr = formula;
+ Debug.log(Debug.TRACE,"Creating a Formula Parser for " + formulaStr);
+ getChar();
+ expression();
+ } else {
+ throw new FormulaParsingException("No equals found!" + makeErrorString());
+ }
+ return tokenVector;
+ }
+
+ /**
+ * Identify + and - operators
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isAddOp(char c) {
+ return (c == '-') || (c == '+');
+ }
+
+ /**
+ * Determine if the current character is a multiop
+ *
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isMultiOp() {
+ return look=='*' || look =='/' || look == '^' || look == '&';
+ }
+
+ /**
+ * Identify <, >, <=, >=, =, <> using the index to find the current character(s)
+ *
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isLogicalOp() {
+ if (!isLogicalOpChar(look)) {
+ return false;
+ } else if ((index+1) >= formulaStr.length()) {//logical operators in their own right : if at end then return true
+ return true;
+ } else if (!isLogicalOpChar(formulaStr.charAt(index))) { // we have >, < or = on their own
+ return true;
+ } else if ((look == '<') && ((formulaStr.charAt(index) == '>') || formulaStr.charAt(index) == '=')) { // <>, or <=
+ return true;
+ } else if ((look == '>') && (formulaStr.charAt(index) == '=')) { // >=
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Identify <, >, <=, >=, =, <>
+ *
+ * @param The <code>String</code> which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isLogicalOp(String op) {
+ return ((op.compareTo(">") == 0) ||
+ (op.compareTo("<") == 0) ||
+ (op.compareTo(">=") == 0) ||
+ (op.compareTo("<=") == 0) ||
+ (op.compareTo("=") == 0) ||
+ (op.compareTo("<>") == 0));
+ }
+
+
+ /**
+ * Identify characters that MAY be logical operator characters
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isLogicalOpChar(char c) {
+ return (c == '>') || (c == '<') || (c == '=');
+ }
+
+ /**
+ * Identify special Cell Reference charaters
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isCellRefSpecialChar(char c) {
+ return (c == ':') || (c == '$') || (c == '.');
+ }
+
+ /**
+ * Identify letters
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isAlpha(char c) {
+ return(Character.isLetter(c));
+ }
+
+ /**
+ * Identify numbers
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isDigit(char c) {
+ return(Character.isDigit(c));
+ }
+
+ /**
+ * Identify numbers
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isPercent(char c) {
+ return (c == '%');
+ }
+
+ /**
+ * Identify letters or numbers
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isAlphaNum(char c) {
+ return(isAlpha(c) || isDigit(c));
+ }
+
+ /**
+ * Identify valid Characters for cell references
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isCellRefChar(char c) {
+ return(isAlpha(c) || isDigit(c) || isCellRefSpecialChar(c));
+ }
+
+ /**
+ * Test if current character is a match and move to next character
+ *
+ * @param c The character which is to be matched
+ */
+ private void match(char c) throws FormulaParsingException {
+
+ if(look==c) {
+ Debug.log(Debug.TRACE,"Operator Found : " + look);
+ getChar();
+ skipWhite();
+ }
+ else
+ throw new FormulaParsingException("Unexpected character '" + c + "'" + makeErrorString());
+ }
+
+ /**
+ * Test if current character is a match and move to next character
+ *
+ * @param symbol The <code>String</code> to be matched.
+ */
+ private void match(String symbol) throws FormulaParsingException {
+
+ int numChars = symbol.length();
+ boolean bContinue = true;
+ for (int i=0;i<numChars && bContinue; i++) {
+ if (look == symbol.charAt(i)) {
+ bContinue = getChar();
+ skipWhite();
+ } else {
+ throw new FormulaParsingException("Unexpected character '" + symbol + "'" + makeErrorString());
+ }
+ }
+ }
+
+ /**
+ * Skip over whitespaces (ie. spaces and tabs)
+ */
+ private void skipWhite() throws FormulaParsingException {
+
+ boolean success = true;
+
+ while(Character.isWhitespace(look) && success) {
+ success = getChar();
+ }
+ }
+
+ /**
+ * This is a factor for multiplication and division operators
+ */
+ private void factor() throws FormulaParsingException {
+ if(isAddOp(look)) { // handle unary addop
+ Character ch = new Character(look);
+ match(look);
+ tokenVector.add(tokenFactory.getOperatorToken(ch.toString(), 1));
+ }
+ if(look=='(') {
+ match('(');
+ tokenVector.add(tokenFactory.getOperatorToken("(", 1));
+ expression();
+ match(')');
+ tokenVector.add(tokenFactory.getOperatorToken(")", 1));
+ } else if(isDigit(look)){
+ getNum();
+ } else {
+ ident();
+ }
+ }
+
+ /**
+ * Pulls the next character from the <code>String</code>
+ *
+ * @return boolean false if the end if the statement
+ * is reached otherwise true
+ */
+ private boolean getChar() throws FormulaParsingException {
+
+ boolean success = true;
+
+ if(index<formulaStr.length()) {
+ look = formulaStr.charAt(index);
+ index++;
+ if(look==',')
+ success = false;
+ } else {
+ success = false;
+ }
+ return success;
+ }
+
+ /**
+ * Parses the number of arguments in a function
+ *
+ * @return The number of arguments
+ */
+ private int arguments() throws FormulaParsingException {
+ int numArgs;
+
+ skipWhite();
+ if(look==')')
+ numArgs = 0;
+ else
+ numArgs = 1;
+
+ while(look!=')') {
+ expression();
+ if(look==',') {
+ numArgs++;
+ match(',');
+ tokenVector.add(tokenFactory.getOperatorToken(",", 1));
+ }
+ }
+ return numArgs;
+ }
+
+ /**
+ * Test to see if we have come across a cell reference or a Name
+ * Definition.
+ */
+ private boolean isCellRef(String s) {
+ char c;
+ boolean result = false;
+
+ for(int i = 0;i<s.length();i++) {
+ c = s.charAt(i);
+ if(isCellRefSpecialChar(c)) {
+ result = true;
+ break;
+ }
+ }
+
+ // if it is a simple cell reference then there will not be a cell
+ // reference 'special char' so we should also look for a digit
+ if(!result) {
+ if(isDigit(s.charAt(1)) || isDigit(s.charAt(2))) {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Test to see if we have come across a cell reference or a function and
+ * add the resulting toek nto the tokenVector.
+ */
+ private void ident() throws FormulaParsingException {
+
+ String cell = getTokenString();
+ if(look=='(') {
+ Debug.log(Debug.TRACE,"Found Function : " + cell);
+
+ int index = tokenVector.size();
+ match('(');
+ tokenVector.add(tokenFactory.getOperatorToken("(", 1));
+ int numArgs = arguments();
+ match(')');
+ tokenVector.add(tokenFactory.getOperatorToken(")", 1));
+ tokenVector.insertElementAt(tokenFactory.getFunctionToken(cell, numArgs), index);
+ } else {
+
+ if(cell.indexOf('.')!=-1) {
+ String cellRef = cell.substring(cell.indexOf('.') + 1, cell.length());
+ if(cellRef.indexOf(':')!=-1) {
+ tokenVector.add(tokenFactory.getOperandToken(cell, "3D_CELL_AREA_REFERENCE"));
+ } else {
+ tokenVector.add(tokenFactory.getOperandToken(cell, "3D_CELL_REFERENCE"));
+ }
+ } else if(cell.indexOf(':')!=-1) {
+ tokenVector.add(tokenFactory.getOperandToken(cell, "CELL_AREA_REFERENCE"));
+ } else if(isCellRef(cell)) {
+ tokenVector.add(tokenFactory.getOperandToken(cell, "CELL_REFERENCE"));
+ } else {
+ tokenVector.add(tokenFactory.getOperandToken(cell, "NAME"));
+ }
+ }
+ }
+
+ /**
+ * Will keep pulling valid logical operators from the formula and return
+ * the resultant <code>String</code>.
+ *
+ * @return a <code>String<code> representing a logical operator
+ */
+ private String getLogicalOperator() throws FormulaParsingException {
+ String op = new String();
+ boolean status;
+
+ do {
+ op += look;
+ status = getChar();
+ } while(isLogicalOpChar(look) && status);
+ skipWhite();
+ return op;
+ }
+
+ /**
+ * Keeps pulling characters from the statement until we get an
+ * operator and returns the resulting string.
+ *
+ * @return A <code>String</code>representing the next token
+ */
+ private String getTokenString() throws FormulaParsingException {
+
+ if(!isAlpha(look) && look!='$')
+ throw new FormulaParsingException("Expected Cell Reference" + makeErrorString());
+ else {
+ String cell = new String();
+ boolean status;
+ do {
+ cell += look;
+ status = getChar();
+ } while(isCellRefChar(look) && status);
+ skipWhite();
+ return cell;
+ }
+ }
+
+ /**
+ * Keeps pulling numbers from the statement and add the resulting integer
+ * token to the tokenVector.
+ */
+ private void getNum() throws FormulaParsingException {
+
+ Debug.log(Debug.TRACE,"getNum : ");
+ if(!isDigit(look))
+ throw new FormulaParsingException("Expected Integer" + makeErrorString());
+ else {
+ String num = new String();
+ boolean status;
+
+ do {
+ num += look;
+ status = getChar();
+ } while((isDigit(look) || ((look == '.') && isDigit(formulaStr.charAt(index)))) && status);
+ skipWhite();
+ tokenVector.add(tokenFactory.getOperandToken(num, "INTEGER"));
+ if(isPercent(look)) {
+ match(look);
+ tokenVector.add(tokenFactory.getOperatorToken("%", 1));
+ Debug.log(Debug.TRACE,"Added Percent token to Vector: ");
+ }
+ Debug.log(Debug.TRACE,"Number parsed : " + num);
+ }
+ }
+
+
+ /**
+ * Term will parse multiplication/division expressions
+ */
+ private void term() throws FormulaParsingException {
+ factor();
+ while(isMultiOp()) {
+ multiOp(Character.toString(look));
+ }
+ }
+
+ /**
+ * Expression is the entry point for the parser. It is the code
+ * that parses addition/subtraction expressions.
+ */
+ private void expression() throws FormulaParsingException {
+
+ if (look == '"') { //Extract a quoted string...
+ StringBuffer buff = new StringBuffer();
+ boolean success = true;
+ success = getChar();
+ while (look != '"' && success) {
+ buff.append(look);
+ success = getChar();
+ }
+
+ if (look != '"') { //We've reached the end of the string without getting a closing quote
+ throw new FormulaParsingException("Expected closing quote." + makeErrorString());
+ } else {
+ tokenVector.add(tokenFactory.getOperandToken(buff.toString(), "STRING"));
+ getChar(); //Move on to the next character
+ }
+ } else {
+ term();
+ }
+ while(isAddOp(look) || isLogicalOp()) {
+ if (isAddOp(look)) {
+ addOp(Character.toString(look));
+ } else if (isLogicalOp()) {
+ logicalOp();
+ }
+ }
+ }
+
+ /**
+ * Test to see if the next token (represented as a <code>String</code>) is
+ * the same as the String passed in. Move the index along to the end of
+ * that String and add that <code>Token</code> to the tokenVector. Then
+ * call <code>term</code> to parse the right hand side of the operator.
+ *
+ * @param op A <code>String</code> representing the operator
+ */
+ private void addOp(String op) throws FormulaParsingException {
+ match(op);
+ tokenVector.add(tokenFactory.getOperatorToken(op, 2));
+ term();
+ }
+
+ /**
+ * Test to see if the next token (represented as a <code>String</code>) is
+ * the same as the String passed in. Move the index along to the end of
+ * that String and add that <code>Token</code> to the tokenVector. Then
+ * call <code>factor</code> to parse the right hand side of the operator.
+ *
+ * @param op A <code>String</code> representing the operator
+ */
+ private void multiOp(String op) throws FormulaParsingException {
+ match(op);
+ tokenVector.add(tokenFactory.getOperatorToken(op, 2));
+ factor();
+ }
+
+ /**
+ * Pull a logical operator starting at the current index, add a token for
+ * that operator to the tokenVector and call <code>term<code> to parse the
+ * right hand side of the operator
+ */
+ private void logicalOp() throws FormulaParsingException {
+ String op = getLogicalOperator();
+ tokenVector.add(tokenFactory.getOperatorToken(op, 2));
+ term();
+ }
+
+ private String makeErrorString() {
+ StringBuffer buff = new StringBuffer();
+ for (int i=0; i<index-1; i++) {
+ buff.append(' ');
+ }
+
+ buff.append('^');
+ return "\n\t" + formulaStr + "\n\t" + buff.toString();
+ }
+ }
+
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java
new file mode 100644
index 000000000000..e8465391e6ff
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+/*
+ * If the formula failed to be parsed properly this exception will be thrown
+ *
+ * Martin Maher
+ */
+
+public class FormulaParsingException extends Exception {
+
+ public FormulaParsingException(String message) {
+ super(message);
+ }
+ }
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java
new file mode 100644
index 000000000000..42c06d88754a
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java
@@ -0,0 +1,204 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.util.HashMap;
+
+public class FunctionLookup extends SymbolLookup {
+
+ private HashMap stringToArgs = null;
+
+ /**
+ * The default constructor - invokes {@link #initialize() initialize()}
+ */
+ public FunctionLookup() {
+ initialize();
+ }
+
+ /**
+ * Initialize the lookup table for functions
+ */
+ public void initialize() {
+ if ((stringToID != null) || (idToString != null) || (stringToArgs !=null)) {
+ return;
+ }
+ stringToID = new HashMap();
+ idToString = new HashMap();
+ stringToArgs = new HashMap();
+
+ // Functions with Variable number of Arguments
+ // Math and Trig
+ addEntry("SUM", TokenConstants.TSUM, -1);
+ addEntry("MIN", TokenConstants.TMIN, -1);
+ addEntry("PRODUCT", TokenConstants.TPRODUCT, -1);
+ addEntry("LOG", TokenConstants.TLOG, -1);
+ addEntry("SUMIF", TokenConstants.TSUMIF, -1);
+ addEntry("TRUNC", TokenConstants.TRUNC, -1);
+ // Financial
+ addEntry("DDB", TokenConstants.TDDB, -1);
+ addEntry("FV", TokenConstants.TFV, -1);
+ addEntry("IRR", TokenConstants.TIRR, -1);
+ addEntry("NPER", TokenConstants.TNPER, -1);
+ addEntry("NPV", TokenConstants.TNPV, -1);
+ addEntry("PMT", TokenConstants.TPMT, -1);
+ addEntry("PV", TokenConstants.TPV, -1);
+ addEntry("RATE", TokenConstants.TRATE, -1);
+ // Statistical
+ addEntry("AVERAGE", TokenConstants.TAVERAGE, -1);
+ addEntry("COUNT", TokenConstants.TCOUNT, -1);
+ addEntry("COUNTA", TokenConstants.TCOUNTA, -1);
+ addEntry("MAX", TokenConstants.TMAX, -1 );
+ addEntry("MIN", TokenConstants.TMIN, -1);
+ addEntry("STDEV", TokenConstants.TSTDEV, -1 );
+ addEntry("STDEVP", TokenConstants.TSTDEVP, -1 );
+ addEntry("VAR", TokenConstants.TVAR, -1);
+ addEntry("VARP", TokenConstants.TVARP, -1);
+ // Lookup
+ addEntry("CHOOSE", TokenConstants.TCHOOSE, -1);
+ addEntry("HLOOKUP", TokenConstants.THLOOKUP, -1);
+ addEntry("INDEX", TokenConstants.TINDEX, -1);
+ addEntry("MATCH", TokenConstants.TMATCH, -1) ;
+ addEntry("VLOOKUP", TokenConstants.TVLOOKUP, -1);
+ // Text
+ addEntry("RIGHT", TokenConstants.TRIGHT, -1);
+ addEntry("SUBSTITUTE", TokenConstants.TSUBSTITUTE, -1);
+ addEntry("FIND", TokenConstants.TFIND, -1);
+ addEntry("LEFT", TokenConstants.TLEFT, -1);
+ // Logical
+ addEntry("AND", TokenConstants.TAND, -1 );
+ addEntry("IF", TokenConstants.TIF, -1) ;
+ addEntry("OR", TokenConstants.TOR, -1);
+
+ // Functions with Fixed number of Arguments
+ // Math and Trig
+ addEntry("ABS", TokenConstants.TABS, 1);
+ addEntry("ACOS", TokenConstants.TACOS, 1);
+ addEntry("ASIN", TokenConstants.TASIN, 1);
+ addEntry("ATAN", TokenConstants.TATAN, 1);
+ addEntry("ATAN2", TokenConstants.TATAN2, 1);
+ addEntry("COS", TokenConstants.TCOS, 1);
+ addEntry("COUNTIF", TokenConstants.TCOUNTIF, 1);
+ addEntry("DEGREES", TokenConstants.TDEGREES, 1);
+ addEntry("EXP", TokenConstants.TEXP, 1);
+ addEntry("FACT", TokenConstants.TFACT, 1);
+ addEntry("INT", TokenConstants.TINTE, 1);
+ addEntry("LN", TokenConstants.TLN, 1);
+ addEntry("LOG10", TokenConstants.TLOG10, 1);
+ addEntry("MOD", TokenConstants.TMOD, 1);
+ addEntry("PI", TokenConstants.TPI, 0);
+ addEntry("POWER", TokenConstants.TPOWERF, 2);
+ addEntry("RADIANS", TokenConstants.TRADIANS, 1);
+ addEntry("RAND", TokenConstants.TRAND, 1);
+ addEntry("ROUND", TokenConstants.TROUND, 1);
+ addEntry("SQRT", TokenConstants.TSQRT, 1);
+ addEntry("TAN", TokenConstants.TTAN, 1);
+ addEntry("SIN", TokenConstants.TSIN, 1);
+ // Financial
+ addEntry("SLN", TokenConstants.TSLN, 3);
+ addEntry("SYD", TokenConstants.TSYD, 4);
+ // Date and Time
+ addEntry("DATE", TokenConstants.TDATE, 3);
+ addEntry("DATEVALUE", TokenConstants.TDATEVALUE, 1);
+ addEntry("DAY", TokenConstants.TDAY, 1);
+ addEntry("HOUR", TokenConstants.THOUR, 1);
+ addEntry("MINUTE", TokenConstants.TMINUTE, 1 );
+ addEntry("MONTH", TokenConstants.TMONTH, 1);
+ addEntry("NOW", TokenConstants.TNOW, 0);
+ addEntry("SECOND", TokenConstants.TSECOND, 1);
+ addEntry("TIME", TokenConstants.TTIME, 3);
+ addEntry("TIMEVALUE", TokenConstants.TTIMEVALUE, 1);
+ addEntry("YEAR", TokenConstants.TYEAR, 1);
+ // Statistical
+ addEntry("COUNTBLANK", TokenConstants.TCOUNTBLANK, 1);
+ // lookup
+ addEntry("COLUMNS", TokenConstants.TCOLUMNS, 1);
+ addEntry("ROWS", TokenConstants.TROWS, 1);
+ // Database
+ addEntry("DAVERAGE", TokenConstants.TDAVAERAGE, 3);
+ addEntry("DCOUNT", TokenConstants.TDCOUNT, 3);
+ addEntry("DCOUNTA", TokenConstants.TDCOUNTA, 2);
+ addEntry("DGET", TokenConstants.TDGET, 3);
+ addEntry("DMAX", TokenConstants.TDMAX, 3);
+ addEntry("DMIN", TokenConstants.TDMIN, 3);
+ addEntry("DPRODUCT", TokenConstants.TDPRODUCT, 3);
+ addEntry("DSTDEV", TokenConstants.TDSTDEV, 3);
+ addEntry("DSTDEVP", TokenConstants.TDSTDEVP, 3) ;
+ addEntry("DSUM", TokenConstants.TDSUM, 3);
+ addEntry("DVAR", TokenConstants.TDVAR, 3);
+ addEntry("DVARP", TokenConstants.TDVARP, 3);
+ // Text
+ addEntry("EXACT", TokenConstants.TEXACT, 2);
+ addEntry("LEN", TokenConstants.TLEN, 1);
+ addEntry("LOWER", TokenConstants.TLOWER, 1);
+ addEntry("MID", TokenConstants.TMID, 3); // ??????
+ addEntry("PROPER", TokenConstants.TPROPER, 1);
+ addEntry("REPLACE", TokenConstants.TREPLACE, 4);
+ addEntry("REPT", TokenConstants.TREPT, 2);
+ addEntry("T", TokenConstants.TT, 1);
+ addEntry("TRIM", TokenConstants.TRIM, 1);
+ addEntry("UPPER", TokenConstants.TUPPER, 1);
+ addEntry("VALUE", TokenConstants.TVALUE, 1);
+ // Logical
+ addEntry("FALSE", TokenConstants.TFALSE, 0);
+ addEntry("NOT", TokenConstants.TNOT, 1);
+ addEntry("TRUE", TokenConstants.TTRUE, 0);
+ // Informational
+ addEntry("ERRORTYPE", TokenConstants.TERRORTYPE, 1);
+ addEntry("ISBLANK", TokenConstants.TISBLANK, 1);
+ addEntry("ISERR", TokenConstants.TISERR, 1);
+ addEntry("ISERROR", TokenConstants.TISERROR, 1);
+ addEntry("ISLOGICAL", TokenConstants.TISLOGICAL, 1);
+ addEntry("ISNA", TokenConstants.TISNA, 1);
+ addEntry("ISNONTEXT", TokenConstants.TISNONTEXT, 1);
+ addEntry("ISNUMBER", TokenConstants.TISNUMBER, 1);
+ addEntry("ISTEXT", TokenConstants.TISTEXT, 1);
+ addEntry("N", TokenConstants.TN, 1);
+ addEntry("NA", TokenConstants.TNA, 0);
+
+ }
+
+ /**
+ * Associate a function with an identifier and specifiy the number of arguments for that function
+ * @param symbol The function string that will act as the key in the lookup table
+ * @param id The identifier for the function
+ * @param args The number of arguments this function requires
+ */
+ public void addEntry(String symbol, int id, int args) {
+ addEntry(symbol, id);
+ stringToArgs.put(symbol, new Integer(args));
+ }
+
+ /**
+ * Retrieve the number of arguments for this function
+ * @param symbol The function name
+ * @return The number of arguments required by this function
+ */
+ public int getArgCountFromString(String symbol) {
+ return ((Integer)stringToArgs.get(symbol)).intValue();
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java
new file mode 100644
index 000000000000..6ad1876e5358
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+import java.util.HashMap;
+
+/**
+ * A lookup table containing information about operands
+ */
+public class OperandLookup extends SymbolLookup {
+
+ /**
+ * The default constructor - invokes {@link #initialize() initialize()}
+ */
+ public OperandLookup() {
+ initialize();
+ }
+
+ /**
+ * Initialize the lookup table for operands
+ */
+ public void initialize() {
+ if ((stringToID != null) || (idToString != null)) {
+ return;
+ }
+ stringToID = new HashMap();
+ idToString = new HashMap();
+ addEntry("CELL_REFERENCE", TokenConstants.TREF);
+ addEntry("CELL_AREA_REFERENCE", TokenConstants.TAREA);
+ addEntry("INTEGER", TokenConstants.TNUM);
+ addEntry("NUMBER", TokenConstants.TNUM);
+ addEntry("STRING", TokenConstants.TSTRING);
+ addEntry("NAME", TokenConstants.TNAME);
+ addEntry("3D_CELL_REFERENCE", TokenConstants.TREF3D);
+ addEntry("3D_CELL_AREA_REFERENCE", TokenConstants.TAREA3D);
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java
new file mode 100644
index 000000000000..de9ed23d8a24
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java
@@ -0,0 +1,73 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.util.HashMap;
+
+/**
+ * A lookup table containing information about operators
+ */
+public class OperatorLookup extends SymbolLookup {
+
+ /**
+ * The default constructor - invokes {@link #initialize() initialize()}
+ */
+ public OperatorLookup() {
+ initialize();
+ }
+
+ /**
+ * Initialize the lookup table for operators
+ */
+ public void initialize() {
+ if ((stringToID != null) || (idToString != null)) {
+ return;
+ }
+ stringToID = new HashMap();
+ idToString = new HashMap();
+ addEntry("UNARY_PLUS", TokenConstants.TUPLUS);
+ addEntry("UNARY_MINUS", TokenConstants.TUMINUS);
+ addEntry("%", TokenConstants.TPERCENT);
+ addEntry("+", TokenConstants.TADD);
+ addEntry("-", TokenConstants.TSUB);
+ addEntry("*", TokenConstants.TMUL);
+ addEntry("/", TokenConstants.TDIV);
+ addEntry(",", TokenConstants.TARGSEP);
+ addEntry("^", TokenConstants.TPOWER);
+ addEntry("&", TokenConstants.TCONCAT);
+ addEntry("(", TokenConstants.TPAREN);
+ addEntry(")", TokenConstants.TCLOSEPAREN);
+ addEntry("<", TokenConstants.TLESS);
+ addEntry(">", TokenConstants.TGREATER);
+ addEntry(">=", TokenConstants.TGTEQUALS);
+ addEntry("<=", TokenConstants.TLESSEQUALS);
+ addEntry("=", TokenConstants.TEQUALS);
+ addEntry("<>", TokenConstants.TNEQUALS);
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java
new file mode 100644
index 000000000000..053266c8008b
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java
@@ -0,0 +1,42 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+public interface ParseToken
+{
+ public boolean isOperand();
+ public boolean isOperator();
+ public int getTokenType();
+
+ //GENERIC TOKENS (MOSTLY UNUSED
+ public static final int TOKEN_OPERATOR = 1;
+ public static final int TOKEN_OPERAND = 2;
+ public static final int TOKEN_FUNCTION_FIXED = 3;
+ public static final int TOKEN_FUNCTION_VARIABLE = 4;
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java
new file mode 100644
index 000000000000..551b77cf6e7f
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.util.HashMap;
+
+/**
+ * This class defines the precedence applied to each operator when performing a conversion
+ * {@link org.openoffice.xmerge.converter.xml.sxc.pexcel.Records.formula.FormulaCompiler.infix2 from infix to RPN.}.
+ */
+public class PrecedenceTable {
+ public static final int DEFAULT_PRECEDENCE = 0;
+ public static final int EQNEQ_PRECEDENCE = 1; // =, <>
+ public static final int GTLTEQ_PRECEDENCE = 1; // >=, <=
+ public static final int GTLT_PRECEDENCE = 2; // >, <
+ public static final int ADDOP_PRECEDENCE = 4; // +, -
+ public static final int MULTOP_PRECEDENCE = 5; // *, /
+ public static final int FACTOR_PRECEDENCE = 6; // ^
+ public static final int CONCAT_PRECEDENCE = 6; // &
+ public static final int UNARY_PRECEDENCE = 7; // !, Unary +, Unary -
+ public static final int PAREN_PRECEDENCE = 8; // (, )
+ public static final int FUNCTION_PRECEDENCE = 8;
+ public static final int COMMA_PRECEDENCE = 8;
+
+ private static HashMap map;
+ static {
+ map = new HashMap();
+
+ map.put("%", new Integer(UNARY_PRECEDENCE));
+ map.put("+", new Integer(ADDOP_PRECEDENCE));
+ map.put("-", new Integer(ADDOP_PRECEDENCE));
+ map.put("*", new Integer(MULTOP_PRECEDENCE));
+ map.put("/", new Integer(MULTOP_PRECEDENCE));
+ map.put("(", new Integer(PAREN_PRECEDENCE));
+ map.put(")", new Integer(PAREN_PRECEDENCE));
+ map.put(",", new Integer(COMMA_PRECEDENCE));
+ map.put(">", new Integer(GTLT_PRECEDENCE));
+ map.put("<", new Integer(GTLT_PRECEDENCE));
+ map.put("=", new Integer(EQNEQ_PRECEDENCE));
+ map.put("&", new Integer(CONCAT_PRECEDENCE));
+ map.put("^", new Integer(FACTOR_PRECEDENCE));
+ map.put(">=", new Integer(GTLTEQ_PRECEDENCE));
+ map.put("<=", new Integer(GTLTEQ_PRECEDENCE));
+ map.put("<>", new Integer(EQNEQ_PRECEDENCE));
+ map.put("FUNCTION", new Integer(FUNCTION_PRECEDENCE));
+ }
+
+ /**
+ * Retrieve the precedence value for a given operator.
+ * @param op Look up the precedence for this operator
+ * @return an integer representing the integer value of the operator
+ */
+ public static int getPrecedence(String op) {
+ Object obj = map.get(op);
+ if (obj == null) {
+ return DEFAULT_PRECEDENCE;
+ }
+ return ((Integer)obj).intValue();
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java
new file mode 100644
index 000000000000..bf7722b973e4
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.util.HashMap;
+
+/**
+ * This interface defines the attributes of a lookup table for this plugin.
+ * Symbols will generally be either operators (_, -, *, etc) or funtion names.
+ */
+public abstract class SymbolLookup {
+
+ protected HashMap stringToID = null;
+ protected HashMap idToString = null;
+
+ /**
+ * Perform lookup table specific initialization. This would typically entail loading values into
+ * the lookup table. It is best to optimize this process so that data is loaded statically and shared
+ * across all instances of the lookup table.
+ */
+ abstract public void initialize();
+
+ /**
+ * Associate a symbol with a numeric value in the lookup table
+ * @param symbol The symbol that will act as the key in the lookup table
+ * @param value The value to be associated with a given symbol
+ */
+ public void addEntry(String symbol, int id) {
+ Integer iObj = new Integer(id);
+ stringToID.put(symbol, iObj);
+ idToString.put(iObj, symbol);
+ }
+
+ /**
+ * Retrieve the symbol associated with a given identifier
+ * @param id The identfier for which we need to retieve the symbol string
+ * @return The string associated with this identifier in the lookup table.
+ */
+ public String getStringFromID(int id) {
+ return (String)idToString.get(new Integer(id));
+ }
+
+ /**
+ * Retrieve the identifier associated with a given symbol
+ * @param symbol The symbol for which we need to retieve the identifier
+ * @throws UnsupportedFunctionException Thown when the symbol is not found in the lookup table
+ * @return The identifier associated with this string in the lookup table.
+ */
+ public int getIDFromString(String symbol) throws UnsupportedFunctionException {
+ Integer i = (Integer)stringToID.get(symbol);
+ if (i == null)
+ throw new UnsupportedFunctionException("Token '" + symbol + "' not supported by Pocket Excel");
+
+ return ((Integer)stringToID.get(symbol)).intValue();
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java
new file mode 100644
index 000000000000..48d35dcef5d1
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+
+/**
+ * A Token is the basic building block of any formula.
+ * A Token can be of four types (Operator, Operand, Function with fixed
+ * arguments and function with a variable number of arguments. Each type can
+ * have numerous id's. Thetypes are define in <code>ParseToken</code> and the
+ * id's are defined in <code>TokenConstants</code>. The other member variables
+ * are priority which is returned from the <code>PrecedenceTable</code>, the
+ * value which is the String equivalent of the token (eg. "+", "$A$12", "SUM")
+ * and the number of arguments which is only valid for operators and functions.
+ * Tokens should never be created directly and instead are created by the
+ * <code>TokenFactory</code>
+ */
+public class Token implements ParseToken {
+
+ private String value;
+ private int type; // operator, operand, function fixed, function variable
+ private int id; // cell reference, SUM, integer
+ private int priority;
+ private int numArgs=-1;
+
+ public Token(String op, int type, int id, int args) {
+ this.value = op;
+ this.type = type;
+ this.id = id;
+ this.numArgs = args;
+ if(type==ParseToken.TOKEN_FUNCTION_VARIABLE) {
+ priority = PrecedenceTable.getPrecedence("FUNCTION");
+ } else if(type==ParseToken.TOKEN_OPERATOR) {
+ priority = PrecedenceTable.getPrecedence(op);
+ } else {
+ priority = PrecedenceTable.getPrecedence("DEFAULT");
+ }
+ }
+
+ /**
+ * Checks if the current token is an operator
+ *
+ * @return A <code>boolean</code> result of the comaparison
+ */
+ public boolean isOperator() {
+ return type == ParseToken.TOKEN_OPERATOR;
+ }
+
+ /**
+ * Checks if the current token is an operand
+ *
+ * @return A <code>boolean</code> result of the comaparison
+ */
+ public boolean isOperand() {
+ return type == ParseToken.TOKEN_OPERAND;
+ }
+
+ /**
+ * Checks if the current token is a function
+ *
+ * @return A <code>boolean</code> result of the comaparison
+ */
+ public boolean isFunction() {
+ return (type==ParseToken.TOKEN_FUNCTION_FIXED) || (type==ParseToken.TOKEN_FUNCTION_VARIABLE);
+ }
+
+ /**
+ * Returns the token type. This can be one of four values (TOKEN_OPERATOR,
+ * TOKEN_OPERAND, TOKEN_FUNCTION_FIXED, TOKEN_FUNCTION_VARIABLE) defined in
+ * <code>ParseToken</code>
+ *
+ * @return A <code>boolean</code> result of the comparison
+ */
+ public int getTokenType() {
+
+ return type;
+ }
+
+ /**
+ * Returns the ID of this token. This ID is equivalent to the pexcel hex
+ * value and is defined in <code>ParseToken</code>
+ *
+ * @return Returns the id of this token
+ */
+ public int getTokenID() {
+
+ return id;
+ }
+
+ /**
+ * Returns the <code>String</code> equivalent of this token
+ *
+ * @return The <code>String</code> representing this Token
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the number of arguments if this token represents an operator or
+ * function. Otherwise returns -1.
+ *
+ * @return The number of arguments
+ */
+ public int getNumArgs() {
+ return numArgs;
+ }
+
+ /**
+ * Checks if the current token is an operator
+ *
+ * @return A <code>boolean</code> result of the comparison
+ */
+ public int getTokenPriority() {
+ return priority;
+ }
+
+ /**
+ * Returns the <code>String</code> equivalent of this token
+ *
+ * @return The <code>String</code> representing this Token
+ */
+ public String toString() {
+ return getValue();
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java
new file mode 100644
index 000000000000..1a636f9ae1f1
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java
@@ -0,0 +1,203 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+public interface TokenConstants {
+
+ // Unary Operator Tokens
+ public static final int TUPLUS = 0x12;
+ public static final int TUMINUS = 0x13;
+ public static final int TPERCENT = 0x14;
+ public static final int TPAREN = 0x15;
+ // Binary Operator Tokens
+ public static final int TADD = 0x03;
+ public static final int TSUB = 0x04;
+ public static final int TMUL = 0x05;
+ public static final int TDIV = 0x06;
+ public static final int TPOWER = 0x07;
+ public static final int TCONCAT = 0x08;
+
+ //Logical operators
+ public static final int TLESS = 0x09;
+ public static final int TLESSEQUALS = 0x0A;
+ public static final int TEQUALS = 0x0B;
+ public static final int TGTEQUALS = 0x0C;
+ public static final int TGREATER = 0x0D;
+ public static final int TNEQUALS = 0x0E;
+
+ // Function Operator Tokens
+ public static final int TFUNC = 0x41;
+ public static final int TFUNCVAR = 0x42;
+
+ // Constant Operand Tokens
+ public static final int TSTRING = 0x17;
+ public static final int TINT = 0x1E;
+ public static final int TNUM = 0x1F;
+ // Operand Tokens
+ public static final int TREF = 0x44;
+ public static final int TAREA = 0x25;
+ public static final int TNAME = 0x23;
+ public static final int TREF3D = 0x3A;
+ public static final int TAREA3D = 0x3B;
+
+ //
+ public static final int TARGSEP = 0x1001;
+ public static final int TCLOSEPAREN = 0x1002;
+
+ // Variable argument Functions
+ // Math and Trig
+ public static final int TSUM = 0x04;
+ public static final int TPRODUCT = 0xB7;
+ public static final int TSUMIF = 0x0159;
+ public static final int TLOG = 0x6D;
+ public static final int TRUNC = 0xC5;
+ // Financial
+ public static final int TDDB = 0x90;
+ public static final int TFV = 0x39;
+ public static final int TIRR = 0x3E;
+ public static final int TNPER = 0x3A;
+ public static final int TNPV = 0x0B;
+ public static final int TPMT = 0x3B;
+ public static final int TPV = 0x38;
+ public static final int TRATE = 0x3C;
+ // Statistical
+ public static final int TAVERAGE = 0x05;
+ public static final int TCOUNT = 0x00;
+ public static final int TCOUNTA = 0xA9;
+ public static final int TMAX = 0x07;
+ public static final int TMIN = 0x06;
+ public static final int TSTDEV = 0x0C;
+ public static final int TSTDEVP = 0xC1;
+ public static final int TVAR = 0x2E;
+ public static final int TVARP = 0xC2;
+ // Lookup
+ public static final int TCHOOSE = 0x64;
+ public static final int THLOOKUP = 0x65;
+ public static final int TINDEX = 0x1D;
+ public static final int TMATCH = 0x40;
+ public static final int TVLOOKUP = 0x66;
+ // Text
+ public static final int TRIGHT = 0x74;
+ public static final int TSUBSTITUTE = 0x78;
+ public static final int TFIND = 0x7c;
+ public static final int TLEFT = 0x73;
+ // Logical
+ public static final int TAND = 0x24; // 42
+ public static final int TIF = 0x01; // 42
+ public static final int TOR = 0x25; // 42
+
+ // Fixed argument Functions
+ // Math and Trig
+ public static final int TABS = 0x18;
+ public static final int TACOS = 0x63;
+ public static final int TASIN = 0x62;
+ public static final int TATAN = 0x12;
+ public static final int TATAN2 = 0x61;
+ public static final int TCOS = 0x10;
+ public static final int TSIN = 0x0F;
+
+ public static final int TCOUNTIF = 0x015A;
+ public static final int TDEGREES = 0x0157;
+ public static final int TEXP = 0x15;
+ public static final int TFACT = 0xB8;
+ public static final int TINTE = 0x19;
+ public static final int TLN = 0x16;
+
+ public static final int TLOG10 = 0x17;
+ public static final int TMOD = 0x27;
+ public static final int TPI = 0x13;
+
+ public static final int TPOWERF = 0x0151;
+ public static final int TRADIANS = 0x0156;
+ public static final int TRAND = 0x3F;
+ public static final int TROUND = 0x1B;
+ public static final int TSQRT = 0x14;
+ public static final int TTAN = 0x11;
+
+ public static final int TSLN = 0x8E;
+ public static final int TSYD = 0x8F;
+
+ // Date and Time
+ public static final int TDATE = 0x41;
+ public static final int TDATEVALUE = 0x8C;
+ public static final int TDAY = 0x43;
+ public static final int THOUR = 0x47;
+ public static final int TMINUTE = 0x48;
+ public static final int TMONTH = 0x44;
+ public static final int TNOW = 0x4A;
+ public static final int TSECOND = 0x49;
+ public static final int TTIME = 0x42;
+ public static final int TTIMEVALUE = 0x8D;
+ public static final int TYEAR = 0x45;
+ // Statistical
+ public static final int TCOUNTBLANK = 0x015B ;
+ // lookup
+ public static final int TCOLUMNS = 0x4D;
+ public static final int TROWS = 0x4C;
+ // Database
+ public static final int TDAVAERAGE = 0x2A;
+ public static final int TDCOUNT = 0x28;
+ public static final int TDCOUNTA = 0xC7;
+ public static final int TDGET = 0xEB;
+ public static final int TDMAX = 0x2C;
+ public static final int TDMIN = 0x2B;
+ public static final int TDPRODUCT = 0xBD;
+ public static final int TDSTDEV = 0x2D;
+ public static final int TDSTDEVP = 0xC3;
+ public static final int TDSUM = 0x29;
+ public static final int TDVAR = 0x2F;
+ public static final int TDVARP = 0xC4;
+ // Text
+ public static final int TEXACT = 0x75;
+ public static final int TLEN = 0x20;
+ public static final int TLOWER = 0x70;
+ public static final int TMID = 0x1F; // ??????
+ public static final int TPROPER = 0x72;
+ public static final int TREPLACE = 0x77;
+ public static final int TREPT = 0x1E;
+ public static final int TT = 0x82;
+ public static final int TRIM = 0x76;
+ public static final int TUPPER = 0x71;
+ public static final int TVALUE = 0x21;
+ // Logical
+ public static final int TFALSE = 0x23;
+ public static final int TNOT = 0x26;
+ public static final int TTRUE = 0x22;
+ // Informational
+ public static final int TERRORTYPE = 0x05;
+ public static final int TISBLANK = 0x81;
+ public static final int TISERR = 0x7E;
+ public static final int TISERROR = 0x03;
+ public static final int TISLOGICAL = 0xC6;
+ public static final int TISNA = 0x02;
+ public static final int TISNONTEXT = 0xBE;
+ public static final int TISNUMBER = 0x80;
+ public static final int TISTEXT = 0x7F;
+ public static final int TN = 0x83;
+ public static final int TNA = 0x0A;
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java
new file mode 100644
index 000000000000..e18c1d10cc04
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java
@@ -0,0 +1,497 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.io.*;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.DefinedName;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+
+/**
+ * The TokenDecoder decodes a byte[] to an equivalent <code>String</code>. The only
+ * public method apart from the default constructor is the getTokenVector method.
+ * This method takes an entire formula as a pexcel byte[] and decodes it into
+ * a series of <code>Token</code>s. It adds these to a <code>Vector</code> which
+ * is returned once all the tokens have been decoded. The Decoder supports
+ * the following tokens.<br><br>
+ *
+ * Operands Floating point's, Cell references (absolute and relative),
+ * cell ranges<br>
+ * Operators +,-,*,/,&lt;,&gt;.&lt;=,&gt;=,&lt;&gt;<br>
+ * Functions All pexcel fixed and varaible argument functions
+ *
+ */
+public class TokenDecoder {
+
+ private TokenFactory tf;
+ private FunctionLookup fl;
+ private OperatorLookup operatorLookup;
+ private OperandLookup operandLookup;
+ private Workbook wb;
+
+ /**
+ * Default Constructor initializes the <code>TokenFactory</code> for generating
+ * <code>Token</code> and the <code>SymbolLookup</code> for generating
+ * Strings from hex values.
+ */
+ public TokenDecoder() {
+ tf = new TokenFactory();
+ fl = new FunctionLookup();
+ operatorLookup = new OperatorLookup();
+ operandLookup = new OperandLookup();
+ }
+
+ /**
+ * Sets global workbook data needed for defined names
+ */
+ public void setWorkbook(Workbook wb) {
+
+ Debug.log(Debug.TRACE, "TokenDecoder : setWorkbook");
+ this.wb = wb;
+ }
+
+ /**
+ * Returns a <code>Vector</code> of <code>Token</code> decoded from a
+ * byte[]. The byte[] is first converted to a
+ * <code>ByteArrayInputStream</code> as this is the easiest way of reading
+ * bytes.
+ *
+ * @param formula A Pocket Excel Formula byte[]
+ * @return A <code>Vector</code> of deoded <code>Token</code>
+ */
+ public Vector getTokenVector(byte[] formula) {
+
+ Vector v = new Vector();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(formula);
+ int b = 0 ;
+ Token t;
+
+ while ((b = bis.read())!=-1)
+ {
+
+
+ switch (b) {
+
+ case TokenConstants.TAREA3D:
+ Debug.log(Debug.TRACE, "Decoded 3D Area Cell Reference: ");
+ v.add(read3DCellAreaRefToken(bis));
+ Debug.log(Debug.TRACE, "Decoded 3D Area Cell Reference: " + v.lastElement());
+ break;
+ case TokenConstants.TREF3D:
+ Debug.log(Debug.TRACE, "Decoded 3D Cell Reference: ");
+ v.add(read3DCellRefToken(bis));
+ Debug.log(Debug.TRACE, "Decoded 3D Cell Reference: " + v.lastElement());
+ break;
+ case TokenConstants.TREF :
+ v.add(readCellRefToken(bis));
+ Debug.log(Debug.TRACE, "Decoded Cell Reference: " + v.lastElement());
+ break;
+ case TokenConstants.TAREA :
+ v.add(readCellAreaRefToken(bis));
+ Debug.log(Debug.TRACE, "Decoded Cell Area Reference: " + v.lastElement());
+ break;
+ case TokenConstants.TNUM :
+ v.add(readNumToken(bis));
+ Debug.log(Debug.TRACE, "Decoded number : " + v.lastElement());
+ break;
+ case TokenConstants.TFUNCVAR :
+ v.add(readFunctionVarToken(bis));
+ Debug.log(Debug.TRACE, "Decoded variable argument function: " + v.lastElement());
+ break;
+ case TokenConstants.TFUNC :
+ v.add(readFunctionToken(bis));
+ Debug.log(Debug.TRACE, "Decoded function: " + v.lastElement());
+ break;
+ case TokenConstants.TSTRING :
+ v.add(readStringToken(bis));
+ Debug.log(Debug.TRACE, "Decoded string: " + v.lastElement());
+ break;
+ case TokenConstants.TNAME :
+ v.add(readNameToken(bis));
+ Debug.log(Debug.TRACE, "Decoded defined name: " + v.lastElement());
+ break;
+ case TokenConstants.TUPLUS:
+ case TokenConstants.TUMINUS:
+ case TokenConstants.TPERCENT:
+ v.add(readOperatorToken(b, 1));
+ Debug.log(Debug.TRACE, "Decoded Unary operator : " + v.lastElement());
+ break;
+ case TokenConstants.TADD :
+ case TokenConstants.TSUB :
+ case TokenConstants.TMUL :
+ case TokenConstants.TDIV :
+ case TokenConstants.TLESS :
+ case TokenConstants.TLESSEQUALS :
+ case TokenConstants.TEQUALS :
+ case TokenConstants.TGTEQUALS :
+ case TokenConstants.TGREATER :
+ case TokenConstants.TNEQUALS :
+ v.add(readOperatorToken(b, 2));
+ Debug.log(Debug.TRACE, "Decoded Binary operator : " + v.lastElement());
+ break;
+
+ default :
+ Debug.log(Debug.TRACE, "Unrecognized byte : " + b);
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Converts a zero based integer to a char (eg. a=0, b=1).
+ * It assumes the integer is less than 26.
+ *
+ * @param i A 0 based index
+ * @return The equivalent character
+ */
+ private char int2Char(int i) {
+ return (char) ('A' + i);
+ }
+
+ /**
+ * Reads a Cell Reference token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded String <code>Token</code>
+ */
+ private Token readStringToken(ByteArrayInputStream bis) {
+
+ int len = ((int)bis.read())*2;
+ int options = (int)bis.read();
+ Debug.log(Debug.TRACE,"String length is " + len + " and Options Flag is " + options);
+ byte [] stringBytes = new byte[len];
+ int numRead =0;
+ if ((numRead = bis.read(stringBytes, 0, len)) != len) {
+ Debug.log(Debug.TRACE,"Expected " + len + " bytes. Could only read " + numRead + " bytes.");
+ //throw new IOException("Expected " + len + " bytes. Could only read " + numRead + " bytes.");
+ }
+ StringBuffer outputString = new StringBuffer();
+ outputString.append('"');
+ try {
+ Debug.log(Debug.TRACE,"Using LE encoding");
+ outputString.append(new String(stringBytes, "UTF-16LE"));
+ } catch (IOException eIO) {
+ outputString.append(new String(stringBytes)); //fall back to default encoding
+ }
+ outputString.append('"');
+
+ return (tf.getOperandToken(outputString.toString(), "STRING"));
+ }
+
+ /**
+ * Reads a Defined Name token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded Name <code>Token</code>
+ */
+ private Token readNameToken(ByteArrayInputStream bis) {
+ byte buffer[] = new byte[2];
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int nameIndex = EndianConverter.readShort(buffer);
+ bis.skip(12); // the next 12 bytes are unused
+ Enumeration e = wb.getDefinedNames();
+ int i = 1;
+ while(i<nameIndex) {
+ e.nextElement();
+ i++;
+ }
+ Debug.log(Debug.TRACE,"Name index is " + nameIndex);
+ DefinedName dn = (DefinedName)e.nextElement();
+ Debug.log(Debug.TRACE,"DefinedName is " + dn.getName());
+ return (tf.getOperandToken(dn.getName(), "NAME"));
+ }
+
+ /**
+ * Reads a Cell Reference token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded Cell Reference <code>Token</code>
+ */
+ private Token readCellRefToken(ByteArrayInputStream bis) {
+
+ byte buffer[] = new byte[2];
+ String outputString = new String();
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int formulaRow = EndianConverter.readShort(buffer);
+ int relativeFlags = (formulaRow & 0xC000)>>14;
+ formulaRow &= 0x3FFF;
+ int formulaCol = (byte) bis.read();
+
+ outputString = int2CellStr(formulaRow, formulaCol, relativeFlags);
+
+ return (tf.getOperandToken(outputString,"CELL_REFERENCE"));
+ }
+
+ /**
+ * Reads a Cell Reference token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded Cell Reference <code>Token</code>
+ */
+ private Token read3DCellRefToken(ByteArrayInputStream bis) {
+
+ byte buffer[] = new byte[2];
+ String outputString = new String();
+
+ bis.skip(10);
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int Sheet1 = EndianConverter.readShort(buffer);
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int Sheet2 = EndianConverter.readShort(buffer);
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int formulaRow = EndianConverter.readShort(buffer);
+ int relativeFlags = (formulaRow & 0xC000)>>14;
+ formulaRow &= 0x3FFF;
+ int formulaCol = (byte) bis.read();
+ String cellRef = "." + int2CellStr(formulaRow, formulaCol, relativeFlags);
+ if(Sheet1 == Sheet2) {
+ outputString = "$" + wb.getSheetName(Sheet1) + cellRef;
+ } else {
+ outputString = "$" + wb.getSheetName(Sheet1) + cellRef + ":$" + wb.getSheetName(Sheet2) + cellRef;
+ }
+
+ return (tf.getOperandToken(outputString,"3D_CELL_REFERENCE"));
+ }
+
+ /**
+ * Reads a Cell Reference token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded Cell Reference <code>Token</code>
+ */
+ private Token read3DCellAreaRefToken(ByteArrayInputStream bis) {
+
+ byte buffer[] = new byte[2];
+ String outputString = new String();
+
+ bis.skip(10);
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int Sheet1 = EndianConverter.readShort(buffer);
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int Sheet2 = EndianConverter.readShort(buffer);
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int formulaRow1 = EndianConverter.readShort(buffer);
+ int relativeFlags1 = (formulaRow1 & 0xC000)>>14;
+ formulaRow1 &= 0x3FFF;
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int formulaRow2 = EndianConverter.readShort(buffer);
+ int relativeFlags2 = (formulaRow2 & 0xC000)>>14;
+ formulaRow2 &= 0x3FFF;
+
+ int formulaCol1 = (byte) bis.read();
+ int formulaCol2 = (byte) bis.read();
+
+ String cellRef1 = "." + int2CellStr(formulaRow1, formulaCol1, relativeFlags1);
+ String cellRef2 = int2CellStr(formulaRow2, formulaCol2, relativeFlags2);
+
+ if(Sheet1 == Sheet2) {
+ outputString = "$" + wb.getSheetName(Sheet1) + cellRef1 + ":" + cellRef2;
+ } else {
+ outputString = "$" + wb.getSheetName(Sheet1) + cellRef1 + ":$" + wb.getSheetName(Sheet2) + "." + cellRef2;
+ }
+
+ return (tf.getOperandToken(outputString,"3D_CELL_AREA_REFERENCE"));
+ }
+
+ /**
+ * Converts a row and col 0 based index to a spreadsheet cell reference.
+ * It also has a relativeFlags which indicates whether or not the
+ * Cell Reference is relative or absolute (Absolute is denoted with '$')
+ *
+ * 00 = absolute row, absolute col
+ * 01 = absolute row, relative col
+ * 10 = relative row, absolute col
+ * 11 = relative row, relative col
+ *
+ * @param row The cell reference 0 based index to the row
+ * @param col The cell reference 0 based index to the row
+ * @param relativeFlags Flags indicating addressing of row and column
+ * @return A <code>String</code> representing a cell reference
+ */
+ private String int2CellStr(int row, int col, int relativeFlags) {
+ String outputString = "";
+ int firstChar = (col + 1) / 26;
+
+ if((relativeFlags & 1) == 0) {
+ outputString += "$";
+ }
+
+ if(firstChar>0) {
+ int secondChar = (col + 1) % 26;
+ outputString += Character.toString(int2Char(firstChar - 1)) + Character.toString(int2Char(secondChar - 1));
+ } else {
+ outputString += Character.toString(int2Char(col));
+ }
+ if((relativeFlags & 2) == 0) {
+ outputString += "$";
+ }
+ outputString += Integer.toString(row+1);
+ return outputString;
+ }
+
+ /**
+ * Reads a Cell Area Reference (cell range) <code>Token</code> from
+ * the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The equivalent Cell Area Reference (cell range)
+ * <code>Token</code>
+ */
+ private Token readCellAreaRefToken(ByteArrayInputStream bis) {
+ byte buffer[] = new byte[2];
+ int formulaRow1, formulaRow2;
+ int formulaCol1, formulaCol2;
+
+ String outputString = new String();
+
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ formulaRow1 = EndianConverter.readShort(buffer);
+ int relativeFlags1 = (formulaRow1 & 0xC000)>>14;
+ formulaRow1 &= 0x3FFF;
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ formulaRow2 = EndianConverter.readShort(buffer);
+ int relativeFlags2 = (formulaRow2 & 0xC000)>>14;
+ formulaRow2 &= 0x3FFF;
+
+ formulaCol1 = (byte) bis.read();
+ formulaCol2 = (byte) bis.read();
+
+ outputString = int2CellStr(formulaRow1, formulaCol1, relativeFlags1);
+ outputString += (":" + int2CellStr(formulaRow2, formulaCol2, relativeFlags2));
+
+ return (tf.getOperandToken(outputString,"CELL_AREA_REFERENCE"));
+ }
+
+
+ /**
+ * Reads a Number (floating point) token from the <code>ByteArrayInputStream</code>
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded Integer <code>Token</code>
+ */
+ private Token readNumToken(ByteArrayInputStream bis) {
+
+ byte numBuffer[] = new byte[8];
+
+ for(int j=0;j<8;j++) {
+ numBuffer[j]=(byte) bis.read();
+ }
+
+ return (tf.getOperandToken(Double.toString(EndianConverter.readDouble(numBuffer)),"NUMBER"));
+ }
+
+ /**
+ * Read an Operator token from the <code>ByteArrayInputStream</code>
+ *
+ * @param b A Pocket Excel number representing an operator.
+ * @param args The number of arguments this operator takes.
+ * @return The decoded Operator <code>Token</code>
+ */
+ private Token readOperatorToken(int b, int args) {
+
+ Token t;
+
+ if(b==TokenConstants.TUPLUS) {
+ t = tf.getOperatorToken("+", args);
+ } else if(b==TokenConstants.TUMINUS) {
+ t = tf.getOperatorToken("-", args);
+ } else {
+ t = tf.getOperatorToken(operatorLookup.getStringFromID(b), args);
+ }
+ return t;
+ }
+
+ /**
+ * Read a Function token from the <code>ByteArrayInputStream</code>
+ * This function can have any number of arguments and this number is read
+ * in with the record
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded variable argument Function <code>Token</code>
+ */
+ private Token readFunctionVarToken(ByteArrayInputStream bis) {
+
+ int numArgs = 0;
+ numArgs = bis.read();
+ byte buffer[] = new byte[2];
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int functionID = EndianConverter.readShort(buffer);
+ return (tf.getFunctionToken(fl.getStringFromID(functionID),numArgs));
+ }
+
+ /**
+ * Read a Function token from the <code>ByteArrayInputStream</code>
+ * This function has a fixed number of arguments which it will get
+ * from <code>FunctionLookup</code>.
+ *
+ * @param bis The <code>ByteArrayInputStream</code> from which we read the
+ * bytes.
+ * @return The decoded fixed argument Function <code>Token</code>
+ */
+ private Token readFunctionToken(ByteArrayInputStream bis) {
+
+ byte buffer[] = new byte[2];
+ buffer[0] = (byte) bis.read();
+ buffer[1] = (byte) bis.read();
+ int functionID = EndianConverter.readShort(buffer);
+ String functionName = fl.getStringFromID(functionID);
+ return (tf.getFunctionToken(functionName,fl.getArgCountFromString(functionName)));
+ }
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java
new file mode 100644
index 000000000000..249e14ac620f
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java
@@ -0,0 +1,559 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import java.io.*;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.EndianConverter;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.DefinedName;
+
+/**
+ * The TokenEncoder encodes a Token to an equivalent pexcel byte[]. The only
+ * public method apart from the default constructor is the getByte method.
+ * This method picks an encoder based onthe Token's type or id field and uses
+ * that encoder to return a byte[] which it returns. This Encoder supports
+ * Operands Floating point's, Cell references (absolute and relative),
+ * cell ranges
+ * Operators +,-,*,/,&lt;,&gt;.&lt;=,&gt;=,&lt;&gt;
+ * Functions All pexcel fixed and varaible argument functions
+ *
+ */
+public class TokenEncoder {
+
+ private FunctionLookup fl;
+ private String parseString;
+ private int index;
+ private Workbook wb;
+
+ /**
+ * Default Constructor
+ */
+ public TokenEncoder() {
+
+ parseString = new String();
+ fl = new FunctionLookup();
+ }
+
+ /**
+ * Sets global workbook data needed for defined names
+ */
+ public void setWorkbook(Workbook wb) {
+
+ this.wb = wb;
+ }
+
+
+ /**
+ * Return the byte[] equivalent of a <code>Token</code>. The various
+ * encoders return <code>Vector</code> of <code>Byte</code> instead
+ * of byte[] because the number of bytes returned varies with each
+ * <code>Token</code> encoded. After the encoding is finished the Vector
+ * in converted to a byte[].
+ *
+ * @param t The <code>Token</code> to be encoded
+ * @return An equivalent Pocket Excel byte[]
+ */
+ public byte[] getByte(Token t) throws IOException {
+
+ Vector tmpByteArray = null; // we use this cause we don't know till after
+ // the encoding takes place how big the byte [] will be
+ //index=0; // This class is declared static in
+ // FormulaHelper so better make sure our index is 0
+ if(t.getTokenType()==ParseToken.TOKEN_OPERATOR) {
+ tmpByteArray = operatorEncoder(t);
+ } else if (t.getTokenType()==ParseToken.TOKEN_FUNCTION_VARIABLE || t.getTokenType()==ParseToken.TOKEN_FUNCTION_FIXED){
+ tmpByteArray = functionEncoder(t);
+ } else { // Operands and functions
+ switch(t.getTokenID()) {
+ case TokenConstants.TNAME :
+ tmpByteArray = nameDefinitionEncoder(t);
+ break;
+ case TokenConstants.TREF3D :
+ tmpByteArray = threeDCellRefEncoder(t);
+ break;
+ case TokenConstants.TAREA3D:
+ tmpByteArray = threeDAreaRefEncoder(t);
+ break;
+ case TokenConstants.TREF :
+ tmpByteArray = cellRefEncoder(t);
+ break;
+ case TokenConstants.TAREA :
+ tmpByteArray = areaRefEncoder(t);
+ break;
+ case TokenConstants.TNUM :
+ tmpByteArray = numEncoder(t);
+ break;
+ case TokenConstants.TSTRING :
+ tmpByteArray = stringEncoder(t);
+ break;
+ default :
+ Debug.log(Debug.ERROR, "Encoder found unrecognized Token");
+ }
+ }
+
+ byte cellRefArray[] = new byte[tmpByteArray.size()];
+ int i = 0;
+ String s = new String();
+ for(Enumeration e = tmpByteArray.elements();e.hasMoreElements();) {
+ Byte tmpByte = (Byte) e.nextElement();
+ s = s + tmpByte + " ";
+ cellRefArray[i] = tmpByte.byteValue();
+ i++;
+ }
+ Debug.log(Debug.TRACE, "Encoding Token " + t.getValue() + " as [" + s + "]");
+ return cellRefArray;
+ }
+
+ /**
+ * An Operator Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector operatorEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ return tmpByteArray;
+ }
+
+
+ /**
+ * A String Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector stringEncoder(Token t) throws IOException{
+
+ Vector tmpByteArray = new Vector();
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ tmpByteArray.add(new Byte((byte)(t.getValue().length())));
+ tmpByteArray.add(new Byte((byte)0x01));
+ byte [] stringBytes = t.getValue().getBytes("UTF-16LE");
+ for (int i=0; i<stringBytes.length; i++) {
+ tmpByteArray.add(new Byte(stringBytes[i]));
+ }
+ return tmpByteArray;
+ }
+
+
+ /**
+ * An Integer Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector numEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+
+ double cellLong = (double) Double.parseDouble(t.getValue());
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ byte[] tempByte = EndianConverter.writeDouble(cellLong);
+ for(int byteIter=0;byteIter<tempByte.length;byteIter++) {
+ tmpByteArray.add(new Byte(tempByte[byteIter]));
+ }
+ return tmpByteArray;
+ }
+
+ /**
+ * Converts a char to an int. It is zero based
+ * so a=0, b=1 etc.
+ *
+ * @param ch the character to be converted
+ * @return -1 if not a character otherwise a 0 based index
+ */
+ private int char2int(char ch) {
+ if(!Character.isLetter(ch))
+ return -1;
+
+ ch = Character.toUpperCase(ch);
+ return ch-'A';
+ }
+
+ /**
+ * Identify letters
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isAlpha(char c) {
+ return(Character.isLetter(c));
+ }
+
+ /**
+ * Identify numbers
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isDigit(char c) {
+ return(Character.isDigit(c));
+ }
+
+ /**
+ * Identify letters or numbers
+ *
+ * @param c The character which is to be identified
+ * @return A boolean returning the result of the comparison
+ */
+ private boolean isAlphaNum(char c) {
+ return(isAlpha(c) || isDigit(c));
+ }
+
+ /**
+ * Parses a column reference and returns it's integer equivalent. (eg.
+ * A=0, D=3, BA=27)
+ *
+ * @return an 0 based index to a column
+ */
+ private int column() {
+ char ch = parseString.charAt(index);
+ String columnStr = new String();
+ int col = 0;
+
+ while(isAlpha(ch)) {
+ columnStr += ch;
+ index++;
+ ch = parseString.charAt(index);
+ }
+
+ if(columnStr.length()==1) {
+ col = char2int(columnStr.charAt(0));
+ } else if (columnStr.length()==2) {
+ col = char2int(columnStr.charAt(0)) + 1;
+ col = (col*26) + char2int(columnStr.charAt(1));
+ } else {
+ Debug.log(Debug.ERROR, "Invalid Column Reference " + columnStr );
+ }
+
+
+ return col;
+ }
+
+ /**
+ * Parses a column reference and returns it's integer equivalent. (eg.
+ * A=0, D=3, BA=27)
+ *
+ * @return an 0 based index to a column
+ */
+ private int row() {
+ char ch = parseString.charAt(index);
+ String rowStr = new String();
+ int row = 0;
+ boolean status = true;
+
+ do {
+ rowStr += ch;
+ index++;
+ if(index>=parseString.length()) {
+ status = false;
+ } else {
+ ch = parseString.charAt(index);
+ }
+ } while(isDigit(ch) && status);
+ return Integer.parseInt(rowStr)-1; // Pexcel uses a 0 based index
+ }
+
+ /**
+ * A Cell Reference Encoder (It supports absolute and relative addressing)
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private byte[] encodeCellCoordinates(String cellCoordinates) {
+ int col = 0, row = 0;
+ int addressing = 0xC000;
+
+ index = 0;
+ parseString = cellCoordinates;
+ Debug.log(Debug.TRACE,"Encoding cell coordinates " + cellCoordinates);
+ if(cellCoordinates.charAt(index)=='$') {
+ addressing &= 0x8000;
+ index++;
+ }
+ col = column();
+ if(cellCoordinates.charAt(index)=='$') {
+ addressing &= 0x4000;
+ index++;
+ }
+ row = row(); // Pexcel uses a 0 based index
+ row |= addressing;
+ byte tokenBytes[] = new byte[3];
+ tokenBytes[0] = (byte)row;
+ tokenBytes[1] = (byte)(row>>8);
+ tokenBytes[2] = (byte)col;
+ return tokenBytes;
+ }
+
+ /**
+ * A name definition Encoder
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector nameDefinitionEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+
+ String nameString = t.getValue();
+ Debug.log(Debug.TRACE,"NameDefinitionEncoder : " + nameString);
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ Enumeration e = wb.getDefinedNames();
+ DefinedName dn;
+ String name;
+ int definedNameIndex = 0;
+ do {
+ dn = (DefinedName)e.nextElement();
+ name = dn.getName();
+ Debug.log(Debug.TRACE,"Name pulled from DefinedName : " + name);
+ definedNameIndex++;
+ } while(!nameString.equalsIgnoreCase(name) && e.hasMoreElements());
+
+ tmpByteArray.add(new Byte((byte)definedNameIndex));
+ tmpByteArray.add(new Byte((byte)0x00));
+
+ for(int i = 0;i < 12;i++) {
+ tmpByteArray.add(new Byte((byte)0x00));
+ }
+
+ return tmpByteArray;
+ }
+ /**
+ * A Cell Reference Encoder. It supports absolute and relative addressing
+ * but not sheetnames.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector cellRefEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ byte cellRefBytes[] = encodeCellCoordinates(t.getValue());
+ for(int i = 0;i < cellRefBytes.length;i++) {
+ tmpByteArray.add(new Byte(cellRefBytes[i]));
+ }
+ return tmpByteArray;
+ }
+
+ /**
+ * This function will find the sheetname index for a given String
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private short findSheetIndex(String s) {
+
+ short sheetIndex = 0;
+ String savedName;
+ String sheetName;
+ if (s.startsWith("$")) {
+ sheetName = s.substring(1,s.length()); // Remove $
+ } else {
+ sheetName = s.substring(0,s.length());
+ }
+ Debug.log(Debug.TRACE,"Searching for Worksheet : " + sheetName);
+ Vector names = wb.getWorksheetNames();
+ Enumeration e = names.elements();
+ do {
+ savedName = (String) e.nextElement();
+ sheetIndex++;
+ } while(!savedName.equalsIgnoreCase(sheetName) && e.hasMoreElements());
+
+ Debug.log(Debug.TRACE,"Setting sheetindex to " + sheetIndex);
+ return (short)(sheetIndex-1);
+ }
+
+ /**
+ * A 3D Cell reference encoder
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector threeDCellRefEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+ parseString = t.getValue();
+ Debug.log(Debug.TRACE,"Encoding 3D Cell reference " + t);
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ tmpByteArray.add(new Byte((byte)0xFF));
+ tmpByteArray.add(new Byte((byte)0xFF));
+ for(int i = 0;i < 8;i++) {
+ tmpByteArray.add(new Byte((byte)0x00));
+ }
+
+ String sheetRef = parseString.substring(0, parseString.indexOf('.') + 1);
+ if (sheetRef.indexOf(':')!=-1) {
+ sheetRef = parseString.substring(0, parseString.indexOf(':'));
+ short sheetNum1 = findSheetIndex(sheetRef);
+ sheetRef = parseString.substring(parseString.indexOf(':') + 1, parseString.length());
+ short sheetNum2 = findSheetIndex(sheetRef);
+ tmpByteArray.add(new Byte((byte)sheetNum1));
+ tmpByteArray.add(new Byte((byte)0x00));
+ tmpByteArray.add(new Byte((byte)sheetNum2));
+ tmpByteArray.add(new Byte((byte)0x00));
+ } else {
+ sheetRef = parseString.substring(0, parseString.indexOf('.'));
+ short sheetNum = findSheetIndex(sheetRef);
+ tmpByteArray.add(new Byte((byte)sheetNum));
+ tmpByteArray.add(new Byte((byte)0x00));
+ tmpByteArray.add(new Byte((byte)sheetNum));
+ tmpByteArray.add(new Byte((byte)0x00));
+ }
+ String s = parseString.substring(parseString.indexOf('.') + 1, parseString.length());
+ Debug.log(Debug.TRACE,"Parsing : " + s);
+ byte cellRefBytes[] = encodeCellCoordinates(s);
+ for(int i = 0;i < cellRefBytes.length;i++) {
+ tmpByteArray.add(new Byte(cellRefBytes[i]));
+ }
+ return tmpByteArray;
+ }
+ /**
+ * A 3D Area Reference Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector threeDAreaRefEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+ parseString = t.getValue();
+ Debug.log(Debug.TRACE,"Encoding 3D Area reference " + t);
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ tmpByteArray.add(new Byte((byte)0xFF));
+ tmpByteArray.add(new Byte((byte)0xFF));
+ for(int i = 0;i < 8;i++) {
+ tmpByteArray.add(new Byte((byte)0x00));
+ }
+
+ String param1= parseString.substring(0, parseString.indexOf(':'));
+ String cellRef1 = param1.substring(parseString.indexOf('.') + 1, param1.length());
+ String sheetRef1 = param1.substring(0, param1.indexOf('.'));
+ short sheetNum1 = findSheetIndex(sheetRef1);
+
+ String param2 = parseString.substring(parseString.indexOf(':') + 1, parseString.length());
+ Debug.log(Debug.TRACE,"param2: " + param2);
+ String cellRef2 = param2.substring(param2.indexOf('.') + 1, param2.length());
+ Debug.log(Debug.TRACE,"cellRef2: " + cellRef2);
+
+ if(param2.indexOf('.')==-1) {
+ tmpByteArray.add(new Byte((byte)sheetNum1));
+ tmpByteArray.add(new Byte((byte)0x00));
+ tmpByteArray.add(new Byte((byte)sheetNum1));
+ tmpByteArray.add(new Byte((byte)0x00));
+ } else {
+ String sheetRef2 = param2.substring(0, param2.indexOf('.'));
+ short sheetNum2 = findSheetIndex(sheetRef2);
+ tmpByteArray.add(new Byte((byte)sheetNum1));
+ tmpByteArray.add(new Byte((byte)0x00));
+ tmpByteArray.add(new Byte((byte)sheetNum2));
+ tmpByteArray.add(new Byte((byte)0x00));
+ }
+
+ byte cellRefBytes1[] = encodeCellCoordinates(cellRef1);
+ byte cellRefBytes2[] = encodeCellCoordinates(cellRef2);
+
+ tmpByteArray.add(new Byte(cellRefBytes1[0]));
+ tmpByteArray.add(new Byte(cellRefBytes1[1]));
+
+ tmpByteArray.add(new Byte(cellRefBytes2[0]));
+ tmpByteArray.add(new Byte(cellRefBytes2[1]));
+
+ tmpByteArray.add(new Byte(cellRefBytes1[2]));
+ tmpByteArray.add(new Byte(cellRefBytes2[2]));
+
+ return tmpByteArray;
+ }
+
+ /**
+ * A Cell Range Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector areaRefEncoder(Token t) {
+
+ Vector tmpByteArray = new Vector();
+
+ tmpByteArray.add(new Byte((byte)t.getTokenID()));
+ String param = t.getValue();
+ String cellRef1 = new String();
+ String cellRef2 = new String();
+
+ if(param.indexOf(':')==-1) {
+ Debug.log(Debug.ERROR, "Invalid Cell Range, could not find :");
+ } else {
+ cellRef1 = param.substring(0, param.indexOf(':'));
+ cellRef2 = param.substring(param.indexOf(':') + 1, param.length());
+ }
+ byte cellRefBytes1[] = encodeCellCoordinates(cellRef1);
+ byte cellRefBytes2[] = encodeCellCoordinates(cellRef2);
+
+ tmpByteArray.add(new Byte(cellRefBytes1[0]));
+ tmpByteArray.add(new Byte(cellRefBytes1[1]));
+
+ tmpByteArray.add(new Byte(cellRefBytes2[0]));
+ tmpByteArray.add(new Byte(cellRefBytes2[1]));
+
+ tmpByteArray.add(new Byte(cellRefBytes1[2]));
+ tmpByteArray.add(new Byte(cellRefBytes2[2]));
+
+ return tmpByteArray;
+ }
+
+ /**
+ * A Function Encoder.
+ *
+ * @param t <code>Token</code> to be encoded
+ * @return A <code>Vector</code> of pexcel <code>Byte</code>
+ */
+ private Vector functionEncoder(Token t) {
+ Vector tmpByteArray = new Vector();
+
+ int id = t.getTokenID();
+ if(t.getTokenType()==ParseToken.TOKEN_FUNCTION_VARIABLE) {
+ tmpByteArray.add(new Byte((byte)TokenConstants.TFUNCVAR));
+ tmpByteArray.add(new Byte((byte)t.getNumArgs()));
+ } else {
+ tmpByteArray.add(new Byte((byte)TokenConstants.TFUNC));
+ }
+
+ tmpByteArray.add(new Byte((byte)id));
+ tmpByteArray.add(new Byte((byte)(id>>8)));
+ return tmpByteArray;
+ }
+
+
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java
new file mode 100644
index 000000000000..e745c7c0f970
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java
@@ -0,0 +1,118 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * This is the Factory class responsible for creating a <code>Token</code>.
+ * It has three methods for returning three different types of Tokens
+ * (Operator, Operand and Function).
+ * This utility class is used by either the <code>FormulaParser</code> or the
+ * <code>FormulaDecoder</code>.
+ */
+public class TokenFactory {
+
+ private OperatorLookup operatorLookup;
+ private OperandLookup operandLookup;
+ private FunctionLookup fl;
+
+ /**
+ * Default Constructor
+ */
+ public TokenFactory() {
+ operatorLookup = new OperatorLookup();
+ operandLookup = new OperandLookup();
+ fl = new FunctionLookup();
+ }
+
+ /**
+ * The Factory method for creating function Tokens
+ *
+ * @return The created <code>Token</code>
+ */
+ public Token getFunctionToken(String s, int args) {
+ Token t = null;
+ // We will have to fix this later to include fixed function tokens
+ // Also will need to handle errors where functions names are incorrect???
+ Debug.log(Debug.TRACE,"TokenFactory creating function Token : " + s);
+ try {
+ t = new Token(s, ParseToken.TOKEN_FUNCTION_VARIABLE, fl.getIDFromString(s), args);
+ } catch (UnsupportedFunctionException eFn) {
+
+ Debug.log(Debug.ERROR, eFn.getMessage());
+ }
+ return t;
+ }
+
+ /**
+ * The Factory method for creating operator Tokens
+ *
+ * @return The created <code>Token</code>
+ */
+ public Token getOperatorToken(String s, int args) {
+
+ Token t = null;
+
+ Debug.log(Debug.TRACE,"TokenFactory creating operator Token : " + s);
+ try {
+ if(args==1) {
+ if(s.equals("+")) {
+ t = new Token(s, ParseToken.TOKEN_OPERATOR, operatorLookup.getIDFromString("UNARY_PLUS"), args);
+ } else if (s.equals("-")) {
+ t = new Token(s, ParseToken.TOKEN_OPERATOR, operatorLookup.getIDFromString("UNARY_MINUS"), args);
+ } else {
+ t = new Token(s, ParseToken.TOKEN_OPERATOR, operatorLookup.getIDFromString(s), args);
+ }
+ } else {
+ t = new Token(s, ParseToken.TOKEN_OPERATOR, operatorLookup.getIDFromString(s), args);
+ }
+ } catch (UnsupportedFunctionException eFn) {
+ Debug.log(Debug.ERROR, eFn.getMessage());
+ }
+ return t;
+ }
+
+ /**
+ * The Factory method for creating Operand Tokens
+ *
+ * @return The created <code>Token</code>
+ */
+ public Token getOperandToken(String s, String type) {
+ Token t = null;
+
+ Debug.log(Debug.TRACE,"TokenFactory creating operand (" + type + ") Token : " + s);
+ try {
+ t = new Token(s, ParseToken.TOKEN_OPERAND, operandLookup.getIDFromString(type), 0);
+ } catch (UnsupportedFunctionException eFn) {
+ Debug.log(Debug.ERROR, eFn.getMessage());
+ }
+
+ return t;
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java
new file mode 100644
index 000000000000..ca2794d3f73d
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java
@@ -0,0 +1,40 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula;
+
+/*
+ * Exception thrown when a function specified in a calc formula has no equivalent in Pocket Excel
+ *
+ * @author : Mike Hayes
+ */
+
+public class UnsupportedFunctionException extends Exception {
+ UnsupportedFunctionException(String message) {
+ super(message);
+ }
+}
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html
new file mode 100644
index 000000000000..6239c2b5b625
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+ <!--
+ #*************************************************************************
+ #
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2000, 2010 Oracle and/or its affiliates.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ This file is part of OpenOffice.org.
+
+ OpenOffice.org is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ OpenOffice.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details
+ (a copy is included in the LICENSE file that accompanied this code).
+
+ You should have received a copy of the GNU Lesser General Public License
+ version 3 along with OpenOffice.org. If not, see
+ <http://www.openoffice.org/license.html>
+ for a copy of the LGPLv3 License.
+
+ #*************************************************************************
+ -->
+
+ <title>org.openoffice.xmerge.converter.xml.sxc.pexcel.records.formula package</title>
+
+</head>
+ <body bgcolor="white">
+
+<p> This package contains the classes necessary for converting pexcel formula
+to and from StarCalc Formula.</p>
+
+</body>
+</html>
diff --git a/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html
new file mode 100644
index 000000000000..ef06a251cfaa
--- /dev/null
+++ b/xmerge/source/pexcel/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+ <!--
+ #*************************************************************************
+ #
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2000, 2010 Oracle and/or its affiliates.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ This file is part of OpenOffice.org.
+
+ OpenOffice.org is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 3
+ only, as published by the Free Software Foundation.
+
+ OpenOffice.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License version 3 for more details
+ (a copy is included in the LICENSE file that accompanied this code).
+
+ You should have received a copy of the GNU Lesser General Public License
+ version 3 along with OpenOffice.org. If not, see
+ <http://www.openoffice.org/license.html>
+ for a copy of the LGPLv3 License.
+
+ #*************************************************************************
+ -->
+
+ <title>org.openoffice.xmerge.converter.xml.sxc.pexcel.records package</title>
+
+</head>
+ <body bgcolor="white">
+
+<p> This package contains the objects that represent BIFF Records for the
+pocket excel format. Each one implements the BIFF Record abstract class which
+contains three basic functions (read, write and getBiffType). BIFF Records
+which are not used do not contain setter's or getter's for their member
+variables as some records have a large number of variables. It should be up
+to the implementer which attributes get set and which get set to default
+values.</p>
+
+</body>
+</html>