summaryrefslogtreecommitdiff
path: root/xmerge/java/org/openoffice/xmerge/converter/xml/sxc
diff options
context:
space:
mode:
Diffstat (limited to 'xmerge/java/org/openoffice/xmerge/converter/xml/sxc')
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/BookSettings.java232
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/CellStyle.java518
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnRowInfo.java198
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnStyle.java309
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/DocumentMergerImpl.java202
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/Format.java480
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/NameDefinition.java219
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/RowStyle.java308
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SheetSettings.java377
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetDecoder.java184
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetEncoder.java134
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcConstants.java53
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocument.java96
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentDeserializer.java797
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentSerializer.java995
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcPluginFactory.java86
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/build.xml147
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/makefile.mk36
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/ConverterCapabilitiesImpl.java116
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcConstants.java48
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDataString.java548
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDecoder.java747
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java585
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/PluginFactoryImpl.java132
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentDeserializerImpl.java141
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentSerializerImpl.java144
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/build.xml139
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/converter.xml47
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/makefile.mk36
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/package.html55
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/package.html42
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java116
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java133
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java71
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java449
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java298
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java132
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java139
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/build.xml136
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/converter.xml47
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/makefile.mk36
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html45
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java65
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java119
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java119
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java130
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java140
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java141
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java111
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java161
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java98
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java100
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java230
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java75
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java388
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java124
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java290
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java266
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java143
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java98
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java222
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java142
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java146
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java128
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java46
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java119
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java158
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java543
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java323
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/build.xml156
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java275
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java156
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java567
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java49
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java210
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java68
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java79
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java46
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java89
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java85
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java157
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java209
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java501
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java564
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java126
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java44
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/build.xml145
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/makefile.mk36
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html44
-rw-r--r--xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html49
90 files changed, 18033 insertions, 0 deletions
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/BookSettings.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/BookSettings.java
new file mode 100644
index 000000000000..3643654ca906
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/BookSettings.java
@@ -0,0 +1,232 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BookSettings.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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;
+
+import java.util.Vector;
+import java.util.Enumeration;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import java.awt.Point;
+
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.XmlUtil;
+
+/**
+ * This is a class representing the different attributes for a worksheet
+ * contained in settings.xml.
+ *
+ * @author Martin Maher
+ */
+public class BookSettings implements OfficeConstants {
+
+ /** A w3c <code>Document</code>. */
+ private org.w3c.dom.Document settings = null;
+
+ private boolean hasColumnRowHeaders = true;
+ private String activeSheet = new String();
+ private Vector worksheetSettings = new Vector();
+
+ /**
+ * Default Constructor for a <code>BookSettings</code>
+ *
+ * @param dimension if it's a row the height, a column the width
+ * @param repeated
+ */
+ public BookSettings(Node root) {
+ readNode(root);
+ }
+
+ /**
+ * Default Constructor for a <code>BookSettings</code>
+ *
+ * @param worksheetSettings if it's a row the height, a column the width
+ */
+ public BookSettings(Vector worksheetSettings) {
+ this.worksheetSettings = worksheetSettings;
+ }
+
+ /**
+ *
+ */
+ public void setColumnRowHeaders(boolean hasColumnRowHeaders) {
+ this.hasColumnRowHeaders = hasColumnRowHeaders;
+ }
+
+ /**
+ *
+ */
+ public boolean hasColumnRowHeaders() {
+ return hasColumnRowHeaders;
+ }
+
+ /**
+ * Gets the <code>Vector</code> of <code>SheetSettings</code>
+ *
+ * @return <code>Vector</code> of <code>SheetSettings</code>
+ */
+ public Vector getSheetSettings() {
+ return worksheetSettings;
+ }
+
+ /**
+ * Gets the active sheet name
+ *
+ * @return the active sheet name
+ */
+ public String getActiveSheet() {
+
+ return activeSheet;
+ }
+
+ /**
+ * Sets the active sheet name
+ *
+ * @param activeSheet the active sheet name
+ */
+ public void setActiveSheet(String activeSheet) {
+
+ this.activeSheet = activeSheet;
+ }
+
+
+ /**
+ * Adds an XML entry for a particular setting
+ *
+ * @param root the root node at which to add the xml entry
+ * @param attriute the name of the attribute to add
+ * @param type the attribute type (int, short etc)
+ * @param value the value of the attribute
+ */
+ private void addConfigItem(Node root, String attribute, String type, String value) {
+
+ Element configItem = settings.createElement(TAG_CONFIG_ITEM);
+ configItem.setAttribute(ATTRIBUTE_CONFIG_NAME, attribute);
+ configItem.setAttribute(ATTRIBUTE_CONFIG_TYPE, type);
+
+ configItem.appendChild(settings.createTextNode(value));
+
+ root.appendChild(configItem);
+ }
+
+ /**
+ * Writes out a settings.xml entry for this BookSettings object
+ *
+ * @param settings a <code>Document</code> object representing the settings.xml
+ * @param root the root xml node to add to
+ */
+ public void writeNode(org.w3c.dom.Document settings, Node root) {
+
+ this.settings = settings;
+ Element configItemMapNamed = (Element) settings.createElement(TAG_CONFIG_ITEM_MAP_NAMED);
+ configItemMapNamed.setAttribute(ATTRIBUTE_CONFIG_NAME, "Tables");
+ for(Enumeration e = worksheetSettings.elements();e.hasMoreElements();) {
+ SheetSettings s = (SheetSettings) e.nextElement();
+ s.writeNode(settings, configItemMapNamed);
+ }
+ addConfigItem(root, "ActiveTable", "string", activeSheet);
+ String booleanValue = Boolean.toString(hasColumnRowHeaders);
+ addConfigItem(root, "HasColumnRowHeaders", "boolean", booleanValue);
+ root.appendChild(configItemMapNamed);
+ }
+
+ /**
+ * Sets a variable based on a String value read from XML
+ *
+ * @param name xml name of the attribute to set
+ * @param value String value fo the attribute
+ */
+ public void addAttribute(String name, String value) {
+
+ if(name.equals("ActiveTable")) {
+ activeSheet = value;
+ } else if(name.equals("HasColumnRowHeaders")) {
+ Boolean b = Boolean.valueOf(value);
+ hasColumnRowHeaders = b.booleanValue();
+ }
+ }
+
+ /**
+ * Reads document settings from xml and inits SheetSettings variables
+ *
+ * @param root XML Node to read from
+ */
+ public void readNode(Node root) {
+
+ if (root.hasChildNodes()) {
+
+ NodeList nodeList = root.getChildNodes();
+ int len = nodeList.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_CONFIG_ITEM)) {
+
+ NamedNodeMap cellAtt = child.getAttributes();
+
+ Node configNameNode =
+ cellAtt.getNamedItem(ATTRIBUTE_CONFIG_NAME);
+
+ String name = configNameNode.getNodeValue();
+ NodeList nodeList2 = child.getChildNodes();
+ int len2 = nodeList2.getLength();
+ String s = "";
+ for (int j = 0; j < len2; j++) {
+ Node child2 = nodeList2.item(j);
+ if (child2.getNodeType() == Node.TEXT_NODE) {
+ s = child2.getNodeValue();
+ }
+ }
+ addAttribute(name, s);
+
+ } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_NAMED)) {
+
+ readNode(child);
+
+ } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_ENTRY)) {
+
+ SheetSettings s = new SheetSettings(child);
+ worksheetSettings.add(s);
+
+ } else {
+
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/CellStyle.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/CellStyle.java
new file mode 100644
index 000000000000..5d4eae4da4b4
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/CellStyle.java
@@ -0,0 +1,518 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: CellStyle.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeDocument;
+import org.openoffice.xmerge.converter.xml.Style;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+import org.openoffice.xmerge.converter.xml.sxw.SxwDocument;
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * Represents a text <code>Style</code> in an OpenOffice document.
+ *
+ * @author Martin Maher
+ */
+public class CellStyle extends Style implements Cloneable {
+
+ private Format fmt = new Format();
+
+ /**
+ * Constructor for use when going from DOM to client device format.
+ *
+ * @param Node The <i>style:style</i> <code>Node</code> containing
+ * the <code>Style</code>. (This <code>Node</code> is
+ * assumed have a <i>family</i> attribute of <i>text</i>).
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public CellStyle(Node node, StyleCatalog sc) {
+ super(node, sc);
+
+ // Run through the attributes of this node, saving
+ // the ones we're interested in.
+ NamedNodeMap attrNodes = node.getAttributes();
+ if (attrNodes != null) {
+ int len = attrNodes.getLength();
+ for (int i = 0; i < len; i++) {
+ Node attr = attrNodes.item(i);
+ handleAttribute(attr.getNodeName(), attr.getNodeValue());
+ }
+ }
+
+ // Look for children. Only ones we care about are "style:properties"
+ // nodes. If any are found, recursively traverse them, passing
+ // along the style element to add properties to.
+ if (node.hasChildNodes()) {
+ NodeList children = node.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ String name = child.getNodeName();
+ if (name.equals("style:properties")) {
+ NamedNodeMap childAttrNodes = child.getAttributes();
+ if (childAttrNodes != null) {
+ int nChildAttrNodes = childAttrNodes.getLength();
+ for (int j = 0; j < nChildAttrNodes; j++) {
+ Node attr = childAttrNodes.item(j);
+ handleAttribute(attr.getNodeName(),
+ attr.getNodeValue());
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Constructor for use when going from client device format to DOM
+ *
+ * @param name Name of cell <code>Style</code>. Can be null.
+ * @param family Family of text <code>Style</code> (usually
+ * <i>text</i>). Can be null.
+ * @param parent Name of parent text <code>Style</code>, or null
+ * for none.
+ * @param fmt size in points.
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public CellStyle(String name, String family, String parent,Format fmt, StyleCatalog sc) {
+ super(name, family, parent, sc);
+ this.fmt = fmt;
+ }
+
+ /**
+ * Returns the <code>Format</code> object for this particular style
+ *
+ * @return the <code>Format</code> object
+ */
+ public Format getFormat() {
+ return fmt;
+ }
+
+ /**
+ * Parse a color specification of the form <i>#rrggbb</i>
+ *
+ * @param value <code>Color</code> specification to parse.
+ *
+ * @return The <code>Color</code> associated the value.
+ */
+ private Color parseColorString(String value) {
+ // Assume color value is of form #rrggbb
+ String r = value.substring(1, 3);
+ String g = value.substring(3, 5);
+ String b = value.substring(5, 7);
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ try {
+ red = Integer.parseInt(r, 16);
+ green = Integer.parseInt(g, 16);
+ blue = Integer.parseInt(b, 16);
+ } catch (NumberFormatException e) {
+ Debug.log(Debug.ERROR, "Problem parsing a color string", e);
+ }
+ return new Color(red, green, blue, 0);
+ }
+
+
+ /**
+ * Set an attribute.
+ *
+ * @param attr The attribute to set.
+ * @param value The attribute value to set.
+ */
+ private void handleAttribute(String attr, String value) {
+
+ if (attr.equals("fo:font-weight")) {
+ fmt.setAttribute(Format.BOLD, value.equals("bold"));
+ }
+
+ else if (attr.equals("fo:font-style")) {
+ if (value.equals("italic") || value.equals("oblique"))
+ fmt.setAttribute(Format.ITALIC, true);
+ else if (value.equals("normal"))
+ fmt.setAttribute(Format.ITALIC, false);
+ }
+
+ else if (attr.equals("style:text-underline")) {
+ fmt.setAttribute(Format.UNDERLINE, !value.equals("none"));
+ }
+
+ else if (attr.equals("style:text-crossing-out")) {
+ fmt.setAttribute(Format.STRIKETHRU, !value.equals("none"));
+ }
+
+ else if (attr.equals("style:text-position")) {
+ if (value.startsWith("super "))
+ fmt.setAttribute(Format.SUPERSCRIPT, true);
+ else if (value.startsWith("sub "))
+ fmt.setAttribute(Format.SUBSCRIPT, true);
+ else if (value.startsWith("0% "))
+ fmt.setAttribute(Format.SUPERSCRIPT | Format.SUBSCRIPT, false);
+ else {
+ String firstPart = value.substring(0, value.indexOf(" "));
+ if (firstPart.endsWith("%")) {
+ firstPart = firstPart.substring(0, value.indexOf("%"));
+ int amount;
+ try {
+ amount = Integer.parseInt(firstPart);
+ } catch (NumberFormatException e) {
+ amount = 0;
+ Debug.log(Debug.ERROR, "Problem with style:text-position tag", e);
+ }
+ if (amount < 0) fmt.setAttribute(Format.SUBSCRIPT, true);
+ else if (amount > 0) fmt.setAttribute(Format.SUPERSCRIPT, false);
+ }
+ }
+ }
+
+ else if (attr.equals("fo:font-size")) {
+ if (value.endsWith("pt")) {
+ String num = value.substring(0, value.length() - 2);
+ fmt.setFontSize(Integer.parseInt(num));
+ }
+ }
+
+ else if (attr.equals("style:font-name"))
+ fmt.setFontName(value);
+
+ else if (attr.equals("fo:color"))
+ fmt.setForeground(parseColorString(value));
+
+ else if (attr.equals("fo:background-color"))
+ fmt.setBackground(parseColorString(value));
+
+ else if (attr.equals("fo:text-align")) {
+ if(value.equals("center")) {
+ fmt.setAlign(Format.CENTER_ALIGN);
+ } else if(value.equals("end")) {
+ fmt.setAlign(Format.RIGHT_ALIGN);
+ } else if(value.equals("start")) {
+ fmt.setAlign(Format.LEFT_ALIGN);
+ }
+ }
+
+ else if (attr.equals("fo:vertical-align")) {
+ if(value.equals("top")) {
+ fmt.setVertAlign(Format.TOP_ALIGN);
+ } else if(value.equals("middle")) {
+ fmt.setVertAlign(Format.MIDDLE_ALIGN);
+ } else if(value.equals("bottom")) {
+ fmt.setVertAlign(Format.BOTTOM_ALIGN);
+ }
+ }
+
+ else if (attr.equals("fo:border")) {
+ fmt.setAttribute(Format.TOP_BORDER, !value.equals("none"));
+ fmt.setAttribute(Format.BOTTOM_BORDER, !value.equals("none"));
+ fmt.setAttribute(Format.LEFT_BORDER, !value.equals("none"));
+ fmt.setAttribute(Format.RIGHT_BORDER, !value.equals("none"));
+ }
+ else if (attr.equals("fo:border-top")) {
+ fmt.setAttribute(Format.TOP_BORDER, !value.equals("none"));
+ }
+ else if (attr.equals("fo:border-bottom")) {
+ fmt.setAttribute(Format.BOTTOM_BORDER, !value.equals("none"));
+ }
+ else if (attr.equals("fo:border-left")) {
+ fmt.setAttribute(Format.LEFT_BORDER, !value.equals("none"));
+ }
+ else if (attr.equals("fo:border-right")) {
+ fmt.setAttribute(Format.RIGHT_BORDER, !value.equals("none"));
+ }
+ else if (attr.equals("fo:wrap-option")) {
+ fmt.setAttribute(Format.WORD_WRAP, value.equals("wrap"));
+ }
+
+ else if (isIgnored(attr)) {}
+
+ else {
+ Debug.log(Debug.INFO, "CellStyle Unhandled: " + attr + "=" + value);
+ }
+ }
+
+
+ /**
+ * Return a <code>Style</code> object corresponding to this one,
+ * but with all of the inherited information from parent
+ * <code>Style</code> objects filled in. The object returned will
+ * be a new object, not a reference to this object, even if it does
+ * not need any information added.
+ *
+ * @return The <code>StyleCatalog</code> in which to look up
+ * ancestors.
+ */
+ public Style getResolved() {
+ // Create a new object to return, which is a clone of this one.
+ CellStyle resolved = null;
+ try {
+ resolved = (CellStyle)this.clone();
+ } catch (Exception e) {
+ Debug.log(Debug.ERROR, "Can't clone", e);
+ }
+
+ // Look up the parentStyle. (If there is no style catalog
+ // specified, we can't do any lookups.)
+ CellStyle parentStyle = null;
+ if (sc != null) {
+ if (parent != null) {
+ parentStyle = (CellStyle)sc.lookup(parent, family, null,
+ this.getClass());
+ if (parentStyle == null)
+ Debug.log(Debug.ERROR, "parent style lookup of "
+ + parent + " failed!");
+ else
+ parentStyle = (CellStyle)parentStyle.getResolved();
+
+ } else if (!name.equals("DEFAULT_STYLE")) {
+ parentStyle = (CellStyle)sc.lookup("DEFAULT_STYLE", null,
+ null, this.getClass());
+ }
+ }
+
+ // If we found a parent, for any attributes which we don't have
+ // set, try to get the values from the parent.
+ if (parentStyle != null) {
+ parentStyle = (CellStyle)parentStyle.getResolved();
+ Format parentFormat = parentStyle.getFormat();
+ Format resolvedFormat = resolved.getFormat();
+
+ if ((fmt.getAlign() == Format.LEFT_ALIGN) && (parentFormat.getAlign() != Format.LEFT_ALIGN))
+ resolvedFormat.setAlign(parentFormat.getAlign());
+ if ((fmt.getVertAlign() == Format.BOTTOM_ALIGN) && (parentFormat.getVertAlign() != Format.BOTTOM_ALIGN))
+ resolvedFormat.setVertAlign(parentFormat.getVertAlign());
+ if ((fmt.getFontSize() == 0) && (parentFormat.getFontSize() != 0))
+ resolvedFormat.setFontSize(parentFormat.getFontSize());
+ if ((fmt.getFontName() == null) && (parentFormat.getFontName() != null))
+ resolvedFormat.setFontName(parentFormat.getFontName());
+ if ((fmt.getForeground() == null) && (parentFormat.getForeground() != null))
+ resolvedFormat.setForeground(parentFormat.getForeground());
+ if ((fmt.getBackground() == null) && (parentFormat.getBackground() != null))
+ resolvedFormat.setBackground(parentFormat.getBackground());
+ for (int m = Format.BOLD; m <= Format.SUBSCRIPT; m = m << 1) {
+ if ((fmt.getAttribute(m)) && (parentFormat.getAttribute(m))) {
+ resolvedFormat.setAttribute(m, parentFormat.getAttribute(m));
+ }
+ }
+
+ }
+ return resolved;
+ }
+
+
+ /**
+ * Create a new <code>Node</code> in the <code>Document</code>, and
+ * write this <code>Style</code> to it.
+ *
+ * @param parentDoc Parent <code>Document</code> of the
+ * <code>Node</code> to create.
+ * @param name Name to use for the new <code>Node</code> (e.g.
+ * <i>style:style</i>)
+ *
+ * @return Created <code>Node</code>.
+ */
+ public Node createNode(org.w3c.dom.Document parentDoc, String name) {
+ Element node = parentDoc.createElement(name);
+ writeAttributes(node);
+ return node;
+ }
+
+
+ /**
+ * Return true if <code>style</code> specifies as much or less
+ * than this <code>Style</code>, and nothing it specifies
+ * contradicts this <code>Style</code>.
+ *
+ * @param style The <code>Style</code> to check.
+ *
+ * @return true if <code>style</code> is a subset, false
+ * otherwise.
+ */
+ public boolean isSubset(Style style) {
+ if (style.getClass() != this.getClass())
+ return false;
+ CellStyle tStyle = (CellStyle)style;
+
+ Format rhs = tStyle.getFormat();
+
+ if(!fmt.isSubset(rhs))
+ return false;
+
+ return true;
+ }
+
+
+ /**
+ * Write this <code>Style</code> object's attributes to a
+ * <code>Node</code> in the <code>Document</code>.
+ *
+ * @param node The <code>Node</code> to add <code>Style</code>
+ * attributes.
+ */
+ public void writeAttributes(Element node) {
+
+ if (fmt.getAlign()==Format.RIGHT_ALIGN)
+ node.setAttribute("fo:text-align", "end");
+
+ if (fmt.getAlign()==Format.LEFT_ALIGN)
+ node.setAttribute("fo:text-align", "start");
+
+ if (fmt.getAlign()==Format.CENTER_ALIGN)
+ node.setAttribute("fo:text-align", "center");
+
+ if (fmt.getVertAlign()==Format.TOP_ALIGN)
+ node.setAttribute("fo:vertical-align", "top");
+
+ if (fmt.getVertAlign()==Format.MIDDLE_ALIGN)
+ node.setAttribute("fo:vertical-align", "middle");
+
+ if (fmt.getVertAlign()==Format.BOTTOM_ALIGN)
+ node.setAttribute("fo:vertical-align", "bottom");
+
+ if (fmt.getAttribute(Format.BOLD))
+ node.setAttribute("fo:font-weight", "bold");
+
+ if (fmt.getAttribute(Format.ITALIC))
+ node.setAttribute("fo:font-style", "italic");
+
+ if (fmt.getAttribute(Format.UNDERLINE))
+ node.setAttribute("style:text-underline", "single");
+
+ if (fmt.getAttribute(Format.STRIKETHRU))
+ node.setAttribute("style:text-crossing-out", "single-line");
+
+ if (fmt.getAttribute(Format.SUPERSCRIPT))
+ node.setAttribute("style:text-position", "super 58%");
+
+ if (fmt.getAttribute(Format.SUBSCRIPT))
+ node.setAttribute("style:text-position", "sub 58%");
+
+ if (fmt.getFontSize() != 0) {
+ Integer fs = new Integer(fmt.getFontSize());
+ node.setAttribute("fo:font-size", fs.toString() + "pt");
+ }
+
+ if (fmt.getFontName() != null)
+ node.setAttribute("style:font-name", fmt.getFontName());
+
+ if (fmt.getForeground() != null)
+ node.setAttribute("fo:color", buildColorString(fmt.getForeground()));
+
+ if (fmt.getBackground() != null)
+ node.setAttribute("fo:background-color",
+ buildColorString(fmt.getBackground()));
+
+ if (fmt.getAttribute(Format.TOP_BORDER))
+ node.setAttribute("fo:border-top", "0.0008inch solid #000000");
+
+ if (fmt.getAttribute(Format.BOTTOM_BORDER))
+ node.setAttribute("fo:border-bottom", "0.0008inch solid #000000");
+
+ if (fmt.getAttribute(Format.RIGHT_BORDER))
+ node.setAttribute("fo:border-right", "0.0008inch solid #000000");
+
+ if (fmt.getAttribute(Format.LEFT_BORDER))
+ node.setAttribute("fo:border-left", "0.0008inch solid #000000");
+
+ if (fmt.getAttribute(Format.WORD_WRAP))
+ node.setAttribute("fo:wrap-option", "wrap");
+
+ }
+
+
+ /**
+ * Given a <code>Color</code>, return a string of the form
+ * <i>#rrggbb</i>.
+ *
+ * @param c The <code>Color</code> value.
+ *
+ * @return The <code>Color</code> value in the form <i>#rrggbb</i>.
+ */
+ private String buildColorString(Color c) {
+ int v[] = new int[3];
+ v[0] = c.getRed();
+ v[1] = c.getGreen();
+ v[2] = c.getBlue();
+ String colorString = new String("#");
+ for (int i = 0; i <= 2; i++) {
+ String xx = Integer.toHexString(v[i]);
+ if (xx.length() < 2)
+ xx = "0" + xx;
+ colorString += xx;
+ }
+ return colorString;
+ }
+
+
+ private static String[] ignored = {
+ "style:text-autospace", "style:text-underline-color",
+ "fo:margin-left", "fo:margin-right", "fo:text-indent",
+ "fo:margin-top", "fo:margin-bottom", "text:line-number",
+ "text:number-lines", "style:country-asian",
+ "style:font-size-asian", "style:font-name-complex",
+ "style:language-complex", "style:country-complex",
+ "style:font-size-complex", "style:punctuation-wrap",
+ "fo:language", "fo:country",
+ "style:font-name-asian", "style:language-asian",
+ "style:line-break", "fo:keep-with-next"
+ };
+
+
+ /*
+ * This code checks whether an attribute is one that we
+ * intentionally ignore.
+ *
+ * @param attribute The attribute to check.
+ *
+ * @return true if <code>attribute</code> can be ignored,
+ * otherwise false.
+ */
+ private boolean isIgnored(String attribute) {
+ for (int i = 0; i < ignored.length; i++) {
+ if (ignored[i].equals(attribute))
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnRowInfo.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnRowInfo.java
new file mode 100644
index 000000000000..a179633de71c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnRowInfo.java
@@ -0,0 +1,198 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ColumnRowInfo.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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;
+
+/**
+ * This is a class to define a table-column structure. This can then be
+ * used by plugins to write or read their own column types.
+ *
+ * @author Martin Maher
+ */
+public class ColumnRowInfo {
+
+ final public static int COLUMN = 0x01;
+ final public static int ROW = 0x02;
+
+ final private static int DEFAULTROWSIZE_MIN = 250;
+ final private static int DEFAULTROWSIZE_MAX = 260;
+
+ private int type;
+ private int dimension = 0;
+ private int repeated = 1;
+ private boolean userDefined = true;
+ private Format fmt = new Format();
+
+ /**
+ * Constructor for a <code>ColumnRowInfo</code>
+ *
+ * @param dimension if it's a row the height, a column the width
+ * @param repeated
+ */
+ public ColumnRowInfo(int type) {
+
+ this.type = type;
+ }
+
+ /**
+ * Constructor for a <code>ColumnRowInfo</code>
+ *
+ * @param dimension if it's a row the height, a column the width
+ * @param repeated how many times it is repeated
+ * @param type whether Row or column record
+ */
+ public ColumnRowInfo(int dimension, int repeated, int type) {
+
+ this.dimension = dimension;
+ this.repeated = repeated;
+ this.type = type;
+ }
+
+ /**
+ * Constructor that includes userDefined field
+ *
+ * @param userDefined whether the record is manually set
+ */
+ public ColumnRowInfo(int dimension, int repeated, int type, boolean userDefined) {
+
+ this(dimension, repeated, type);
+ this.userDefined = userDefined;
+ }
+
+ /**
+ * sets the definition
+ *
+ * @param newDefinition sets the definition
+ */
+ public void setFormat(Format fmt) {
+
+ this.fmt = fmt;
+ }
+
+ /**
+ * returns Name of the definition
+ *
+ * @return the name which identifies the definition
+ */
+ public Format getFormat() {
+
+ return fmt;
+ }
+
+ /**
+ * returns Name of the definition
+ *
+ * @return the name which identifies the definition
+ */
+ public int getSize() {
+
+ return dimension;
+ }
+
+ /**
+ * sets the definition
+ *
+ * @param newDefinition sets the definition
+ */
+ public void setSize(int dimension) {
+
+ this.dimension = dimension;
+ }
+ /**
+ * Returns the definition itself
+ *
+ * @return the definition
+ */
+ public int getRepeated() {
+
+ return repeated;
+ }
+
+ /**
+ * Returns the base Cell address
+ *
+ * @return the base cell address
+ */
+ public void setRepeated(int repeated) {
+
+ this.repeated = repeated;
+ }
+
+ /**
+ * Returns the definition itself
+ *
+ * @return the definition
+ */
+ public boolean isRow() {
+
+ if(type==ROW)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Returns the base Cell address
+ *
+ * @return the base cell address
+ */
+ public boolean isColumn() {
+
+ if(type==COLUMN)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Test if the row height as been set manually
+ *
+ * @return true if user defined otherwise false
+ */
+ public boolean isUserDefined() {
+
+ return userDefined;
+ }
+
+ /**
+ * Test if the row height is default
+ *
+ * @return true if default otherwise false
+ */
+ public boolean isDefaultSize() {
+
+ if( type==ROW &&
+ dimension>DEFAULTROWSIZE_MIN &&
+ dimension<DEFAULTROWSIZE_MAX)
+ return true;
+ else
+ return false;
+ }
+}
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnStyle.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnStyle.java
new file mode 100644
index 000000000000..2b9c169ff352
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/ColumnStyle.java
@@ -0,0 +1,309 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ColumnStyle.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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;
+
+import java.awt.Color;
+import java.io.IOException;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeDocument;
+import org.openoffice.xmerge.converter.xml.Style;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.TwipsConverter;
+
+/**
+ * Represents a text <code>Style</code> in an OpenOffice document.
+ *
+ * @author Martin Maher
+ */
+public class ColumnStyle extends Style implements Cloneable {
+
+ private int colWidth = 0;
+ /**
+ * Constructor for use when going from DOM to client device format.
+ *
+ * @param Node The <i>style:style</i> <code>Node</code> containing
+ * the <code>Style</code>. (This <code>Node</code> is
+ * assumed have a <i>family</i> attribute of <i>text</i>).
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public ColumnStyle(Node node, StyleCatalog sc) {
+ super(node, sc);
+
+ // Run through the attributes of this node, saving
+ // the ones we're interested in.
+ NamedNodeMap attrNodes = node.getAttributes();
+ if (attrNodes != null) {
+ int len = attrNodes.getLength();
+ for (int i = 0; i < len; i++) {
+ Node attr = attrNodes.item(i);
+ handleAttribute(attr.getNodeName(), attr.getNodeValue());
+ }
+ }
+
+ // Look for children. Only ones we care about are "style:properties"
+ // nodes. If any are found, recursively traverse them, passing
+ // along the style element to add properties to.
+ if (node.hasChildNodes()) {
+ NodeList children = node.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ String name = child.getNodeName();
+ if (name.equals("style:properties")) {
+ NamedNodeMap childAttrNodes = child.getAttributes();
+ if (childAttrNodes != null) {
+ int nChildAttrNodes = childAttrNodes.getLength();
+ for (int j = 0; j < nChildAttrNodes; j++) {
+ Node attr = childAttrNodes.item(j);
+ handleAttribute(attr.getNodeName(),
+ attr.getNodeValue());
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Constructor for use when going from client device format to DOM
+ *
+ * @param name Name of text <code>Style</code>. Can be null.
+ * @param family Family of text <code>Style</code> (usually
+ * <i>text</i>). Can be null.
+ * @param parent Name of parent text <code>Style</code>, or null
+ * for none.
+ * @param mask the width of this column
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public ColumnStyle(String name, String family, String parent,int colWidth, StyleCatalog sc) {
+ super(name, family, parent, sc);
+ this.colWidth = colWidth;
+ }
+
+ /**
+ * Returns the width of this column
+ *
+ * @return the <code>Format</code> object
+ */
+ public int getColWidth() {
+ return colWidth;
+ }
+
+ /**
+ * Sets the width of this column
+ *
+ * @return the <code>Format</code> object
+ */
+ public void setColWidth(int colWidth) {
+
+ this.colWidth = colWidth;
+ }
+
+ /**
+ * Parse a colwidth in the form "1.234cm" to twips
+ *
+ * @param value <code>String</code> specification to parse.
+ *
+ * @return The twips equivalent.
+ */
+ private int parseColWidth(String value) {
+
+ int width = 255; // Default value
+
+ if(value.indexOf("cm")!=-1) {
+ float widthCM = Float.parseFloat(value.substring(0,value.indexOf("c")));
+ width = TwipsConverter.cm2twips(widthCM);
+ } else if(value.indexOf("inch")!=-1) {
+ float widthInch = Float.parseFloat(value.substring(0,value.indexOf("i")));
+ width = TwipsConverter.inches2twips(widthInch);
+ }
+
+ return (width);
+ }
+
+
+ /**
+ * Set an attribute.
+ *
+ * @param attr The attribute to set.
+ * @param value The attribute value to set.
+ */
+ private void handleAttribute(String attr, String value) {
+
+ if (attr.equals("style:column-width")) {
+ colWidth = parseColWidth(value);
+ }
+ else {
+ Debug.log(Debug.INFO, "ColumnStyle Unhandled: " + attr + "=" + value);
+ }
+ }
+
+
+ /**
+ * Return a <code>Style</code> object corresponding to this one,
+ * but with all of the inherited information from parent
+ * <code>Style</code> objects filled in. The object returned will
+ * be a new object, not a reference to this object, even if it does
+ * not need any information added.
+ *
+ * @return The <code>StyleCatalog</code> in which to look up
+ * ancestors.
+ */
+ public Style getResolved() {
+ // Create a new object to return, which is a clone of this one.
+ ColumnStyle resolved = null;
+ try {
+ resolved = (ColumnStyle)this.clone();
+ } catch (Exception e) {
+ Debug.log(Debug.ERROR, "Can't clone", e);
+ }
+
+ // Look up the parentStyle. (If there is no style catalog
+ // specified, we can't do any lookups.)
+ ColumnStyle parentStyle = null;
+ if (sc != null) {
+ if (parent != null) {
+ parentStyle = (ColumnStyle)sc.lookup(parent, family, null,
+ this.getClass());
+ if (parentStyle == null)
+ Debug.log(Debug.ERROR, "parent style lookup of "
+ + parent + " failed!");
+ else
+ parentStyle = (ColumnStyle)parentStyle.getResolved();
+
+ } else if (!name.equals("DEFAULT_STYLE")) {
+ parentStyle = (ColumnStyle)sc.lookup("DEFAULT_STYLE", null,
+ null, this.getClass());
+ }
+ }
+
+ // If we found a parent, for any attributes which we don't have
+ // set, try to get the values from the parent.
+ if (parentStyle != null) {
+ parentStyle = (ColumnStyle)parentStyle.getResolved();
+
+ if ((colWidth == 0) && (parentStyle.getColWidth() != 0))
+ resolved.setColWidth(parentStyle.getColWidth());
+ }
+ return resolved;
+ }
+
+
+ /**
+ * Create a new <code>Node</code> in the <code>Document</code>, and
+ * write this <code>Style</code> to it.
+ *
+ * @param parentDoc Parent <code>Document</code> of the
+ * <code>Node</code> to create.
+ * @param name Name to use for the new <code>Node</code> (e.g.
+ * <i>style:style</i>)
+ *
+ * @return Created <code>Node</code>.
+ */
+ public Node createNode(org.w3c.dom.Document parentDoc, String name) {
+ Element node = parentDoc.createElement(name);
+ writeAttributes(node);
+ return node;
+ }
+
+
+ /**
+ * Return true if <code>style</code> specifies as much or less
+ * than this <code>Style</code>, and nothing it specifies
+ * contradicts this <code>Style</code>.
+ *
+ * @param style The <code>Style</code> to check.
+ *
+ * @return true if <code>style</code> is a subset, false
+ * otherwise.
+ */
+ public boolean isSubset(Style style) {
+ if (style.getClass() != this.getClass())
+ return false;
+ ColumnStyle tStyle = (ColumnStyle)style;
+
+ if(colWidth!=tStyle.getColWidth())
+ return false;
+
+ return true;
+ }
+
+
+ /**
+ * Write this <code>Style</code> object's attributes to a
+ * <code>Node</code> in the <code>Document</code>.
+ *
+ * @param node The <code>Node</code> to add <code>Style</code>
+ * attributes.
+ */
+ public void writeAttributes(Element node) {
+
+ if(colWidth!=0) {
+ String width = TwipsConverter.twips2cm(colWidth) + "cm";
+ node.setAttribute("style:column-width", width);
+ }
+ }
+
+
+ private static String[] ignored = {
+ "fo:break-before", "fo:keep-with-next"
+ };
+
+
+ /*
+ * This code checks whether an attribute is one that we
+ * intentionally ignore.
+ *
+ * @param attribute The attribute to check.
+ *
+ * @return true if <code>attribute</code> can be ignored,
+ * otherwise false.
+ */
+ private boolean isIgnored(String attribute) {
+ for (int i = 0; i < ignored.length; i++) {
+ if (ignored[i].equals(attribute))
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/DocumentMergerImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/DocumentMergerImpl.java
new file mode 100644
index 000000000000..3ae4f16acfcf
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/DocumentMergerImpl.java
@@ -0,0 +1,202 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DocumentMergerImpl.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.DocumentMerger;
+import org.openoffice.xmerge.MergeException;
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.merger.DiffAlgorithm;
+import org.openoffice.xmerge.merger.Difference;
+import org.openoffice.xmerge.merger.Iterator;
+import org.openoffice.xmerge.merger.DiffAlgorithm;
+import org.openoffice.xmerge.merger.NodeMergeAlgorithm;
+import org.openoffice.xmerge.merger.diff.IteratorRowCompare;
+import org.openoffice.xmerge.merger.diff.RowIterator;
+import org.openoffice.xmerge.merger.merge.SheetMerge;
+import org.openoffice.xmerge.merger.merge.PositionBaseRowMerge;
+import org.openoffice.xmerge.merger.MergeAlgorithm;
+import org.openoffice.xmerge.util.XmlUtil;
+import org.openoffice.xmerge.util.Debug;
+
+
+/**
+ * Generic small device implementation of <code>DocumentMerger</code> for
+ * the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcPluginFactory
+ * SxcPluginFactory}. Used with SXC <code>Document</code> objects.</p>
+ */
+public class DocumentMergerImpl implements DocumentMerger {
+
+ private ConverterCapabilities cc_;
+ private org.openoffice.xmerge.Document orig = null;
+
+ /**
+ * Constructor
+ *
+ * @param doc The original &quot;Office&quot; <code>Document</code>
+ * to merge.
+ * @param cc The <code>ConverterCapabilities</code>.
+ */
+ public DocumentMergerImpl(org.openoffice.xmerge.Document doc, ConverterCapabilities cc) {
+ cc_ = cc;
+ this.orig = doc;
+ }
+
+ public void merge(Document modifiedDoc) throws MergeException {
+
+ SxcDocument sdoc1 = (SxcDocument)orig;
+ SxcDocument sdoc2 = (SxcDocument)modifiedDoc;
+
+ org.w3c.dom.Document doc1 = sdoc1.getContentDOM();
+ org.w3c.dom.Document doc2 = sdoc2.getContentDOM();
+
+ Element elem1 = doc1.getDocumentElement();
+ Element elem2 = doc2.getDocumentElement();
+
+ // get table name
+ NodeList workSheetList1 =
+ elem1.getElementsByTagName(OfficeConstants.TAG_TABLE);
+ NodeList workSheetList2 =
+ elem2.getElementsByTagName(OfficeConstants.TAG_TABLE);
+
+ int numOfWorkSheet = workSheetList1.getLength();
+
+ for (int i=0; i < numOfWorkSheet; i++) {
+ Node workSheet = workSheetList1.item(i);
+
+ // try to match the workSheet
+ Node matchingWorkSheet = matchWorkSheet(workSheet, workSheetList2);
+
+ if (matchingWorkSheet != null) {
+
+ // need to put it into a row Iterator
+ // use a straight comparsion algorithm then do a merge on it
+ Iterator i1 = new RowIterator(cc_, workSheet);
+ Iterator i2 = new RowIterator(cc_, matchingWorkSheet);
+
+ // find out the diff
+ DiffAlgorithm diffAlgo = new IteratorRowCompare();
+
+ // find out the paragrah level diffs
+ Difference[] diffResult = diffAlgo.computeDiffs(i1, i2);
+
+ if (Debug.isFlagSet(Debug.INFO)) {
+ Debug.log(Debug.INFO, "Diff Result: ");
+
+ for (int j = 0; j < diffResult.length; j++) {
+ Debug.log(Debug.INFO, diffResult[j].debug());
+ }
+ }
+
+ // merge back the result
+ NodeMergeAlgorithm rowMerger = new PositionBaseRowMerge(cc_);
+ MergeAlgorithm merger = new SheetMerge(cc_, rowMerger);
+
+ Iterator result = null;
+
+ merger.applyDifference(i1, i2, diffResult);
+ }
+ }
+
+ numOfWorkSheet = workSheetList2.getLength();
+
+ // for those workSheet from target don't have a matching one
+ // in the original workSheet list, we add it
+
+ // find out the office body node first
+ NodeList officeBodyList =
+ elem1.getElementsByTagName(OfficeConstants.TAG_OFFICE_BODY);
+
+ Node officeBody = officeBodyList.item(0);
+
+ // for each WorkSheets, try to see whether we have it or not
+ for (int j=0; j < numOfWorkSheet; j++) {
+ Node workSheet= workSheetList2.item(j);
+
+ // try to match the workSheet
+ //
+ Node matchingWorkSheet = matchWorkSheet(workSheet, workSheetList1);
+
+ // add the new WorkSheet to the original document iff match not
+ // found
+ //
+ if (matchingWorkSheet == null) {
+ Node cloneNode = XmlUtil.deepClone(officeBody, workSheet);
+ officeBody.appendChild(cloneNode);
+ }
+ }
+ }
+
+ /**
+ * Try to find a WorkSheet from the modified WorkSheetList that
+ * has a matching table name from the original WorkSheet.
+ *
+ * @param orgSheet The original WorkSheet.
+ * @param modSheetList The modified WorkSheet.
+ *
+ * @return The Node in modSheetList that matches the orgSheet.
+ */
+ private Node matchWorkSheet(Node orgSheet, NodeList modSheetList) {
+
+ Node matchSheet = null;
+
+ String orgTableName = ((Element)orgSheet).getAttribute(
+ OfficeConstants.ATTRIBUTE_TABLE_NAME);
+
+ if (orgTableName == null)
+ return null;
+
+ int numOfWorkSheet = modSheetList.getLength();
+
+ String modTableName;
+
+ for (int i=0; i < numOfWorkSheet; i++) {
+ modTableName = ((Element)modSheetList.item(i)).getAttribute(
+ OfficeConstants.ATTRIBUTE_TABLE_NAME);
+ if (modTableName == null)
+ continue;
+
+ if (orgTableName.equals(modTableName)) {
+ matchSheet = modSheetList.item(i);
+ break;
+ }
+ }
+
+ return matchSheet;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/Format.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/Format.java
new file mode 100644
index 000000000000..8e58ea0dd968
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/Format.java
@@ -0,0 +1,480 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Format.java,v $
+ * $Revision: 1.13 $
+ *
+ * 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;
+
+import java.awt.Color;
+
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * This class specifies the format for a given spreadsheet cell.
+ *
+ * @author Mark Murnane
+ * @author Martin Maher (Extended Style Support)
+ */
+public class Format implements Cloneable {
+
+ /** Horizontal Alignment Constants. */
+ final public static int RIGHT_ALIGN = 0x01;
+ final public static int CENTER_ALIGN = 0x02;
+ final public static int LEFT_ALIGN = 0x03;
+ final public static int JUST_ALIGN = 0x04;
+
+ /** Vertical Alignment Constants. */
+ final public static int TOP_ALIGN = 0x01;
+ final public static int MIDDLE_ALIGN = 0x02;
+ final public static int BOTTOM_ALIGN = 0x03;
+
+ /** Indicates <i>bold</i> text. */
+ final public static int BOLD = 0x01;
+ /** Indicates <i>italic</i> text. */
+ final public static int ITALIC = 0x02;
+ /** Indicates <i>underlined</i> text. */
+ final public static int UNDERLINE = 0x04;
+ /** Indicates <i>strike-through</i> in the text. */
+ final public static int STRIKETHRU = 0x08;
+ /** Indicates <i>superscripted</i> text. */
+ final public static int SUPERSCRIPT = 0x10;
+ /** Indicates <i>subscripted</i> text. */
+ final public static int SUBSCRIPT = 0x20;
+
+ final public static int LEFT_BORDER = 0x40;
+ final public static int RIGHT_BORDER = 0x80;
+ final public static int TOP_BORDER = 0x100;
+ final public static int BOTTOM_BORDER = 0x200;
+
+ final public static int WORD_WRAP = 0x400;
+
+ private int align;
+ private int vertAlign;
+ private String category;
+ private String value;
+ private String formatSpecifier;
+ private int decimalPlaces;
+
+ /** Font name. */
+ private String fontName;
+ /** Font size in points. */
+ protected int sizeInPoints;
+
+ private Color foreground, background;
+
+ /** Values of text attributes. */
+ protected int attributes = 0;
+ /** Bitwise mask of text attributes. */
+ protected int mask = 0;
+
+ /**
+ * Constructor for creating a new <code>Format</code>.
+ */
+ public Format() {
+ clearFormatting();
+ }
+
+ /**
+ * Constructor that creates a new <code>Format</code> object
+ * by setting all the format attributes.
+ *
+ */
+ public Format(int attributes, int fontSize, String fontName) {
+
+ this.attributes = attributes;
+ sizeInPoints = fontSize;
+ this.fontName = fontName;
+ }
+
+ /**
+ * Constructor for creating a new <code>Format</code> object
+ * based on an existing one.
+ *
+ * @param fmt <code>Format</code> to copy.
+ */
+ public Format(Format fmt) {
+ category = fmt.getCategory();
+ value = fmt.getValue();
+ formatSpecifier = fmt.getFormatSpecifier();
+ decimalPlaces = fmt.getDecimalPlaces();
+
+ attributes = fmt.attributes;
+ mask = fmt.mask;
+
+ fontName = fmt.getFontName();
+ align = fmt.getAlign();
+ vertAlign = fmt.getVertAlign();
+ foreground = fmt.getForeground();
+ background = fmt.getBackground();
+ sizeInPoints = fmt.sizeInPoints;
+ }
+
+
+ /**
+ * Reset this <code>Format</code> description.
+ */
+ public void clearFormatting() {
+ category = "";
+ value = "";
+ formatSpecifier = "";
+ decimalPlaces = 0;
+ attributes = 0;
+ mask = 0;
+ sizeInPoints = 10;
+ align = LEFT_ALIGN;
+ vertAlign = BOTTOM_ALIGN;
+ fontName = "";
+ foreground = null;
+ background = null;
+ }
+
+ /**
+ * Set one or more text attributes to <i>on</i>.
+ *
+ * @param flags Flag attributes to set <i>on</i>.
+ */
+ public void setAttribute(int flags, boolean toggle) {
+ mask |= flags;
+ if(toggle) {
+ attributes |= flags;
+ } else {
+ attributes &= ~flags;
+ }
+ }
+
+ /**
+ * Return true if the <code>attribute</code> is set to <i>on</i>
+ *
+ * @param attribute Attribute to check ({@link #BOLD},
+ * {@link #ITALIC}, etc.)
+ *
+ * @return true if <code>attribute</code> is set to <i>on</i>,
+ * otherwise false.
+ */
+ public boolean getAttribute(int attribute) {
+ if ((mask & attribute) == 0)
+ return false;
+ return (!((attributes & attribute) == 0));
+ }
+
+ /**
+ * Return true if text <code>attribute</code> is set in this
+ * <code>Style</code>.An attribute that is set may have a
+ * value of <i>on</i> or <i>off</i>.
+ *
+ * @param attribute The attribute to check ({@link #BOLD},
+ * {@link #ITALIC}, etc.).
+ *
+ * @return true if text <code>attribute</code> is set in this
+ * <code>Style</code>, false otherwise.
+ */
+ public boolean isSet(int attribute) {
+ return (!((mask & attribute) == 0));
+ }
+
+
+ /**
+ * Set the formatting category of this object, ie number, date,
+ * currency.The <code>OfficeConstants</code> class contains string
+ * constants for the category types.
+ *
+ * @see org.openoffice.xmerge.converter.xml.OfficeConstants
+ *
+ * @param newCategory The name of the category to be set.
+ */
+ public void setCategory(String newCategory) {
+ category = newCategory;
+ }
+
+ /**
+ * Return the formatting category of the object.
+ *
+ * @see org.openoffice.xmerge.converter.xml.OfficeConstants
+ *
+ * @return The formatting category of the object.
+ */
+ public String getCategory() {
+ return category;
+ }
+
+ /**
+ * In the case of Formula returns the value of the formula.
+ *
+ * @return The value of the formula
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * In the case of formula the contents are set as the formula string and
+ * the value of the formula is a formatting attribute.
+ *
+ * @param newValue the formuala value
+ */
+ public void setValue(String newValue) {
+ value = newValue;
+ }
+
+
+ /**
+ * Set the <code>Format</code> specifier for this category.
+ *
+ * @param formatString The new <code>Format</code> specifier.
+ */
+ public void setFormatSpecifier(String formatString) {
+ formatSpecifier = formatString;
+ }
+
+
+ /**
+ * Get the <code>Format</code> specifier for this category.
+ *
+ * @return <code>Format</code> specifier for this category.
+ */
+ public String getFormatSpecifier() {
+ return formatSpecifier;
+ }
+
+
+ /**
+ * Set the precision of the number to be displayed.
+ *
+ * @param precision The number of decimal places to display.
+ */
+ public void setDecimalPlaces(int precision) {
+ decimalPlaces = precision;
+ }
+
+
+ /**
+ * Get the number of decimal places displayed.
+ *
+ * @return Number of decimal places.
+ */
+ public int getDecimalPlaces() {
+ return decimalPlaces;
+ }
+
+
+ /**
+ * Set the font used for this cell.
+ *
+ * @param fontName The name of the font.
+ */
+ public void setFontName(String fontName) {
+ this.fontName = fontName;
+ }
+
+
+ /**
+ * Get the font used for this cell.
+ *
+ * @return The font name.
+ */
+ public String getFontName() {
+ return fontName;
+ }
+
+ /**
+ * Set the font used for this cell.
+ *
+ * @param fontName The name of the font.
+ */
+ public void setFontSize(int fontSize) {
+ sizeInPoints = fontSize;
+ }
+
+
+ /**
+ * Get the font used for this cell.
+ *
+ * @return The font name.
+ */
+ public int getFontSize() {
+ return sizeInPoints;
+ }
+
+ /**
+ * Set the alignmen used for this cell.
+ *
+ * @param fontName The name of the font.
+ */
+ public void setVertAlign(int vertAlign) {
+ this.vertAlign = vertAlign;
+ }
+
+
+ /**
+ * Get the alignment used for this cell.
+ *
+ * @return The font name.
+ */
+ public int getVertAlign() {
+ return vertAlign;
+ }
+
+ /**
+ * Set the alignmen used for this cell.
+ *
+ * @param fontName The name of the font.
+ */
+ public void setAlign(int align) {
+ this.align = align;
+ }
+
+
+ /**
+ * Get the alignment used for this cell.
+ *
+ * @return The font name.
+ */
+ public int getAlign() {
+ return align;
+ }
+ /**
+ * Set the Foreground <code>Color</code> for this cell.
+ *
+ * @param color A <code>Color</code> object representing the
+ * foreground color.
+ */
+ public void setForeground(Color c) {
+ if(c!=null)
+ foreground = new Color(c.getRGB());
+ }
+
+
+ /**
+ * Get the Foreground <code>Color</code> for this cell.
+ *
+ * @return Foreground <code>Color</code> value.
+ */
+ public Color getForeground() {
+ return foreground;
+ }
+
+
+ /**
+ * Set the Background <code>Color</code> for this cell
+ *
+ * @param color A <code>Color</code> object representing
+ * the background color.
+ */
+ public void setBackground(Color c) {
+ if(c!=null)
+ background = new Color(c.getRGB());
+ }
+
+
+ /**
+ * Get the Foreground <code>Color</code> for this cell
+ *
+ * @return Background <code>Color</code> value
+ */
+ public Color getBackground() {
+ return background;
+ }
+
+ /**
+ * Get the Foreground <code>Color</code> for this cell
+ *
+ * @return Background <code>Color</code> value
+ */
+ public String toString() {
+ return new String("Value : " + getValue() + " Category : " + getCategory());
+ }
+
+ /**
+ * Tests if the current <code>Format</code> object has default attribute
+ * values.
+ *
+ * @return true if it contains default value
+ */
+ public boolean isDefault() {
+
+ Format rhs = new Format();
+
+ if (rhs.attributes!= attributes)
+ return false;
+
+ if (foreground!=rhs.foreground)
+ return false;
+
+ if (background!=rhs.background)
+ return false;
+
+ if (rhs.align!= align)
+ return false;
+
+ if (rhs.vertAlign!= vertAlign)
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Return true if <code>style</code> specifies as much or less
+ * than this <code>Style</code>, and nothing it specifies
+ * contradicts this <code>Style</code>.
+ *
+ * @param style The <code>Style</code> to check.
+ *
+ * @return true if <code>style</code> is a subset, false
+ * otherwise.
+ */
+ public boolean isSubset(Format rhs) {
+ if (rhs.getClass() != this.getClass())
+ return false;
+
+ if (rhs.attributes!= attributes)
+ return false;
+
+ if (rhs.sizeInPoints != 0) {
+ if (sizeInPoints != rhs.sizeInPoints)
+ return false;
+ }
+
+ if (fontName!=rhs.fontName)
+ return false;
+
+ if (foreground!=rhs.foreground)
+ return false;
+
+ if (background!=rhs.background)
+ return false;
+
+ if (rhs.align!= align)
+ return false;
+
+ if (rhs.vertAlign!= vertAlign)
+ return false;
+
+ return true;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/NameDefinition.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/NameDefinition.java
new file mode 100644
index 000000000000..65f0979c4ed2
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/NameDefinition.java
@@ -0,0 +1,219 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: NameDefinition.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.XmlUtil;
+
+/**
+ * This is a class to define a Name Definition structure. This can then be
+ * used by plugins to write or read their own definition types.
+ *
+ * @author Martin Maher
+ */
+public class NameDefinition implements OfficeConstants {
+
+ private String name; // name which identifies the definition
+ private String definition; // the definition itself
+ private String baseCellAddress; // the basecelladdress
+ private boolean rangeType = false; // true if definition of type range
+ private boolean expressionType = false; // true if definition of type expression
+
+ /**
+ * Default Constructor for a <code>NameDefinition</code>
+ *
+ */
+ public NameDefinition() {
+
+ }
+
+ /**
+ * Constructor that takes a <code>Node</code> to build a
+ * <code>NameDefinition</code>
+ *
+ * @param root XML Node to read from
+ */
+ public NameDefinition(Node root) {
+ readNode(root);
+ }
+
+ /**
+ * Default Constructor for a <code>NameDefinition</code>
+ *
+ */
+ public NameDefinition(String name, String definition, String
+ baseCellAddress, boolean rangeType, boolean expressionType ) {
+ this.name = name;
+ this.definition = definition;
+ this.baseCellAddress = baseCellAddress;
+ this.rangeType = rangeType;
+ this.expressionType = expressionType;
+ }
+
+ /**
+ * returns Name of the definition
+ *
+ * @return the name which identifies the definition
+ */
+ public String getName() {
+
+ return name;
+ }
+ /**
+ * sets the definition
+ *
+ * @param newDefinition sets the definition
+ */
+ public void setDefinition(String newDefinition) {
+
+ definition = newDefinition;
+ }
+ /**
+ * Returns the definition itself
+ *
+ * @return the definition
+ */
+ public String getDefinition() {
+
+ return definition;
+ }
+
+ /**
+ * Returns the base Cell address
+ *
+ * @return the base cell address
+ */
+ public String getBaseCellAddress() {
+
+ return baseCellAddress;
+ }
+
+ /**
+ * Tests if definition is of type expression
+ *
+ * @return whether or not this name definition is of type expression
+ */
+ public boolean isExpressionType() {
+ return expressionType;
+ }
+
+ /**
+ * Tests if definition is of type range
+ *
+ * @return whether or not this name definition is of type range
+ */
+ public boolean isRangeType() {
+ return rangeType;
+ }
+
+ /**
+ * Writes out a content.xml entry for this NameDefinition object
+ *
+ * @param settings a <code>Document</code> object representing the settings.xml
+ * @param root the root xml node to add to
+ */
+ public void writeNode(org.w3c.dom.Document doc, Node root) {
+
+ if(isRangeType()) {
+
+ Debug.log(Debug.TRACE, "Found Range Name : " + getName());
+ Element namedRangeElement = (Element) doc.createElement(TAG_TABLE_NAMED_RANGE);
+ namedRangeElement.setAttribute(ATTRIBUTE_TABLE_NAME, getName());
+ namedRangeElement.setAttribute(ATTRIBUTE_TABLE_BASE_CELL_ADDRESS, getBaseCellAddress());
+ namedRangeElement.setAttribute(ATTRIBUTE_TABLE_CELL_RANGE_ADDRESS, getDefinition());
+ root.appendChild(namedRangeElement);
+ } else if (isExpressionType()) {
+
+ Debug.log(Debug.TRACE, "Found Expression Name : " + getName());
+ Element namedExpressionElement = (Element) doc.createElement(TAG_TABLE_NAMED_EXPRESSION);
+ namedExpressionElement.setAttribute(ATTRIBUTE_TABLE_NAME, getName());
+ namedExpressionElement.setAttribute(ATTRIBUTE_TABLE_BASE_CELL_ADDRESS,getBaseCellAddress());
+ namedExpressionElement.setAttribute(ATTRIBUTE_TABLE_EXPRESSION, getDefinition());
+ root.appendChild(namedExpressionElement);
+ } else {
+
+ Debug.log(Debug.TRACE, "Unknown Name Definition : " + getName());
+ }
+ }
+
+ /**
+ * Reads document settings from xml and inits Settings variables
+ *
+ * @param root XML Node to read from
+ */
+ public void readNode(Node root) {
+
+ String nodeName = root.getNodeName();
+ NamedNodeMap cellAtt = root.getAttributes();
+
+ if (nodeName.equals(TAG_TABLE_NAMED_RANGE)) {
+
+ Node tableNameNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_NAME);
+ Node tableBaseCellAddress =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_BASE_CELL_ADDRESS);
+ Node tableCellRangeAddress =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_CELL_RANGE_ADDRESS);
+ Debug.log(Debug.TRACE,"Named-range : " + tableNameNode.getNodeValue());
+ // Create a named-range name definition
+ name = tableNameNode.getNodeValue();
+ definition = tableCellRangeAddress.getNodeValue();
+ baseCellAddress = tableBaseCellAddress.getNodeValue();
+ expressionType = true;
+ rangeType = false;
+
+ } else if (nodeName.equals(TAG_TABLE_NAMED_EXPRESSION)) {
+
+ Node tableNameNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_NAME);
+ Node tableBaseCellAddress =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_BASE_CELL_ADDRESS);
+ Node tableExpression=
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_EXPRESSION);
+ Debug.log(Debug.TRACE,"Named-expression: " + tableNameNode.getNodeValue());
+ // Create a named-range name definition
+ name = tableNameNode.getNodeValue();
+ definition = tableExpression.getNodeValue();
+ baseCellAddress = tableBaseCellAddress.getNodeValue();
+ expressionType = false;
+ rangeType = true;
+ } else {
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(root) + " />");
+ }
+ }
+
+}
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/RowStyle.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/RowStyle.java
new file mode 100644
index 000000000000..71839e238d43
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/RowStyle.java
@@ -0,0 +1,308 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: RowStyle.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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;
+
+import java.io.IOException;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeDocument;
+import org.openoffice.xmerge.converter.xml.Style;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.TwipsConverter;
+
+/**
+ * Represents a text <code>Style</code> in an OpenOffice document.
+ *
+ * @author Martin Maher
+ */
+public class RowStyle extends Style implements Cloneable {
+
+ private int rowHeight = 255;
+ /**
+ * Constructor for use when going from DOM to client device format.
+ *
+ * @param Node The <i>style:style</i> <code>Node</code> containing
+ * the <code>Style</code>. (This <code>Node</code> is
+ * assumed have a <i>family</i> attribute of <i>text</i>).
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public RowStyle(Node node, StyleCatalog sc) {
+ super(node, sc);
+
+ // Run through the attributes of this node, saving
+ // the ones we're interested in.
+ NamedNodeMap attrNodes = node.getAttributes();
+ if (attrNodes != null) {
+ int len = attrNodes.getLength();
+ for (int i = 0; i < len; i++) {
+ Node attr = attrNodes.item(i);
+ handleAttribute(attr.getNodeName(), attr.getNodeValue());
+ }
+ }
+
+ // Look for children. Only ones we care about are "style:properties"
+ // nodes. If any are found, recursively traverse them, passing
+ // along the style element to add properties to.
+ if (node.hasChildNodes()) {
+ NodeList children = node.getChildNodes();
+ int len = children.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = children.item(i);
+ String name = child.getNodeName();
+ if (name.equals("style:properties")) {
+ NamedNodeMap childAttrNodes = child.getAttributes();
+ if (childAttrNodes != null) {
+ int nChildAttrNodes = childAttrNodes.getLength();
+ for (int j = 0; j < nChildAttrNodes; j++) {
+ Node attr = childAttrNodes.item(j);
+ handleAttribute(attr.getNodeName(),
+ attr.getNodeValue());
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Constructor for use when going from client device format to DOM
+ *
+ * @param name Name of text <code>Style</code>. Can be null.
+ * @param family Family of text <code>Style</code> (usually
+ * <i>text</i>). Can be null.
+ * @param parent Name of parent text <code>Style</code>, or null
+ * for none.
+ * @param mask The height of this row
+ * @param sc The <code>StyleCatalog</code>, which is used for
+ * looking up ancestor <code>Style</code> objects.
+ */
+ public RowStyle(String name, String family, String parent,int rowHeight, StyleCatalog sc) {
+ super(name, family, parent, sc);
+ this.rowHeight=rowHeight;
+ }
+
+ /**
+ * Returns the height of this row
+ *
+ * @return the <code>Format</code> object
+ */
+ public int getRowHeight() {
+ return rowHeight;
+ }
+
+ /**
+ * Sets the height of this row
+ *
+ * @return the <code>Format</code> object
+ */
+ public void setRowHeight(int RowHeight) {
+
+ this.rowHeight = rowHeight;
+ }
+ /**
+ * Parse a colheight in the form "1.234cm" to twips
+ *
+ * @param value <code>String</code> specification to parse.
+ *
+ * @return The twips equivalent.
+ */
+ private int parseRowHeight(String value) {
+
+ int height = 255; // Default value
+
+ if(value.indexOf("cm")!=-1) {
+ float heightCM = Float.parseFloat(value.substring(0,value.indexOf("c")));
+ height = TwipsConverter.cm2twips(heightCM);
+ } else if(value.indexOf("inch")!=-1) {
+ float heightInch = Float.parseFloat(value.substring(0,value.indexOf("i")));
+ height = TwipsConverter.inches2twips(heightInch);
+ }
+
+ return (height);
+
+ }
+
+
+ /**
+ * Set an attribute.
+ *
+ * @param attr The attribute to set.
+ * @param value The attribute value to set.
+ */
+ private void handleAttribute(String attr, String value) {
+
+ if (attr.equals("style:row-height")) {
+ rowHeight = parseRowHeight(value);
+ }
+ else {
+ Debug.log(Debug.INFO, "RowStyle Unhandled: " + attr + "=" + value);
+ }
+ }
+
+
+ /**
+ * Return a <code>Style</code> object corresponding to this one,
+ * but with all of the inherited information from parent
+ * <code>Style</code> objects filled in. The object returned will
+ * be a new object, not a reference to this object, even if it does
+ * not need any information added.
+ *
+ * @return The <code>StyleCatalog</code> in which to look up
+ * ancestors.
+ */
+ public Style getResolved() {
+ // Create a new object to return, which is a clone of this one.
+ RowStyle resolved = null;
+ try {
+ resolved = (RowStyle)this.clone();
+ } catch (Exception e) {
+ Debug.log(Debug.ERROR, "Can't clone", e);
+ }
+
+ // Look up the parentStyle. (If there is no style catalog
+ // specified, we can't do any lookups.)
+ RowStyle parentStyle = null;
+ if (sc != null) {
+ if (parent != null) {
+ parentStyle = (RowStyle)sc.lookup(parent, family, null,
+ this.getClass());
+ if (parentStyle == null)
+ Debug.log(Debug.ERROR, "parent style lookup of "
+ + parent + " failed!");
+ else
+ parentStyle = (RowStyle)parentStyle.getResolved();
+
+ } else if (!name.equals("DEFAULT_STYLE")) {
+ parentStyle = (RowStyle)sc.lookup("DEFAULT_STYLE", null,
+ null, this.getClass());
+ }
+ }
+
+ // If we found a parent, for any attributes which we don't have
+ // set, try to get the values from the parent.
+ if (parentStyle != null) {
+ parentStyle = (RowStyle)parentStyle.getResolved();
+
+ if ((rowHeight == 0) && (parentStyle.getRowHeight() != 0))
+ resolved.setRowHeight(parentStyle.getRowHeight());
+ }
+ return resolved;
+ }
+
+
+ /**
+ * Create a new <code>Node</code> in the <code>Document</code>, and
+ * write this <code>Style</code> to it.
+ *
+ * @param parentDoc Parent <code>Document</code> of the
+ * <code>Node</code> to create.
+ * @param name Name to use for the new <code>Node</code> (e.g.
+ * <i>style:style</i>)
+ *
+ * @return Created <code>Node</code>.
+ */
+ public Node createNode(org.w3c.dom.Document parentDoc, String name) {
+ Element node = parentDoc.createElement(name);
+ writeAttributes(node);
+ return node;
+ }
+
+
+ /**
+ * Return true if <code>style</code> specifies as much or less
+ * than this <code>Style</code>, and nothing it specifies
+ * contradicts this <code>Style</code>.
+ *
+ * @param style The <code>Style</code> to check.
+ *
+ * @return true if <code>style</code> is a subset, false
+ * otherwise.
+ */
+ public boolean isSubset(Style style) {
+ if (style.getClass() != this.getClass())
+ return false;
+ RowStyle tStyle = (RowStyle)style;
+
+ if(rowHeight!=tStyle.getRowHeight())
+ return false;
+
+ return true;
+ }
+
+
+ /**
+ * Write this <code>Style</code> object's attributes to a
+ * <code>Node</code> in the <code>Document</code>.
+ *
+ * @param node The <code>Node</code> to add <code>Style</code>
+ * attributes.
+ */
+ public void writeAttributes(Element node) {
+
+ if(rowHeight!=0) {
+ String height = TwipsConverter.twips2cm(rowHeight) + "cm";
+ node.setAttribute("style:row-height", height);
+ }
+ }
+
+
+ private static String[] ignored = {
+ "fo:break-before", "fo:keep-with-next"
+ };
+
+
+ /*
+ * This code checks whether an attribute is one that we
+ * intentionally ignore.
+ *
+ * @param attribute The attribute to check.
+ *
+ * @return true if <code>attribute</code> can be ignored,
+ * otherwise false.
+ */
+ private boolean isIgnored(String attribute) {
+ for (int i = 0; i < ignored.length; i++) {
+ if (ignored[i].equals(attribute))
+ return true;
+ }
+ return false;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SheetSettings.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SheetSettings.java
new file mode 100644
index 000000000000..765da090611c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SheetSettings.java
@@ -0,0 +1,377 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SheetSettings.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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;
+
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+import java.awt.Point;
+
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * This is a class representing the different attributes for a worksheet
+ * contained in settings.xml.
+ *
+ * @author Martin Maher
+ */
+public class SheetSettings implements OfficeConstants {
+
+ /** A w3c <code>Document</code>. */
+ private org.w3c.dom.Document settings = null;
+
+ private String sheetName;
+ private int cursorX = 0;
+ private int cursorY = 0;
+ private int splitTypeX;
+ private int splitTypeY;
+ private int splitPointX = 0;
+ private int splitPointY = 0;
+ private int posLeft = 0;
+ private int posRight = 0;
+ private int posBottom = 0;
+ private int posTop = 0;
+ private int paneNumber = 2;
+
+ final public static int NONE = 0x00;
+ final public static int SPLIT = 0x01;
+ final public static int FREEZE = 0x02;
+
+
+ /**
+ * Default Constructor for a <code>ColumnRowInfo</code>
+ *
+ */
+ public SheetSettings() {
+ }
+
+ /**
+ * Constructor that takes a <code>Node</code> to build a <code>SheetSettings</code>
+ *
+ * @param root XML Node to read from
+ */
+ public SheetSettings(Node root) {
+ readNode(root);
+ }
+
+ /**
+ * Constructor for a <code>ColumnRowInfo</code>
+ *
+ * @param dimension if it's a row the height, a column the width
+ * @param repeated
+ */
+ public SheetSettings(String name) {
+ sheetName = name;
+ }
+
+ /**
+ * sets the position of the acitve cell
+ *
+ * @param activeCell the current curor position
+ */
+ public void setCursor(Point activeCell) {
+
+ cursorX = (int) activeCell.getX();
+ cursorY = (int) activeCell.getY();
+ }
+
+ /**
+ * Gets the position of the acitve cell
+ *
+ * @return The position as a <code>Point</code>
+ */
+ public Point getCursor() {
+
+ return (new Point(cursorX, cursorY));
+ }
+
+ /**
+ * Sets the position of the freeze
+ *
+ * @param splitPoint the point at where the split occurs
+ */
+ public void setFreeze(Point splitPoint) {
+
+ splitTypeX = FREEZE;
+ splitTypeY = FREEZE;
+ splitPointX = (int) splitPoint.getX();
+ splitPointY = (int) splitPoint.getY();
+ }
+
+ /**
+ * Sets the position of the split
+ *
+ * @param splitPoint the point at where the split occurs
+ */
+ public void setSplit(Point splitPoint) {
+
+ splitTypeX = SPLIT;
+ splitTypeY = SPLIT;
+ splitPointX = (int) splitPoint.getX();
+ splitPointY = (int) splitPoint.getY();
+ }
+
+ /**
+ * sets the position and type of the split
+ *
+ * @return The position as a <code>Point</code> where the split occurs
+ */
+ public Point getSplit() {
+
+ return (new Point(splitPointX, splitPointY));
+ }
+
+ /**
+ * sets the position and type of the split
+ *
+ * @return The position as a <code>Point</code> where the split occurs
+ */
+ public Point getSplitType() {
+
+ return (new Point(splitTypeX, splitTypeY));
+ }
+
+ /**
+ * Sets the top row visible in the lower pane and the leftmost column
+ * visibile in the right pane.
+ *
+ * @param top The top row visible in the lower pane
+ * @param left The leftmost column visibile in the right pane
+ */
+ public void setTopLeft(int top, int left) {
+
+ posLeft = left;
+ posTop = top;
+ }
+
+ /**
+ * Gets the the leftmost column visibile in the right pane.
+ *
+ * @return the 0-based index to the column
+ */
+ public int getLeft() {
+
+ return posLeft;
+ }
+ /**
+ * Sets the top row visible in the lower pane and the leftmost column
+ * visibile in the right pane.
+ *
+ * @param top The top row visible in the lower pane
+ * @param left The leftmost column visibile in the right pane
+ */
+ public int getTop() {
+
+ return posTop;
+ }
+
+ /**
+ * Gets the active Panel
+ * 0 - Bottom Right, 1 - Top Right
+ * 2 - Bottom Left, 3 - Top Left
+ *
+ * @return int representing the active panel
+ */
+ public int getPaneNumber() {
+
+ return paneNumber;
+ }
+
+ /**
+ * Sets the sheetname this settings object applies to
+ *
+ * @param sheetName the name of the worksheet
+ */
+ public void setSheetName(String sheetName) {
+
+ this.sheetName = sheetName;
+
+ }
+
+ /**
+ * Sets the active pane number
+ * 0 - Bottom Right, 1 - Top Right
+ * 2 - Bottom Left, 3 - Top Left
+ *
+ * @param paneNumber the pane number
+ */
+ public void setPaneNumber(int paneNumber) {
+
+ this.paneNumber = paneNumber;
+ }
+
+ /**
+ * Gets the name of the worksheet these <code>Settings</code> apply to
+ *
+ * @return the name of the worksheet
+ */
+ public String getSheetName() {
+
+ return sheetName;
+ }
+
+ /**
+ * Adds an XML entry for a particular setting
+ *
+ * @param root the root node at which to add the xml entry
+ * @param attriute the name of the attribute to add
+ * @param type the attribute type (int, short etc)
+ * @param value the value of the attribute
+ */
+ private void addConfigItem(Node root, String attribute, String type, String value) {
+
+ Element configItem = settings.createElement(TAG_CONFIG_ITEM);
+ configItem.setAttribute(ATTRIBUTE_CONFIG_NAME, attribute);
+ configItem.setAttribute(ATTRIBUTE_CONFIG_TYPE, type);
+
+ configItem.appendChild(settings.createTextNode(value));
+
+ root.appendChild(configItem);
+ }
+
+ /**
+ * Writes out a settings.xml entry for this SheetSettings object
+ *
+ * @param settings a <code>Document</code> object representing the settings.xml
+ * @param root the root xml node to add to
+ */
+ public void writeNode(org.w3c.dom.Document settings, Node root) {
+
+ this.settings = settings;
+ Element configItemMapEntry = (Element) settings.createElement(TAG_CONFIG_ITEM_MAP_ENTRY);
+ configItemMapEntry.setAttribute(ATTRIBUTE_CONFIG_NAME, getSheetName());
+ addConfigItem(configItemMapEntry, "CursorPositionX", "int", Integer.toString(cursorX));
+ addConfigItem(configItemMapEntry, "CursorPositionY", "int", Integer.toString(cursorY));
+
+ String splitMode = Integer.toString(splitTypeX);
+ if(splitPointX==0) {
+ splitMode = "0";
+ }
+ addConfigItem(configItemMapEntry, "HorizontalSplitMode", "short", splitMode);
+
+ splitMode = Integer.toString(splitTypeY);
+ if(splitPointY==0) {
+ splitMode = "0";
+ }
+ addConfigItem(configItemMapEntry, "VerticalSplitMode", "short", splitMode);
+
+ addConfigItem(configItemMapEntry, "HorizontalSplitPosition", "int", Integer.toString(splitPointX));
+ addConfigItem(configItemMapEntry, "VerticalSplitPosition", "int", Integer.toString(splitPointY));
+ addConfigItem(configItemMapEntry, "ActiveSplitRange", "short", Integer.toString(paneNumber));
+
+ addConfigItem(configItemMapEntry, "PositionLeft", "int", "0");
+ addConfigItem(configItemMapEntry, "PositionRight", "int", Integer.toString(posLeft));
+ addConfigItem(configItemMapEntry, "PositionTop", "int", "0");
+ addConfigItem(configItemMapEntry, "PositionBottom", "int", Integer.toString(posTop));
+ root.appendChild(configItemMapEntry);
+ }
+
+ /**
+ * Sets a variable based on a String value read from XML
+ *
+ * @param name xml name of the attribute to set
+ * @param value String value fo the attribute
+ */
+ public void addAttribute(String name, String value) {
+
+ if(name.equals("CursorPositionX")) {
+ cursorX = Integer.parseInt(value);
+ } else if(name.equals("CursorPositionY")) {
+ cursorY = Integer.parseInt(value);
+
+ } else if(name.equals("HorizontalSplitPosition")) {
+ splitPointX = Integer.parseInt(value);
+ } else if(name.equals("VerticalSplitPosition")) {
+ splitPointY = Integer.parseInt(value);
+ } else if(name.equals("ActiveSplitRange")) {
+ paneNumber = Integer.parseInt(value);
+
+ } else if(name.equals("PositionRight")) {
+ posLeft = Integer.parseInt(value);
+ } else if(name.equals("PositionBottom")) {
+ posTop = Integer.parseInt(value);
+
+ } else if(name.equals("HorizontalSplitMode")) {
+ splitTypeX = Integer.parseInt(value);
+ } else if(name.equals("VerticalSplitMode")) {
+ splitTypeY = Integer.parseInt(value);
+ }
+ }
+
+ /**
+ * Reads document settings from xml and inits SheetSettings variables
+ *
+ * @param root XML Node to read from
+ */
+ public void readNode(Node root) {
+
+ NamedNodeMap sheetAtt = root.getAttributes();
+
+ Node sheetNameNode = sheetAtt.getNamedItem(ATTRIBUTE_CONFIG_NAME);
+
+ sheetName = sheetNameNode.getNodeValue();
+
+ if (root.hasChildNodes()) {
+
+ NodeList nodeList = root.getChildNodes();
+ int len = nodeList.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_CONFIG_ITEM)) {
+
+ NamedNodeMap cellAtt = child.getAttributes();
+
+ Node configNameNode =
+ cellAtt.getNamedItem(ATTRIBUTE_CONFIG_NAME);
+
+ String name = configNameNode.getNodeValue();
+ NodeList nodeList2 = child.getChildNodes();
+ int len2 = nodeList2.getLength();
+ String s = "";
+ for (int j = 0; j < len2; j++) {
+ Node child2 = nodeList2.item(j);
+ if (child2.getNodeType() == Node.TEXT_NODE) {
+ s = child2.getNodeValue();
+ }
+ }
+ addAttribute(name, s);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetDecoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetDecoder.java
new file mode 100644
index 000000000000..5a6408ba6694
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetDecoder.java
@@ -0,0 +1,184 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SpreadsheetDecoder.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.ConvertData;
+
+/**
+ * This class is a abstract class for encoding a &quot;Device&quot;
+ * <code>Document</code> format into an alternative spreadsheet format.
+ *
+ * @author Mark Murnane
+ */
+public abstract class SpreadsheetDecoder {
+
+ /**
+ * Constructor for creating new <code>SpreadsheetDecoder</code>.
+ */
+ public SpreadsheetDecoder(String name, String password) throws IOException {
+ }
+
+ /**
+ * Returns the total number of sheets in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public abstract int getNumberOfSheets();
+
+ /**
+ * Returns an Enumeration to a Vector of <code>NameDefinition</code>.
+ *
+ * @return The Enumeration
+ */
+ public abstract Enumeration getNameDefinitions();
+
+ /**
+ * Returns an <code>BookSettings</code>
+ *
+ * @return The Enumeration
+ */
+ public abstract BookSettings getSettings();
+
+ /**
+ * Returns an Enumeration to a Vector of <code>ColumnRowInfo</code>.
+ *
+ * @return The Enumeration
+ */
+ public abstract Enumeration getColumnRowInfos();
+
+ /**
+ * Returns the number of populated rows in the current WorkSheet.
+ *
+ * @return the number of populated rows in the current WorkSheet.
+ */
+ public abstract int getNumberOfRows();
+
+
+ /**
+ * Returns the number of populated columns in the current WorkSheet.
+ *
+ * @return The number of populated columns in the current WorkSheet.
+ */
+ public abstract int getNumberOfColumns();
+
+
+ /**
+ * Returns the name of the current WorkSheet.
+ *
+ * @return Name of the current WorkSheet.
+ */
+ public abstract String getSheetName();
+
+
+ /**
+ * Returns the number of the active column.
+ *
+ * @return The number of the active column.
+ */
+ public abstract int getColNumber();
+
+
+ /**
+ * Returns the number of the active row.
+ *
+ * @return The number of the active row.
+ */
+ public abstract int getRowNumber();
+
+
+ /**
+ * Sets the active WorkSheet.
+ *
+ * @param sheetIndex The index of the sheet to be made active.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract void setWorksheet(int sheetIndex) throws IOException;
+
+
+ /**
+ * Move on the next populated cell in the current WorkSheet.
+ *
+ * @return true if successful, false otherwise.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract boolean goToNextCell() throws IOException;
+
+
+ /**
+ * Return the contents of the active cell.
+ *
+ * @return The cell contents.
+ */
+ public abstract String getCellContents();
+
+ /**
+ * Return the value of the active cell. Used in the case of Formula where
+ * the cell contents and the cell value are not the same thing.
+ *
+ * @return The cell value.
+ */
+ public abstract String getCellValue();
+
+ /**
+ * Return the data type of the active cell.
+ *
+ * @return The cell data type.
+ */
+ public abstract String getCellDataType();
+
+
+ /**
+ * Return a <code>Format</code> object describing the active cells
+ * formatting.
+ *
+ * @return <code>Format</code> object for the cell.
+ */
+ public abstract Format getCellFormat();
+
+
+ /**
+ * Add the contents of a <code>ConvertData</code> to the workbook.
+ *
+ * @param cd The <code>ConvertData</code> containing the
+ * content.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract void addDeviceContent(ConvertData cd) throws IOException;
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetEncoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetEncoder.java
new file mode 100644
index 000000000000..81e6914b1bfe
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SpreadsheetEncoder.java
@@ -0,0 +1,134 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SpreadsheetEncoder.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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;
+
+import java.io.IOException;
+import java.util.Vector;
+
+import org.openoffice.xmerge.util.IntArrayList;
+
+/**
+ * <p>This class is a abstract class for encoding an SXC into an
+ * alternative spreadsheet format.</p>
+ *
+ * <p>TODO - Add appropriate exceptions to each of the methods.</p>
+ *
+ * @author Mark Murnane
+ */
+public abstract class SpreadsheetEncoder {
+
+
+ /**
+ * Creates new SpreadsheetEncoder.
+ *
+ * @param name The name of the WorkBook to be created.
+ * @param password An optional password for the WorkBook.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public SpreadsheetEncoder(String name, String password) throws IOException { };
+
+
+ /**
+ * Create a new WorkSheet within the WorkBook.
+ *
+ * @param sheetName The name of the WorkSheet.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract void createWorksheet(String sheetName) throws IOException;
+
+
+ /**
+ * 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 abstract void setCellFormat(int row, int column, Format fmt);
+
+
+ /**
+ * 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.
+ */
+ public abstract void addCell(int row, int column,
+ Format fmt, String cellContents) throws IOException;
+
+
+ /**
+ * Get the number of sheets in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public abstract int getNumberOfSheets();
+
+
+ /**
+ * Get the names of the sheets in the WorkBook.
+ *
+ * @param sheet The required sheet.
+ */
+ public abstract String getSheetName(int sheet);
+
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public abstract void setColumnRows(Vector columnRows) throws IOException;
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public abstract void setNameDefinition(NameDefinition nd) throws IOException;
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public abstract void addSettings(BookSettings s) throws IOException;
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcConstants.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcConstants.java
new file mode 100644
index 000000000000..793fe47bfc23
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcConstants.java
@@ -0,0 +1,53 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcConstants.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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;
+
+
+/**
+ * Interface defining constants for Sxc attributes.
+ *
+ * @author Martin Maher
+ */
+public interface SxcConstants {
+
+ /** Family name for column styles. */
+ public static final String COLUMN_STYLE_FAMILY = "table-column";
+
+ /** Family name for row styles. */
+ public static final String ROW_STYLE_FAMILY = "table-row";
+
+ /** Family name for table-cell styles. */
+ public static final String TABLE_CELL_STYLE_FAMILY = "table-cell";
+
+ /** Name of the default style. */
+ public static final String DEFAULT_STYLE = "Default";
+}
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocument.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocument.java
new file mode 100644
index 000000000000..8a76b4260fc5
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocument.java
@@ -0,0 +1,96 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocument.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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;
+
+import org.w3c.dom.Document;
+import org.openoffice.xmerge.converter.xml.OfficeDocument;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+
+/**
+ * This class is an implementation of <code>OfficeDocument</code> for
+ * the SXC format.
+ */
+public class SxcDocument extends OfficeDocument {
+
+ /**
+ * Constructor with arguments to set <code>name</code>.
+ *
+ * @param name The name of the <code>Document</code>
+ */
+ public SxcDocument(String name) {
+ super(name);
+ }
+
+
+ /**
+ * Constructor with arguments to set <code>name</code>, the
+ * <code>namespaceAware</code> flag, and the <code>validating</code>
+ * flag.
+ *
+ * @param name The name of the <code>Document</code>.
+ * @param namespaceAware The value of the <code>namespaceAware</code>
+ * flag.
+ * @param validating The value of the <code>validating</code> flag.
+ */
+ public SxcDocument(String name, boolean namespaceAware, boolean validating) {
+
+ super(name, namespaceAware, validating);
+ }
+
+ /**
+ * Returns the Office file extension for the SXC format.
+ *
+ * @return The Office file extension for the SXC format.
+ */
+ protected String getFileExtension() {
+ return OfficeConstants.SXC_FILE_EXTENSION;
+ }
+
+ /**
+ * Returns the Office attribute for the SXC format.
+ *
+ * @return The Office attribute for the SXC format.
+ */
+ protected String getOfficeClassAttribute() {
+ return OfficeConstants.SXC_TYPE;
+ }
+
+ /**
+ * Method to return the MIME type of the document.
+ *
+ * @return String The document's MIME type.
+ */
+ protected final String getDocumentMimeType() {
+ return OfficeConstants.SXC_MIME_TYPE;
+ }
+
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentDeserializer.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentDeserializer.java
new file mode 100644
index 000000000000..01e9987172b4
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentDeserializer.java
@@ -0,0 +1,797 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentDeserializer.java,v $
+ * $Revision: 1.14 $
+ *
+ * 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;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.Element;
+
+import java.awt.Point;
+import java.io.IOException;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.ConvertException;
+import org.openoffice.xmerge.DocumentDeserializer;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocument;
+import org.openoffice.xmerge.converter.xml.sxc.BookSettings;
+import org.openoffice.xmerge.converter.xml.sxc.SheetSettings;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.sxc.CellStyle;
+import org.openoffice.xmerge.converter.xml.Style;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * <p>General spreadsheet implementation of <code>DocumentDeserializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcPluginFactory
+ * SxcPluginFactory}. Used with SXC <code>Document</code> objects.</p>
+ *
+ * <p>The <code>deserialize</code> method uses a <code>DocDecoder</code>
+ * to read the device spreadsheet format into a <code>String</code>
+ * object, then it calls <code>buildDocument</code> to create a
+ * <code>SxcDocument</code> object from it.</p>
+ *
+ * @author Paul Rank
+ * @author Mark Murnane
+ * @author Martin Maher
+ */
+public abstract class SxcDocumentDeserializer implements OfficeConstants,
+ DocumentDeserializer {
+
+ /**
+ * A <code>SpreadsheetDecoder</code> object for decoding from
+ * device formats.
+ */
+ private SpreadsheetDecoder decoder = null;
+
+ /** A w3c <code>Document</code>. */
+ private org.w3c.dom.Document settings = null;
+
+ /** A w3c <code>Document</code>. */
+ private org.w3c.dom.Document doc = null;
+
+ /** An <code>ConvertData</code> object assigned to this object. */
+ private ConvertData cd = null;
+
+ /** A style catalog for the workbook */
+ private StyleCatalog styleCat = null;
+
+ private int textStyles = 1;
+ private int colStyles = 1;
+ private int rowStyles = 1;
+
+ /**
+ * Constructor.
+ *
+ * @param cd <code>ConvertData</code> consisting of a
+ * device content object.
+ */
+ public SxcDocumentDeserializer(ConvertData cd) {
+ this.cd = cd;
+ }
+
+
+ /**
+ * This abstract method will be implemented by concrete subclasses
+ * and will return an application-specific Decoder.
+ *
+ * @param workbook The WorkBook to read.
+ * @param password The WorkBook password.
+ *
+ * @return The appropriate <code>SpreadSheetDecoder</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract SpreadsheetDecoder createDecoder(String workbook, String[] worksheetNames, String password)
+ throws IOException;
+
+
+ /**
+ * <p>This method will return the name of the WorkBook from the
+ * <code>ConvertData</code>. Allows for situations where the
+ * WorkBook name differs from the Device Content name.</p>
+ *
+ * <p>Implemented in the Deserializer as the Decoder's constructor requires
+ * a name.</p>
+ *
+ * @param cd The <code>ConvertData</code> containing the Device
+ * content.
+ *
+ * @return The WorkBook name.
+ */
+ protected abstract String getWorkbookName(ConvertData cd) throws IOException;
+
+
+ /**
+ * This method will return the name of the WorkSheet from the
+ * <code>ConvertData</code>.
+ *
+ * @param cd The <code>ConvertData</code> containing the Device
+ * content.
+ *
+ * @return The WorkSheet names.
+ */
+ protected abstract String[] getWorksheetNames(ConvertData cd) throws IOException;
+
+
+ /**
+ * <p>Method to convert a set of &quot;Device&quot;
+ * <code>Document</code> objects into a <code>SxcDocument</code>
+ * object and returns it as a <code>Document</code>.</p>
+ *
+ * <p>This method is not thread safe for performance reasons.
+ * This method should not be called from within two threads.
+ * It would be best to call this method only once per object
+ * instance.</p>
+ *
+ * @return document An <code>SxcDocument</code> consisting
+ * of the data converted from the input
+ * stream.
+ *
+ * @throws ConvertException If any conversion error occurs.
+ * @throws IOException If any I/O error occurs.
+ */
+ public Document deserialize() throws ConvertException,
+ IOException {
+
+ // Get the name of the WorkBook from the ConvertData.
+ String[] worksheetNames = getWorksheetNames(cd);
+ String workbookName = getWorkbookName(cd);
+
+ // Create a document
+ SxcDocument sxcDoc = new SxcDocument(workbookName);
+ sxcDoc.initContentDOM();
+ sxcDoc.initSettingsDOM();
+
+ // Default to an initial 5 entries in the catalog.
+ styleCat = new StyleCatalog(5);
+
+ doc = sxcDoc.getContentDOM();
+ settings = sxcDoc.getSettingsDOM();
+ initFontTable();
+ // Little fact for the curious reader: workbookName should
+ // be the name of the StarCalc file minus the file extension suffix.
+
+ // Create a Decoder to decode the DeviceContent to a spreadsheet document
+ // TODO - we aren't using a password in StarCalc, so we can
+ // use any value for password here. If StarCalc XML supports
+ // passwords in the future, we should try to get the correct
+ // password value here.
+ //
+ decoder = createDecoder(workbookName, worksheetNames, "password");
+
+ Debug.log(Debug.TRACE, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ Debug.log(Debug.TRACE, "<DEBUGLOG>");
+
+ decoder.addDeviceContent(cd);
+ decode();
+
+ Debug.log(Debug.TRACE, "</DEBUGLOG>");
+
+ return sxcDoc;
+ }
+
+ /**
+ * This initializes a font table so we can imclude some basic font
+ * support for spreadsheets.
+ *
+ */
+ private void initFontTable() {
+
+ String fontTable[]= new String[] { "Tahoma", "Tahoma", "swiss", "variable",
+ "Courier New", "&apos;Courier New&apos;", "modern", "fixed"};
+ // Traverse to the office:body element.
+ // There should only be one.
+ NodeList list = doc.getElementsByTagName(TAG_OFFICE_FONT_DECLS);
+ Node root = list.item(0);
+
+ for(int i=0;i<fontTable.length;) {
+
+ // Create an element node for the table
+ Element tableElement = (Element) doc.createElement(TAG_STYLE_FONT_DECL);
+
+ tableElement.setAttribute(ATTRIBUTE_STYLE_NAME, fontTable[i++]);
+ tableElement.setAttribute(ATTRIBUTE_FO_FONT_FAMILY, fontTable[i++]);
+ tableElement.setAttribute(ATTRIBUTE_FO_FONT_FAMILY_GENERIC, fontTable[i++]);
+ tableElement.setAttribute(ATTRIBUTE_STYLE_FONT_PITCH, fontTable[i++]);
+
+ root.appendChild(tableElement);
+ }
+
+ }
+
+ /**
+ * Outer level method used to decode a WorkBook
+ * into a <code>Document</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void decode() throws IOException {
+
+ // Get number of worksheets
+ int numSheets = decoder.getNumberOfSheets();
+ // #i33702# - check for an Empty InputStream.
+ if(numSheets == 0)
+ {
+ System.err.println("Error decoding invalid Input stream");
+ return;
+ }
+
+ // Traverse to the office:body element.
+ // There should only be one.
+ NodeList list = doc.getElementsByTagName(TAG_OFFICE_BODY);
+ Node node = list.item(0);
+
+ for (int i = 0; i < numSheets; i++) {
+
+ // Set the decoder to the correct worksheet
+ decoder.setWorksheet(i);
+
+ int len = list.getLength();
+
+ if (len > 0) {
+
+ // Process the spreadsheet
+ processTable(node);
+ }
+ }
+
+ // Add the Defined Name table if there is one
+ Enumeration nameDefinitionTable = decoder.getNameDefinitions();
+ if(nameDefinitionTable.hasMoreElements()) {
+ processNameDefinition(node, nameDefinitionTable);
+ }
+
+ // add settings
+ NodeList settingsList = settings.getElementsByTagName(TAG_OFFICE_SETTINGS);
+ Node settingsNode = settingsList.item(0);;
+ processSettings(settingsNode);
+
+ }
+
+
+
+ /**
+ * This method process the settings portion
+ * of the <code>Document</code>.
+ *
+ * @param root The root <code>Node</code> of the
+ * <code>Document</code> we are building. This
+ * <code>Node</code> should be a TAG_OFFICE_SETTINGS
+ * tag.
+ */
+ protected void processSettings(Node root) {
+
+ Element configItemSetEntry = (Element) settings.createElement(TAG_CONFIG_ITEM_SET);
+ configItemSetEntry.setAttribute(ATTRIBUTE_CONFIG_NAME, "view-settings");
+ Element configItemMapIndexed = (Element) settings.createElement(TAG_CONFIG_ITEM_MAP_INDEXED);
+ configItemMapIndexed.setAttribute(ATTRIBUTE_CONFIG_NAME, "Views");
+ Element configItemMapEntry = (Element) settings.createElement(TAG_CONFIG_ITEM_MAP_ENTRY);
+ BookSettings bs = (BookSettings) decoder.getSettings();
+ bs.writeNode(settings, configItemMapEntry);
+
+ configItemMapIndexed.appendChild(configItemMapEntry);
+ configItemSetEntry.appendChild(configItemMapIndexed);
+ root.appendChild(configItemSetEntry);
+ }
+
+ /**
+ * This method process a Name Definition Table and generates a portion
+ * of the <code>Document</code>.
+ *
+ * @param root The root <code>Node</code> of the
+ * <code>Document</code> we are building. This
+ * <code>Node</code> should be a TAG_OFFICE_BODY
+ * tag.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void processNameDefinition(Node root, Enumeration eNameDefinitions) throws IOException {
+
+ Debug.log(Debug.TRACE, "<NAMED-EXPRESSIONS>");
+
+ Element namedExpressionsElement = (Element) doc.createElement(TAG_NAMED_EXPRESSIONS);
+
+ while(eNameDefinitions.hasMoreElements()) {
+
+ NameDefinition tableEntry = (NameDefinition) eNameDefinitions.nextElement();
+ tableEntry.writeNode(doc, namedExpressionsElement);
+ }
+
+ root.appendChild(namedExpressionsElement);
+
+ Debug.log(Debug.TRACE, "</NAMED-EXPRESSIONS>");
+ }
+
+ /**
+ * This method process a WorkSheet and generates a portion
+ * of the <code>Document</code>. A spreadsheet is represented
+ * as a table Node in StarOffice XML format.
+ *
+ * @param root The root <code>Node</code> of the
+ * <code>Document</code> we are building. This
+ * <code>Node</code> should be a TAG_OFFICE_BODY
+ * tag.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void processTable(Node root) throws IOException {
+
+ Debug.log(Debug.TRACE, "<TABLE>");
+
+ // Create an element node for the table
+ Element tableElement = (Element) doc.createElement(TAG_TABLE);
+
+ // Get the sheet name
+ String sheetName = decoder.getSheetName();
+
+ // Set the table name attribute
+ tableElement.setAttribute(ATTRIBUTE_TABLE_NAME, sheetName);
+
+ // TODO - style currently hardcoded - get real value
+ // Set table style-name attribute
+ tableElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, "Default");
+
+ // Append the table element to the root node
+ root.appendChild(tableElement);
+
+ Debug.log(Debug.TRACE, "<SheetName>" + sheetName + "</SheetName>");
+
+ // add the various different table-columns
+ processColumns(tableElement);
+
+ // Get each cell and add to doc
+ processCells(tableElement);
+
+ Debug.log(Debug.TRACE, "</TABLE>");
+ }
+
+ /**
+ * <p>This method process the cells in a <code>Document</code>
+ * and generates a portion of the <code>Document</code>.</p>
+ *
+ * <p>This method assumes that records are sorted by
+ * row and then column.</p>
+ *
+ * @param root The <code>Node</code> of the <code>Document</code>
+ * we are building that we will append our cell
+ * <code>Node</code> objects. This <code>Node</code>
+ * should be a TAG_TABLE tag.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void processColumns(Node root) throws IOException {
+
+ for(Enumeration e = decoder.getColumnRowInfos();e.hasMoreElements();) {
+
+ ColumnRowInfo ci = (ColumnRowInfo) e.nextElement();
+ if(ci.isColumn()) {
+ ColumnStyle cStyle = new ColumnStyle("Default",SxcConstants.COLUMN_STYLE_FAMILY,
+ SxcConstants.DEFAULT_STYLE, ci.getSize(), null);
+
+ Style result[] = (Style[]) styleCat.getMatching(cStyle);
+ String styleName;
+ if(result.length==0) {
+
+ cStyle.setName("co" + colStyles++);
+ styleName = cStyle.getName();
+ Debug.log(Debug.TRACE,"No existing style found, adding " + styleName);
+ styleCat.add(cStyle);
+ } else {
+ ColumnStyle existingStyle = (ColumnStyle) result[0];
+ styleName = existingStyle.getName();
+ Debug.log(Debug.TRACE,"Existing style found : " + styleName);
+ }
+
+ // Create an element node for the new row
+ Element colElement = (Element) doc.createElement(TAG_TABLE_COLUMN);
+ colElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, styleName);
+ if(ci.getRepeated()!=1) {
+ String repeatStr = String.valueOf(ci.getRepeated());
+ colElement.setAttribute(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED, repeatStr);
+ }
+ root.appendChild(colElement);
+ }
+ }
+ }
+
+ /**
+ * <p>This method process the cells in a <code>Document</code>
+ * and generates a portion of the <code>Document</code>.</p>
+ *
+ * <p>This method assumes that records are sorted by
+ * row and then column.</p>
+ *
+ * @param root The <code>Node</code> of the <code>Document</code>
+ * we are building that we will append our cell
+ * <code>Node</code> objects. This <code>Node</code>
+ * should be a TAG_TABLE tag.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void processCells(Node root) throws IOException {
+
+ // The current row element
+ Element rowElement = null;
+
+ // The current cell element
+ Element cellElement = null;
+
+ // The row number - we may not have any rows (empty sheet)
+ // so set to zero.
+ int row = 0;
+
+ // The column number - This is the expected column number of
+ // the next cell we are reading.
+ int col = 1;
+
+ // The number of columns in the spreadsheet
+ int lastColumn = decoder.getNumberOfColumns();
+
+ //
+ Node autoStylesNode = null;
+
+ // Loop over all cells in the spreadsheet
+ while (decoder.goToNextCell()) {
+
+ // Get the row number
+ int newRow = decoder.getRowNumber();
+
+ // Is the cell in a new row, or part of the current row?
+ if (newRow != row) {
+
+ // Make sure that all the cells in the previous row
+ // have been entered.
+ if (col <= lastColumn && rowElement != null) {
+ int numSkippedCells = lastColumn - col + 1;
+ addEmptyCells(numSkippedCells, rowElement);
+ }
+
+ // log an end row - if we already have a row
+ if (row != 0) {
+ Debug.log(Debug.TRACE, "</tr>");
+ }
+
+ // How far is the new row from the last row?
+ int deltaRows = newRow - row;
+
+ // Check if we have skipped any rows
+ if (deltaRows > 1) {
+ // Add in empty rows
+ addEmptyRows(deltaRows-1, root, lastColumn);
+ }
+
+ // Re-initialize column (since we are in a new row)
+ col = 1;
+
+ // Create an element node for the new row
+ rowElement = (Element) doc.createElement(TAG_TABLE_ROW);
+
+
+ for(Enumeration e = decoder.getColumnRowInfos();e.hasMoreElements();) {
+ ColumnRowInfo cri = (ColumnRowInfo) e.nextElement();
+ if(cri.isRow() && cri.getRepeated()==newRow-1) {
+ // We have the correct Row BIFFRecord for this row
+ RowStyle rStyle = new RowStyle("Default",SxcConstants.ROW_STYLE_FAMILY,
+ SxcConstants.DEFAULT_STYLE, cri.getSize(), null);
+
+ Style result[] = (Style[]) styleCat.getMatching(rStyle);
+ String styleName;
+ if(result.length==0) {
+
+ rStyle.setName("ro" + rowStyles++);
+ styleName = rStyle.getName();
+ Debug.log(Debug.TRACE,"No existing style found, adding " + styleName);
+ styleCat.add(rStyle);
+ } else {
+ RowStyle existingStyle = (RowStyle) result[0];
+ styleName = existingStyle.getName();
+ Debug.log(Debug.TRACE,"Existing style found : " + styleName);
+ }
+ rowElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, styleName);
+ // For now we will not use the repeat column attribute
+ }
+ }
+
+ // Append the row element to the root node
+ root.appendChild(rowElement);
+
+ // Update row number
+ row = newRow;
+
+ Debug.log(Debug.TRACE, "<tr>");
+ }
+
+ // Get the column number of the current cell
+ int newCol = decoder.getColNumber();
+
+ // Check to see if some columns were skipped
+ if (newCol != col) {
+
+ // How many columns have we skipped?
+ int numColsSkipped = newCol - col;
+
+ addEmptyCells(numColsSkipped, rowElement);
+
+ // Update the column number to account for the
+ // skipped cells
+ col = newCol;
+ }
+
+ // Lets start dealing with the cell data
+ Debug.log(Debug.TRACE, "<td>");
+
+ // Get the cell's contents
+ String cellContents = decoder.getCellContents();
+
+ // Get the type of the data in the cell
+ String cellType = decoder.getCellDataType();
+
+ // Get the cell format
+ Format fmt = decoder.getCellFormat();
+
+ // Create an element node for the cell
+ cellElement = (Element) doc.createElement(TAG_TABLE_CELL);
+
+ Node bodyNode = doc.getElementsByTagName(TAG_OFFICE_BODY).item(0);
+
+ // Not every document has an automatic style tag
+ autoStylesNode = doc.getElementsByTagName(
+ TAG_OFFICE_AUTOMATIC_STYLES).item(0);
+
+ if (autoStylesNode == null) {
+ autoStylesNode = doc.createElement(TAG_OFFICE_AUTOMATIC_STYLES);
+ doc.insertBefore(autoStylesNode, bodyNode);
+ }
+
+ CellStyle tStyle = new
+ CellStyle( "Default",SxcConstants.TABLE_CELL_STYLE_FAMILY,
+ SxcConstants.DEFAULT_STYLE, fmt, null);
+ String styleName;
+ Style result[] = (Style[]) styleCat.getMatching(tStyle);
+ if(result.length==0) {
+
+ tStyle.setName("ce" + textStyles++);
+ styleName = tStyle.getName();
+ Debug.log(Debug.TRACE,"No existing style found, adding " + styleName);
+ styleCat.add(tStyle);
+ } else {
+ CellStyle existingStyle = (CellStyle) result[0];
+ styleName = existingStyle.getName();
+ Debug.log(Debug.TRACE,"Existing style found : " + styleName);
+ }
+
+ cellElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, styleName);
+
+ // Store the cell data into the appropriate attributes
+ processCellData(cellElement, cellType, cellContents);
+
+ // Append the cell element to the row node
+ rowElement.appendChild(cellElement);
+
+ // Append the cellContents as a text node
+ Element textElement = (Element) doc.createElement(TAG_PARAGRAPH);
+ cellElement.appendChild(textElement);
+ textElement.appendChild(doc.createTextNode(cellContents));
+
+ Debug.log(Debug.TRACE, cellContents);
+ Debug.log(Debug.TRACE, "</td>");
+
+ // Increment to the column number of the next expected cell
+ col++;
+ }
+
+ // Make sure that the last row is padded correctly
+ if (col <= lastColumn && rowElement != null) {
+ int numSkippedCells = lastColumn - col + 1;
+ addEmptyCells(numSkippedCells, rowElement);
+ }
+
+ // Now write the style catalog to the document
+ if(autoStylesNode!=null) {
+ Debug.log(Debug.TRACE,"Well the autostyle node was found!!!");
+ NodeList nl = styleCat.writeNode(doc, "dummy").getChildNodes();
+ int nlLen = nl.getLength(); // nl.item reduces the length
+ for (int i = 0; i < nlLen; i++) {
+ autoStylesNode.appendChild(nl.item(0));
+ }
+ }
+
+ if (row != 0) {
+
+ // The sheet does have rows, so write out a /tr
+ Debug.log(Debug.TRACE, "</tr>");
+ }
+ }
+
+
+ /**
+ * This method will add empty rows to the <code>Document</code>.
+ * It is called when the conversion process encounters
+ * a row (or rows) that do not contain any data in its cells.
+ *
+ * @param numEmptyRows The number of empty rows that we
+ * need to add to the <code>Document</code>.
+ * @param root The <code>Node</code> of the
+ * <code>Document</code> we are building
+ * that we will append our empty row
+ * <code>Node</code> objects. This
+ * <code>Node</code> should be a TAG_TABLE
+ * tag.
+ * @param numEmptyCells The number of empty cells in the
+ * empty row.
+ */
+ protected void addEmptyRows(int numEmptyRows, Node root, int numEmptyCells) {
+
+ // Create an element node for the row
+ Element rowElement = (Element) doc.createElement(TAG_TABLE_ROW);
+
+ // TODO - style currently hardcoded - get real value
+ // Set row style-name attribute
+ rowElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, "Default");
+
+ // Set cell number-rows-repeated attribute
+ rowElement.setAttribute(ATTRIBUTE_TABLE_NUM_ROWS_REPEATED,
+ Integer.toString(numEmptyRows));
+
+ // Append the row element to the root node
+ root.appendChild(rowElement);
+
+ // Open Office requires the empty row to have an empty cell (or cells)
+ addEmptyCells(numEmptyCells, rowElement);
+
+ // Write empty rows to the log
+ for (int i = 0; i < numEmptyRows; i++) {
+ Debug.log(Debug.TRACE, "<tr />");
+ }
+
+ }
+
+
+ /**
+ * This method will add empty cells to the <code>Document</code>.
+ * It is called when the conversion process encounters a row
+ * that contains some cells without data.
+ *
+ * @param numColsSkipped The number of empty cells
+ * that we need to add to the
+ * current row.
+ * @param row The <code>Node</code> of the
+ * <code>Document</code> we
+ * are building that we will
+ * append our empty cell
+ * <code>Node</code> objects.
+ * This <code>Node</code> should
+ * be a TAG_TABLE_ROW tag.
+ */
+ protected void addEmptyCells(int numColsSkipped, Node row) {
+
+ // Create an empty cellElement
+ Element cellElement = (Element) doc.createElement(TAG_TABLE_CELL);
+
+ // TODO - style currently hardcoded - get real value
+ // Set cell style-name attribute
+ cellElement.setAttribute(ATTRIBUTE_TABLE_STYLE_NAME, "Default");
+
+ // If we skipped more than 1 cell, we must set the
+ // appropriate attribute
+ if (numColsSkipped > 1) {
+
+ // Set cell number-columns-repeated attribute
+ cellElement.setAttribute(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED,
+ Integer.toString(numColsSkipped));
+ }
+
+ // Append the empty cell element to the row node
+ row.appendChild(cellElement);
+
+ // Write empty cells to the log
+ for (int i = 0; i < numColsSkipped; i++) {
+ Debug.log(Debug.TRACE, "<td />");
+ }
+ }
+
+
+ /**
+ * This method process the data in a cell and sets
+ * the appropriate attributes on the cell <code>Element</code>.
+ *
+ * @param cellElement A TAG_TABLE_CELL <code>Element</code>
+ * that we will be adding attributes to
+ * based on the type of data in the cell.
+ * @param type The type of data contained in the cell.
+ * @param contents The contents of the data contained in
+ * the cell.
+ */
+ protected void processCellData(Element cellElement, String type,
+ String contents) {
+
+ // Set cell value-type attribute
+ cellElement.setAttribute(ATTRIBUTE_TABLE_VALUE_TYPE, type);
+
+ // Does the cell contain a formula?
+ if (contents.startsWith("=")) {
+
+ cellElement.setAttribute(ATTRIBUTE_TABLE_FORMULA, contents);
+
+ cellElement.setAttribute(ATTRIBUTE_TABLE_VALUE, decoder.getCellValue());
+ // String data does not require any additional attributes
+ } else if (!type.equals(CELLTYPE_STRING)) {
+
+ if (type.equals(CELLTYPE_TIME)) {
+
+ // Data returned in StarOffice XML format, so store in
+ // attribute
+ cellElement.setAttribute(ATTRIBUTE_TABLE_TIME_VALUE,
+ contents);
+
+ } else if (type.equals(CELLTYPE_DATE)) {
+
+ // Data returned in StarOffice XML format, so store in
+ // attribute
+ cellElement.setAttribute(ATTRIBUTE_TABLE_DATE_VALUE,
+ contents);
+
+ } else if (type.equals(CELLTYPE_BOOLEAN)) {
+
+ // StarOffice XML format requires stored boolean value
+ // to be in lower case
+ cellElement.setAttribute(ATTRIBUTE_TABLE_BOOLEAN_VALUE,
+ contents.toLowerCase());
+
+ } else if (type.equals(CELLTYPE_CURRENCY)) {
+ // TODO - StarOffice XML format requires a correct style to
+ // display currencies correctly. Need to implement styles.
+ // TODO - USD is for US currencies. Need to pick up
+ // the correct currency location from the source file.
+ cellElement.setAttribute(ATTRIBUTE_TABLE_CURRENCY, "USD");
+
+ // Data comes stripped of currency symbols
+ cellElement.setAttribute(ATTRIBUTE_TABLE_VALUE, contents);
+
+ } else if (type.equals(CELLTYPE_PERCENT)) {
+ // Data comes stripped of percent signs
+ cellElement.setAttribute(ATTRIBUTE_TABLE_VALUE, contents);
+
+ } else {
+ // Remaining data types use table-value attribute
+
+ cellElement.setAttribute(ATTRIBUTE_TABLE_VALUE, contents);
+ }
+ }
+ }
+
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentSerializer.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentSerializer.java
new file mode 100644
index 000000000000..bf0516c5345c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcDocumentSerializer.java
@@ -0,0 +1,995 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentSerializer.java,v $
+ * $Revision: 1.22 $
+ *
+ * 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;
+
+import java.awt.Color;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.ConvertException;
+import org.openoffice.xmerge.DocumentSerializer;
+
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocument;
+import org.openoffice.xmerge.converter.xml.ParaStyle;
+import org.openoffice.xmerge.converter.xml.sxc.CellStyle;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.XmlUtil;
+
+/**
+ * <p>General spreadsheet implementation of <code>DocumentSerializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcPluginFactory
+ * SxcPluginFactory}. Used with SXC <code>Document</code> objects.</p>
+ *
+ * <p>The <code>serialize</code> method traverses the DOM
+ * <code>Document</code> from the given <code>Document</code> object.
+ * It uses a <code>DocEncoder</code> object for the actual conversion
+ * of contents to the device spreadsheet format.</p>
+ *
+ * @author Paul Rank
+ * @author Mark Murnane
+ */
+public abstract class SxcDocumentSerializer implements OfficeConstants,
+ DocumentSerializer {
+
+ /** The cell foreground <code>Color</code>. */
+ private Color foreground = Color.black;
+
+ /** The cell background <code>Color</code>. */
+ private Color background = Color.white;
+
+ /** The cell format. */
+ private long format = 0;
+
+ /** <code>Format</code> object describing the cell. */
+ private Format fmt = null;
+
+ /** The row number. */
+ private int rowID = 1;
+
+ /** The column number. */
+ private int colID = 1;
+
+ /** The number of times the current row is repeated. */
+ private int rowsRepeated = 1;
+
+ /** The number of times the current column is repeated. */
+ private int colsRepeated = 1;
+
+ /** The number of times the current column is repeated. */
+ private StyleCatalog styleCat = null;
+ /**
+ * An array of column widths of the current worksheet. Width is
+ * measured in number of characters.
+ */
+ private Vector ColumnRowList;
+
+ /** Width, in characters, of the current cell display data. */
+ private int displayWidth = 0;
+
+ /**
+ * A <code>SpreadsheetEncoder</code> object for encoding to
+ * appropriate format.
+ */
+ protected SpreadsheetEncoder encoder = null;
+
+ /** <code>SxcDocument</code> object that this converter processes. */
+ protected SxcDocument sxcDoc = null;
+
+
+ /**
+ * Constructor.
+ *
+ * @param document Input <code>SxcDocument</code>
+ * <code>Document</code>.
+ */
+ public SxcDocumentSerializer(Document document) {
+ fmt = new Format();
+ sxcDoc = (SxcDocument) document;
+ }
+
+
+ /**
+ * <p>Method to convert a DOM <code>Document</code> into
+ * &quot;Device&quot; <code>Document</code> objects.</p>
+ *
+ * <p>This method is not thread safe for performance reasons.
+ * This method should not be called from within two threads.
+ * It would be best to call this method only once per object
+ * instance.</p>
+ *
+ * @return <code>ConvertData</code> containing &quot;Device&quot;
+ * <code>Document</code> objects.
+ *
+ * @throws ConvertException If any conversion error occurs.
+ * @throws IOException If any I/O error occurs.
+ */
+ public abstract ConvertData serialize() throws ConvertException,
+ IOException;
+
+
+ /**
+ * This method traverses <i>office:settings</i> <code>Element</code>.
+ *
+ * @param node <i>office:settings</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void traverseSettings(Node node) throws IOException {
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+ int len = nodeList.getLength();
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_CONFIG_ITEM_SET)) {
+
+ traverseSettings(child);
+
+ } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_INDEXED)) {
+
+ traverseSettings(child);
+
+ } else if (nodeName.equals(TAG_CONFIG_ITEM_MAP_ENTRY)) {
+
+ BookSettings bs = new BookSettings(child);
+ encoder.addSettings(bs);
+
+ } else {
+
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Handles the loading of defined styles from the style.xml file as well
+ * as automatic styles from the content.xml file.
+ *
+ * Any change to a defined style, such as a short bold section, falls into
+ * the latter category.
+ */
+ protected void loadStyles(SxcDocument sxcDoc) {
+
+ org.w3c.dom.Document contentDom = sxcDoc.getContentDOM();
+
+ styleCat = new StyleCatalog(25);
+
+ NodeList nl = null;
+ String families[] = new String[] { SxcConstants.COLUMN_STYLE_FAMILY,
+ SxcConstants.ROW_STYLE_FAMILY,
+ SxcConstants.TABLE_CELL_STYLE_FAMILY };
+ Class classes[] = new Class[] { ColumnStyle.class,
+ RowStyle.class,
+ CellStyle.class};
+
+ /*
+ * Process the content XML for any other style info.
+ * Should only be automatic types here.
+ */
+ nl = contentDom.getElementsByTagName(TAG_OFFICE_AUTOMATIC_STYLES);
+ if (nl.getLength() != 0) {
+ styleCat.add(nl.item(0), families, classes, null, false);
+ }
+ }
+
+ /**
+ * This method traverses <i>office:body</i> <code>Element</code>.
+ *
+ * @param node <i>office:body</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseBody(Node node) throws IOException {
+
+ Debug.log(Debug.TRACE, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ Debug.log(Debug.TRACE, "<DEBUGLOG>");
+
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+ int len = nodeList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node searchNode = nodeList.item(i);
+ if (searchNode.getNodeType() == Node.ELEMENT_NODE) {
+
+ String nodeName = searchNode.getNodeName();
+
+ if (nodeName.equals(TAG_NAMED_EXPRESSIONS)) {
+
+ traverseNamedExpressions(searchNode);
+
+ } else {
+
+ Debug.log(Debug.TRACE, "Skipping " + XmlUtil.getNodeInfo(searchNode) + " />");
+ }
+ }
+ }
+
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_TABLE)) {
+
+ traverseTable(child);
+
+ } else {
+
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
+ }
+ }
+ }
+ }
+
+ Debug.log(Debug.TRACE, "</DEBUGLOG>");
+ }
+
+
+ /**
+ * This method traverses the <i>table:table</i> element
+ * <code>Node</code>.
+ *
+ * @param node A <i>table:table</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseNamedExpressions(Node node) throws IOException {
+
+ Debug.log(Debug.TRACE, "<NAMED:EXPRESSIONS>");
+
+ NamedNodeMap att = node.getAttributes();
+
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+ int len = nodeList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ NameDefinition nd = new NameDefinition(child);
+ encoder.setNameDefinition(nd);
+ }
+ }
+ }
+
+ Debug.log(Debug.TRACE, "</NAMED:EXPRESSIONS>");
+ }
+
+ /**
+ * This method traverses the <i>table:table</i> element
+ * <code>Node</code>.
+ *
+ * @param node A <i>table:table</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseTable(Node node) throws IOException {
+
+ Debug.log(Debug.TRACE, "<TABLE>");
+
+ ColumnRowList = new Vector();
+
+ // Get table attributes
+ // TODO - extract style from attribute
+
+ NamedNodeMap att = node.getAttributes();
+
+ String tableName =
+ att.getNamedItem(ATTRIBUTE_TABLE_NAME).getNodeValue();
+
+ rowID = 1;
+
+ encoder.createWorksheet(tableName);
+
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+ int len = nodeList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_TABLE_ROW)) {
+ // TODO - handle all the possible rows
+ // spelled out in the entities
+
+ traverseTableRow(child);
+
+ } else if (nodeName.equals(TAG_TABLE_COLUMN)) {
+
+ traverseTableColumn(child);
+
+ } else if (nodeName.equals(TAG_TABLE_SCENARIO)) {
+
+ // TODO
+
+ } else {
+
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
+ }
+ }
+ }
+ }
+
+ // Add column width info to the current sheet
+ encoder.setColumnRows(ColumnRowList);
+
+ Debug.log(Debug.TRACE, "</TABLE>");
+ }
+
+ /**
+ * This method traverses the <i>table:table-row</i> element
+ * <code>Node</code>.
+ *
+ * @param node A <i>table:table-row</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseTableRow(Node node) throws IOException {
+
+ // Get the attributes of the row
+ NamedNodeMap cellAtt = node.getAttributes();
+
+ if (cellAtt != null) {
+
+ Node rowStyle =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);
+
+ Node tableNumRowRepeatingNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_ROWS_REPEATED);
+ int repeatedRows = 1;
+
+ if(tableNumRowRepeatingNode!=null) {
+ String repeatStr = tableNumRowRepeatingNode.getNodeValue();
+ Debug.log(Debug.TRACE, "traverseTableRow() repeated-rows : " + repeatStr);
+ repeatedRows = Integer.parseInt(repeatStr);
+ }
+
+ String styleName = new String("");
+
+ if ( rowStyle != null) {
+ styleName = rowStyle.getNodeValue();
+ }
+ if(styleName.equalsIgnoreCase("Default") || styleName.length()==0) {
+
+ Debug.log(Debug.TRACE, "No defined Row Style Attribute was found");
+
+ } else {
+
+ RowStyle rStyle = ( RowStyle)styleCat.lookup(styleName,
+ SxcConstants.ROW_STYLE_FAMILY, null,
+ RowStyle.class);
+
+ int rowHeight = rStyle.getRowHeight();
+
+ Debug.log(Debug.TRACE, "traverseTableRow() Row Height : " + rowHeight);
+ ColumnRowInfo ri = new ColumnRowInfo( rowHeight,
+ repeatedRows,
+ ColumnRowInfo.ROW,
+ rowHeight!=0);
+ ColumnRowList.add(ri);
+ }
+
+ // Get the attribute representing the number of rows repeated
+ Node rowsRepeatedNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_ROWS_REPEATED);
+
+ // There is a number of rows repeated attribute:
+ if (rowsRepeatedNode != null) {
+
+ // Get the number of times the row is repeated
+ String rowsRepeatedString = rowsRepeatedNode.getNodeValue();
+
+ Integer rowsRepeatedInt = new Integer(rowsRepeatedString);
+
+ rowsRepeated = rowsRepeatedInt.intValue();
+
+ } else {
+
+ // The row is not repeated
+ rowsRepeated = 1;
+ }
+ }
+
+ Debug.log(Debug.TRACE, "<TR>");
+
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+ int len = nodeList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node child = nodeList.item(i);
+
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = child.getNodeName();
+
+ if (nodeName.equals(TAG_TABLE_CELL)) {
+
+ traverseCell(child);
+
+ } else {
+
+ Debug.log(Debug.TRACE, "<OTHERS " + XmlUtil.getNodeInfo(child) + " />");
+ }
+ }
+ }
+ }
+
+ // Increase the row counter by the number of rows which are repeated
+ rowID += rowsRepeated;
+
+ // Re-initialize number of rows repeated before processing the next
+ // row data.
+ rowsRepeated = 1;
+
+ // When starting a new row, set the column counter back to the
+ // first column.
+ colID = 1;
+
+ // Re-initialize number of columns repeated before processing
+ // the next row data.
+ colsRepeated = 1;
+
+ Debug.log(Debug.TRACE, "</TR>");
+ }
+
+
+ /**
+ * This method traverses the <i>table:table-column</i>
+ * <code>Node</code>. Not yet implemented.
+ *
+ * @param node A <i>table:table-column</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseTableColumn(Node node) throws IOException {
+
+ Debug.log(Debug.TRACE, "traverseColumn() : ");
+ NamedNodeMap cellAtt = node.getAttributes();
+ Node tableStyleNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);
+ Node tableNumColRepeatingNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED);
+ Node tableDefaultCellStyle = cellAtt.getNamedItem(ATTRIBUTE_DEFAULT_CELL_STYLE);
+
+ int repeatedColumns = 1;
+ int columnWidth = 0;
+ ColumnRowInfo col = new ColumnRowInfo(ColumnRowInfo.COLUMN);
+
+ if(tableNumColRepeatingNode!=null) {
+ Debug.log(Debug.TRACE, "traverseColumn() repeated-cols : " + tableNumColRepeatingNode.getNodeValue());
+ repeatedColumns = Integer.parseInt(tableNumColRepeatingNode.getNodeValue());
+ col.setRepeated(repeatedColumns);
+ }
+
+ String cellStyleName = new String("");
+
+ if(tableDefaultCellStyle!=null) {
+ cellStyleName = tableDefaultCellStyle.getNodeValue();
+
+ Debug.log(Debug.TRACE, "traverseColumn() default-cell-style : " + cellStyleName);
+ }
+
+ if(cellStyleName.equalsIgnoreCase("Default") || cellStyleName.length()==0) {
+
+ Debug.log(Debug.TRACE, "No default cell Style Attribute was found");
+
+ } else {
+
+ CellStyle cellStyle = (CellStyle)styleCat.lookup(cellStyleName,
+ SxcConstants.TABLE_CELL_STYLE_FAMILY, null,
+ CellStyle.class);
+ Format defaultFmt = new Format(cellStyle.getFormat());
+ col.setFormat(defaultFmt);
+ }
+
+ String styleName = new String("");
+
+ if(tableStyleNode!=null) {
+ styleName = tableStyleNode.getNodeValue();
+ }
+
+ if(styleName.equalsIgnoreCase("Default") || styleName.length()==0) {
+
+ Debug.log(Debug.TRACE, "No defined Style Attribute was found");
+
+ } else {
+
+ ColumnStyle cStyle = (ColumnStyle)styleCat.lookup(styleName,
+ SxcConstants.COLUMN_STYLE_FAMILY, null,
+ ColumnStyle.class);
+
+ columnWidth = cStyle.getColWidth();
+ col.setSize(columnWidth);
+ Debug.log(Debug.TRACE, "traverseColumn() Column Width : " + columnWidth);
+
+ }
+ ColumnRowList.add(col);
+ }
+
+ /**
+ * This method traverses a <i>table:table-cell</i> element
+ * <code>Node</code>.
+ *
+ * @param node a <i>table:table-cell</i> <code>Node</code>.
+ *
+ * @throws IOException if any I/O error occurs.
+ */
+ protected void traverseCell(Node node) throws IOException {
+
+ NamedNodeMap cellAtt = node.getAttributes();
+
+ int debug_i=0;
+ Node debug_attrib = null;
+ fmt.clearFormatting();
+ if (cellAtt == null || cellAtt.item(0) == null)
+ {
+ Debug.log(Debug.INFO, "No Cell Attributes\n");
+ // return;
+ }
+ else
+ {
+ while ((debug_attrib = cellAtt.item(debug_i++)) != null)
+ {
+ Debug.log(Debug.INFO, "Cell Attribute " + debug_i +
+ ": " + debug_attrib.getNodeName() + " : " +
+ debug_attrib.getNodeValue() + "\n");
+ }
+ }
+
+ // Get the type of data in the cell
+ Node tableValueTypeNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE_TYPE);
+
+ // Get the number of columns this cell is repeated
+ Node colsRepeatedNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_NUM_COLUMNS_REPEATED);
+
+ // Get the style type
+ Node tableStyleNode =
+ cellAtt.getNamedItem(ATTRIBUTE_TABLE_STYLE_NAME);
+
+ String styleName = new String("");
+
+ if(tableStyleNode!=null) {
+ styleName = tableStyleNode.getNodeValue();
+ }
+
+ if(styleName.equalsIgnoreCase("Default")) {
+
+ Debug.log(Debug.TRACE, "No defined Style Attribute was found");
+
+ } else if(styleName.length()!=0) {
+
+ CellStyle cStyle = (CellStyle)styleCat.lookup(styleName,
+ SxcConstants.TABLE_CELL_STYLE_FAMILY, null,
+ CellStyle.class);
+
+ Format definedFormat = cStyle.getFormat();
+ fmt = new Format(definedFormat);
+ }
+
+ // There is a number of cols repeated attribute
+ if (colsRepeatedNode != null) {
+
+ // Get the number of times the cell is repeated
+ String colsRepeatedString = colsRepeatedNode.getNodeValue();
+
+ Integer colsRepeatedInt = new Integer(colsRepeatedString);
+ colsRepeated = colsRepeatedInt.intValue();
+ } else {
+
+ // The cell is not repeated
+ colsRepeated = 1;
+ }
+
+
+ // if there is no style we need to check to see if there is a default
+ // cell style defined in the table-column's
+
+ if (fmt.isDefault() && styleName.length()==0) {
+ int index = 1;
+ for(Enumeration e = ColumnRowList.elements();e.hasMoreElements();) {
+ ColumnRowInfo cri = (ColumnRowInfo) e.nextElement();
+ if(cri.isColumn()) {
+ if(colID>=index && colID<(index+cri.getRepeated())) {
+ fmt = new Format(cri.getFormat());
+ }
+ index += cri.getRepeated();
+ }
+ }
+ }
+
+
+ // for (int j = 0; j < colsRepeated; j++) {
+
+
+ if (tableValueTypeNode != null) {
+
+ // Make sure we initialize to 0 the width of the current cell
+ displayWidth = 0;
+
+ String cellType =
+ tableValueTypeNode.getNodeValue();
+
+ if (cellType.equalsIgnoreCase(CELLTYPE_STRING)) {
+
+ // has text:p tag
+ fmt.setCategory(CELLTYPE_STRING);
+ Node tableStringValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STRING_VALUE);
+ Debug.log(Debug.TRACE,"Cell Type String : " + tableStringValueNode);
+ if(tableStringValueNode != null) {
+ fmt.setValue(tableStringValueNode.getNodeValue());
+ }
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_FLOAT)) {
+
+ // has table:value attribute
+ // has text:p tag
+
+ // Determine the number of decimal places StarCalc
+ // is displaying for this floating point output.
+ fmt.setCategory(CELLTYPE_FLOAT);
+ fmt.setDecimalPlaces(getDecimalPlaces(node));
+ Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
+ fmt.setValue(tableValueNode.getNodeValue());
+
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_TIME)) {
+
+ // has table:time-value attribute
+ // has text:p tag - which is the value we convert
+
+ fmt.setCategory(CELLTYPE_TIME);
+ Node tableTimeNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_TIME_VALUE);
+ fmt.setValue(tableTimeNode.getNodeValue());
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_DATE)) {
+
+ // has table:date-value attribute
+ // has text:p tag - which is the value we convert
+
+ fmt.setCategory(CELLTYPE_DATE);
+ Node tableDateNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_DATE_VALUE);
+ fmt.setValue(tableDateNode.getNodeValue());
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_CURRENCY)) {
+
+ // has table:currency
+ // has table:value attribute
+ // has text:p tag
+
+ fmt.setCategory(CELLTYPE_CURRENCY);
+ fmt.setDecimalPlaces(getDecimalPlaces(node));
+ Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
+ fmt.setValue(tableValueNode.getNodeValue());
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_BOOLEAN)) {
+
+ // has table:boolean-value attribute
+ // has text:p tag - which is the value we convert
+
+ fmt.setCategory(CELLTYPE_BOOLEAN);
+ Node tableBooleanNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_BOOLEAN_VALUE);
+ fmt.setValue(tableBooleanNode.getNodeValue());
+
+ } else if (cellType.equalsIgnoreCase(CELLTYPE_PERCENT)) {
+
+ // has table:value attribute
+ // has text:p tag
+
+ fmt.setCategory(CELLTYPE_PERCENT);
+ fmt.setDecimalPlaces(getDecimalPlaces(node));
+ Node tableValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_VALUE);
+ fmt.setValue(tableValueNode.getNodeValue());
+
+ } else {
+
+ Debug.log(Debug.TRACE,"No defined value type" + cellType);
+ // Should never get here
+
+ }
+ }
+
+ Node tableFormulaNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_FORMULA);
+
+ if(tableFormulaNode != null)
+ {
+ if(tableValueTypeNode == null) { // If there is no value-type Node we must assume string-value
+ fmt.setCategory(CELLTYPE_STRING);
+ Node tableStringValueNode = cellAtt.getNamedItem(ATTRIBUTE_TABLE_STRING_VALUE);
+ fmt.setValue(tableStringValueNode.getNodeValue());
+ }
+ String cellFormula = tableFormulaNode.getNodeValue();
+ addCell(cellFormula);
+ } else {
+
+ // Text node, Date node, or Time node
+ //
+ Debug.log(Debug.INFO,
+ "TextNode, DateNode, TimeNode or BooleanNode\n");
+ // This handles the case where we have style information but no content
+ if (node.hasChildNodes()) {
+ NodeList childList = node.getChildNodes();
+ int len = childList.getLength();
+
+ for (int i = 0; i < len; i++) {
+ Node child = childList.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String childName = child.getNodeName();
+ if (childName.equals(TAG_PARAGRAPH)) {
+ traverseParagraph(child);
+ }
+ }
+ }
+ } else if(!fmt.isDefault()) {
+ addCell("");
+ }
+ }
+
+ // Clear out format for current cell after it is written
+ format = 0;
+
+ // Increase the column counter by the number of times the
+ // last cell was repeated.
+ colID += colsRepeated;
+
+ // Re-initialize the number of columns repeated before processing
+ // the next cell data.
+ colsRepeated = 1;
+
+ }
+
+
+ /**
+ * This method traverses the <i>text:p</i> element <code>Node</code>.
+ *
+ * @param node A <i>text:p</i> <code>Node</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void traverseParagraph(Node node) throws IOException {
+
+ NamedNodeMap cellAtt = node.getAttributes();
+
+ int debug_i=0;
+ Node debug_attrib = null;
+ if (cellAtt == null || cellAtt.item(0) == null)
+ {
+ Debug.log(Debug.INFO, "No Paragraph Attributes\n");
+ }
+ else
+ {
+ while ((debug_attrib = cellAtt.item(debug_i++)) != null)
+ {
+ Debug.log(Debug.INFO, "Paragraph Attribute " + debug_i +
+ ": " + debug_attrib.getNodeName() + " : " +
+ debug_attrib.getNodeValue() + "\n");
+ }
+ }
+
+ if (node.hasChildNodes()) {
+
+ NodeList nodeList = node.getChildNodes();
+
+ int len = nodeList.getLength();
+
+ StringBuffer buffer = new StringBuffer();
+
+ for (int i = 0; i < len; i++) {
+
+ Node child = nodeList.item(i);
+
+ // TODO: need to handle space/tabs/newline nodes later
+ short nodeType = child.getNodeType();
+
+ switch (nodeType) {
+
+ case Node.TEXT_NODE:
+ buffer.append(child.getNodeValue());
+ break;
+
+ case Node.ENTITY_REFERENCE_NODE:
+
+ NodeList nodeList2 = child.getChildNodes();
+ int len2 = nodeList2.getLength();
+
+ for (int j = 0; j < len2; j++) {
+ Node child2 = nodeList2.item(j);
+
+ if (child2.getNodeType() == Node.TEXT_NODE) {
+ buffer.append(child2.getNodeValue());
+ }
+ }
+
+ break;
+ }
+ }
+
+ String s = buffer.toString();
+ // displayWidth = calculateContentWidth(s);
+ addCell(s);
+
+ }
+ }
+
+
+ /**
+ * This method will take the input cell value and add
+ * it to the spreadsheet <code>Document</code> we are currently
+ * encoding. This method correctly handles cells that are
+ * repeated in either the row, cell, or both directions.
+ *
+ * @param cellValue The contents of the cell we want to add
+ * to the spreadsheet <code>Document</code>.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ protected void addCell(String cellValue) throws IOException {
+
+ int col = colID;
+ int row = rowID;
+
+ for (int i = 0; i < rowsRepeated; i++) {
+
+ // Log the columns when there are rowsRepeated.
+ if (i > 0) {
+ Debug.log(Debug.TRACE, "</TR>");
+ Debug.log(Debug.TRACE, "<TR>");
+ }
+
+ col = colID;
+
+ for (int j = 0; j < colsRepeated; j++) {
+
+ Debug.log(Debug.TRACE, "<TD>");
+
+
+ // Add the cell data to the encoded spreadsheet document
+ encoder.addCell(row, col, fmt, cellValue);
+
+ Debug.log(Debug.TRACE, cellValue);
+ Debug.log(Debug.TRACE, "</TD>");
+
+ col++;
+ }
+
+ row++;
+
+ }
+
+ }
+
+
+
+ /**
+ * This method takes a <i>table:table-cell</i> <code>Node</code>
+ * and traverses down to the <i>text:p</i> tag. The value is
+ * extracted from the <i>text:p</i> tag and the number of decimal
+ * places is calculated.
+ *
+ * @param node A <i>table:table-cell</i> <code>Node</code>.
+ *
+ * @return The number of decimal places in the display
+ * string of the data in the input <code>Node</code>.
+ */
+ protected int getDecimalPlaces(Node node) {
+
+ int decimals = 0;
+
+ Element element = null;
+
+ // cast org.w3c.dom.Node to org.w3c.dom.Element
+ if (node instanceof Element) {
+ element = (Element) node;
+ } else {
+ return decimals;
+ }
+
+ // Traverse to the text:p element, there should only be one.
+ NodeList list = element.getElementsByTagName(TAG_PARAGRAPH);
+
+ if (list.getLength() != 1) {
+ return decimals;
+ }
+
+ Node paragraph = list.item(0);
+
+ if (paragraph.hasChildNodes()) {
+
+ NodeList nodeList = paragraph.getChildNodes();
+
+ int len = nodeList.getLength();
+
+ for (int j = 0; j < len; j++) {
+
+ Node child = nodeList.item(j);
+
+ if (child.getNodeType() == Node.TEXT_NODE) {
+
+ String s = child.getNodeValue();
+
+ // displayWidth = calculateContentWidth(s);
+
+ int k = s.lastIndexOf(".");
+ if (k > 0) {
+ s = s.substring(k+1);
+ decimals = s.length();
+ }
+ }
+ }
+ }
+
+ return decimals;
+ }
+
+ /*
+ * Utility method to retrieve a Node attribute.
+ */
+ private String getAttribute (Node node, String attribute) {
+ NamedNodeMap attrNodes = node.getAttributes();
+
+ if (attrNodes != null) {
+ Node attr = attrNodes.getNamedItem(attribute);
+ if (attr != null) {
+ return attr.getNodeValue();
+ }
+ }
+ return null;
+ }
+
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcPluginFactory.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcPluginFactory.java
new file mode 100644
index 000000000000..5ad490f332dc
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/SxcPluginFactory.java
@@ -0,0 +1,86 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcPluginFactory.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.util.registry.ConverterInfo;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.PluginFactory;
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.DocumentMergerFactory;
+
+
+/**
+ * General implementation of the <code>PluginFactory</code> interface
+ * for SXC <code>Document</code> objects.
+ *
+ * @see org.openoffice.xmerge.DocumentDeserializer
+ * @see org.openoffice.xmerge.DocumentMerger
+ * @see org.openoffice.xmerge.DocumentSerializer
+ */
+public abstract class SxcPluginFactory
+ extends PluginFactory implements DocumentMergerFactory {
+
+
+ /**
+ * Constructor that caches the <code>ConvertInfo</code> that
+ * corresponds to the registry information for this plug-in.
+ *
+ * @param ci <code>ConvertInfo</code> object.
+ */
+ public SxcPluginFactory(ConverterInfo ci) {
+ super(ci);
+ }
+
+
+ public Document createOfficeDocument(String name, InputStream is)
+ throws IOException {
+
+ // read zipped XML stream
+ //
+ SxcDocument doc = new SxcDocument(name);
+ doc.read(is);
+ return doc;
+ }
+
+ public Document createOfficeDocument(String name, InputStream is,boolean isZip)
+ throws IOException {
+
+ // read zipped XML stream
+ //
+ SxcDocument doc = new SxcDocument(name);
+ doc.read(is,isZip);
+ return doc;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/build.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/build.xml
new file mode 100644
index 000000000000..d8219c1f46a5
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/build.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.9 $
+
+ 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.
+
+-->
+<project name="xmrg_jooxcx_sxc" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- project prefix, used for targets and build.lst -->
+ <property name="prj.prefix" value="xmrg"/>
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="xmrg_jooxcx_sxc"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="../../../../../../.."/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="${prj}/java"/>
+
+ <!-- path component for current java package -->
+ <property name="package"
+ value="org/openoffice/xmerge/converter/xml/sxc"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for javac tasks -->
+ <path id="classpath">
+ <pathelement location="${build.class}"/>
+ <pathelement location="${solar.jar}/parser.jar"/>
+ <pathelement location="${solar.jar}/jaxp.jar"/>
+ <pathelement location="${solar.jar}/xerces.jar"/>
+ </path>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <!-- ================================================================= -->
+ <!-- solar build environment targets -->
+ <!-- ================================================================= -->
+
+ <target name="build_dir" unless="build.dir">
+ <property name="build.dir" value="${out}"/>
+ </target>
+
+ <target name="solar" depends="build_dir" if="solar.update">
+ <property name="solar.properties"
+ value="${solar.bin}/solar.properties"/>
+ </target>
+
+ <target name="init" depends="solar">
+ <property name="build.compiler" value="classic"/>
+ <property file="${solar.properties}"/>
+ <property file="${build.dir}/class/solar.properties"/>
+ </target>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare" depends="init" if="build.class">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <!-- compile java sources in ${package} -->
+ <target name="compile" depends="prepare" if="build.class">
+ <javac srcdir="${java.dir}"
+ destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprecation}"
+ optimize="${optimize}">
+ <classpath refid="classpath"/>
+ <include name="${package}/CellStyle.java"/>
+ <include name="${package}/ColumnStyle.java"/>
+ <include name="${package}/ColumnRowInfo.java"/>
+ <include name="${package}/RowStyle.java"/>
+ <include name="${package}/SxcConstants.java"/>
+ <include name="${package}/SxcDocument.java"/>
+ <include name="${package}/Format.java"/>
+ <include name="${package}/BookSettings.java"/>
+ <include name="${package}/SheetSettings.java"/>
+ <include name="${package}/NameDefinition.java"/>
+ <include name="${package}/SpreadsheetDecoder.java"/>
+ <include name="${package}/SpreadsheetEncoder.java"/>
+ <include name="${package}/SxcDocumentDeserializer.java"/>
+ <include name="${package}/SxcDocumentSerializer.java"/>
+ <include name="${package}/DocumentMergerImpl.java"/>
+ <include name="${package}/SxcPluginFactory.java"/>
+
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+</project>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/makefile.mk b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/makefile.mk
new file mode 100644
index 000000000000..1c2e06d1ef57
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/makefile.mk
@@ -0,0 +1,36 @@
+#***************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# 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.
+#
+#***************************************************************************
+
+TARGET=xmrg_jooxcx_sxc
+PRJ=../../../../../../..
+
+.INCLUDE : ant.mk
+ALLTAR: ANTBUILD
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/ConverterCapabilitiesImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/ConverterCapabilitiesImpl.java
new file mode 100644
index 000000000000..54ce2e236a4d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/ConverterCapabilitiesImpl.java
@@ -0,0 +1,116 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ConverterCapabilitiesImpl.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.minicalc;
+
+import org.openoffice.xmerge.ConverterCapabilities;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+
+
+/**
+ * <p>MiniCalc implementation of <code>ConverterCapabilities</code> for
+ * the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.minicalc.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>Used with StarCalc SXC to/from MiniCalc 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/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcConstants.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcConstants.java
new file mode 100644
index 000000000000..c14178ee96e1
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcConstants.java
@@ -0,0 +1,48 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MinicalcConstants.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.minicalc;
+
+import org.openoffice.xmerge.converter.palm.PdbUtil;
+
+/**
+ * Constants used for encoding and decoding the MiniCalc format.
+ *
+ * @author Herbie Ong
+ */
+interface MinicalcConstants {
+
+ /** Creator ID. */
+ public static final int CREATOR_ID = PdbUtil.intID("PiMC");
+
+ /** Type ID. */
+ public static final int TYPE_ID = PdbUtil.intID("Data");
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDataString.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDataString.java
new file mode 100644
index 000000000000..77bfe75539b8
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDataString.java
@@ -0,0 +1,548 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MinicalcDataString.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.minicalc;
+
+/**
+ * This class is used by <code>MinicalcDecoder</code> to manipulate a
+ * <code>String</code> containing MiniCalc cell data.
+ *
+ * @author Paul Rank
+ */
+public class MinicalcDataString {
+
+ /** The String representation of the MiniCalc data. */
+ private String data = null;
+
+
+ /**
+ * Constructor stores the MiniCalc data <code>String</code>.
+ *
+ * @param data A <code>String</code> containing MiniCalc
+ * cell data.
+ */
+ public MinicalcDataString(String data) {
+ this.data = data;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a <i>formula</i>.
+ *
+ * @return true if the MiniCalc data <code>String</code> is a
+ * <i>formula</i>, false if the MiniCalc data <code>String</code>
+ * is not a <i>formula</i>.
+ */
+ public boolean isFormula() {
+
+ if (data.startsWith("=")) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a <i>percentage</i>.
+ *
+ * @return true if the MiniCalc data <code>String</code> is a
+ * <i>percentage</i>, false if the MiniCalc data
+ * <code>String</code> is not a <i>percentage</i>.
+ */
+ public boolean isPercent() {
+
+ if (data.endsWith("%")) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a
+ * <i>boolean</i> value.
+ *
+ * @return true if the MiniCalc data <code>String</code> is
+ * a <i>boolean</i>, false if the MiniCalc data
+ * <code>String</code> is not a <i>boolean</i>.
+ */
+ public boolean isBoolean() {
+
+ if (data.equalsIgnoreCase("false") ||
+ data.equalsIgnoreCase("true")) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a <i>date</i>.
+ *
+ * @return true if the MiniCalc data <code>String</code> is
+ * a <i>date</i>, false if the MiniCalc data <code>String</code>
+ * is not a <i>date</i>.
+ */
+ public boolean isDate() {
+
+ // Starting index into the date string - month
+ int start = 0;
+
+ // Search for "/", which separates month from day
+ int end = data.indexOf("/");
+
+ // Separator was found
+ if (end > 0) {
+
+ String monthString = data.substring(start, end);
+
+ try {
+ Float f = Float.valueOf(monthString);
+ if ((f.intValue() < 0) || (f.intValue() > 12)) {
+ return false;
+ }
+ }
+ catch (NumberFormatException e) {
+
+ // no, it is not a currency type
+ return false;
+ }
+
+ // start is now the starting index of day
+ start = end+1;
+
+ // Search for "/", which separates day from year
+ end = data.indexOf("/", start);
+
+ // Separator was found
+ if (end > 0) {
+
+ String dayString = data.substring(start, end);
+
+ try {
+ Float f = Float.valueOf(dayString);
+ if ((f.intValue() < 0) || (f.intValue() > 31))
+ return false;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a currency type
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ // start is now at the starting index of the year
+ start = end + 1;
+
+ String yearString = data.substring(start);
+ try {
+ Float f = Float.valueOf(yearString);
+ if (f.intValue() < 0) {
+ return false;
+ }
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a currency type
+ return false;
+ }
+
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a <i>time</i>.
+ *
+ * @return true if the MiniCalc data <code>String</code>
+ * is a <i>time</i>, false if the MiniCalc data
+ * <code>String</code> is not a <i>time</i>.
+ */
+ public boolean isTime() {
+
+ // Starting index into the time string - hour
+ int start = 0;
+
+ // Search for ":", which separates hour from minute
+ int end = data.indexOf(":");
+
+
+ // Separator was found
+ if (end > 0) {
+
+ String hourString = data.substring(start, end);
+ try {
+ Float f = Float.valueOf(hourString);
+ if ((f.intValue() < 0) || (f.intValue() > 24))
+ return false;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a time type
+ return false;
+ }
+
+ // start is now the starting index of minute
+ start = end+1;
+
+ // Search for ":", which separates minute from second
+ end = data.indexOf(":", start);
+
+ // Separator was found
+ if (end > 0) {
+
+ String minuteString = data.substring(start, end);
+
+ try {
+ Float f = Float.valueOf(minuteString);
+ if ((f.intValue() < 0) || (f.intValue() > 60))
+ return false;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a time type
+ return false;
+ }
+
+ // start is now at the starting index of the seconds
+ start = end+1;
+
+ // The seconds are in the string
+ if (data.length() > start) {
+
+ String secondString = data.substring(start);
+
+
+ try {
+ Float f = Float.valueOf(secondString);
+ if ((f.intValue() < 0) || (f.intValue() > 60))
+ return false;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a time type
+ return false;
+ }
+ }
+
+ }
+
+ return true;
+
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Checks if the MiniCalc data <code>String</code> is a <i>currency</i>
+ * value.
+ *
+ * @return true if the MiniCalc data <code>String</code> is
+ * a <i>currency</i>, false if the MiniCalc data
+ * <code>String</code> is not a <i>currency</i>.
+ */
+ public boolean isCurrency() {
+
+ boolean result = false;
+
+ // TODO - we currently only check for US currencies
+
+ if (data.endsWith("$")) {
+ String number = data.substring(0, data.length()-1);
+ try {
+ Float f = Float.valueOf(number);
+ result = true;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a currency type
+ result = false;
+ }
+ }
+
+ else if (data.startsWith("$")) {
+ String number = data.substring(1, data.length());
+ try {
+ Float f = Float.valueOf(number);
+ result = true;
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a currency type
+ result = false;
+ }
+ }
+
+ return result;
+
+ }
+
+
+ /**
+ * This method removes the percent sign from the MiniCalc data
+ * <code>String</code>. If the percent sign is not the last
+ * character of the MiniCalc data <code>String</code>, the
+ * MiniCalc data <code>String</code> is returned.
+ *
+ * @return The MiniCalc data <code>String</code> minus the
+ * percent sign. If the MiniCalc data <code>String</code>
+ * does not begin with a percent sign, the MiniCalc data
+ * <code>String</code> is returned.
+ */
+ public String percentRemoveSign() {
+
+ String number = data;
+
+ if (data.endsWith("%")) {
+ // "%" is the last character, so remove
+ number = data.substring(0, data.length()-1);
+
+ try {
+ Float f = Float.valueOf(number);
+ float f1 = f.floatValue()/100f;
+ Float f2 = new Float(f1);
+ number = f2.toString();
+ }
+ catch (NumberFormatException e) {
+ // no, it is not a float type
+ }
+ }
+
+ return number;
+ }
+
+
+ /**
+ * This method removes the currency sign from the MiniCalc data
+ * <code>String</code>. If the currency sign is not the first or
+ * last character of the MiniCalc data <code>String</code>, the
+ * MiniCalc data <code>String</code> is returned.
+ *
+ * @return The MiniCalc data <code>String</code> minus the currency
+ * sign. If the MiniCalc data <code>String</code> does not
+ * begin or end with a currency sign, the MiniCalc
+ * data <code>String</code> is returned.
+ */
+ public String currencyRemoveSign() {
+
+ String number = data;
+
+ // TODO - only works with US currencies
+
+ if (data.endsWith("$")) {
+
+ number = data.substring(0, data.length()-1);
+
+ } else if (data.startsWith("$")) {
+
+ number = data.substring(1, data.length());
+ }
+
+ return number;
+
+ }
+
+
+ /**
+ * <p>This method converts a MiniCalc date from MiniCalc
+ * format to StarOffice XML format.</p>
+ *
+ * <p>MiniCalc format:</p>
+ *
+ * <p><blockquote>
+ * MM/DD/YY or MM/DD/YYYY
+ * </blockquote></p>
+ *
+ * <p>StarOffice XML format:</p>
+ *
+ * <p><blockquote>
+ * YYYY-MM-DD
+ * </blockquote></p>
+ *
+ * @return The MiniCalc date converted to StarOffice XML
+ * format.
+ */
+ public String convertToStarDate() {
+
+ // The output date string
+ String out;
+
+ String monthString = "01";
+ String dayString = "01";
+ String yearString = "1900";
+
+ // Starting index into the date string - month
+ int start = 0;
+
+ // Search for "/", which separates month from day
+ int end = data.indexOf("/");
+
+ // Separator was found
+ if (end > 0) {
+
+ monthString = data.substring(start, end);
+
+ Integer monthInt = new Integer(monthString);
+
+ // Make sure month is 2 digits
+ if (monthInt.intValue() < 10) {
+ monthString = "0" + monthString;
+ }
+
+ // start is now the starting index of day
+ start = end+1;
+
+ // Search for "/", which separates day from year
+ end = data.indexOf("/", start);
+
+ // Separator was found
+ if (end > 0) {
+
+ dayString = data.substring(start, end);
+
+ Integer dayInt = new Integer(dayString);
+
+ // Make sure day is 2 digits
+ if (dayInt.intValue() < 10) {
+ dayString = "0" + dayString;
+ }
+
+ // start is now at the starting index of the year
+ start = end + 1;
+
+ // The year is in the string
+ if (data.length() > start) {
+
+ yearString = data.substring(start);
+
+ Integer yearInt = new Integer(yearString);
+ int year = yearInt.intValue();
+
+ if (year < 31) {
+
+ // MiniCalc years between 0 and 30 correspond to
+ // 2000 - 2030
+ year += 2000;
+
+ } else if (year < 100) {
+
+ // MiniCalc years between 31 and 99 correspond
+ // to 1931 - 1999
+ year += 1900;
+ }
+
+ yearString = Integer.toString(year);
+ }
+ }
+ }
+
+ // Set out to StarOffice XML date format
+ out = yearString + "-" + monthString + "-" + dayString;
+
+ return out;
+ }
+
+
+ /**
+ * This method converts the MiniCalc time from MiniCalc
+ * format to StarOffice XML format.
+ *
+ * <p>MiniCalc format:</p>
+ *
+ * <p><blockquote>
+ * hh:mm:ss
+ * </blockquote></p>
+ *
+ * <p>StarOffice XML format:</p>
+ *
+ * <p><blockquote>
+ * PThhHmmMssS
+ * </blockquote></p>
+ *
+ * @return The MiniCalc time converted to StarOffice XML
+ * format.
+ */
+ public String convertToStarTime() {
+
+ // The output time string
+ String out;
+
+ String hourString = "00";
+ String minuteString = "00";
+ String secondString = "00";
+
+ // Starting index into the time string - hour
+ int start = 0;
+
+ // Search for ":", which separates hour from minute
+ int end = data.indexOf(":");
+
+ // Separator was found
+ if (end > 0) {
+
+ hourString = data.substring(start, end);
+
+ // start is now the starting index of minute
+ start = end+1;
+
+ // Search for ":", which separates minute from second
+ end = data.indexOf(":", start);
+
+ // Separator was found
+ if (end > 0) {
+
+ minuteString = data.substring(start, end);
+
+ // start is now at the starting index of the seconds
+ start = end+1;
+
+ // The seconds are in the string
+ if (data.length() > start) {
+
+ secondString = data.substring(start);
+ }
+
+ }
+ }
+
+ // TODO - PT is for pacific time, where can we get the
+ // localized value from?
+
+ // Set to StarOffice XML time format
+ out = "PT"+hourString+"H"+minuteString+"M"+secondString+"S";
+
+ return out;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDecoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDecoder.java
new file mode 100644
index 000000000000..1df98ae65455
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcDecoder.java
@@ -0,0 +1,747 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MinicalcDecoder.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.minicalc;
+
+import jmc.Workbook;
+import jmc.Worksheet;
+import jmc.CellAttributes;
+import jmc.CellDescriptor;
+import jmc.JMCconstants;
+import jmc.JMCException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+import org.openoffice.xmerge.converter.palm.PalmDB;
+import org.openoffice.xmerge.converter.palm.Record;
+import org.openoffice.xmerge.converter.palm.PalmDocument;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializer;
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetDecoder;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+
+/**
+ * This class is used by {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializerImpl}
+ * SxcDocumentDeserializerImpl} to decode the MiniCalc format.
+ *
+ * @author Paul Rank
+ */
+final class MinicalcDecoder extends SpreadsheetDecoder {
+
+ /** MiniCalc WorkBook to store sheets. */
+ private Workbook wb;
+
+ /** MiniCalc sheet - only one sheet can be open at a time. */
+ private Worksheet ws;
+
+ /** The current cell - only one cell can be active at a time. */
+ private CellDescriptor cell = null;
+
+ /** Format object describing the current cell. */
+ private Format fmt = null;
+
+ /** The password for the WorkBook. */
+ private String password = null;
+
+ /** The number of rows in the current WorkSheet. */
+ private int maxRows = 0;
+
+ /** The number of columns in the current WorkSheet. */
+ private int maxCols = 0;
+
+ /** The names of the worksheets. */
+ private String[] worksheetNames = null;
+
+ /**
+ * Constructor creates a MiniCalc WorkBook.
+ *
+ * @param name The name of the WorkBook.
+ * @param password The password for the workBook.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ MinicalcDecoder(String name, String[] worksheetNames, String password) throws IOException {
+
+ super(name, password);
+
+ fmt = new Format();
+
+ this.password = password;
+ this.worksheetNames = worksheetNames;
+
+ try {
+
+ wb = new Workbook(name, password);
+
+ }
+ catch (JMCException e) {
+
+ Debug.log(Debug.ERROR, "MinicalcDecoder.constructor:" + e.getMessage());
+
+ throw new IOException(e.getMessage());
+ // e.printStackTrace();
+
+ }
+ }
+
+
+ /**
+ * This method takes a <code>ConvertData</code> as input and
+ * converts it into a MiniCalc WorkSheet. The WorkSheet is then
+ * added to the WorkBook.
+ *
+ * @param InputStream An <code>ConvertData</code> containing a
+ * MiniCalc WorkSheet.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public void addDeviceContent(ConvertData cd) throws IOException {
+
+ try {
+ PalmDocument palmDoc;
+ int j = 0;
+
+ Enumeration e = cd.getDocumentEnumeration();
+ while(e.hasMoreElements()) {
+
+ palmDoc = (PalmDocument) e.nextElement();
+ // Convert PDB to WorkBook/WorkSheet format
+ PalmDB pdb = palmDoc.getPdb();
+
+ // This will be done at least once
+ String sheetName = worksheetNames[j];
+
+ // Get number of records in the pdb
+ int numRecords = pdb.getRecordCount();
+
+ // sheetName does not contain the WorkBook name, but we need the
+ // full name.
+ String fullSheetName = new String(wb.getWorkbookName() + "-" + sheetName);
+
+ // Create a new (empty) WorkSheet
+ ws = new Worksheet();
+
+ // Initialize the WorkSheet
+ ws.initWorksheet(fullSheetName, numRecords);
+
+ // Loop over the number of records in the PDB
+ for (int i = 0; i < numRecords; i++) {
+
+ // Read record i from the PDB
+ Record rec = pdb.getRecord(i);
+
+ byte cBytes[] = rec.getBytes();
+
+ // Create an InputStream
+ ByteArrayInputStream bis = new ByteArrayInputStream(cBytes);
+
+ // Get the size of the stream
+ int bisSize = cBytes.length;
+
+ // Add each record to the WorkSheet
+ ws.readNextRecord(bis, bisSize);
+ }
+
+
+ // Add the WorkSheet to the WorkBook
+ wb.addWorksheet(ws);
+ j++;
+ }
+ }
+ catch (JMCException e) {
+
+ Debug.log(Debug.ERROR, "MinicalcDecoder.addPDB:" + e.getMessage());
+
+ throw new IOException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * This method returns the number of spreadsheets
+ * stored in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public int getNumberOfSheets() {
+
+ return wb.getNumberOfSheets();
+ }
+
+
+ /**
+ * 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 {
+
+ try {
+
+ ws = wb.getWorksheet(sheetIndex);
+
+ // Initialize access to the WorkSheet so that we can calculate
+ // the number of rows and columns
+ ws.initAccess(password);
+
+ maxRows = 0;
+ maxCols = 0;
+
+ while (goToNextCell()) {
+ maxRows = Math.max(maxRows, cell.getRowNumber());
+ maxCols = Math.max(maxCols, cell.getColNumber());
+ }
+
+ // Re-initialize access to the WorkSheet
+ ws.initAccess(password);
+
+ }
+ catch (JMCException e) {
+
+ Debug.log(Debug.ERROR, "MinicalcDecoder.setWorksheet:" + e.getMessage());
+
+ throw new IOException(e.getMessage());
+ // e.printStackTrace();
+
+ }
+ }
+
+
+ /**
+ * This method returns the name of the current spreadsheet.
+ *
+ * @return The name of the current WorkSheet.
+ */
+ public String getSheetName() {
+
+ String sheetName = ws.getName();
+
+ return sheetName;
+ }
+
+
+ /**
+ * 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 gotCell = false;
+
+ try {
+ cell = ws.getNextCell();
+
+ if (cell != null) {
+ gotCell = true;
+ }
+
+ // As we read each cell, get its formatting info
+ readCellFormat();
+ }
+ catch (JMCException e) {
+
+ Debug.log(Debug.ERROR, "MinicalcDecoder.goToNextCell:" + e.getMessage());
+
+ throw new IOException(e.getMessage());
+ // e.printStackTrace();
+
+ }
+
+ return gotCell;
+ }
+
+
+ /**
+ * 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.getRowNumber();
+ }
+
+ 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.getColNumber();
+ }
+
+ 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 = null;
+
+ if (cell != null) {
+ contents = cell.getCellContents();
+
+ // Active cell, but no content
+ if (contents == null)
+ return new String("");
+
+ // Does the cell contain a formula?
+ if (contents.startsWith("=")) {
+ contents = parseFormula(contents);
+ }
+ // Make sure that any MiniCalc peculiarities are stripped off
+ if (fmt.getCategory().equalsIgnoreCase(OfficeConstants.CELLTYPE_CURRENCY)) {
+ contents = currencyRemoveSign(contents);
+ }
+ else if (fmt.getCategory().equalsIgnoreCase(OfficeConstants.CELLTYPE_PERCENT)) {
+ contents = percentRemoveSign(contents);
+ }
+ else if (fmt.getCategory().equalsIgnoreCase(OfficeConstants.CELLTYPE_DATE)) {
+ contents = convertToStarDate(contents);
+ }
+ else if (fmt.getCategory().equalsIgnoreCase(OfficeConstants.CELLTYPE_TIME)) {
+ contents = convertToStarTime(contents);
+ }
+ }
+
+ return contents;
+ }
+
+ /**
+ * This method is meant to return the value of the formula cell. However
+ * in minicalc this value is not used so hence the stubbed function
+ *
+ * @return the value fo the formula cell
+ */
+ public String getCellValue() {
+ return null;
+ }
+
+ /**
+ * <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;
+ }
+
+ /**
+ * <p>This method returns the type of the data in the current cell.</p>
+ *
+ * <p>Possible Data Types:</p>
+ *
+ * <ul><li>
+ * Percent - MiniCalc can store as a number or as a string.
+ *
+ * When stored as a string, the % sign is stored in the
+ * string . The MiniCalc format is "string".
+ * Example 10.1% is stored as the string "10.1%"
+ *
+ * When stored as a number, the decimal representation
+ * is stored. The MiniCalc format is "percentage".
+ * Example: 10.1% is stored as "0.101"
+ * </li><li>
+ * Currency - MiniCalc stores currency as a number with the format
+ * set to "currency".
+ * A user can also enter a value with a dollar sign
+ * (example $18.56) into MiniCalc and not set the format
+ * as currency. We treat this type of data as a
+ * currency data type.
+ * </li><li>
+ * Boolean - MiniCalc stores in a string as "true" or "false"
+ * </li><li>
+ *
+ * Date - MiniCalc stores a date in a string as either
+ * MM/DD/YY or MM/DD/YYYY. Any variation from the above
+ * format will not be considered a date.
+ * </li><li>
+ * Time - MiniCalc stores a time in a string as hh:mm:ss. Any
+ * variation from this format will not be considered a time.
+ * </li><li>
+ * Float - MiniCalc stores as a number and it is not percent
+ * or currency.
+ * </li><li>
+ * String - MiniCalc stores as a string (surprise). Doesn't parse
+ * to any of the other data types.
+ * </li><li>
+ * @return The type of the data in the current cell.
+ * </li></ul>
+ */
+ public String getCellDataType() {
+
+ boolean isNumber = false;
+
+ // Get format value set on the cell in MiniCalc
+ String format = getCellFormatType();
+
+ // Initialize the data type to the format
+ String type = format;
+
+ String contents = getCellContents();
+
+ if (contents != null) {
+
+ MinicalcDataString data = new MinicalcDataString(contents);
+
+ // Check if it is a formula
+ if (data.isFormula()) {
+ Debug.log(Debug.INFO, " " + contents + " Is a Function Format = "
+ + format + "\n");
+ return type;
+ }
+
+ try {
+ // Check to see if it is a number
+ Double d = Double.valueOf(contents);
+ isNumber = true;
+ Debug.log(Debug.INFO, " " + contents + " Is a Number Format = " + format);
+
+ } catch (NumberFormatException e) {
+ Debug.log(Debug.INFO, " " + contents + " Not a Number Format= " + format);
+ // no, it is not a number
+ isNumber = false;
+ }
+
+
+ if (isNumber) {
+
+ // Numbers are Float, Currency, and Percent
+ if (format.equals(OfficeConstants.CELLTYPE_CURRENCY)) {
+
+ type = OfficeConstants.CELLTYPE_CURRENCY;
+
+ } else if (format.equals(OfficeConstants.CELLTYPE_PERCENT)) {
+
+ type = OfficeConstants.CELLTYPE_PERCENT;
+
+ } else {
+
+ type = OfficeConstants.CELLTYPE_FLOAT;
+ }
+
+ } else if (data.isBoolean()) {
+
+ // Data is a Boolean type
+ type = OfficeConstants.CELLTYPE_BOOLEAN;
+
+ } else if (data.isDate()) {
+
+ // Data is a Date type
+ type = OfficeConstants.CELLTYPE_DATE;
+
+ } else if (data.isTime()) {
+
+ // Data is a Time type
+ type = OfficeConstants.CELLTYPE_TIME;
+
+ } else if (data.isPercent()) {
+
+ // Data is percent
+ type = OfficeConstants.CELLTYPE_PERCENT;
+
+ } else if (data.isCurrency()) {
+
+ // Data is a Currency type
+ type = OfficeConstants.CELLTYPE_CURRENCY;
+
+ } else {
+
+ // Data can't be float, since it isn't a number
+
+ // We've already tried parsing it as all other data
+ // types, the only remaining option is a string
+ type = OfficeConstants.CELLTYPE_STRING;
+ }
+ }
+
+ Debug.log(Debug.INFO, " TYPE = " + type + "\n");
+
+ return type;
+ }
+
+
+ /**
+ * This method returns the format of the data in the current cell.
+ *
+ * @return The format of the data in the current cell.
+ */
+ String getCellFormatType() {
+
+ // Set type to default data type
+ String type = OfficeConstants.CELLTYPE_FLOAT;
+
+ if (cell != null) {
+
+ // Get the attributes for the current cell
+ CellAttributes att = cell.getCellAttributes();
+
+ if (att != null) {
+
+ // Extract the format info from the attributes
+ long format = att.getFormat();
+
+ // The cell type is stored in bits 5-8
+ long cellType = format & 0x000000F0L;
+
+ // The number of decimal places is stored in bits 1-4
+ long decimals = format & 0x0000000FL;
+
+ if (cellType == JMCconstants.FF_FORMAT_GENERIC) {
+
+ // MiniCalc stores both Strings and Booleans
+ // in the generic type. We must check the contents
+ // to differentiate between the two.
+
+ // Get cell's contents
+ String contents = getCellContents();
+
+ if (contents.equalsIgnoreCase("false") ||
+ contents.equalsIgnoreCase("true")) {
+
+ type = OfficeConstants.CELLTYPE_BOOLEAN;
+
+
+ } else {
+
+ type = OfficeConstants.CELLTYPE_STRING;
+
+ }
+
+ } else if (cellType == JMCconstants.FF_FORMAT_DECIMAL) {
+
+ type = OfficeConstants.CELLTYPE_FLOAT;
+
+ } else if (cellType == JMCconstants.FF_FORMAT_TIME) {
+
+ type = OfficeConstants.CELLTYPE_TIME;
+
+ } else if (cellType == JMCconstants.FF_FORMAT_DATE) {
+
+ type = OfficeConstants.CELLTYPE_DATE;
+
+ } else if (cellType == JMCconstants.FF_FORMAT_CURRENCY) {
+
+ type = OfficeConstants.CELLTYPE_CURRENCY;
+
+ } else if (cellType == JMCconstants.FF_FORMAT_PERCENT) {
+
+ type = OfficeConstants.CELLTYPE_PERCENT;
+ }
+
+ }
+ }
+
+ return type;
+ }
+
+
+ /**
+ * This method takes a <code>String</code> that contains a
+ * currency value and removes the $ from the <code>String</code>.
+ * If the dollar sign is not the first or last character of the
+ * input <code>String</code>, the input <code>String</code> is
+ * simply returned.
+ *
+ * @param contents The input <code>String</code> from which to
+ * remove the dollar sign.
+ *
+ * @return The input <code>String</code> minus the dollar sign.
+ * If the input <code>String</code> did not begin or end
+ * with a dollar sign, contents is returned.
+ */
+ private String currencyRemoveSign(String contents) {
+ MinicalcDataString mcString = new MinicalcDataString(contents);
+ String currencyString = mcString.currencyRemoveSign();
+ return currencyString;
+ }
+
+
+ /**
+ * This method takes a <code>String</code> that contains a percent
+ * value and removes the % from the <code>String</code>. If the
+ * percent sign is not the last character of the input
+ * <code>String</code>, the input <code>String</code> is simply
+ * returned.
+ *
+ * @param contents The input String from which to remove the
+ * percent sign.
+ *
+ * @return The input <code>String</code> minus the percent sign.
+ * If the input <code>String</code> did not begin with
+ * a percent sign, contents is returned.
+ */
+ private String percentRemoveSign(String contents) {
+ MinicalcDataString mcString = new MinicalcDataString(contents);
+ String percentString = mcString.percentRemoveSign();
+ return percentString;
+ }
+
+
+ /**
+ * This method returns takes a <code>String</code> that contains
+ * a time value and converts it from MiniCalc format to StarOffice
+ * XML time format.
+ *
+ * @param contents The input <code>String</code> containing a
+ * MiniCalc time.
+ *
+ * @return The input <code>String</code> converted to StarOffice
+ * XML time format.
+ */
+ private String convertToStarTime(String contents) {
+ MinicalcDataString mcString = new MinicalcDataString(contents);
+ String timeString = mcString.convertToStarTime();
+ return timeString;
+ }
+
+ /**
+ * This method returns takes a <code>String</code> that contains
+ * a date value and converts it from MiniCalc format to StarOffice
+ * XML date format.
+ *
+ * @param contents The input <code>String</code> containing a
+ * MiniCalc date.
+ *
+ * @return The input <code>String</code> converted to StarOffice
+ * XML date format.
+ */
+ private String convertToStarDate(String contents) {
+ MinicalcDataString mcString = new MinicalcDataString(contents);
+ String dateString = mcString.convertToStarDate();
+ return dateString;
+ }
+
+
+ /**
+ * 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() {
+ // Make sure there are no remnants from the last time
+ fmt.clearFormatting();
+
+ fmt.setCategory(getCellFormatType());
+
+ // TODO - Get any more formatting data here
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java
new file mode 100644
index 000000000000..60f68474554d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java
@@ -0,0 +1,585 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: MinicalcEncoder.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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.minicalc;
+
+import jmc.Workbook;
+import jmc.Worksheet;
+import jmc.CellAttributes;
+import jmc.CellDescriptor;
+import jmc.JMCconstants;
+import jmc.JMCException;
+
+import java.awt.Color;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.openoffice.xmerge.converter.palm.Record;
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.IntArrayList;
+
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetEncoder;
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+
+/**
+ * This class is used by {@link
+ * org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializerImpl
+ * SxcDocumentSerializerImpl} to encode the MiniCalc format.
+ *
+ * @author Paul Rank
+ */
+final class MinicalcEncoder extends SpreadsheetEncoder {
+
+ /** MiniCalc WorkBook to store sheets. */
+ private Workbook wb;
+
+ /** MiniCalc sheet - only one sheet can be open at a time. */
+ private Worksheet ws;
+
+ /**
+ * Estimate of the number of Palm pixels per character. Used for
+ * estimating the width of a cell on a Palm device.
+ */
+ private final static int pixelsPerChar = 6;
+
+ /**
+ * The minimum width (in pixels) that we allow a column to be set to
+ * on a Palm device.
+ */
+ private final static int minWidth = 10;
+
+ /**
+ * The maximum width (in pixels) that we allow a column to be set to
+ * on a Palm device.
+ */
+ private final static int maxWidth = 80;
+
+
+ /**
+ * Constructor creates a MiniCalc WorkBook.
+ *
+ * @param log Log object for logging.
+ * @param name The name of the WorkBook.
+ * @param password The password for the WorkBook.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ MinicalcEncoder(String name, String password) throws IOException {
+
+ super(name, password);
+
+ try {
+ wb = new Workbook(name, password);
+ }
+ catch (JMCException e) {
+ Debug.log(Debug.ERROR, "new Workbook threw exception:" + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * 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 {
+
+ try {
+ ws = wb.createWorksheet(sheetName);
+ }
+ catch (JMCException e) {
+ Debug.log(Debug.ERROR, "wb.createWorksheet threw exception:" + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+ }
+
+
+ /**
+ * This method gets the number of sheets in the WorkBook.
+ *
+ * @return The number of sheets in the WorkBook.
+ */
+ public int getNumberOfSheets() {
+
+ int numSheets = wb.getNumberOfSheets();
+ return numSheets;
+ }
+
+
+ /**
+ * This method encodes the MiniCalc WorkBook information
+ * into an palm <code>Record</code> array in MiniCalc
+ * database format.
+ *
+ * @return Array of <code>Record</code> holding MiniCalc
+ * contents.
+ *
+ * @throws IOException If any I/O error occurs.
+ */
+ public Record[] getRecords(int sheetID) throws IOException {
+
+ // Get the WorkSheet for the input sheetID
+ ws = wb.getWorksheet(sheetID);
+
+ // Need to call ws.initWrite() before we start querying the WorkSheet
+ try {
+ ws.initWrite();
+ }
+ catch (JMCException e) {
+ Debug.log(Debug.ERROR, "ws.initWrite in getRecords:" + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+
+ // Get the number of records in the WorkSheet
+ int numRecords = ws.getNumberOfRecords();
+
+ // Create the Record array
+ Record[] allRecords = new Record[numRecords];
+
+
+ // Get each record from the WorkSheet and store in allRecords[]
+ try {
+ for (int i = 0; i < allRecords.length; i++) {
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ int length = ws.writeNextRecord(bos);
+
+ byte cBytes[] = bos.toByteArray();
+
+ allRecords[i] = new Record(cBytes);
+ }
+ }
+ catch (Exception e) {
+ Debug.log(Debug.ERROR, "ws.writeNextRecord in getRecords:" + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+
+ return allRecords;
+ }
+
+
+ /**
+ * 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) {
+
+ 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 '['
+ 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 ':':
+ // We have a cell range reference.
+ // May need to strip out the leading '.'
+ if (inBrace)
+ firstCharAfterColon = true;
+ outFormula.append(inFormula.charAt(in));
+ break;
+
+ case '.':
+ if (inBrace == true) {
+ if (firstCharAfterBrace == false &&
+ firstCharAfterColon == false) {
+ // Not the first character after the open brace.
+ // We have hit a separator between a sheet reference
+ // and a cell reference. MiniCalc uses a ! as
+ // this type of separator.
+ outFormula.append('!');
+ }
+ else {
+ firstCharAfterBrace = false;
+ firstCharAfterColon = false;
+ // Since we are in a StarOffice cell reference,
+ // and we are the first character, we need to
+ // strip out the '.'
+ }
+ break;
+ } else {
+ // We hit valid data, lets add it to the formula string
+ 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;
+ }
+ }
+
+ 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 {
+
+ CellAttributes ca = new CellAttributes(getFormat(fmt),
+ fmt.getForeground(),
+ fmt.getBackground());
+ if (cellContents.startsWith("=")) {
+ cellContents = parseFormula(cellContents);
+ Debug.log(Debug.INFO, "YAHOO Found Formula" + cellContents);
+ }
+
+ CellDescriptor cellDes = new CellDescriptor(row, column, ca, cellContents);
+
+ try {
+ ws.putCell(cellDes);
+ }
+ catch (JMCException jmce) {
+ Debug.log(Debug.ERROR, "ws.putCell threw exception: " + jmce.getMessage());
+ throw new IOException(jmce.getMessage());
+ }
+ }
+
+
+ /**
+ * Set the width of the columns in the WorkBook.
+ *
+ * @param columnWidths An <code>IntArrayList</code> of column
+ * widths.
+ */
+ public void setColumnWidths(IntArrayList columnWidths) throws IOException {
+ // Get the number of columns
+ int numColumns = columnWidths.size();
+
+ // Return if there are no columns in the listr
+ if (numColumns == 0) {
+ return;
+ }
+
+ // Need to set the FORM_FLAGS_NONDEFAULT flag for the column widths
+ // to be used in MiniCalc
+ long format = JMCconstants.FORM_FLAGS_NONDEFAULT;
+
+ CellAttributes ca = new CellAttributes(format);
+
+ try {
+ for (int i = 0; i < numColumns; i++) {
+ // Get the column width in Palm pixels
+ int width = columnWidths.get(i) * pixelsPerChar;
+
+ // Check limits on column width
+ if (width < minWidth) {
+ width = minWidth;
+ } else if (width > maxWidth) {
+ width = maxWidth;
+ }
+
+ // Add the column descriptor to the WorkSheet
+ ws.putColumn(i + 1, width, ca);
+ }
+ }
+ catch (JMCException jmce) {
+ Debug.log(Debug.ERROR, "ws.putColumn threw exception: " + jmce.getMessage());
+ throw new IOException(jmce.getMessage());
+ }
+ }
+
+
+ /**
+ * 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) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to generic, since MiniCalc does not have a string type.
+ format = format | JMCconstants.FF_FORMAT_GENERIC;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>floating point</i>.
+ *
+ * @param format The cell format. May already contain
+ * display info, such as alignment or
+ * font type.
+ * @param decimalPlaces The number of decimal places to
+ * set in the floating point number.
+ *
+ * @return The updated format of the cell.
+ */
+ private long setFormatFloat(long format, int decimalPlaces) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to floating point with correct number of decimal places
+ format = format | JMCconstants.FF_FORMAT_DECIMAL | decimalPlaces;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>time</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 setFormatTime(long format) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to time.
+ format = format | JMCconstants.FF_FORMAT_TIME;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>date</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 setFormatDate(long format) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to date.
+ format = format | JMCconstants.FF_FORMAT_DATE;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>currency</i>.
+ *
+ * @param format The cell format-may already contain
+ * display info, such as alignment or
+ * font type.
+ * @param decimalPlaces The number of decimal places to set.
+ *
+ * @return The updated format of the cell.
+ */
+ private long setFormatCurrency(long format, int decimalPlaces) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to Currency with correct number of decimal places
+ format = format | JMCconstants.FF_FORMAT_CURRENCY | decimalPlaces;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>boolean</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 setFormatBoolean(long format) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to generic, since MiniCalc does not have a Boolean type.
+ format = format | JMCconstants.FF_FORMAT_GENERIC;
+
+ return format;
+ }
+
+
+ /**
+ * This method sets the format of a cell to <i>percent</i>.
+ *
+ * @param format The cell format-may already contain
+ * display info, such as alignment or
+ * font type.
+ * @param decimalPlaces The number of decimal places to set.
+ *
+ * @return The updated format of the cell.
+ */
+ private long setFormatPercent(long format, int decimalPlaces) {
+
+ format = clearCellFormatType(format);
+
+ // Set format to Percent with correct number of decimal places
+ format = format | JMCconstants.FF_FORMAT_PERCENT | decimalPlaces;
+
+ return format;
+ }
+
+
+ /**
+ * This method clears out the format bits associated with
+ * the type of data (<i>float</i>, <i>time</i>, etc...) in
+ * a cell.
+ *
+ * @param format The original format for the cell.
+ *
+ * @return The updated cell format with the bits associated
+ * with the type of data (float, time, etc...)
+ * zeroed out.
+ */
+ private long clearCellFormatType(long format) {
+
+ // First 4 bits are for the number of decimal places
+ // bits 5-8 are for the data format (float, time, etc...)
+
+ // Clear out first 8 bits
+ format = format & 0xFFFFFFFFFFFFFF00L;
+
+ return format;
+ }
+
+
+ /**
+ * 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) {
+ }
+
+
+ /**
+ * Get the names of the sheets in the WorkBook.
+ *
+ * @param sheet The required sheet.
+ */
+ public String getSheetName(int sheet) {
+ return wb.getWorksheet(sheet).getName();
+ }
+
+
+ /*
+ * This method returns a MiniCalc style format from the
+ * <code>Format</code> object.
+ */
+ private long getFormat(Format fmt)
+ {
+ String category = fmt.getCategory();
+
+ if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_BOOLEAN)) {
+ return setFormatBoolean(0);
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_CURRENCY)) {
+ return setFormatCurrency(0, fmt.getDecimalPlaces());
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_DATE)) {
+ return setFormatDate(0);
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_FLOAT)) {
+ return setFormatFloat(0, fmt.getDecimalPlaces());
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_PERCENT)) {
+ return setFormatPercent(0, fmt.getDecimalPlaces());
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_STRING)) {
+ return setFormatString(0);
+ }
+ else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_TIME)) {
+ return setFormatTime(0);
+ }
+ else {
+ // Should never get here, but just in case
+ System.out.println("XXXXX Formatting information not found");
+ return 0;
+ }
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/PluginFactoryImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/PluginFactoryImpl.java
new file mode 100644
index 000000000000..a3b1d53abaff
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/PluginFactoryImpl.java
@@ -0,0 +1,132 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PluginFactoryImpl.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.minicalc;
+
+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.palm.PalmDocument;
+import org.openoffice.xmerge.util.registry.ConverterInfo;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * <p>MiniCalc implementation of the <code>PluginFactory</code>.
+ * This encapsulates conversion of StarCalc XML format to and from
+ * MiniCalc 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 {
+
+ PalmDocument palmDoc = new PalmDocument(is);
+ return palmDoc;
+ }
+
+ public DocumentMerger createDocumentMerger(Document doc) {
+
+ DocumentMergerImpl merger = new DocumentMergerImpl(doc, converterCap);
+ return merger;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentDeserializerImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentDeserializerImpl.java
new file mode 100644
index 000000000000..1161b5522ca1
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentDeserializerImpl.java
@@ -0,0 +1,141 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentDeserializerImpl.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.minicalc;
+
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializer;
+import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetDecoder;
+import org.openoffice.xmerge.converter.palm.PalmDB;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.converter.palm.PalmDocument;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * <p>MiniCalc implementation of <code>DocumentDeserializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.minicalc.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>This converts a set of files in MiniCalc PDB 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 MinicalcDecoder(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();
+ PalmDocument palmDoc = (PalmDocument) e.nextElement();
+ String workbookName = palmDoc.getName();
+
+ // Search for "-", which separates workbook from worksheet
+ int end = workbookName.indexOf("-");
+
+ if (end > 0) {
+ workbookName = workbookName.substring(0, end);
+ }
+
+ 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 {
+ int numberOfPDBs = cd.getNumDocuments();
+ String worksheetName[] = new String[numberOfPDBs];
+ int i=0;
+ Enumeration e = cd.getDocumentEnumeration();
+ while (e.hasMoreElements()) {
+ PalmDocument palmDoc = (PalmDocument) e.nextElement();
+ worksheetName[i] = palmDoc.getName();
+
+ // Search for the "-", which seperates workbook from worksheet
+ int start = worksheetName[i].indexOf("-");
+
+ if (start != -1) {
+ worksheetName[i] = worksheetName[i].substring(start + 1);
+ }
+ i++;
+ }
+
+ return worksheetName;
+ }
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentSerializerImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentSerializerImpl.java
new file mode 100644
index 000000000000..69b584fadf09
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/SxcDocumentSerializerImpl.java
@@ -0,0 +1,144 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentSerializerImpl.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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.minicalc;
+
+import java.awt.Color;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+import java.io.IOException;
+
+import org.openoffice.xmerge.Document;
+import org.openoffice.xmerge.ConvertData;
+import org.openoffice.xmerge.ConvertException;
+import org.openoffice.xmerge.converter.palm.PalmDB;
+import org.openoffice.xmerge.converter.palm.Record;
+import org.openoffice.xmerge.converter.palm.PalmDocument;
+
+import jmc.JMCconstants;
+
+import org.openoffice.xmerge.converter.xml.sxc.Format;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializer;
+
+/**
+ * <p>MiniCalc implementation of <code>SxcDocumentDeserializer</code>
+ * for the {@link
+ * org.openoffice.xmerge.converter.xml.sxc.minicalc.PluginFactoryImpl
+ * PluginFactoryImpl}.</p>
+ *
+ * <p>This converts StarOffice XML format to a set of files in
+ * MiniCalc PDB 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 MinicalcEncoder(docName, password);
+
+ // get dom document
+ org.w3c.dom.Document domDoc = sxcDoc.getContentDOM();
+
+ // 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 the number of sheets in the workbook
+ // This will equal the number of PDBs we need
+ ConvertData cd = new ConvertData();
+ int numSheets = encoder.getNumberOfSheets();
+
+ for (int i = 0; i < numSheets; i++) {
+
+ // Get records for sheet i
+ Record records[] = ((MinicalcEncoder) encoder).getRecords(i);
+
+ // Get the sheet name for sheet i
+ String fullSheetName = new String(docName
+ + "-"
+ + encoder.getSheetName(i));
+
+ // Create a PalmDB object
+ PalmDocument palmDoc = new PalmDocument(fullSheetName,
+ MinicalcConstants.CREATOR_ID,
+ MinicalcConstants.TYPE_ID, JMCconstants.AppVersion,
+ PalmDB.PDB_HEADER_ATTR_BACKUP, records);
+
+ cd.addDocument(palmDoc);
+ }
+
+
+ // OutputStream os = new FileOutputStream(docName);
+
+ //pdbSet.write(os);
+ //os.flush();
+
+ //ConvertDataEntry cde = new ConvertDataOutputStream(os, docName);
+ //cd.addCDE(cde);
+
+ return cd;
+ }
+
+
+
+}
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/build.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/build.xml
new file mode 100644
index 000000000000..c1898c2fa3d5
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/build.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.4 $
+
+ 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.
+
+-->
+<project name="xmrg_jooxcxs_minicalc" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- project prefix, used for targets and build.lst -->
+ <property name="prj.prefix" value="xmrg"/>
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="xmrg_jooxcxs_minicalc"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="../../../../../../../.."/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="${prj}/java"/>
+
+ <!-- path component for current java package -->
+ <property name="package"
+ value="org/openoffice/xmerge/converter/xml/sxc/minicalc"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for javac tasks -->
+ <path id="classpath">
+ <pathelement location="${build.class}"/>
+ <pathelement location="${solar.jar}/parser.jar"/>
+ <pathelement location="${solar.jar}/jaxp.jar"/>
+ <pathelement location="${solar.jar}/xerces.jar"/>
+ <pathelement location="${solar.jar}/jmc.jar"/>
+ </path>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <!-- ================================================================= -->
+ <!-- solar build environment targets -->
+ <!-- ================================================================= -->
+
+ <target name="build_dir" unless="build.dir">
+ <property name="build.dir" value="${out}"/>
+ </target>
+
+ <target name="solar" depends="build_dir" if="solar.update">
+ <property name="solar.properties"
+ value="${solar.bin}/solar.properties"/>
+ </target>
+
+ <target name="init" depends="solar">
+ <property name="build.compiler" value="classic"/>
+ <property file="${solar.properties}"/>
+ <property file="${build.dir}/class/solar.properties"/>
+ </target>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare" depends="init" if="build.class">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <!-- compile java sources in ${package} -->
+ <target name="compile" depends="prepare" if="build.class">
+ <javac srcdir="${java.dir}"
+ destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprecation}"
+ optimize="${optimize}">
+ <classpath refid="classpath"/>
+ <include name="${package}/MinicalcConstants.java"/>
+ <include name="${package}/MinicalcDecoder.java"/>
+ <include name="${package}/MinicalcEncoder.java"/>
+ <include name="${package}/MinicalcDataString.java"/>
+ <include name="${package}/SxcDocumentDeserializerImpl.java"/>
+ <include name="${package}/SxcDocumentSerializerImpl.java"/>
+ <include name="${package}/ConverterCapabilitiesImpl.java"/>
+ <include name="${package}/PluginFactoryImpl.java"/>
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+</project>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/converter.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/converter.xml
new file mode 100644
index 000000000000..263021fa324d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/converter.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: converter.xml,v $
+
+ $Revision: 1.4 $
+
+ 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.
+
+-->
+<converters>
+ <converter type="staroffice/sxc" version="1.0">
+ <converter-display-name>
+ Minicalc 6.4
+ </converter-display-name>
+ <converter-description>
+ StarCalc XML to/from Minicalc 6.4 conversion
+ </converter-description>
+ <converter-vendor>OpenOffice.org</converter-vendor>
+ <converter-class-impl>
+ org.openoffice.xmerge.converter.xml.sxc.minicalc.PluginFactoryImpl
+ </converter-class-impl>
+ <converter-target type="application/x-minicalc" />
+ </converter>
+</converters>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/makefile.mk b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/makefile.mk
new file mode 100644
index 000000000000..78d4211e162d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/makefile.mk
@@ -0,0 +1,36 @@
+#***************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# 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.
+#
+#***************************************************************************
+
+TARGET=xmrg_jooxcxs_minicalc
+PRJ=../../../../../../../..
+
+.INCLUDE : ant.mk
+ALLTAR: ANTBUILD
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/package.html b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/package.html
new file mode 100644
index 000000000000..191ed77ec344
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/package.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: package.html,v $
+
+ $Revision: 1.3 $
+
+ 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.minicalc package</title>
+</head>
+
+<body bgcolor="white">
+
+<p>Provides the tools for doing the conversion of StarWriter XML to
+and from MiniCalc format.</p>
+
+<p>It follows the {@link org.openoffice.xmerge} framework for the conversion process.</p>
+
+<p>Since it converts to/from a Palm application format, these converters
+follow the <a href=../../../../converter/palm/package-summary.html#streamformat>
+PalmDB stream format</a> for writing out to the Palm sync client or reading
+in from the Palm sync client.</p>
+
+<p>Note that <code>PluginFactoryImpl</code> also provides a
+<code>DocumentMerger</code> object, i.e. {@link org.openoffice.xmerge.converter.xml.sxw.aportisdoc.DocumentMergerImpl DocumentMergerImpl}.
+This functionality was derived from its superclass
+{@link org.openoffice.xmerge.converter.xml.sxw.SxwPluginFactory SxwPluginFactory}.</p>
+
+</body>
+</html>
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/package.html b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/package.html
new file mode 100644
index 000000000000..258d0158af1d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/package.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: package.html,v $
+
+ $Revision: 1.3 $
+
+ 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 package</title>
+</head>
+
+<body bgcolor="white">
+<p>Provides base implementation of StarCalc XML conversion to and from
+different &quot;Device&quot; <code>Document</code> formats.</p>
+
+</body>
+</html>
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java
new file mode 100644
index 000000000000..2e51ee685e21
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/ConverterCapabilitiesImpl.java
@@ -0,0 +1,116 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ConverterCapabilitiesImpl.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java
new file mode 100644
index 000000000000..389b0169e49b
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PluginFactoryImpl.java
@@ -0,0 +1,133 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PluginFactoryImpl.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java
new file mode 100644
index 000000000000..22382e0faf8c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelConstants.java
@@ -0,0 +1,71 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PocketExcelConstants.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java
new file mode 100644
index 000000000000..c5f263766da2
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelDecoder.java
@@ -0,0 +1,449 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PocketExcelDecoder.java,v $
+ * $Revision: 1.23 $
+ *
+ * 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.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Stack;
+import java.util.LinkedList;
+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.SheetSettings;
+import org.openoffice.xmerge.converter.xml.sxc.BookSettings;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentDeserializer;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java
new file mode 100644
index 000000000000..44e9de76394d
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/PocketExcelEncoder.java
@@ -0,0 +1,298 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PocketExcelEncoder.java,v $
+ * $Revision: 1.17 $
+ *
+ * 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.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Vector;
+
+import org.openoffice.xmerge.util.Debug;
+import org.openoffice.xmerge.util.IntArrayList;
+
+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.SheetSettings;
+import org.openoffice.xmerge.converter.xml.sxc.NameDefinition;
+import org.openoffice.xmerge.converter.xml.OfficeConstants;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java
new file mode 100644
index 000000000000..5bca66b92b92
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentDeserializerImpl.java
@@ -0,0 +1,132 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentDeserializerImpl.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java
new file mode 100644
index 000000000000..ff3de98c3478
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/SxcDocumentSerializerImpl.java
@@ -0,0 +1,139 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SxcDocumentSerializerImpl.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.awt.Color;
+
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Element;
+
+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.Format;
+import org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializer;
+import org.openoffice.xmerge.converter.xml.sxc.pexcel.records.Workbook;
+import org.openoffice.xmerge.converter.xml.StyleCatalog;
+
+/**
+ * <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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/build.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/build.xml
new file mode 100644
index 000000000000..02c1e44a9ea7
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/build.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.5 $
+
+ 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.
+
+-->
+<project name="xmrg_jooxcxs_pexcel" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- project prefix, used for targets and build.lst -->
+ <property name="prj.prefix" value="xmrg"/>
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="xmrg_jooxcxs_pexcel"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="../../../../../../../.."/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="${prj}/java"/>
+
+ <!-- path component for current java package -->
+ <property name="package"
+ value="org/openoffice/xmerge/converter/xml/sxc/pexcel"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for javac tasks -->
+ <path id="classpath">
+ <pathelement location="${build.class}"/>
+ <pathelement location="${solar.jar}/parser.jar"/>
+ <pathelement location="${solar.jar}/jaxp.jar"/>
+ </path>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <!-- ================================================================= -->
+ <!-- solar build environment targets -->
+ <!-- ================================================================= -->
+
+ <target name="build_dir" unless="build.dir">
+ <property name="build.dir" value="${out}"/>
+ </target>
+
+ <target name="solar" depends="build_dir" if="solar.update">
+ <property name="solar.properties"
+ value="${solar.bin}/solar.properties"/>
+ </target>
+
+ <target name="init" depends="solar">
+ <property name="build.compiler" value="classic"/>
+ <property file="${solar.properties}"/>
+ <property file="${build.dir}/class/solar.properties"/>
+ </target>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare" depends="init" if="build.class">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <!-- compile java sources in ${package} -->
+ <target name="compile" depends="prepare" if="build.class">
+ <javac srcdir="${java.dir}"
+ destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprecation}"
+ optimize="${optimize}">
+ <classpath refid="classpath"/>
+ <include name="${package}/PocketExcelConstants.java"/>
+ <include name="${package}/PocketExcelDecoder.java"/>
+ <include name="${package}/PocketExcelEncoder.java"/>
+ <include name="${package}/SxcDocumentDeserializerImpl.java"/>
+ <include name="${package}/SxcDocumentSerializerImpl.java"/>
+ <include name="${package}/ConverterCapabilitiesImpl.java"/>
+ <include name="${package}/PluginFactoryImpl.java"/>
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+</project>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/converter.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/converter.xml
new file mode 100644
index 000000000000..1d6627afe49c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/converter.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: converter.xml,v $
+
+ $Revision: 1.3 $
+
+ 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.
+
+-->
+<converters>
+ <converter type="staroffice/sxc" version="1.0">
+ <converter-display-name>
+ Pocket Excel 2.0
+ </converter-display-name>
+ <converter-description>
+ StarCalc XML to/from Pocket Excel 2.0 conversion
+ </converter-description>
+ <converter-vendor>OpenOffice.org</converter-vendor>
+ <converter-class-impl>
+ org.openoffice.xmerge.converter.xml.sxc.pexcel.PluginFactoryImpl
+ </converter-class-impl>
+ <converter-target type="application/x-pocket-excel" />
+ </converter>
+</converters>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/makefile.mk b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/makefile.mk
new file mode 100644
index 000000000000..c8d22159c375
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/makefile.mk
@@ -0,0 +1,36 @@
+#***************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# 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.
+#
+#***************************************************************************
+
+TARGET=xmrg_jooxcxs_pexcel
+PRJ=../../../../../../../..
+
+.INCLUDE : ant.mk
+ALLTAR: ANTBUILD
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html
new file mode 100644
index 000000000000..c7da1abfbc56
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/package.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: package.html,v $
+
+ $Revision: 1.3 $
+
+ 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java
new file mode 100644
index 000000000000..685d6153c621
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BIFFRecord.java
@@ -0,0 +1,65 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BIFFRecord.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java
new file mode 100644
index 000000000000..a7b328f6cf8a
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BeginningOfFile.java
@@ -0,0 +1,119 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BeginningOfFile.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java
new file mode 100644
index 000000000000..3bd70f0c7a91
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BlankCell.java
@@ -0,0 +1,119 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BlankCell.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java
new file mode 100644
index 000000000000..6fca4ddd57d2
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoolErrCell.java
@@ -0,0 +1,130 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BoolErrCell.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java
new file mode 100644
index 000000000000..db34aa600fb9
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/BoundSheet.java
@@ -0,0 +1,140 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: BoundSheet.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.util.EndianConverter;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java
new file mode 100644
index 000000000000..2bb22b35666f
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CellValue.java
@@ -0,0 +1,141 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: CellValue.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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;
+
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java
new file mode 100644
index 000000000000..55184582ebdb
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/CodePage.java
@@ -0,0 +1,111 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: CodePage.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java
new file mode 100644
index 000000000000..d3e61e1b4fec
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ColInfo.java
@@ -0,0 +1,161 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ColInfo.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java
new file mode 100644
index 000000000000..12a451334386
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefColWidth.java
@@ -0,0 +1,98 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DefColWidth.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java
new file mode 100644
index 000000000000..d924f339fe37
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefRowHeight.java
@@ -0,0 +1,100 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DefRowHeight.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java
new file mode 100644
index 000000000000..3fad2410162e
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/DefinedName.java
@@ -0,0 +1,230 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: DefinedName.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java
new file mode 100644
index 000000000000..77a4e97835cf
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Eof.java
@@ -0,0 +1,75 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Eof.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java
new file mode 100644
index 000000000000..254c2f2bddf4
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/ExtendedFormat.java
@@ -0,0 +1,388 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ExtendedFormat.java,v $
+ * $Revision: 1.11 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java
new file mode 100644
index 000000000000..db80eccb9cb8
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FloatNumber.java
@@ -0,0 +1,124 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FloatNumber.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java
new file mode 100644
index 000000000000..50ff9e5e64d7
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/FontDescription.java
@@ -0,0 +1,290 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FontDescription.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java
new file mode 100644
index 000000000000..b2f74f1f6be9
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Formula.java
@@ -0,0 +1,266 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Formula.java,v $
+ * $Revision: 1.11 $
+ *
+ * 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.DataInputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Calendar;
+import java.util.Date;
+import java.text.DateFormat;
+
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java
new file mode 100644
index 000000000000..aafe992cad47
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/LabelCell.java
@@ -0,0 +1,143 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: LabelCell.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java
new file mode 100644
index 000000000000..0735b401a6b8
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/NumberFormat.java
@@ -0,0 +1,98 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: NumberFormat.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.DataInputStream;
+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 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java
new file mode 100644
index 000000000000..4155a658ae40
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Pane.java
@@ -0,0 +1,222 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Pane.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java
new file mode 100644
index 000000000000..5ffb49da45d5
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Row.java
@@ -0,0 +1,142 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Row.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java
new file mode 100644
index 000000000000..bafafc9c371f
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Selection.java
@@ -0,0 +1,146 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Selection.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java
new file mode 100644
index 000000000000..772affb2e817
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/StringValue.java
@@ -0,0 +1,128 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: StringValue.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java
new file mode 100644
index 000000000000..2446e86089ed
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/UnsupportedFormulaException.java
@@ -0,0 +1,46 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: UnsupportedFormulaException.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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;
+
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java
new file mode 100644
index 000000000000..24b8aa92f580
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window1.java
@@ -0,0 +1,119 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Window1.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java
new file mode 100644
index 000000000000..e587de7ea3b4
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Window2.java
@@ -0,0 +1,158 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Window2.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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.DataInputStream;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java
new file mode 100644
index 000000000000..d29efd8d9938
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Workbook.java
@@ -0,0 +1,543 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Workbook.java,v $
+ * $Revision: 1.17 $
+ *
+ * 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.util.IntArrayList;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java
new file mode 100644
index 000000000000..d0e4f829722a
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/Worksheet.java
@@ -0,0 +1,323 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Worksheet.java,v $
+ * $Revision: 1.10 $
+ *
+ * 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.IntArrayList;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/build.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/build.xml
new file mode 100644
index 000000000000..a30c348c84f3
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/build.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.6 $
+
+ 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.
+
+-->
+<project name="xmrg_jooxcxsp_records" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- project prefix, used for targets and build.lst -->
+ <property name="prj.prefix" value="xmrg"/>
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="xmrg_jooxcxsp_records"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="../../../../../../../../.."/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="${prj}/java"/>
+
+ <!-- path component for current java package -->
+ <property name="package"
+ value="org/openoffice/xmerge/converter/xml/sxc/pexcel/records"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for javac tasks -->
+ <path id="classpath">
+ <pathelement location="${build.class}"/>
+ <pathelement location="${solar.jar}/parser.jar"/>
+ <pathelement location="${solar.jar}/jaxp.jar"/>
+ </path>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <!-- ================================================================= -->
+ <!-- solar build environment targets -->
+ <!-- ================================================================= -->
+
+ <target name="build_dir" unless="build.dir">
+ <property name="build.dir" value="${out}"/>
+ </target>
+
+ <target name="solar" depends="build_dir" if="solar.update">
+ <property name="solar.properties"
+ value="${solar.bin}/solar.properties"/>
+ </target>
+
+ <target name="init" depends="solar">
+ <property name="build.compiler" value="classic"/>
+ <property file="${solar.properties}"/>
+ <property file="${build.dir}/class/solar.properties"/>
+ </target>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare" depends="init" if="build.class">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <!-- compile java sources in ${package} -->
+ <target name="compile" depends="prepare" if="build.class">
+ <javac srcdir="${java.dir}"
+ destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprecation}"
+ optimize="${optimize}">
+ <classpath refid="classpath"/>
+ <include name="${package}/BIFFRecord.java"/>
+ <include name="${package}/CellValue.java"/>
+ <include name="${package}/Workbook.java"/>
+ <include name="${package}/Worksheet.java"/>
+ <include name="${package}/BeginningOfFile.java"/>
+ <include name="${package}/BlankCell.java"/>
+ <include name="${package}/BoolErrCell.java"/>
+ <include name="${package}/BoundSheet.java"/>
+ <include name="${package}/CodePage.java"/>
+ <include name="${package}/ColInfo.java"/>
+ <include name="${package}/DefColWidth.java"/>
+ <include name="${package}/DefRowHeight.java"/>
+ <include name="${package}/DefinedName.java"/>
+ <include name="${package}/Eof.java"/>
+ <include name="${package}/ExtendedFormat.java"/>
+ <include name="${package}/FloatNumber.java"/>
+ <include name="${package}/FontDescription.java"/>
+ <include name="${package}/UnsupportedFormulaException.java"/>
+ <include name="${package}/Formula.java"/>
+ <include name="${package}/LabelCell.java"/>
+ <include name="${package}/NumberFormat.java"/>
+ <include name="${package}/Pane.java"/>
+ <include name="${package}/Row.java"/>
+ <include name="${package}/Selection.java"/>
+ <include name="${package}/StringValue.java"/>
+ <include name="${package}/Window1.java"/>
+ <include name="${package}/Window2.java"/>
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+</project>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java
new file mode 100644
index 000000000000..49474e5de25f
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaCompiler.java
@@ -0,0 +1,275 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FormulaCompiler.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java
new file mode 100644
index 000000000000..2e4e773a5f27
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaHelper.java
@@ -0,0 +1,156 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FormulaHelper.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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.util.Debug;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java
new file mode 100644
index 000000000000..2422a5297b96
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParser.java
@@ -0,0 +1,567 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FormulaParser.java,v $
+ * $Revision: 1.11 $
+ *
+ * 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.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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java
new file mode 100644
index 000000000000..f961bcbf49a0
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FormulaParsingException.java
@@ -0,0 +1,49 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FormulaParsingException.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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
+ */
+
+import java.io.*;
+
+import org.openoffice.xmerge.util.Debug;
+
+public class FormulaParsingException extends Exception {
+
+ public FormulaParsingException(String message) {
+ super(message);
+ }
+ }
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java
new file mode 100644
index 000000000000..c8205b6d4754
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/FunctionLookup.java
@@ -0,0 +1,210 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: FunctionLookup.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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;
+
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java
new file mode 100644
index 000000000000..e8a547d1b9d6
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperandLookup.java
@@ -0,0 +1,68 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: OperandLookup.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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;
+
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java
new file mode 100644
index 000000000000..0e376a6d0152
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/OperatorLookup.java
@@ -0,0 +1,79 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: OperatorLookup.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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;
+
+import org.openoffice.xmerge.util.Debug;
+
+/**
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java
new file mode 100644
index 000000000000..41912b046e7c
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/ParseToken.java
@@ -0,0 +1,46 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ParseToken.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java
new file mode 100644
index 000000000000..265334f553f1
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/PrecedenceTable.java
@@ -0,0 +1,89 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: PrecedenceTable.java,v $
+ * $Revision: 1.5 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java
new file mode 100644
index 000000000000..9c9ba638b448
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/SymbolLookup.java
@@ -0,0 +1,85 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SymbolLookup.java,v $
+ * $Revision: 1.4 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java
new file mode 100644
index 000000000000..4ec1884dae8b
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/Token.java
@@ -0,0 +1,157 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: Token.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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.*;
+
+/**
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java
new file mode 100644
index 000000000000..b8b37be7772e
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenConstants.java
@@ -0,0 +1,209 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TokenConstants.java,v $
+ * $Revision: 1.7 $
+ *
+ * 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.*;
+
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java
new file mode 100644
index 000000000000..3390463e3756
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenDecoder.java
@@ -0,0 +1,501 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TokenDecoder.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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 (bis.available()!=0)
+ {
+ b = bis.read();
+
+ 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java
new file mode 100644
index 000000000000..d2002df2819a
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenEncoder.java
@@ -0,0 +1,564 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TokenEncoder.java,v $
+ * $Revision: 1.8 $
+ *
+ * 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.BoundSheet;
+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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java
new file mode 100644
index 000000000000..427b56383dfc
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/TokenFactory.java
@@ -0,0 +1,126 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: TokenFactory.java,v $
+ * $Revision: 1.6 $
+ *
+ * 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;
+
+/**
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java
new file mode 100644
index 000000000000..6eeae73cb0b8
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/UnsupportedFunctionException.java
@@ -0,0 +1,44 @@
+/************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: UnsupportedFunctionException.java,v $
+ * $Revision: 1.3 $
+ *
+ * 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/build.xml b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/build.xml
new file mode 100644
index 000000000000..05865f52c740
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/build.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: build.xml,v $
+
+ $Revision: 1.3 $
+
+ 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.
+
+-->
+<project name="xmrg_jooxcxspr_formula" default="main" basedir=".">
+
+ <!-- ================================================================= -->
+ <!-- settings -->
+ <!-- ================================================================= -->
+
+ <!-- project prefix, used for targets and build.lst -->
+ <property name="prj.prefix" value="xmrg"/>
+
+ <!-- name of this sub target used in recursive builds -->
+ <property name="target" value="xmrg_jooxcxspr_formula"/>
+
+ <!-- relative path to project directory -->
+ <property name="prj" value="../../../../../../../../../.."/>
+
+ <!-- start of java source code package structure -->
+ <property name="java.dir" value="${prj}/java"/>
+
+ <!-- path component for current java package -->
+ <property name="package"
+ value="org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula"/>
+
+ <!-- define how to handle CLASSPATH environment -->
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <!-- classpath settings for javac tasks -->
+ <path id="classpath">
+ <pathelement location="${build.class}"/>
+ <pathelement location="${solar.jar}/parser.jar"/>
+ <pathelement location="${solar.jar}/jaxp.jar"/>
+ </path>
+
+ <!-- set wether we want to compile with or without deprecation -->
+ <property name="deprecation" value="on"/>
+
+ <!-- ================================================================= -->
+ <!-- solar build environment targets -->
+ <!-- ================================================================= -->
+
+ <target name="build_dir" unless="build.dir">
+ <property name="build.dir" value="${out}"/>
+ </target>
+
+ <target name="solar" depends="build_dir" if="solar.update">
+ <property name="solar.properties"
+ value="${solar.bin}/solar.properties"/>
+ </target>
+
+ <target name="init" depends="solar">
+ <property name="build.compiler" value="classic"/>
+ <property file="${solar.properties}"/>
+ <property file="${build.dir}/class/solar.properties"/>
+ </target>
+
+ <target name="info">
+ <echo message="--------------------"/>
+ <echo message="${target}"/>
+ <echo message="--------------------"/>
+ </target>
+
+
+ <!-- ================================================================= -->
+ <!-- custom targets -->
+ <!-- ================================================================= -->
+
+ <!-- the main target, called in recursive builds -->
+ <target name="main" depends="info,prepare,compile"/>
+
+ <!-- prepare output directories -->
+ <target name="prepare" depends="init" if="build.class">
+ <mkdir dir="${build.dir}"/>
+ <mkdir dir="${build.class}"/>
+ </target>
+
+ <!-- compile java sources in ${package} -->
+ <target name="compile" depends="prepare" if="build.class">
+ <javac srcdir="${java.dir}"
+ destdir="${build.class}"
+ debug="${debug}"
+ deprecation="${deprecation}"
+ optimize="${optimize}">
+ <classpath refid="classpath"/>
+ <include name="${package}/FormulaCompiler.java"/>
+ <include name="${package}/FormulaHelper.java"/>
+ <include name="${package}/FormulaParser.java"/>
+ <include name="${package}/FormulaParsingException.java"/>
+ <include name="${package}/FunctionLookup.java"/>
+ <include name="${package}/OperandLookup.java"/>
+ <include name="${package}/Operatorookup.java"/>
+ <include name="${package}/ParseToken.java"/>
+ <include name="${package}/PrecedenceTable.java"/>
+ <include name="${package}/SymbolLookup.java"/>
+ <include name="${package}/Token.java"/>
+ <include name="${package}/TokenConstants.java"/>
+ <include name="${package}/TokenDecoder.java"/>
+ <include name="${package}/TokenEncoder.java"/>
+ <include name="${package}/TokenFactory.java"/>
+ <include name="${package}/UnsupportedFunctionException.java"/>
+ </javac>
+ </target>
+
+ <!-- clean up -->
+ <target name="clean" depends="prepare">
+ <delete includeEmptyDirs="true">
+ <fileset dir="${build.class}">
+ <patternset>
+ <include name="${package}/*.class"/>
+ </patternset>
+ </fileset>
+ </delete>
+ </target>
+
+</project>
+
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/makefile.mk b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/makefile.mk
new file mode 100644
index 000000000000..47db7a258006
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/makefile.mk
@@ -0,0 +1,36 @@
+#***************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# 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.
+#
+#***************************************************************************
+
+TARGET=xmrg_jooxcxs_pexcel
+PRJ=../../../../../../../../..
+
+.INCLUDE : ant.mk
+ALLTAR: ANTBUILD
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html
new file mode 100644
index 000000000000..7e719f53bebe
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/formula/package.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: package.html,v $
+
+ $Revision: 1.3 $
+
+ 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/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html
new file mode 100644
index 000000000000..79188bf45310
--- /dev/null
+++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/pexcel/records/package.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ Copyright 2008 by Sun Microsystems, Inc.
+
+ OpenOffice.org - a multi-platform office productivity suite
+
+ $RCSfile: package.html,v $
+
+ $Revision: 1.4 $
+
+ 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>