--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class CHP implements Cloneable
+{
+ boolean _bold;
+ boolean _italic;
+ boolean _fRMarkDel;
+ boolean _fOutline;
+ boolean _fSmallCaps;
+ boolean _fCaps;
+ boolean _fVanish;
+ boolean _fRMark;
+ boolean _fSpec;
+ boolean _fStrike;
+ boolean _fObj;
+ boolean _fShadow;
+ boolean _fLowerCase;
+ boolean _fData;
+ boolean _fOle2;
+ boolean _fEmboss;
+ boolean _fImprint;
+ boolean _fDStrike;
+
+ short _ftcAscii;
+ short _ftcFE;
+ short _ftcOther;
+ short _ftc;
+ int _hps;//font size in half points
+ int _dxaSpace;//space following each character in the run expressed in twip units
+ byte _iss;//superscript/subscript indices 0 means no super/subscripting 1 means text in run is superscripted 2 means text in run is subscripted
+ byte _kul;//underline code see spec
+ byte _ico;//color of text see spec
+ short _hpsPos;//super/subscript position in half points; positive means text is raised; negative means text is lowered
+ short _lidDefault;//language for non-Far East text
+ short _lidFE;//language for Far East text
+ byte _idctHint;
+ int _wCharScale;
+ short _chse;
+
+ int _specialFC;//varies depending on whether this is a special char
+ short _ibstRMark;//index to author IDs stored in hsttbfRMark. used when text in run was newly typed when revision marking was enabled
+ short _ibstRMarkDel;//index to author IDs stored in hsttbfRMark. used when text in run was newly typed when revision marking was enabled
+ int[] _dttmRMark = new int[2];//Date/time at which this run of text was
+ int[] _dttmRMarkDel = new int[2];//entered/modified by the author. (Only
+ //recorded when revision marking is on.)Date/time at which this run of text was deleted by the author. (Only recorded when revision marking is on.)
+ int _istd;
+ int _baseIstd = -1;
+ int _fcPic;
+ short _ftcSym;// see spec
+ short _xchSym;//see spec
+ byte _ysr;//hyphenation rules
+ byte _chYsr;//used for hyphenation see spec
+ int _hpsKern;//kerning distance for characters in run recorded in half points
+ int _fcObj;
+ byte _icoHighlight;//highlight color
+ boolean _fChsDiff;
+ boolean _highlighted;//when true characters are highlighted with color specified by chp.icoHighlight
+ boolean _fPropMark;//when true, properties have been changed with revision marking on
+ short _ibstPropRMark;//index to author IDs stored in hsttbfRMark. used when properties have been changed when revision marking was enabled
+ int _dttmPropRMark;//Date/time at which properties of this were changed for this run of text by the author
+ byte _sfxtText;//text animation see spec
+ boolean _fDispFldRMark;//see spec
+ short _ibstDispFldRMark;//Index to author IDs stored in hsttbfRMark. used when ListNum field numbering has been changed when revision marking was enabled
+ int _dttmDispFldRMark;//The date for the ListNum field number change
+ byte[] _xstDispFldRMark = new byte[32];//The string value of the ListNum field when revision mark tracking began
+ short _shd;//shading
+ short[] _brc = new short[2];//border
+ short _paddingStart = 0;
+ short _paddingEnd = 0;
+
+ public CHP()
+ {
+ _istd = 10;
+ _hps = 20;
+ _lidDefault = 0x0400;
+ _lidFE = 0x0400;
+
+ }
+ public void copy(CHP toCopy)
+ {
+ _bold = toCopy._bold;
+ _italic = toCopy._italic;
+ _fRMarkDel = toCopy._fRMarkDel;
+ _fOutline = toCopy._fOutline;
+ _fSmallCaps = toCopy._fSmallCaps;
+ _fCaps = toCopy._fCaps;
+ _fVanish = toCopy._fVanish;
+ _fRMark = toCopy._fRMark;
+ _fSpec = toCopy._fSpec;
+ _fStrike = toCopy._fStrike;
+ _fObj = toCopy._fObj;
+ _fShadow = toCopy._fShadow;
+ _fLowerCase = toCopy._fLowerCase;
+ _fData = toCopy._fData;
+ _fOle2 = toCopy._fOle2;
+ _fEmboss = toCopy._fEmboss;
+ _fImprint = toCopy._fImprint;
+ _fDStrike = toCopy._fDStrike;
+
+ _ftcAscii = toCopy._ftcAscii;
+ _ftcFE = toCopy._ftcFE;
+ _ftcOther = toCopy._ftcOther;
+ _ftc = toCopy._ftc;
+ _hps = toCopy._hps;
+ _dxaSpace = toCopy._dxaSpace;
+ _iss = toCopy._iss;
+ _kul = toCopy._kul;
+ _ico = toCopy._ico;
+ _hpsPos = toCopy._hpsPos;
+ _lidDefault = toCopy._lidDefault;
+ _lidFE = toCopy._lidFE;
+ _idctHint = toCopy._idctHint;
+ _wCharScale = toCopy._wCharScale;
+ _chse = toCopy._chse;
+
+ _specialFC = toCopy._specialFC;
+ _ibstRMark = toCopy._ibstRMark;
+ _ibstRMarkDel = toCopy._ibstRMarkDel;
+ _dttmRMark = toCopy._dttmRMark;
+ _dttmRMarkDel = toCopy._dttmRMarkDel;
+
+ _istd = toCopy._istd;
+ _baseIstd = toCopy._baseIstd;
+ _fcPic = toCopy._fcPic;
+ _ftcSym = toCopy._ftcSym;
+ _xchSym = toCopy._xchSym;
+ _ysr = toCopy._ysr;
+ _chYsr = toCopy._chYsr;
+ _hpsKern = toCopy._hpsKern;
+ _fcObj = toCopy._fcObj;
+ _icoHighlight = toCopy._icoHighlight;
+ _fChsDiff = toCopy._fChsDiff;
+ _highlighted = toCopy._highlighted;
+ _fPropMark = toCopy._fPropMark;
+ _ibstPropRMark = toCopy._ibstPropRMark;
+ _dttmPropRMark = toCopy._dttmPropRMark;
+ _sfxtText = toCopy._sfxtText;
+ _fDispFldRMark = toCopy._fDispFldRMark;
+ _ibstDispFldRMark = toCopy._ibstDispFldRMark;
+ _dttmDispFldRMark = toCopy._dttmDispFldRMark;
+ _xstDispFldRMark = toCopy._xstDispFldRMark;
+ _shd = toCopy._shd;
+ _brc = toCopy._brc;
+
+ }
+
+ public Object clone() throws CloneNotSupportedException
+ {
+ CHP clone = (CHP)super.clone();
+ clone._brc = new short[2];
+ System.arraycopy(_brc, 0, clone._brc, 0, 2);
+ return clone;
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class FontTable
+{
+ String[] fontNames;
+
+ public FontTable(byte[] fontTable)
+ {
+ int size = Utils.convertBytesToShort(fontTable, 0);
+ fontNames = new String[size];
+
+ int currentIndex = 4;
+ for(int x = 0; x < size; x++)
+ {
+ byte ffnLength = fontTable[currentIndex];
+
+ int nameOffset = currentIndex + 40;
+ StringBuffer nameBuf = new StringBuffer();
+ char ch = Utils.getUnicodeCharacter(fontTable, nameOffset);
+ while(ch != '\0')
+ {
+ nameBuf.append(ch);
+ nameOffset += 2;
+ ch = Utils.getUnicodeCharacter(fontTable, nameOffset);
+ }
+ fontNames[x] = nameBuf.toString();
+ if(fontNames[x].startsWith("Times"))
+ {
+ fontNames[x] = "Times";
+ }
+
+ currentIndex += ffnLength + 1;
+ }
+
+ }
+ public String getFont(int index)
+ {
+ return fontNames[index];
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class HeaderFooter
+{
+ public static final int HEADER_EVEN = 1;
+ public static final int HEADER_ODD = 2;
+ public static final int FOOTER_EVEN = 3;
+ public static final int FOOTER_ODD = 4;
+ public static final int HEADER_FIRST = 5;
+ public static final int FOOTER_FIRST = 6;
+
+ private int _type;
+ private int _start;
+ private int _end;
+
+ public HeaderFooter(int type, int startFC, int endFC)
+ {
+ _type = type;
+ _start = startFC;
+ _end = endFC;
+ }
+ public int getStart()
+ {
+ return _start;
+ }
+ public int getEnd()
+ {
+ return _end;
+ }
+ public boolean isEmpty()
+ {
+ if(_start - _end == 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class NewOleFile extends RandomAccessFile
+{
+ private byte[] LAOLA_ID_ARRAY = new byte[]{(byte)0xd0, (byte)0xcf, (byte)0x11,
+ (byte)0xe0, (byte)0xa1, (byte)0xb1,
+ (byte)0x1a, (byte)0xe1};
+ private int _num_bbd_blocks;
+ private int _root_startblock;
+ private int _sbd_startblock;
+ private long _size;
+ private int[] _bbd_list;
+ protected int[] _big_block_depot;
+ protected int[] _small_block_depot;
+ Hashtable _propertySetsHT = new Hashtable();
+ Vector _propertySetsV = new Vector();
+
+ public NewOleFile(String fileName, String mode) throws FileNotFoundException
+ {
+ super(fileName, mode);
+ try
+ {
+ init();
+ }
+ catch(Throwable e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void init() throws IOException
+ {
+
+ for(int x = 0; x < LAOLA_ID_ARRAY.length; x++)
+ {
+ if(LAOLA_ID_ARRAY[x] != readByte())
+ {
+ throw new IOException("Not an OLE file");
+ }
+ }
+ _size = length();
+ _num_bbd_blocks = readInt(0x2c);
+ _root_startblock = readInt(0x30);
+ _sbd_startblock = readInt(0x3c);
+ _bbd_list = new int[_num_bbd_blocks];
+ //populate bbd_list. If _num_bbd_blocks > 109 I have to do it
+ //differently
+ if(_num_bbd_blocks <= 109)
+ {
+ seek(0x4c);
+ for(int x = 0; x < _num_bbd_blocks; x++)
+ {
+ _bbd_list[x] = readIntLE();
+ }
+ }
+ else
+ {
+ populateBbdList();
+ }
+ //populate the big block depot
+ _big_block_depot = new int[_num_bbd_blocks * 128];
+ int counter = 0;
+ for(int x = 0; x < _num_bbd_blocks; x++)
+ {
+ byte[] bigBlock = new byte[512];
+ int offset = (_bbd_list[x] + 1) * 512;
+ seek(offset);
+ for(int y = 0; y < 128; y++)
+ {
+ _big_block_depot[counter++] = readIntLE();
+ }
+ }
+ _small_block_depot = createSmallBlockDepot();
+ int[] rootChain = readChain(_big_block_depot, _root_startblock);
+ initializePropertySets(rootChain);
+
+ }
+ public static void main(String args[])
+ {
+ try
+ {
+ NewOleFile file = new NewOleFile(args[0], "r");
+ }
+ catch(Exception e)
+ {
+ }
+ }
+ protected int[] readChain(int[] blockChain, int startBlock) throws IOException
+ {
+
+ int[] tempChain = new int[blockChain.length];
+ tempChain[0] = startBlock;
+ int x = 1;
+ for(;;x++)
+ {
+ int nextVal = blockChain[tempChain[x-1]];
+ if(nextVal != -2)
+ {
+ tempChain[x] = nextVal;
+ }
+ else
+ {
+ break;
+ }
+ }
+ int[] newChain = new int[x];
+ System.arraycopy(tempChain, 0, newChain, 0, x);
+
+ return newChain;
+ }
+ private void initializePropertySets(int[] rootChain) throws IOException
+ {
+ for(int x = 0; x < rootChain.length; x++)
+ {
+ int offset = (rootChain[x] + 1) * 512;
+ seek(offset);
+ for(int y = 0; y < 4; y++)
+ {
+ //read the block the makes up the property set
+ byte[] propArray = new byte[128];
+ read(propArray);
+
+ //parse the byte array for properties
+ int nameSize = Utils.convertBytesToShort(propArray[0x41], propArray[0x40])/2 - 1;
+ if(nameSize > 0)
+ {
+ StringBuffer nameBuffer = new StringBuffer(nameSize);
+ for(int z = 0; z < nameSize; z++)
+ {
+ nameBuffer.append((char)propArray[z*2]);
+ }
+ int type = propArray[0x42];
+ int previous_pps = Utils.convertBytesToInt(propArray[0x47], propArray[0x46], propArray[0x45], propArray[0x44]);
+ int next_pps = Utils.convertBytesToInt(propArray[0x4b], propArray[0x4a], propArray[0x49], propArray[0x48]);
+ int pps_dir = Utils.convertBytesToInt(propArray[0x4f], propArray[0x4e], propArray[0x4d], propArray[0x4c]);
+ int pps_sb = Utils.convertBytesToInt(propArray[0x77], propArray[0x76], propArray[0x75], propArray[0x74]);
+ int pps_size = Utils.convertBytesToInt(propArray[0x7b], propArray[0x7a], propArray[0x79], propArray[0x78]);
+
+ PropertySet propSet = new PropertySet(nameBuffer.toString(),
+ type, previous_pps, next_pps,
+ pps_dir, pps_sb, pps_size,
+ (x*4) + y);
+ _propertySetsHT.put(nameBuffer.toString(), propSet);
+ _propertySetsV.add(propSet);
+ }
+ }
+ }
+
+ }
+ private int[] createSmallBlockDepot() throws IOException
+ {
+
+ int[] sbd_list = readChain(_big_block_depot, _sbd_startblock);
+ int[] small_block_depot = new int[sbd_list.length * 128];
+
+ for(int x = 0; x < sbd_list.length && sbd_list[x] != -2; x++)
+ {
+ int offset = ((sbd_list[x] + 1) * 512);
+ seek(offset);
+ for(int y = 0; y < 128; y++)
+ {
+ small_block_depot[y] = readIntLE();
+ }
+ }
+ return small_block_depot;
+ }
+
+ private void populateBbdList() throws IOException
+ {
+ seek(0x4c);
+ for(int x = 0; x < 109; x++)
+ {
+ _bbd_list[x] = readIntLE();
+ }
+ int pos = 109;
+ int remainder = _num_bbd_blocks - 109;
+ seek(0x48);
+ int numLists = readIntLE();
+ seek(0x44);
+ int firstList = readIntLE();
+
+ firstList = (firstList + 1) * 512;
+
+ for(int y = 0; y < numLists; y++)
+ {
+ int size = Math.min(127, remainder);
+ for(int z = 0; z < size; z++)
+ {
+ seek(firstList + (z * 4));
+ _bbd_list[pos++] = readIntLE();
+ }
+ if(size == 127)
+ {
+ seek(firstList + (127 * 4));
+ firstList = readIntLE();
+ firstList = (firstList + 1) * 512;
+ remainder -= 127;
+ }
+ }
+
+ }
+ private int readInt(long offset) throws IOException
+ {
+ seek(offset);
+ return readIntLE();
+ }
+ private int readIntLE() throws IOException
+ {
+ byte[] intBytes = new byte[4];
+ read(intBytes);
+ return Utils.convertBytesToInt(intBytes[3], intBytes[2], intBytes[1], intBytes[0]);
+ }
+
+
+
+
+
+}
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class PAP implements Cloneable
+{
+ int _istd;//index to style descriptor.
+ byte _jc;//justification code
+ byte _fKeep;//keep entire paragraph on one page if possible
+ byte _fKeepFollow;//keep paragraph on same page with next paragraph if possible
+ byte _fPageBreakBefore;//start this paragraph on new page
+ byte _positionByte;//multiple flags see spec;
+ byte _brcp;//rectangle border codes for Macword 3.0
+ byte _brcl;//border line styles for Macword 3.0
+ byte _ilvl;//when non-zero, list level for this paragraph
+ byte _fNoLnn;//no line numbering for this paragraph. (makes this an exception to the section property of line numbering)
+ int _ilfo;//when non-zero, (1-based) index into the pllfo identifying the list to which the paragraph belongs
+ byte _fSideBySide;//when 1, paragraph is a side by side paragraph
+ byte _fNoAutoHyph;//when 0, text in paragraph may be auto hyphenated.
+ byte _fWindowControl;//when 1, Word will prevent widowed lines in this paragraph from being placed at the beginning of a page
+ int _dxaRight;//indent from right margin (signed).
+ int _dxaLeft;//indent from left margin (signed)
+ int _dxaLeft1;//first line indent; signed number relative to dxaLeft
+ int[] _lspd = new int[2];//line spacing descriptor see spec
+ int _dyaBefore;// vertical spacing before paragraph (unsigned)
+ int _dyaAfter;//vertical spacing after paragraph (unsigned)
+ byte[] _phe = new byte[12];//height of current paragraph
+ byte _fCrLf;//undocumented
+ byte _fUsePgsuSettings;//undocumented
+ byte _fAdjustRight;//undocumented
+ byte _fKinsoku;// when 1, apply kinsoku rules when performing line wrapping
+ byte _fWordWrap;//when 1, perform word wrap
+ byte _fOverflowPunct;//when 1, apply overflow punctuation rules when performing line wrapping
+ byte _fTopLinePunct;//when 1, perform top line punctuation processing
+ byte _fAutoSpaceDE;//when 1, auto space FE and alphabetic characters
+ byte _fAutoSpaceDN;// when 1, auto space FE and numeric characters
+ int _wAlignFont;//font alignment 0 Hanging 1 Centered 2 Roman 3 Variable 4 Auto
+ short _fontAlign;//multiVal see Spec.
+ byte _fInTable;//when 1, paragraph is contained in a table row
+ byte _fTtp;//when 1, paragraph consists only of the row mark special character and marks the end of a table row
+ byte _wr;//Wrap Code for absolute objects
+ byte _fLocked;//when 1, paragraph may not be edited
+ int _dxaAbs;//see spec
+ int _dyaAbs;//see spec
+ int _dxaWidth;//when not == 0, paragraph is constrained to be dxaWidth wide, independent of current margin or column settings
+ short[] _brcTop = new short[2];//spec for border above paragraph
+ short[] _brcLeft = new short[2];//specification for border to the left of
+ short[] _brcBottom = new short[2];//paragraphspecification for border below
+ short[] _brcRight = new short[2];//paragraphspecification for border to the
+ short[] _brcBetween = new short[2];//right of paragraphsee spec
+ short[] _brcBar = new short[2];//specification of border to place on
+ short _brcTop1;//outside of text when facing pages are to be displayed.spec
+ short _brcLeft1;//for border above paragraphspecification for border to the
+ short _brcBottom1;//left ofparagraphspecification for border below
+ short _brcRight1;//paragraphspecification for border to the
+ short _brcBetween1;//right of paragraphsee spec
+ short _brcBar1;//specification of border to place on outside of text when facing pages are to be displayed.
+ int _dxaFromText;//horizontal distance to be maintained between an absolutely positioned paragraph and any non-absolute positioned text
+ int _dyaFromText;//vertical distance to be maintained between an absolutely positioned paragraph and any non-absolute positioned text
+ int _dyaHeight;//see spec
+ int _shd;//shading
+ int _dcs;//drop cap specifier
+ byte[] _anld = new byte[84];//autonumber list descriptor (see ANLD definition)
+ short _fPropRMark;//when 1, properties have been changed with revision marking on
+ short _ibstPropRMark;//index to author IDs stored in hsttbfRMark. used when properties have been changed when revision marking was enabled
+ byte[] _dttmPropRMark = new byte[4];//Date/time at which properties of this were changed for this run of text by the author. (Only recorded when revision marking is on.)
+ byte[] _numrm = new byte[8];//paragraph numbering revision mark data (see NUMRM)
+ short _itbdMac;//number of tabs stops defined for paragraph. Must be >= 0 and <= 64.
+
+
+
+ public PAP()
+ {
+ _fWindowControl = 1;
+ //lspd[0] = 240;
+ _lspd[1] = 1;
+ _ilvl = 9;
+ }
+ public Object clone() throws CloneNotSupportedException
+ {
+ PAP clone = (PAP)super.clone();
+
+ clone._brcBar = new short[2];
+ clone._brcBottom = new short[2];
+ clone._brcLeft = new short[2];
+ clone._brcBetween = new short[2];
+ clone._brcRight = new short[2];
+ clone._brcTop = new short[2];
+ clone._lspd = new int[2];
+ clone._phe = new byte[12];
+ clone._anld = new byte[84];
+ clone._dttmPropRMark = new byte[4];
+ clone._numrm = new byte[8];
+
+ System.arraycopy(_brcBar, 0, clone._brcBar, 0, 2);
+ System.arraycopy(_brcBottom, 0, clone._brcBottom, 0, 2);
+ System.arraycopy(_brcLeft, 0, clone._brcLeft, 0, 2);
+ System.arraycopy(_brcBetween, 0, clone._brcBetween, 0, 2);
+ System.arraycopy(_brcRight, 0, clone._brcRight, 0, 2);
+ System.arraycopy(_brcTop, 0, clone._brcTop, 0, 2);
+ System.arraycopy(_lspd, 0, clone._lspd, 0, 2);
+ System.arraycopy(_phe, 0, clone._phe, 0, 12);
+ System.arraycopy(_anld, 0, clone._anld, 0, 84);
+ System.arraycopy(_dttmPropRMark, 0, clone._dttmPropRMark, 0, 4);
+ System.arraycopy(_numrm, 0, clone._numrm, 0, 8);
+
+ return clone;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class PropertySet
+{
+ private String _name;
+ private int _type;
+ private int _previous;
+ private int _next;
+ private int _dir;
+ private int _sb;
+ private int _size;
+ private int _num;
+
+ public PropertySet(String name, int type, int previous, int next, int dir,
+ int sb, int size, int num)
+ {
+ _name = name;
+ _type = type;
+ _previous = previous;
+ _next = next;
+ _dir = dir;
+ _sb = sb;
+ _size = size;
+ _num = num;
+ }
+ public int getSize()
+ {
+ return _size;
+ }
+ public int getStartBlock()
+ {
+ return _sb;
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class SEP
+{
+ int _index;
+ byte _bkc;
+ boolean _fTitlePage;
+ boolean _fAutoPgn;
+ byte _nfcPgn;
+ boolean _fUnlocked;
+ byte _cnsPgn;
+ boolean _fPgnRestart;
+ boolean _fEndNote;
+ byte _lnc;
+ byte _grpfIhdt;
+ short _nLnnMod;
+ int _dxaLnn;
+ short _dxaPgn;
+ short _dyaPgn;
+ boolean _fLBetween;
+ byte _vjc;
+ short _dmBinFirst;
+ short _dmBinOther;
+ short _dmPaperReq;
+ short[] _brcTop = new short[2];
+ short[] _brcLeft = new short[2];
+ short[] _brcBottom = new short[2];
+ short[] _brcRight = new short[2];
+ boolean _fPropMark;
+ int _dxtCharSpace;
+ int _dyaLinePitch;
+ short _clm;
+ byte _dmOrientPage;
+ byte _iHeadingPgn;
+ short _pgnStart;
+ short _lnnMin;
+ short _wTextFlow;
+ short _pgbProp;
+ int _xaPage;
+ int _yaPage;
+ int _dxaLeft;
+ int _dxaRight;
+ int _dyaTop;
+ int _dyaBottom;
+ int _dzaGutter;
+ int _dyaHdrTop;
+ int _dyaHdrBottom;
+ short _ccolM1;
+ boolean _fEvenlySpaced;
+ int _dxaColumns;
+ int[] _rgdxaColumnWidthSpacing;
+ byte _dmOrientFirst;
+ byte[] _olstAnn;
+
+
+
+ public SEP()
+ {
+ _bkc = 2;
+ _dyaPgn = 720;
+ _dxaPgn = 720;
+ _fEndNote = true;
+ _fEvenlySpaced = true;
+ _xaPage = 12240;
+ _yaPage = 15840;
+ _dyaHdrTop = 720;
+ _dyaHdrBottom = 720;
+ _dmOrientPage = 1;
+ _dxaColumns = 720;
+ _dyaTop = 1440;
+ _dxaLeft = 1800;
+ _dyaBottom = 1440;
+ _dxaRight = 1800;
+ _pgnStart = 1;
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class StyleDescription
+{
+
+ private static int PARAGRAPH_STYLE = 1;
+ private static int CHARACTER_STYLE = 2;
+
+ int _baseStyleIndex;
+ int _styleTypeCode;
+ int _numUPX;
+ byte[] _papx;
+ byte[] _chpx;
+ PAP _pap;
+ CHP _chp;
+
+ public StyleDescription()
+ {
+ _pap = new PAP();
+ _chp = new CHP();
+ }
+ public StyleDescription(byte[] std, int baseLength, boolean word9)
+ {
+ int infoShort = Utils.convertBytesToShort(std, 2);
+ _styleTypeCode = (infoShort & 0xf);
+ _baseStyleIndex = (infoShort & 0xfff0) >> 4;
+
+ infoShort = Utils.convertBytesToShort(std, 4);
+ _numUPX = infoShort & 0xf;
+
+ //first byte(s) of variable length section of std is the length of the
+ //style name and aliases string
+ int nameLength = 0;
+ int multiplier = 1;
+ if(word9)
+ {
+ nameLength = Utils.convertBytesToShort(std, baseLength);
+ multiplier = 2;
+ }
+ else
+ {
+ nameLength = std[baseLength];
+ }
+ //2 bytes for length, length then null terminator.
+ int grupxStart = multiplier + ((nameLength + 1) * multiplier) + baseLength;
+
+ int offset = 0;
+ for(int x = 0; x < _numUPX; x++)
+ {
+ int upxSize = Utils.convertBytesToShort(std, grupxStart + offset);
+ if(_styleTypeCode == PARAGRAPH_STYLE)
+ {
+ if(x == 0)
+ {
+ _papx = new byte[upxSize];
+ System.arraycopy(std, grupxStart + offset + 2, _papx, 0, upxSize);
+ }
+ else if(x == 1)
+ {
+ _chpx = new byte[upxSize];
+ System.arraycopy(std, grupxStart + offset + 2, _chpx, 0, upxSize);
+ }
+ }
+ else if(_styleTypeCode == CHARACTER_STYLE && x == 0)
+ {
+ _chpx = new byte[upxSize];
+ System.arraycopy(std, grupxStart + offset + 2, _chpx, 0, upxSize);
+ }
+
+ if(upxSize % 2 == 1)
+ {
+ ++upxSize;
+ }
+ offset += 2 + upxSize;
+ }
+
+
+
+ }
+ public int getBaseStyle()
+ {
+ return _baseStyleIndex;
+ }
+ public byte[] getCHPX()
+ {
+ return _chpx;
+ }
+ public byte[] getPAPX()
+ {
+ return _papx;
+ }
+ public PAP getPAP()
+ {
+ return _pap;
+ }
+ public CHP getCHP()
+ {
+ return _chp;
+ }
+ public void setPAP(PAP pap)
+ {
+ _pap = pap;
+ }
+ public void setCHP(CHP chp)
+ {
+ _chp = chp;
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+import java.util.*;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class StyleSheet
+{
+
+ private static final int NIL_STYLE = 4095;
+ private static final int PAP_TYPE = 1;
+ private static final int CHP_TYPE = 2;
+ private static final int SEP_TYPE = 4;
+ private static final int TAP_TYPE = 5;
+ //Vector _styleDescriptions;
+ StyleDescription _nilStyle = new StyleDescription();
+ StyleDescription[] _styleDescriptions;
+
+ public StyleSheet(byte[] styleSheet)
+ {
+ int stshiLength = Utils.convertBytesToShort(styleSheet, 0);
+ int stdCount = Utils.convertBytesToShort(styleSheet, 2);
+ int baseLength = Utils.convertBytesToShort(styleSheet, 4);
+ int[] rgftc = new int[3];
+
+ rgftc[0] = Utils.convertBytesToInt(styleSheet, 14);
+ rgftc[1] = Utils.convertBytesToInt(styleSheet, 18);
+ rgftc[2] = Utils.convertBytesToInt(styleSheet, 22);
+
+ int offset = 0;
+ _styleDescriptions = new StyleDescription[stdCount];
+ for(int x = 0; x < stdCount; x++)
+ {
+ int stdOffset = (2 + stshiLength) + offset;
+ int stdSize = Utils.convertBytesToShort(styleSheet, stdOffset);
+ if(stdSize > 0)
+ {
+ byte[] std = new byte[stdSize];
+
+ //get past the size
+ stdOffset += 2;
+ System.arraycopy(styleSheet, stdOffset, std, 0, stdSize);
+ StyleDescription aStyle = new StyleDescription(std, baseLength, true);
+
+ _styleDescriptions[x] = aStyle;
+ }
+
+
+ offset += stdSize + 2;
+
+ }
+ for(int x = 0; x < _styleDescriptions.length; x++)
+ {
+ if(_styleDescriptions[x] != null)
+ {
+ createPap(x);
+ createChp(x);
+ }
+ }
+ }
+ private void createPap(int istd)
+ {
+ StyleDescription sd = _styleDescriptions[istd];
+ PAP pap = sd.getPAP();
+ byte[] papx = sd.getPAPX();
+ int baseIndex = sd.getBaseStyle();
+ if(pap == null && papx != null)
+ {
+ PAP parentPAP = _nilStyle.getPAP();
+ if(baseIndex != NIL_STYLE)
+ {
+
+ parentPAP = _styleDescriptions[baseIndex].getPAP();
+ if(parentPAP == null)
+ {
+ createPap(baseIndex);
+ parentPAP = _styleDescriptions[baseIndex].getPAP();
+ }
+
+ }
+
+ pap = (PAP)uncompressProperty(papx, parentPAP, this);
+ sd.setPAP(pap);
+ }
+ }
+ private void createChp(int istd)
+ {
+ StyleDescription sd = _styleDescriptions[istd];
+ CHP chp = sd.getCHP();
+ byte[] chpx = sd.getCHPX();
+ int baseIndex = sd.getBaseStyle();
+ if(chp == null && chpx != null)
+ {
+ CHP parentCHP = _nilStyle.getCHP();
+ if(baseIndex != NIL_STYLE)
+ {
+
+ parentCHP = _styleDescriptions[baseIndex].getCHP();
+ if(parentCHP == null)
+ {
+ createChp(baseIndex);
+ parentCHP = _styleDescriptions[baseIndex].getCHP();
+ }
+
+ }
+
+ chp = (CHP)uncompressProperty(chpx, parentCHP, this);
+ sd.setCHP(chp);
+ }
+ }
+ public StyleDescription getStyleDescription(int x)
+ {
+ return _styleDescriptions[x];
+ }
+ static void doCHPOperation(CHP oldCHP, CHP newCHP, int operand, int param,
+ byte[] varParam, byte[] grpprl, int offset,
+ StyleSheet styleSheet)
+ {
+ switch(operand)
+ {
+ case 0:
+ newCHP._fRMarkDel = getFlag(param);
+ break;
+ case 0x1:
+ newCHP._fRMark = getFlag(param);
+ break;
+ case 0x2:
+ break;
+ case 0x3:
+ newCHP._fcPic = param;
+ newCHP._fSpec = true;
+ break;
+ case 0x4:
+ newCHP._ibstRMark = (short)param;
+ break;
+ case 0x5:
+ newCHP._dttmRMark[0] = Utils.convertBytesToShort(grpprl, (offset - 4));
+ newCHP._dttmRMark[1] = Utils.convertBytesToShort(grpprl, (offset - 2));
+ break;
+ case 0x6:
+ newCHP._fData = getFlag(param);
+ break;
+ case 0x7:
+ //don't care about this
+ break;
+ case 0x8:
+ short chsDiff = (short)((param & 0xff0000) >>> 8);
+ newCHP._fChsDiff = getFlag(chsDiff);
+ newCHP._chse = (short)(param & 0xffff);
+ break;
+ case 0x9:
+ newCHP._fSpec = true;
+ newCHP._ftcSym = (short)Utils.convertBytesToShort(varParam, 0);
+ newCHP._xchSym = (short)Utils.convertBytesToShort(varParam, 2);
+ break;
+ case 0xa:
+ newCHP._fOle2 = getFlag(param);
+ break;
+ case 0xb:
+ //?
+ break;
+ case 0xc:
+ newCHP._icoHighlight = (byte)param;
+ newCHP._highlighted = getFlag(param);
+ break;
+ case 0xd:
+ break;
+ case 0xe:
+ newCHP._fcObj = param;
+ break;
+ case 0xf:
+ break;
+ case 0x10:
+ //?
+ break;
+ case 0x11:
+ break;
+ case 0x12:
+ break;
+ case 0x13:
+ break;
+ case 0x14:
+ break;
+ case 0x15:
+ break;
+ case 0x16:
+ break;
+ case 0x17:
+ break;
+ case 0x18:
+ break;
+ case 0x19:
+ break;
+ case 0x1a:
+ break;
+ case 0x1b:
+ break;
+ case 0x1c:
+ break;
+ case 0x1d:
+ break;
+ case 0x1e:
+ break;
+ case 0x1f:
+ break;
+ case 0x20:
+ break;
+ case 0x21:
+ break;
+ case 0x22:
+ break;
+ case 0x23:
+ break;
+ case 0x24:
+ break;
+ case 0x25:
+ break;
+ case 0x26:
+ break;
+ case 0x27:
+ break;
+ case 0x28:
+ break;
+ case 0x29:
+ break;
+ case 0x2a:
+ break;
+ case 0x2b:
+ break;
+ case 0x2c:
+ break;
+ case 0x2d:
+ break;
+ case 0x2e:
+ break;
+ case 0x2f:
+ break;
+ case 0x30:
+ newCHP._istd = param;
+ break;
+ case 0x31:
+ //permutation vector for fast saves who cares!
+ break;
+ case 0x32:
+ newCHP._bold = false;
+ newCHP._italic = false;
+ newCHP._fOutline = false;
+ newCHP._fStrike = false;
+ newCHP._fShadow = false;
+ newCHP._fSmallCaps = false;
+ newCHP._fCaps = false;
+ newCHP._fVanish = false;
+ newCHP._kul = 0;
+ newCHP._ico = 0;
+ break;
+ case 0x33:
+ newCHP.copy(oldCHP);
+ return;
+ case 0x34:
+ break;
+ case 0x35:
+ newCHP._bold = getCHPFlag((byte)param, oldCHP._bold);
+ break;
+ case 0x36:
+ newCHP._italic = getCHPFlag((byte)param, oldCHP._italic);
+ break;
+ case 0x37:
+ newCHP._fStrike = getCHPFlag((byte)param, oldCHP._fStrike);
+ break;
+ case 0x38:
+ newCHP._fOutline = getCHPFlag((byte)param, oldCHP._fOutline);
+ break;
+ case 0x39:
+ newCHP._fShadow = getCHPFlag((byte)param, oldCHP._fShadow);
+ break;
+ case 0x3a:
+ newCHP._fSmallCaps = getCHPFlag((byte)param, oldCHP._fSmallCaps);
+ break;
+ case 0x3b:
+ newCHP._fCaps = getCHPFlag((byte)param, oldCHP._fCaps);
+ break;
+ case 0x3c:
+ newCHP._fVanish = getCHPFlag((byte)param, oldCHP._fVanish);
+ break;
+ case 0x3d:
+ newCHP._ftc = (short)param;
+ break;
+ case 0x3e:
+ newCHP._kul = (byte)param;
+ break;
+ case 0x3f:
+ int hps = param & 0xff;
+ if(hps != 0)
+ {
+ newCHP._hps = hps;
+ }
+ byte cInc = (byte)(((byte)(param & 0xfe00) >>> 4) >> 1);
+ if(cInc != 0)
+ {
+ newCHP._hps = Math.max(newCHP._hps + (cInc * 2), 2);
+ }
+ byte hpsPos = (byte)((param & 0xff0000) >>> 8);
+ if(hpsPos != 0x80)
+ {
+ newCHP._hpsPos = hpsPos;
+ }
+ boolean fAdjust = (param & 0x0100) > 0;
+ if(fAdjust && hpsPos != 128 && hpsPos != 0 && oldCHP._hpsPos == 0)
+ {
+ newCHP._hps = Math.max(newCHP._hps + (-2), 2);
+ }
+ if(fAdjust && hpsPos == 0 && oldCHP._hpsPos != 0)
+ {
+ newCHP._hps = Math.max(newCHP._hps + 2, 2);
+ }
+ break;
+ case 0x40:
+ newCHP._dxaSpace = param;
+ break;
+ case 0x41:
+ newCHP._lidDefault = (short)param;
+ break;
+ case 0x42:
+ newCHP._ico = (byte)param;
+ break;
+ case 0x43:
+ newCHP._hps = param;
+ break;
+ case 0x44:
+ byte hpsLvl = (byte)param;
+ newCHP._hps = Math.max(newCHP._hps + (hpsLvl * 2), 2);
+ break;
+ case 0x45:
+ newCHP._hpsPos = (short)param;
+ break;
+ case 0x46:
+ if(param != 0)
+ {
+ if(oldCHP._hpsPos == 0)
+ {
+ newCHP._hps = Math.max(newCHP._hps + (-2), 2);
+ }
+ }
+ else
+ {
+ if(oldCHP._hpsPos != 0)
+ {
+ newCHP._hps = Math.max(newCHP._hps + 2, 2);
+ }
+ }
+ break;
+ case 0x47:
+ CHP genCHP = new CHP();
+ genCHP._ftc = 4;
+ genCHP = (CHP)uncompressProperty(varParam, genCHP, styleSheet);
+ CHP styleCHP = styleSheet.getStyleDescription(oldCHP._baseIstd).getCHP();
+ if(genCHP._bold == newCHP._bold)
+ {
+ newCHP._bold = styleCHP._bold;
+ }
+ if(genCHP._italic == newCHP._italic)
+ {
+ newCHP._italic = styleCHP._italic;
+ }
+ if(genCHP._fSmallCaps == newCHP._fSmallCaps)
+ {
+ newCHP._fSmallCaps = styleCHP._fSmallCaps;
+ }
+ if(genCHP._fVanish == newCHP._fVanish)
+ {
+ newCHP._fVanish = styleCHP._fVanish;
+ }
+ if(genCHP._fStrike == newCHP._fStrike)
+ {
+ newCHP._fStrike = styleCHP._fStrike;
+ }
+ if(genCHP._fCaps == newCHP._fCaps)
+ {
+ newCHP._fCaps = styleCHP._fCaps;
+ }
+ if(genCHP._ftcAscii == newCHP._ftcAscii)
+ {
+ newCHP._ftcAscii = styleCHP._ftcAscii;
+ }
+ if(genCHP._ftcFE == newCHP._ftcFE)
+ {
+ newCHP._ftcFE = styleCHP._ftcFE;
+ }
+ if(genCHP._ftcOther == newCHP._ftcOther)
+ {
+ newCHP._ftcOther = styleCHP._ftcOther;
+ }
+ if(genCHP._hps == newCHP._hps)
+ {
+ newCHP._hps = styleCHP._hps;
+ }
+ if(genCHP._hpsPos == newCHP._hpsPos)
+ {
+ newCHP._hpsPos = styleCHP._hpsPos;
+ }
+ if(genCHP._kul == newCHP._kul)
+ {
+ newCHP._kul = styleCHP._kul;
+ }
+ if(genCHP._dxaSpace == newCHP._dxaSpace)
+ {
+ newCHP._dxaSpace = styleCHP._dxaSpace;
+ }
+ if(genCHP._ico == newCHP._ico)
+ {
+ newCHP._ico = styleCHP._ico;
+ }
+ if(genCHP._lidDefault == newCHP._lidDefault)
+ {
+ newCHP._lidDefault = styleCHP._lidDefault;
+ }
+ if(genCHP._lidFE == newCHP._lidFE)
+ {
+ newCHP._lidFE = styleCHP._lidFE;
+ }
+ break;
+ case 0x48:
+ newCHP._iss = (byte)param;
+ break;
+ case 0x49:
+ newCHP._hps = Utils.convertBytesToShort(varParam, 0);
+ break;
+ case 0x4a:
+ int increment = Utils.convertBytesToShort(varParam, 0);
+ newCHP._hps = Math.max(newCHP._hps + increment, 8);
+ break;
+ case 0x4b:
+ newCHP._hpsKern = param;
+ break;
+ case 0x4c:
+ doCHPOperation(oldCHP, newCHP, 0x47, param, varParam, grpprl, offset, styleSheet);
+ break;
+ case 0x4d:
+ float percentage = (float)param/100.0f;
+ int add = (int)((float)percentage * (float)newCHP._hps);
+ newCHP._hps += add;
+ break;
+ case 0x4e:
+ newCHP._ysr = (byte)param;
+ break;
+ case 0x4f:
+ newCHP._ftcAscii = (short)param;
+ break;
+ case 0x50:
+ newCHP._ftcFE = (short)param;
+ break;
+ case 0x51:
+ newCHP._ftcOther = (short)param;
+ break;
+ case 0x52:
+ break;
+ case 0x53:
+ newCHP._fDStrike = getFlag(param);
+ break;
+ case 0x54:
+ newCHP._fImprint = getFlag(param);
+ break;
+ case 0x55:
+ newCHP._fSpec = getFlag(param);
+ break;
+ case 0x56:
+ newCHP._fObj = getFlag(param);
+ break;
+ case 0x57:
+ newCHP._fPropMark = getFlag(varParam[0]);
+ newCHP._ibstPropRMark = (short)Utils.convertBytesToShort(varParam, 1);
+ newCHP._dttmPropRMark = Utils.convertBytesToInt(varParam, 3);
+ break;
+ case 0x58:
+ newCHP._fEmboss = getFlag(param);
+ break;
+ case 0x59:
+ newCHP._sfxtText = (byte)param;
+ break;
+ case 0x5a:
+ break;
+ case 0x5b:
+ break;
+ case 0x5c:
+ break;
+ case 0x5d:
+ break;
+ case 0x5e:
+ break;
+ case 0x5f:
+ break;
+ case 0x60:
+ break;
+ case 0x61:
+ break;
+ case 0x62:
+ newCHP._fDispFldRMark = getFlag(varParam[0]);
+ newCHP._ibstDispFldRMark = (short)Utils.convertBytesToShort(varParam, 1);
+ newCHP._dttmDispFldRMark = Utils.convertBytesToInt(varParam, 3);
+ System.arraycopy(varParam, 7, newCHP._xstDispFldRMark, 0, 32);
+ break;
+ case 0x63:
+ newCHP._ibstRMarkDel = (short)param;
+ break;
+ case 0x64:
+ newCHP._dttmRMarkDel[0] = Utils.convertBytesToShort(grpprl, offset - 4);
+ newCHP._dttmRMarkDel[1] = Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x65:
+ newCHP._brc[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newCHP._brc[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x66:
+ newCHP._shd = (short)param;
+ break;
+ case 0x67:
+ break;
+ case 0x68:
+ break;
+ case 0x69:
+ break;
+ case 0x6a:
+ break;
+ case 0x6b:
+ break;
+ case 0x6c:
+ break;
+ case 0x6d:
+ newCHP._lidDefault = (short)param;
+ break;
+ case 0x6e:
+ newCHP._lidFE = (short)param;
+ break;
+ case 0x6f:
+ newCHP._idctHint = (byte)param;
+ break;
+ }
+ }
+
+ static Object uncompressProperty(byte[] grpprl, Object parent, StyleSheet styleSheet)
+ {
+ return uncompressProperty(grpprl, parent, styleSheet, true);
+ }
+
+
+ static Object uncompressProperty(byte[] grpprl, Object parent, StyleSheet styleSheet, boolean doIstd)
+ {
+ Object newProperty = null;
+ int offset = 0;
+ int propertyType = PAP_TYPE;
+
+
+ if(parent instanceof PAP)
+ {
+ try
+ {
+ newProperty = ((PAP)parent).clone();
+ }
+ catch(Exception e){}
+ if(doIstd)
+ {
+ ((PAP)newProperty)._istd = Utils.convertBytesToShort(grpprl, 0);
+
+ offset = 2;
+ }
+ }
+ else if(parent instanceof CHP)
+ {
+ try
+ {
+ newProperty = ((CHP)parent).clone();
+ ((CHP)newProperty)._baseIstd = ((CHP)parent)._istd;
+ }
+ catch(Exception e){}
+ propertyType = CHP_TYPE;
+ }
+ else if(parent instanceof SEP)
+ {
+ newProperty = parent;
+ propertyType = SEP_TYPE;
+ }
+ else if(parent instanceof TAP)
+ {
+ newProperty = parent;
+ propertyType = TAP_TYPE;
+ offset = 2;//because this is really just a papx
+ }
+ else
+ {
+ return null;
+ }
+
+ while(offset < grpprl.length)
+ {
+ short sprm = Utils.convertBytesToShort(grpprl, offset);
+ offset += 2;
+
+ byte spra = (byte)((sprm & 0xe000) >> 13);
+ int opSize = 0;
+ int param = 0;
+ byte[] varParam = null;
+
+ switch(spra)
+ {
+ case 0:
+ case 1:
+ opSize = 1;
+ param = grpprl[offset];
+ break;
+ case 2:
+ opSize = 2;
+ param = Utils.convertBytesToShort(grpprl, offset);
+ break;
+ case 3:
+ opSize = 4;
+ param = Utils.convertBytesToInt(grpprl, offset);
+ break;
+ case 4:
+ case 5:
+ opSize = 2;
+ param = Utils.convertBytesToShort(grpprl, offset);
+ break;
+ case 6://variable size
+
+ //there is one sprm that is a very special case
+ if(sprm != (short)0xd608)
+ {
+ opSize = Utils.convertUnsignedByteToInt(grpprl[offset]);
+ offset++;
+ }
+ else
+ {
+ opSize = Utils.convertBytesToShort(grpprl, offset) - 1;
+ offset += 2;
+ }
+ varParam = new byte[opSize];
+ System.arraycopy(grpprl, offset, varParam, 0, opSize);
+
+ break;
+ case 7:
+ opSize = 3;
+ param = Utils.convertBytesToInt((byte)0, grpprl[offset + 2], grpprl[offset + 1], grpprl[offset]);
+ break;
+ default:
+ throw new RuntimeException("unrecognized pap opcode");
+ }
+
+ offset += opSize;
+ short operand = (short)(sprm & 0x1ff);
+ byte type = (byte)((sprm & 0x1c00) >> 10);
+ switch(propertyType)
+ {
+ case PAP_TYPE:
+ if(type == 1)//papx stores TAP sprms along with PAP sprms
+ {
+ doPAPOperation((PAP)newProperty, operand, param, varParam, grpprl,
+ offset, spra);
+ }
+ break;
+ case CHP_TYPE:
+
+ doCHPOperation((CHP)parent, (CHP)newProperty, operand, param, varParam,
+ grpprl, offset, styleSheet);
+ break;
+ case SEP_TYPE:
+
+ doSEPOperation((SEP)newProperty, operand, param, varParam);
+ break;
+ case TAP_TYPE:
+ if(type == 5)
+ {
+ doTAPOperation((TAP)newProperty, operand, param, varParam);
+ }
+ break;
+ }
+
+
+ }
+ return newProperty;
+
+ }
+ static void doPAPOperation(PAP newPAP, int operand, int param,
+ byte[] varParam, byte[] grpprl, int offset,
+ int spra)
+ {
+ switch(operand)
+ {
+ case 0:
+ newPAP._istd = param;
+ break;
+ case 0x1:
+ //permuteIstd(newPAP, varParam);
+ break;
+ case 0x2:
+ if(newPAP._istd <=9 || newPAP._istd >=1)
+ {
+ newPAP._istd += param;
+ if(param > 0)
+ {
+ newPAP._istd = Math.max(newPAP._istd, 9);
+ }
+ else
+ {
+ newPAP._istd = Math.min(newPAP._istd, 1);
+ }
+ }
+ break;
+ case 0x3:
+ newPAP._jc = (byte)param;
+ break;
+ case 0x4:
+ newPAP._fSideBySide = (byte)param;
+ break;
+ case 0x5:
+ newPAP._fKeep = (byte)param;
+ break;
+ case 0x6:
+ newPAP._fKeepFollow = (byte)param;
+ break;
+ case 0x7:
+ newPAP._fPageBreakBefore = (byte)param;
+ break;
+ case 0x8:
+ newPAP._brcl = (byte)param;
+ break;
+ case 0x9:
+ newPAP._brcp = (byte)param;
+ break;
+ case 0xa:
+ newPAP._ilvl = (byte)param;
+ break;
+ case 0xb:
+ newPAP._ilfo = param;
+ break;
+ case 0xc:
+ newPAP._fNoLnn = (byte)param;
+ break;
+ case 0xd:
+ /**@todo handle tabs*/
+ break;
+ case 0xe:
+ newPAP._dxaRight = param;
+ break;
+ case 0xf:
+ newPAP._dxaLeft = param;
+ break;
+ case 0x10:
+ newPAP._dxaLeft += param;
+ newPAP._dxaLeft = Math.max(0, newPAP._dxaLeft);
+ break;
+ case 0x11:
+ newPAP._dxaLeft1 = param;
+ break;
+ case 0x12:
+ newPAP._lspd[0] = Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._lspd[1] = Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x13:
+ newPAP._dyaBefore = param;
+ break;
+ case 0x14:
+ newPAP._dyaAfter = param;
+ break;
+ case 0x15:
+ /**@todo handle tabs*/
+ break;
+ case 0x16:
+ newPAP._fInTable = (byte)param;
+ break;
+ case 0x17:
+ newPAP._fTtp =(byte)param;
+ break;
+ case 0x18:
+ newPAP._dxaAbs = param;
+ break;
+ case 0x19:
+ newPAP._dyaAbs = param;
+ break;
+ case 0x1a:
+ newPAP._dxaWidth = param;
+ break;
+ case 0x1b:
+ /** @todo handle paragraph postioning*/
+ /*byte pcVert = (param & 0x0c) >> 2;
+ byte pcHorz = param & 0x03;
+ if(pcVert != 3)
+ {
+ newPAP._pcVert = pcVert;
+ }
+ if(pcHorz != 3)
+ {
+ newPAP._pcHorz = pcHorz;
+ }*/
+ break;
+ case 0x1c:
+ newPAP._brcTop1 = (short)param;
+ break;
+ case 0x1d:
+ newPAP._brcLeft1 = (short)param;
+ break;
+ case 0x1e:
+ newPAP._brcBottom1 = (short)param;
+ break;
+ case 0x1f:
+ newPAP._brcRight1 = (short)param;
+ break;
+ case 0x20:
+ newPAP._brcBetween1 = (short)param;
+ break;
+ case 0x21:
+ newPAP._brcBar1 = (byte)param;
+ break;
+ case 0x22:
+ newPAP._dxaFromText = param;
+ break;
+ case 0x23:
+ newPAP._wr = (byte)param;
+ break;
+ case 0x24:
+ newPAP._brcTop[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcTop[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x25:
+ newPAP._brcLeft[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcLeft[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x26:
+ newPAP._brcBottom[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcBottom[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x27:
+ newPAP._brcRight[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcRight[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x28:
+ newPAP._brcBetween[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcBetween[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x29:
+ newPAP._brcBar[0] = (short)Utils.convertBytesToShort(grpprl, offset - 4);
+ newPAP._brcBar[1] = (short)Utils.convertBytesToShort(grpprl, offset - 2);
+ break;
+ case 0x2a:
+ newPAP._fNoAutoHyph = (byte)param;
+ break;
+ case 0x2b:
+ newPAP._dyaHeight = param;
+ break;
+ case 0x2c:
+ newPAP._dcs = param;
+ break;
+ case 0x2d:
+ newPAP._shd = param;
+ break;
+ case 0x2e:
+ newPAP._dyaFromText = param;
+ break;
+ case 0x2f:
+ newPAP._dxaFromText = param;
+ break;
+ case 0x30:
+ newPAP._fLocked = (byte)param;
+ break;
+ case 0x31:
+ newPAP._fWindowControl = (byte)param;
+ break;
+ case 0x32:
+ //undocumented
+ break;
+ case 0x33:
+ newPAP._fKinsoku = (byte)param;
+ break;
+ case 0x34:
+ newPAP._fWordWrap = (byte)param;
+ break;
+ case 0x35:
+ newPAP._fOverflowPunct = (byte)param;
+ break;
+ case 0x36:
+ newPAP._fTopLinePunct = (byte)param;
+ break;
+ case 0x37:
+ newPAP._fAutoSpaceDE = (byte)param;
+ break;
+ case 0x38:
+ newPAP._fAutoSpaceDN = (byte)param;
+ break;
+ case 0x39:
+ newPAP._wAlignFont = param;
+ break;
+ case 0x3a:
+ newPAP._fontAlign = (short)param;
+ break;
+ case 0x3b:
+ //obsolete
+ break;
+ case 0x3e:
+ newPAP._anld = varParam;
+ break;
+ case 0x3f:
+ //don't really need this. spec is confusing regarding this
+ //sprm
+ break;
+ case 0x40:
+ //newPAP._lvl = param;
+ break;
+ case 0x41:
+ //?
+ break;
+ case 0x43:
+ //?
+ break;
+ case 0x44:
+ //?
+ break;
+ case 0x45:
+ if(spra == 6)
+ {
+ newPAP._numrm = varParam;
+ }
+ else
+ {
+ /**@todo handle large PAPX from data stream*/
+ }
+ break;
+
+ case 0x47:
+ newPAP._fUsePgsuSettings = (byte)param;
+ break;
+ case 0x48:
+ newPAP._fAdjustRight = (byte)param;
+ break;
+ default:
+ break;
+ }
+ }
+ static void doTAPOperation(TAP newTAP, int operand, int param, byte[] varParam)
+ {
+ switch(operand)
+ {
+ case 0:
+ newTAP._jc = (short)param;
+ break;
+ case 0x01:
+ {
+ int adjust = param - (newTAP._rgdxaCenter[0] + newTAP._dxaGapHalf);
+ for(int x = 0; x < newTAP._itcMac; x++)
+ {
+ newTAP._rgdxaCenter[x] += adjust;
+ }
+ break;
+ }
+ case 0x02:
+ if(newTAP._rgdxaCenter != null)
+ {
+ int adjust = newTAP._dxaGapHalf - param;
+ newTAP._rgdxaCenter[0] += adjust;
+ }
+ newTAP._dxaGapHalf = param;
+ break;
+ case 0x03:
+ newTAP._fCantSplit = getFlag(param);
+ break;
+ case 0x04:
+ newTAP._fTableHeader = getFlag(param);
+ break;
+ case 0x05:
+
+ newTAP._brcTop[0] = Utils.convertBytesToShort(varParam, 0);
+ newTAP._brcTop[1] = Utils.convertBytesToShort(varParam, 2);
+
+ newTAP._brcLeft[0] = Utils.convertBytesToShort(varParam, 4);
+ newTAP._brcLeft[1] = Utils.convertBytesToShort(varParam, 6);
+
+ newTAP._brcBottom[0] = Utils.convertBytesToShort(varParam, 8);
+ newTAP._brcBottom[1] = Utils.convertBytesToShort(varParam, 10);
+
+ newTAP._brcRight[0] = Utils.convertBytesToShort(varParam, 12);
+ newTAP._brcRight[1] = Utils.convertBytesToShort(varParam, 14);
+
+ newTAP._brcHorizontal[0] = Utils.convertBytesToShort(varParam, 16);
+ newTAP._brcHorizontal[1] = Utils.convertBytesToShort(varParam, 18);
+
+ newTAP._brcVertical[0] = Utils.convertBytesToShort(varParam, 20);
+ newTAP._brcVertical[1] = Utils.convertBytesToShort(varParam, 22);
+ break;
+ case 0x06:
+ //obsolete, used in word 1.x
+ break;
+ case 0x07:
+ newTAP._dyaRowHeight = param;
+ break;
+ case 0x08:
+ //I use varParam[0] and newTAP._itcMac interchangably
+ newTAP._itcMac = varParam[0];
+ newTAP._rgdxaCenter = new short[varParam[0] + 1];
+ newTAP._rgtc = new TC[varParam[0]];
+
+ for(int x = 0; x < newTAP._itcMac; x++)
+ {
+ newTAP._rgdxaCenter[x] = Utils.convertBytesToShort(varParam , 1 + (x * 2));
+ newTAP._rgtc[x] = TC.convertBytesToTC(varParam, 1 + ((varParam[0] + 1) * 2) + (x * 20));
+ }
+ newTAP._rgdxaCenter[newTAP._itcMac] = Utils.convertBytesToShort(varParam , 1 + (newTAP._itcMac * 2));
+ break;
+ case 0x09:
+ /** @todo handle cell shading*/
+ break;
+ case 0x0a:
+ /** @todo handle word defined table styles*/
+ break;
+ case 0x20:
+ for(int x = varParam[0]; x < varParam[1]; x++)
+ {
+ if((varParam[2] & 0x08) > 0)
+ {
+ newTAP._rgtc[x]._brcRight[0] = Utils.convertBytesToShort(varParam, 6);
+ newTAP._rgtc[x]._brcRight[1] = Utils.convertBytesToShort(varParam, 8);
+ }
+ else if((varParam[2] & 0x04) > 0)
+ {
+ newTAP._rgtc[x]._brcBottom[0] = Utils.convertBytesToShort(varParam, 6);
+ newTAP._rgtc[x]._brcBottom[1] = Utils.convertBytesToShort(varParam, 8);
+ }
+ else if((varParam[2] & 0x02) > 0)
+ {
+ newTAP._rgtc[x]._brcLeft[0] = Utils.convertBytesToShort(varParam, 6);
+ newTAP._rgtc[x]._brcLeft[1] = Utils.convertBytesToShort(varParam, 8);
+ }
+ else if((varParam[2] & 0x01) > 0)
+ {
+ newTAP._rgtc[x]._brcTop[0] = Utils.convertBytesToShort(varParam, 6);
+ newTAP._rgtc[x]._brcTop[1] = Utils.convertBytesToShort(varParam, 8);
+ }
+ }
+ break;
+ case 0x21:
+ int index = (param & 0xff000000) >> 24;
+ int count = (param & 0x00ff0000) >> 16;
+ int width = (param & 0x0000ffff);
+
+ short[] rgdxaCenter = new short[newTAP._itcMac + count + 1];
+ TC[] rgtc = new TC[newTAP._itcMac + count];
+ if(index >= newTAP._itcMac)
+ {
+ index = newTAP._itcMac;
+ System.arraycopy(newTAP._rgdxaCenter, 0, rgdxaCenter, 0, newTAP._itcMac + 1);
+ System.arraycopy(newTAP._rgtc, 0, rgtc, 0, newTAP._itcMac);
+ }
+ else
+ {
+ //copy rgdxaCenter
+ System.arraycopy(newTAP._rgdxaCenter, 0, rgdxaCenter, 0, index + 1);
+ System.arraycopy(newTAP._rgdxaCenter, index + 1, rgdxaCenter, index + count, (newTAP._itcMac) - (index));
+ //copy rgtc
+ System.arraycopy(newTAP._rgtc, 0, rgtc, 0, index);
+ System.arraycopy(newTAP._rgtc, index, rgtc, index + count, newTAP._itcMac - index);
+ }
+
+ for(int x = index; x < index + count; x++)
+ {
+ rgtc[x] = new TC();
+ rgdxaCenter[x] = (short)(rgdxaCenter[x-1] + width);
+ }
+ rgdxaCenter[index + count] = (short)(rgdxaCenter[(index + count)-1] + width);
+ break;
+ /**@todo handle table sprms from complex files*/
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ break;
+ default:
+ break;
+ }
+ }
+ static void doSEPOperation(SEP newSEP, int operand, int param, byte[] varParam)
+ {
+ switch(operand)
+ {
+ case 0:
+ newSEP._cnsPgn = (byte)param;
+ break;
+ case 0x1:
+ newSEP._iHeadingPgn = (byte)param;
+ break;
+ case 0x2:
+ newSEP._olstAnn = varParam;
+ break;
+ case 0x3:
+ //not quite sure
+ break;
+ case 0x4:
+ //not quite sure
+ break;
+ case 0x5:
+ newSEP._fEvenlySpaced = getFlag(param);
+ break;
+ case 0x6:
+ newSEP._fUnlocked = getFlag(param);
+ break;
+ case 0x7:
+ newSEP._dmBinFirst = (short)param;
+ break;
+ case 0x8:
+ newSEP._dmBinOther = (short)param;
+ break;
+ case 0x9:
+ newSEP._bkc = (byte)param;
+ break;
+ case 0xa:
+ newSEP._fTitlePage = getFlag(param);
+ break;
+ case 0xb:
+ newSEP._ccolM1 = (short)param;
+ break;
+ case 0xc:
+ newSEP._dxaColumns = param;
+ break;
+ case 0xd:
+ newSEP._fAutoPgn = getFlag(param);
+ break;
+ case 0xe:
+ newSEP._nfcPgn = (byte)param;
+ break;
+ case 0xf:
+ newSEP._dyaPgn = (short)param;
+ break;
+ case 0x10:
+ newSEP._dxaPgn = (short)param;
+ break;
+ case 0x11:
+ newSEP._fPgnRestart = getFlag(param);
+ break;
+ case 0x12:
+ newSEP._fEndNote = getFlag(param);
+ break;
+ case 0x13:
+ newSEP._lnc = (byte)param;
+ break;
+ case 0x14:
+ newSEP._grpfIhdt = (byte)param;
+ break;
+ case 0x15:
+ newSEP._nLnnMod = (short)param;
+ break;
+ case 0x16:
+ newSEP._dxaLnn = param;
+ break;
+ case 0x17:
+ newSEP._dyaHdrTop = param;
+ break;
+ case 0x18:
+ newSEP._dyaHdrBottom = param;
+ break;
+ case 0x19:
+ newSEP._fLBetween = getFlag(param);
+ break;
+ case 0x1a:
+ newSEP._vjc = (byte)param;
+ break;
+ case 0x1b:
+ newSEP._lnnMin = (short)param;
+ break;
+ case 0x1c:
+ newSEP._pgnStart = (short)param;
+ break;
+ case 0x1d:
+ newSEP._dmOrientPage = (byte)param;
+ break;
+ case 0x1e:
+ //nothing
+ break;
+ case 0x1f:
+ newSEP._xaPage = param;
+ break;
+ case 0x20:
+ newSEP._yaPage = param;
+ break;
+ case 0x21:
+ newSEP._dxaLeft = param;
+ break;
+ case 0x22:
+ newSEP._dxaRight = param;
+ break;
+ case 0x23:
+ newSEP._dyaTop = param;
+ break;
+ case 0x24:
+ newSEP._dyaBottom = param;
+ break;
+ case 0x25:
+ newSEP._dzaGutter = param;
+ break;
+ case 0x26:
+ newSEP._dmPaperReq = (short)param;
+ break;
+ case 0x27:
+ newSEP._fPropMark = getFlag(varParam[0]);
+ break;
+ case 0x28:
+ break;
+ case 0x29:
+ break;
+ case 0x2a:
+ break;
+ case 0x2b:
+ newSEP._brcTop[0] = (short)(param & 0xffff);
+ newSEP._brcTop[1] = (short)((param & 0xffff0000) >> 16);
+ break;
+ case 0x2c:
+ newSEP._brcLeft[0] = (short)(param & 0xffff);
+ newSEP._brcLeft[1] = (short)((param & 0xffff0000) >> 16);
+ break;
+ case 0x2d:
+ newSEP._brcBottom[0] = (short)(param & 0xffff);
+ newSEP._brcBottom[1] = (short)((param & 0xffff0000) >> 16);
+ break;
+ case 0x2e:
+ newSEP._brcRight[0] = (short)(param & 0xffff);
+ newSEP._brcRight[1] = (short)((param & 0xffff0000) >> 16);
+ break;
+ case 0x2f:
+ newSEP._pgbProp = (short)param;
+ break;
+ case 0x30:
+ newSEP._dxtCharSpace = param;
+ break;
+ case 0x31:
+ newSEP._dyaLinePitch = param;
+ break;
+ case 0x33:
+ newSEP._wTextFlow = (short)param;
+ break;
+ default:
+ break;
+ }
+
+ }
+ private static boolean getCHPFlag(byte x, boolean oldVal)
+ {
+ switch(x)
+ {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ case (byte)0x80:
+ return oldVal;
+ case (byte)0x81:
+ return !oldVal;
+ default:
+ return false;
+ }
+ }
+ public static boolean getFlag(int x)
+ {
+ if(x != 0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class TAP
+{
+ short _jc;
+ int _dxaGapHalf;
+ int _dyaRowHeight;
+ boolean _fCantSplit;
+ boolean _fTableHeader;
+ boolean _fLastRow;
+ short _itcMac;
+ short[] _rgdxaCenter;
+ short[] _brcLeft = new short[2];
+ short[] _brcRight = new short[2];
+ short[] _brcTop = new short[2];
+ short[] _brcBottom = new short[2];
+ short[] _brcHorizontal = new short[2];
+ short[] _brcVertical = new short[2];
+
+ TC[] _rgtc;
+
+
+ public TAP()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class TC
+{
+
+ boolean _fFirstMerged;
+ boolean _fMerged;
+ boolean _fVertical;
+ boolean _fBackward;
+ boolean _fRotateFont;
+ boolean _fVertMerge;
+ boolean _fVertRestart;
+ short _vertAlign;
+ short[] _brcTop = new short[2];
+ short[] _brcLeft = new short[2];
+ short[] _brcBottom = new short[2];
+ short[] _brcRight = new short [2];
+
+ public TC()
+ {
+ }
+ static TC convertBytesToTC(byte[] array, int offset)
+ {
+ TC tc = new TC();
+ int rgf = Utils.convertBytesToShort(array, offset);
+ tc._fFirstMerged = (rgf & 0x0001) > 0;
+ tc._fMerged = (rgf & 0x0002) > 0;
+ tc._fVertical = (rgf & 0x0004) > 0;
+ tc._fBackward = (rgf & 0x0008) > 0;
+ tc._fRotateFont = (rgf & 0x0010) > 0;
+ tc._fVertMerge = (rgf & 0x0020) > 0;
+ tc._fVertRestart = (rgf & 0x0040) > 0;
+ tc._vertAlign = (short)((rgf & 0x0180) >> 7);
+
+ tc._brcTop[0] = Utils.convertBytesToShort(array, offset + 4);
+ tc._brcTop[1] = Utils.convertBytesToShort(array, offset + 6);
+
+ tc._brcLeft[0] = Utils.convertBytesToShort(array, offset + 8);
+ tc._brcLeft[1] = Utils.convertBytesToShort(array, offset + 10);
+
+ tc._brcBottom[0] = Utils.convertBytesToShort(array, offset + 12);
+ tc._brcBottom[1] = Utils.convertBytesToShort(array, offset + 14);
+
+ tc._brcRight[0] = Utils.convertBytesToShort(array, offset + 16);
+ tc._brcRight[1] = Utils.convertBytesToShort(array, offset + 18);
+
+ return tc;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+import java.util.*;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class TableRow
+{
+ TAP _descriptor;
+ Vector _cells;
+
+ public TableRow(Vector cells, TAP descriptor)
+ {
+ _cells = cells;
+ _descriptor = descriptor;
+ }
+ public TAP getTAP()
+ {
+ return _descriptor;
+ }
+ public Vector getCells()
+ {
+ return _cells;
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.poi.hdf.extractor;
+
+import org.apache.poi.hdf.extractor.util.*;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class TextPiece extends PropertyNode implements Comparable
+{
+ private boolean _usesUnicode;
+ private int _length;
+
+ public TextPiece(int start, int length, boolean unicode)
+ {
+ super(start, start + length, null);
+ _usesUnicode = unicode;
+ _length = length;
+ //_fcStart = start;
+ //_fcEnd = start + length;
+
+ }
+ public boolean usesUnicode()
+ {
+ return _usesUnicode;
+ }
+
+ public int compareTo(Object obj) {
+ return 0;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class Utils
+{
+
+ public static short convertBytesToShort(byte firstByte, byte secondByte)
+ {
+ return (short)convertBytesToInt((byte)0, (byte)0, firstByte, secondByte);
+ }
+ public static int convertBytesToInt(byte firstByte, byte secondByte,
+ byte thirdByte, byte fourthByte)
+ {
+ int firstInt = 0xff & firstByte;
+ int secondInt = 0xff & secondByte;
+ int thirdInt = 0xff & thirdByte;
+ int fourthInt = 0xff & fourthByte;
+
+ return (firstInt << 24) | (secondInt << 16) | (thirdInt << 8) | fourthInt;
+ }
+ public static short convertBytesToShort(byte[] array, int offset)
+ {
+ return convertBytesToShort(array[offset + 1], array[offset]);
+ }
+ public static int convertBytesToInt(byte[] array, int offset)
+ {
+ return convertBytesToInt(array[offset + 3], array[offset + 2], array[offset + 1], array[offset]);
+ }
+ public static int convertUnsignedByteToInt(byte b)
+ {
+ return (0xff & b);
+ }
+ public static char getUnicodeCharacter(byte[] array, int offset)
+ {
+ return (char)convertBytesToShort(array, offset);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor;
+
+import org.apache.poi.hdf.extractor.util.*;
+import org.apache.poi.hdf.extractor.data.*;
+import java.util.*;
+import java.io.*;
+import javax.swing.*;
+//import javax.swing.text.StyleContext;
+import java.awt.*;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class WordDocument extends NewOleFile
+{
+ byte[] _header;
+
+ StyleSheet _styleSheet;
+ ListTables _listTables;
+ DOP _docProps = new DOP();
+ int _currentList = -1;
+ int _tableSize;
+ int _sectionCounter = 1;
+ FontTable _fonts;
+
+ BTreeSet _text = new BTreeSet();
+ BTreeSet _characterTable = new BTreeSet();
+ BTreeSet _paragraphTable = new BTreeSet();
+ BTreeSet _sectionTable = new BTreeSet();
+
+ //WordDocWriter _writer = this;
+ StringBuffer _headerBuffer = new StringBuffer();
+ StringBuffer _bodyBuffer = new StringBuffer();
+ StringBuffer _cellBuffer;
+
+ Vector _cells;
+ Vector _table;
+
+ byte[] _plcfHdd;
+ int _fcMin;
+ int _ccpText;
+ int _ccpFtn;
+
+
+ private static int HEADER_EVEN_INDEX = 0;
+ private static int HEADER_ODD_INDEX = 1;
+ private static int FOOTER_EVEN_INDEX = 2;
+ private static int FOOTER_ODD_INDEX = 3;
+ private static int HEADER_FIRST_INDEX = 4;
+ private static int FOOTER_FIRST_INDEX = 5;
+
+
+ public static void main(String args[])
+ {
+ /*try
+ {
+ WordDocument file = new WordDocument(args[0], "r");
+ Writer out = new BufferedWriter(new FileWriter(args[1]));
+ file.writeAllText(out);
+ out.flush();
+ out.close();
+ }
+ catch(Throwable t)
+ {
+ t.printStackTrace();
+ }*/
+ try
+ {
+ WordDocument file = new WordDocument(args[0], "r");
+ file.closeDoc();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ System.exit(0);
+ }
+ public void writeAllText(Writer out) throws IOException
+ {
+ int textStart = Utils.convertBytesToInt(_header, 0x18);
+ int textEnd = Utils.convertBytesToInt(_header, 0x1c);
+ Vector textPieces = findProperties(textStart, textEnd, _text.root);
+ int size = textPieces.size();
+
+ for(int x = 0; x < size; x++)
+ {
+ TextPiece nextPiece = (TextPiece)textPieces.get(x);
+ int start = nextPiece.getStart();
+ int end = nextPiece.getEnd();
+ boolean unicode = nextPiece.usesUnicode();
+ int add = 1;
+
+ if(unicode)
+ {
+ add = 2;
+ }
+ char ch;
+ for(int y = start; y < end; y += add)
+ {
+ if(unicode)
+ {
+ ch = (char)Utils.convertBytesToShort(_header, y);
+ }
+ else
+ {
+ ch = (char)_header[y];
+ }
+ out.write(ch);
+ }
+ }
+ }
+ public WordDocument(String fileName, String mode) throws IOException
+ {
+ super(fileName, mode);
+
+ readFIB();
+
+ Vector sections = findProperties(_fcMin, _fcMin + _ccpText, _sectionTable.root);
+
+ int size = sections.size();
+ for(int x = 0; x < size; x++)
+ {
+ SepxNode node = (SepxNode)sections.get(x);
+ int start = node.getStart();
+ int end = node.getEnd();
+ SEP sep = (SEP)StyleSheet.uncompressProperty(node.getSepx(), new SEP(), _styleSheet);
+ writeSection(Math.max(_fcMin, start), Math.min(_fcMin + _ccpText, end), sep, _text, _paragraphTable, _characterTable, _styleSheet);
+ }
+
+ }
+ private void readFIB() throws IOException
+ {
+ PropertySet headerProps = (PropertySet)_propertySetsHT.get("WordDocument");
+
+ if(headerProps.getSize() >= 4096)
+ {
+ _header = createBufferFromBBD(headerProps.getStartBlock());
+ }
+ int info = Utils.convertBytesToShort(_header, 0xa);
+
+ _fcMin = Utils.convertBytesToInt(_header, 0x18);
+ _ccpText = Utils.convertBytesToInt(_header, 0x4c);
+ _ccpFtn = Utils.convertBytesToInt(_header, 0x50);
+
+ int charPLC = Utils.convertBytesToInt(_header, 0xfa);
+ int charPlcSize = Utils.convertBytesToInt(_header, 0xfe);
+ int parPLC = Utils.convertBytesToInt(_header, 0x102);
+ int parPlcSize = Utils.convertBytesToInt(_header, 0x106);
+ boolean useTable1 = (info & 0x200) != 0;
+
+ processComplexFile(useTable1, charPLC, charPlcSize, parPLC, parPlcSize);
+ }
+
+ private boolean processComplexFile(boolean useTable1, int charTable,
+ int charPlcSize, int parTable, int parPlcSize) throws IOException
+ {
+ int complexOffset = Utils.convertBytesToInt(_header, 0x1a2);
+ //int complexSize = Utils.convertBytesToInt(_header, 0x1a6);
+
+ //if(complexSize <= 0)
+ //{
+ // return false;
+ //}
+
+ PropertySet tableProps = null;
+ if(useTable1)
+ {
+ tableProps = (PropertySet)_propertySetsHT.get("1Table");
+ }
+ else
+ {
+ tableProps = (PropertySet)_propertySetsHT.get("0Table");
+ }
+ //get table properties
+ int size = tableProps.getSize();
+ int startBlock = tableProps.getStartBlock();
+
+ byte[] tableStream = null;
+ //big enough to use BBD?
+ if(size >= 4096)
+ {
+ tableStream = createBufferFromBBD(startBlock);
+ }
+ initDocProperties(tableStream);
+ initPclfHdd(tableStream);
+ findText(tableStream, complexOffset);
+ findFormatting(tableStream, charTable, charPlcSize, parTable, parPlcSize);
+
+ return true;
+
+ }
+ private void findText(byte[] tableStream, int complexOffset) throws IOException
+ {
+ //actual text
+ int pos = complexOffset;
+ while(tableStream[pos] == 1)
+ {
+ pos++;
+ int skip = Utils.convertBytesToShort(tableStream, pos);
+ pos += 2 + skip;
+ }
+ if(tableStream[pos] != 2)
+ {
+ throw new IOException("corrupted Word file");
+ }
+ else
+ {
+ int pieceTableSize = Utils.convertBytesToInt(tableStream, ++pos);
+ pos += 4;
+ int pieces = (pieceTableSize - 4) / 12;
+ for (int x = 0; x < pieces; x++)
+ {
+ int filePos = Utils.convertBytesToInt(tableStream, pos + ((pieces + 1) * 4) + (x * 8) + 2);
+ boolean unicode = false;
+ if ((filePos & 0x40000000) == 0)
+ {
+ unicode = true;
+ }
+ else
+ {
+ unicode = false;
+ filePos &= ~(0x40000000);//gives me FC in doc stream
+ filePos /= 2;
+ }
+ int totLength = Utils.convertBytesToInt(tableStream, pos + (x + 1) * 4) -
+ Utils.convertBytesToInt(tableStream, pos + (x * 4));
+
+ TextPiece piece = new TextPiece(filePos, totLength, unicode);
+ _text.add(piece);
+
+ }
+
+ }
+ }
+ private void printText(CHP chp, byte[] grpprl, int filePos, int length)
+ {
+
+ }
+
+ private void findFormatting(byte[] tableStream, int charOffset,
+ int charPlcSize, int parOffset, int parPlcSize) throws IOException
+ {
+ openDoc();
+ createStyleSheet(tableStream);
+ createListTables(tableStream);
+ createFontTable(tableStream);
+
+ //find character runs
+ //Get all the chpx info and store it
+
+ int arraySize = (charPlcSize - 4)/8;
+ //int[][] parFkpTable = new int[arraySize][2];
+ //first we must go through the bin table and find the fkps
+ for(int x = 0; x < arraySize; x++)
+ {
+
+ //get fc of the start of the paragraph
+ //parFkpTable[x][0] = Utils.convertBytesToInt(tableStream, parOffset + (x * 4));
+ //get pn containing the chpx for the paragraph
+ //parFkpTable[x][1] = Utils.convertBytesToInt(tableStream, parOffset + (4 * (arraySize + 1) + (4 * x)));
+ int PN = Utils.convertBytesToInt(tableStream, charOffset + (4 * (arraySize + 1) + (4 * x)));
+
+ byte[] fkp = new byte[512];
+ System.arraycopy(_header, (PN * 512), fkp, 0, 512);
+ //take each fkp and get the paps
+ int crun = Utils.convertUnsignedByteToInt(fkp[511]);
+ for(int y = 0; y < crun; y++)
+ {
+ //get the beginning fc of each paragraph text run
+ int fcStart = Utils.convertBytesToInt(fkp, y * 4);
+ int fcEnd = Utils.convertBytesToInt(fkp, (y+1) * 4);
+ //get the offset in fkp of the papx for this paragraph
+ int chpxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + y]);
+
+ //optimization if offset == 0 use "Normal" style
+ if(chpxOffset == 0)
+
+ {
+ _characterTable.add(new ChpxNode(fcStart, fcEnd, new byte[0]));
+ continue;
+ }
+
+ int size = Utils.convertUnsignedByteToInt(fkp[chpxOffset]);
+
+ byte[] chpx = new byte[size];
+ System.arraycopy(fkp, ++chpxOffset, chpx, 0, size);
+ //_papTable.put(new Integer(fcStart), papx);
+ _characterTable.add(new ChpxNode(fcStart, fcEnd, chpx));
+ }
+
+ }
+
+ //find paragraphs
+ arraySize = (parPlcSize - 4)/8;
+ //first we must go through the bin table and find the fkps
+ for(int x = 0; x < arraySize; x++)
+ {
+ int PN = Utils.convertBytesToInt(tableStream, parOffset + (4 * (arraySize + 1) + (4 * x)));
+
+ byte[] fkp = new byte[512];
+ System.arraycopy(_header, (PN * 512), fkp, 0, 512);
+ //take each fkp and get the paps
+ int crun = Utils.convertUnsignedByteToInt(fkp[511]);
+ for(int y = 0; y < crun; y++)
+ {
+ //get the beginning fc of each paragraph text run
+ int fcStart = Utils.convertBytesToInt(fkp, y * 4);
+ int fcEnd = Utils.convertBytesToInt(fkp, (y+1) * 4);
+ //get the offset in fkp of the papx for this paragraph
+ int papxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + (y * 13)]);
+ int size = 2 * Utils.convertUnsignedByteToInt(fkp[papxOffset]);
+ if(size == 0)
+ {
+ size = 2 * Utils.convertUnsignedByteToInt(fkp[++papxOffset]);
+ }
+ else
+ {
+ size--;
+ }
+
+ byte[] papx = new byte[size];
+ System.arraycopy(fkp, ++papxOffset, papx, 0, size);
+ _paragraphTable.add(new PapxNode(fcStart, fcEnd, papx));
+
+ }
+
+ }
+ //find sections
+ int fcMin = Utils.convertBytesToInt(_header, 0x18);
+ int plcfsedFC = Utils.convertBytesToInt(_header, 0xca);
+ int plcfsedSize = Utils.convertBytesToInt(_header, 0xce);
+ byte[] plcfsed = new byte[plcfsedSize];
+ System.arraycopy(tableStream, plcfsedFC, plcfsed, 0, plcfsedSize);
+
+ arraySize = (plcfsedSize - 4)/16;
+
+ //openDoc();
+
+ for(int x = 0; x < arraySize; x++)
+ {
+ int sectionStart = Utils.convertBytesToInt(plcfsed, x * 4) + fcMin;
+ int sectionEnd = Utils.convertBytesToInt(plcfsed, (x+1) * 4) + fcMin;
+ int sepxStart = Utils.convertBytesToInt(plcfsed, 4 * (arraySize + 1) + (x * 12) + 2);
+ int sepxSize = Utils.convertBytesToShort(_header, sepxStart);
+ byte[] sepx = new byte[sepxSize];
+ System.arraycopy(_header, sepxStart + 2, sepx, 0, sepxSize);
+ SepxNode node = new SepxNode(x + 1, sectionStart, sectionEnd, sepx);
+ _sectionTable.add(node);
+ //HeaderFooter[] hdrftr = findSectionHdrFtr(x);
+ }
+
+
+ }
+ public void openDoc()
+ {
+ _headerBuffer.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r\n");
+ _headerBuffer.append("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\r\n");
+ _headerBuffer.append("<fo:layout-master-set>\r\n");
+ //_headerBuffer.append("<fo:simple-page-master master-name=\"my-page\">\r\n");
+
+ }
+ private HeaderFooter findSectionHdrFtr(int type, int index)
+ {
+ if(_plcfHdd.length < 50)
+ {
+ return new HeaderFooter(0,0,0);
+ }
+ int start = _fcMin + _ccpText + _ccpFtn;
+ int end = start;
+ int arrayIndex = 0;
+
+ switch(type)
+ {
+ case HeaderFooter.HEADER_EVEN:
+ arrayIndex = (HEADER_EVEN_INDEX + (index * 6));
+ break;
+ case HeaderFooter.FOOTER_EVEN:
+ arrayIndex = (FOOTER_EVEN_INDEX + (index * 6));
+ break;
+ case HeaderFooter.HEADER_ODD:
+ arrayIndex = (HEADER_ODD_INDEX + (index * 6));
+ break;
+ case HeaderFooter.FOOTER_ODD:
+ arrayIndex = (FOOTER_ODD_INDEX + (index * 6));
+ break;
+ case HeaderFooter.HEADER_FIRST:
+ arrayIndex = (HEADER_FIRST_INDEX + (index * 6));
+ break;
+ case HeaderFooter.FOOTER_FIRST:
+ arrayIndex = (FOOTER_FIRST_INDEX + (index * 6));
+ break;
+ }
+ start += Utils.convertBytesToInt(_plcfHdd, (arrayIndex * 4));
+ end += Utils.convertBytesToInt(_plcfHdd, (arrayIndex + 1) * 4);
+
+ HeaderFooter retValue = new HeaderFooter(type, start, end);
+
+ if((end - start) == 0 && index > 1)
+ {
+ retValue = findSectionHdrFtr(type, index - 1);
+ }
+ return retValue;
+ }
+ private void initDocProperties(byte[] tableStream)
+ {
+ int pos = Utils.convertBytesToInt(_header, 0x192);
+ int size = Utils.convertBytesToInt(_header, 0x196);
+ byte[] dop = new byte[size];
+
+ System.arraycopy(tableStream, pos, dop, 0, size);
+
+ _docProps._fFacingPages = (dop[0] & 0x1) > 0;
+ _docProps._fpc = (dop[0] & 0x60) >> 5;
+
+ short num = Utils.convertBytesToShort(dop, 2);
+ _docProps._rncFtn = (num & 0x3);
+ _docProps._nFtn = (short)(num & 0xfffc) >> 2;
+ num = Utils.convertBytesToShort(dop, 52);
+ _docProps._rncEdn = num & 0x3;
+ _docProps._nEdn = (short)(num & 0xfffc) >> 2;
+ num = Utils.convertBytesToShort(dop, 54);
+ _docProps._epc = num & 0x3;
+ }
+
+ public void writeSection(int start, int end, SEP sep, BTreeSet text,
+ BTreeSet paragraphTable, BTreeSet characterTable,
+ StyleSheet stylesheet)
+ {
+
+ HeaderFooter titleHeader = findSectionHdrFtr(HeaderFooter.HEADER_FIRST, _sectionCounter);
+ HeaderFooter titleFooter = findSectionHdrFtr(HeaderFooter.FOOTER_FIRST, _sectionCounter);
+ HeaderFooter oddHeader = findSectionHdrFtr(HeaderFooter.HEADER_ODD, _sectionCounter);
+ HeaderFooter evenHeader = findSectionHdrFtr(HeaderFooter.HEADER_EVEN, _sectionCounter);
+ HeaderFooter oddFooter = findSectionHdrFtr(HeaderFooter.FOOTER_ODD, _sectionCounter);
+ HeaderFooter evenFooter = findSectionHdrFtr(HeaderFooter.FOOTER_EVEN, _sectionCounter);
+
+ String titlePage = null;
+ String evenPage = null;
+ String oddPage = null;
+ String regPage = null;
+
+ String sequenceName = null;
+
+ /*if(sep._fTitlePage)
+ {
+ titlePage = createPageMaster(sep, "first", _sectionCounter, createRegion("before", "title-header"), createRegion("after", "title-footer"));
+
+ if(!titleHeader.isEmpty())
+ {
+ addStaticContent("title-header" + _sectionCounter, titleHeader);
+ }
+ if(!titleFooter.isEmpty())
+ {
+ addStaticContent("title-footer" + _sectionCounter, titleFooter);
+ }
+ }*/
+
+ if(_docProps._fFacingPages)
+ {
+ if(sep._fTitlePage)
+ {
+ String before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter);
+ String after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter);
+ titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
+ }
+ String before = createRegion(true, evenHeader, sep, "even-header" + _sectionCounter);
+ String after = createRegion(false, evenFooter, sep, "even-footer" + _sectionCounter);
+ evenPage = createPageMaster(sep, "even", _sectionCounter, before, after);
+ before = createRegion(true, oddHeader, sep, "odd-header" + _sectionCounter);
+ after = createRegion(false, oddFooter, sep, "odd-footer" + _sectionCounter);
+ oddPage = createPageMaster(sep, "odd", _sectionCounter, before, after);
+ sequenceName = createEvenOddPageSequence(titlePage, evenPage, oddPage, _sectionCounter);
+
+ openPage(sequenceName, "reference");
+
+ if(sep._fTitlePage)
+ {
+
+
+ if(!titleHeader.isEmpty())
+ {
+ addStaticContent("title-header" + _sectionCounter, titleHeader);
+ }
+ if(!titleFooter.isEmpty())
+ {
+ addStaticContent("title-footer" + _sectionCounter, titleFooter);
+ }
+ }
+
+ //handle the headers and footers for odd and even pages
+ if(!oddHeader.isEmpty())
+ {
+ addStaticContent("odd-header" + _sectionCounter, oddHeader);
+ }
+ if(!oddFooter.isEmpty())
+ {
+ addStaticContent("odd-footer" + _sectionCounter, oddFooter);
+ }
+ if(!evenHeader.isEmpty())
+ {
+ addStaticContent("even-header" + _sectionCounter, evenHeader);
+ }
+ if(!evenFooter.isEmpty())
+ {
+ addStaticContent("even-footer" + _sectionCounter, evenFooter);
+ }
+ openFlow();
+ addBlockContent(start, end, text, paragraphTable, characterTable);
+ closeFlow();
+ closePage();
+ }
+ else
+ {
+ /*if(sep._fTitlePage)
+ {
+ String before = createRegion(true, titleHeader, sep);
+ String after = createRegion(false, titleFooter, sep);
+ titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
+ }*/
+ String before = createRegion(true, oddHeader, sep, null);
+ String after = createRegion(false, oddFooter, sep, null);
+ regPage = createPageMaster(sep, "page", _sectionCounter, before, after);
+
+ if(sep._fTitlePage)
+ {
+ before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter);
+ after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter);
+ titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
+ sequenceName = createPageSequence(titlePage, regPage, _sectionCounter);
+ openPage(sequenceName, "reference");
+
+ if(!titleHeader.isEmpty())
+ {
+ addStaticContent("title-header" + _sectionCounter, titleHeader);
+ }
+ if(!titleFooter.isEmpty())
+ {
+ addStaticContent("title-footer" + _sectionCounter, titleFooter);
+ }
+ }
+ else
+ {
+ openPage(regPage, "name");
+ }
+ if(!oddHeader.isEmpty())
+ {
+ addStaticContent("xsl-region-before", oddHeader);
+ }
+ if(!oddFooter.isEmpty())
+ {
+ addStaticContent("xsl-region-after", oddFooter);
+ }
+ openFlow();
+ addBlockContent(start, end, text, paragraphTable, characterTable);
+ closeFlow();
+ closePage();
+ }
+ _sectionCounter++;
+ }
+
+ private int calculateHeaderHeight(int start, int end, int pageWidth)
+ {
+ Vector paragraphs = findProperties(start, end, _paragraphTable.root);
+ int size = paragraphs.size();
+ Vector lineHeights = new Vector();
+ //StyleContext context = StyleContext.getDefaultStyleContext();
+
+ for(int x = 0; x < size; x++)
+ {
+ PapxNode node = (PapxNode)paragraphs.get(x);
+ int parStart = Math.max(node.getStart(), start);
+ int parEnd = Math.min(node.getEnd(), end);
+
+ int lineWidth = 0;
+ int maxHeight = 0;
+
+ Vector textRuns = findProperties(parStart, parEnd, _characterTable.root);
+ int charSize = textRuns.size();
+
+ //StringBuffer lineBuffer = new StringBuffer();
+ for(int y = 0; y < charSize; y++)
+ {
+ ChpxNode charNode = (ChpxNode)textRuns.get(y);
+ int istd = Utils.convertBytesToShort(node.getPapx(), 0);
+ StyleDescription sd = _styleSheet.getStyleDescription(istd);
+ CHP chp = (CHP)StyleSheet.uncompressProperty(charNode.getChpx(), sd.getCHP(), _styleSheet);
+
+ //get Font info
+ //FontMetrics metrics = getFontMetrics(chp, context);
+
+ int height = 10;//metrics.getHeight();
+ maxHeight = Math.max(maxHeight, height);
+
+ int charStart = Math.max(parStart, charNode.getStart());
+ int charEnd = Math.min(parEnd, charNode.getEnd());
+
+ Vector text = findProperties(charStart, charEnd, _text.root);
+
+ int textSize = text.size();
+ StringBuffer buf = new StringBuffer();
+ for(int z = 0; z < textSize; z++)
+ {
+
+ TextPiece piece = (TextPiece)text.get(z);
+ int textStart = Math.max(piece.getStart(), charStart);
+ int textEnd = Math.min(piece.getEnd(), charEnd);
+
+ if(piece.usesUnicode())
+ {
+ addUnicodeText(textStart, textEnd, buf);
+ }
+ else
+ {
+ addText(textStart, textEnd, buf);
+ }
+ }
+
+ String tempString = buf.toString();
+ lineWidth += 10 * tempString.length();//metrics.stringWidth(tempString);
+ if(lineWidth > pageWidth)
+ {
+ lineHeights.add(new Integer(maxHeight));
+ maxHeight = 0;
+ lineWidth = 0;
+ }
+ }
+ lineHeights.add(new Integer(maxHeight));
+ }
+ int sum = 0;
+ size = lineHeights.size();
+ for(int x = 0; x < size; x++)
+ {
+ Integer height = (Integer)lineHeights.get(x);
+ sum += height.intValue();
+ }
+
+ return sum;
+ }
+/* private FontMetrics getFontMetrics(CHP chp, StyleContext context)
+ {
+ String fontName = _fonts.getFont(chp._ftcAscii);
+ int style = 0;
+ if(chp._bold)
+ {
+ style |= Font.BOLD;
+ }
+ if(chp._italic)
+ {
+ style |= Font.ITALIC;
+ }
+
+ Font font = new Font(fontName, style, chp._hps/2);
+
+
+ return context.getFontMetrics(font);
+ }*/
+ private String createRegion(boolean before, HeaderFooter header, SEP sep, String name)
+ {
+ if(header.isEmpty())
+ {
+ return "";
+ }
+ String region = "region-name=\"" + name + "\"";
+ if(name == null)
+ {
+ region = "";
+ }
+ int height = calculateHeaderHeight(header.getStart(), header.getEnd(), sep._xaPage/20);
+ int marginTop = 0;
+ int marginBottom = 0;
+ int extent = 0;
+ String where = null;
+ String align = null;
+
+ if(before)
+ {
+ where = "before";
+ align = "before";
+ marginTop = sep._dyaHdrTop/20;
+ extent = height + marginTop;
+ sep._dyaTop = Math.max(extent*20, sep._dyaTop);
+ }
+ else
+ {
+ where = "after";
+ align = "after";
+ marginBottom = sep._dyaHdrBottom/20;
+ extent = height + marginBottom;
+ sep._dyaBottom = Math.max(extent*20, sep._dyaBottom);
+ }
+
+ int marginLeft = sep._dxaLeft/20;
+ int marginRight = sep._dxaRight/20;
+
+ return "<fo:region-" + where + " display-align=\"" + align + "\" extent=\"" +
+ extent + "pt\" padding-left=\"" + marginLeft + "pt\" padding-right=\"" +
+ marginRight + "pt\" padding-top=\"" + marginTop + "pt\" padding-bottom=\"" +
+ marginBottom + "pt\" " + region + "/>";
+
+ }
+ private String createRegion(String where, String name)
+ {
+ return "<fo:region-" + where + " overflow=\"scroll\" region-name=\"" + name + "\"/>";
+ }
+ private String createEvenOddPageSequence(String titlePage, String evenPage, String oddPage, int counter)
+ {
+ String name = "my-sequence" + counter;
+ _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> ");
+ _headerBuffer.append("<fo:repeatable-page-master-alternatives>");
+ if(titlePage != null)
+ {
+ _headerBuffer.append("<fo:conditional-page-master-reference " +
+ "page-position=\"first\" master-reference=\"" +
+ titlePage + "\"/>");
+ }
+ _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"odd\" ");
+ _headerBuffer.append("master-reference=\""+ oddPage + "\"/> ");
+ _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"even\" ");
+ _headerBuffer.append("master-reference=\"" + evenPage + "\"/> ");
+ _headerBuffer.append("</fo:repeatable-page-master-alternatives>");
+ _headerBuffer.append("</fo:page-sequence-master>");
+ return name;
+ }
+ private String createPageSequence(String titlePage, String regPage, int counter)
+ {
+ String name = null;
+ if(titlePage != null)
+ {
+ name = "my-sequence" + counter;
+ _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> ");
+ _headerBuffer.append("<fo:single-page-master-reference master-reference=\"" + titlePage + "\"/>");
+ _headerBuffer.append("<fo:repeatable-page-master-reference master-reference=\"" + regPage + "\"/>");
+ _headerBuffer.append("</fo:page-sequence-master>");
+ }
+ return name;
+ }
+ private void addBlockContent(int start, int end, BTreeSet text,
+ BTreeSet paragraphTable, BTreeSet characterTable)
+ {
+
+ BTreeSet.BTreeNode root = paragraphTable.root;
+ Vector pars = findProperties(start, end, root);
+ //root = characterTable.root;
+ int size = pars.size();
+
+ for(int c = 0; c < size; c++)
+ {
+ PapxNode currentNode = (PapxNode)pars.get(c);
+ createParagraph(start, end, currentNode, characterTable, text);
+ }
+ //closePage();
+ }
+ private String getTextAlignment(byte jc)
+ {
+ switch(jc)
+ {
+ case 0:
+ return "start";
+ case 1:
+ return "center";
+ case 2:
+ return "end";
+ case 3:
+ return "justify";
+ default:
+ return "left";
+ }
+ }
+ private void createParagraph(int start, int end, PapxNode currentNode,
+ BTreeSet characterTable, BTreeSet text)
+ {
+ StringBuffer blockBuffer = _bodyBuffer;
+ byte[] papx = currentNode.getPapx();
+ int istd = Utils.convertBytesToShort(papx, 0);
+ StyleDescription std = _styleSheet.getStyleDescription(istd);
+ PAP pap = (PAP)StyleSheet.uncompressProperty(papx, std.getPAP(), _styleSheet);
+
+ //handle table cells
+ if(pap._fInTable > 0)
+ {
+ if(pap._fTtp == 0)
+ {
+ if(_cellBuffer == null)
+ {
+ _cellBuffer = new StringBuffer();
+ }
+ blockBuffer = _cellBuffer;
+ }
+ else
+ {
+ if(_table == null)
+ {
+ _table = new Vector();
+ }
+ TAP tap = (TAP)StyleSheet.uncompressProperty(papx, new TAP(), _styleSheet);
+ TableRow nextRow = new TableRow(_cells, tap);
+ _table.add(nextRow);
+ _cells = null;
+ return;
+ }
+ }
+ else
+ {
+ //just prints out any table that is stored in _table
+ printTable();
+ }
+
+ if(pap._ilfo > 0)
+ {
+ LVL lvl = _listTables.getLevel(pap._ilfo, pap._ilvl);
+ addListParagraphContent(lvl, blockBuffer, pap, currentNode, start, end, std);
+ }
+ else
+ {
+ addParagraphContent(blockBuffer, pap, currentNode, start, end, std);
+ }
+
+ }
+
+ private void addListParagraphContent(LVL lvl, StringBuffer blockBuffer, PAP pap,
+ PapxNode currentNode, int start, int end,
+ StyleDescription std)
+ {
+ pap = (PAP)StyleSheet.uncompressProperty(lvl._papx, pap, _styleSheet, false);
+
+ addParagraphProperties(pap, blockBuffer);
+
+ Vector charRuns = findProperties(Math.max(currentNode.getStart(), start),
+ Math.min(currentNode.getEnd(), end),
+ _characterTable.root);
+ int len = charRuns.size();
+
+ CHP numChp = (CHP)StyleSheet.uncompressProperty(((ChpxNode)charRuns.get(len-1)).getChpx(), std.getCHP(), _styleSheet);
+
+ numChp = (CHP)StyleSheet.uncompressProperty(lvl._chpx, numChp, _styleSheet);
+
+ //StyleContext context = StyleContext.getDefaultStyleContext();
+ //FontMetrics metrics = getFontMetrics(numChp, context);
+ int indent = -1 * pap._dxaLeft1;
+ String bulletText = getBulletText(lvl, pap);
+
+ indent = indent - (bulletText.length() * 10) * 20;//(metrics.stringWidth(bulletText) * 20);
+
+ if(indent > 0)
+ {
+ numChp._paddingEnd = (short)indent;
+ }
+
+ addCharacterProperties(numChp, blockBuffer);
+ int listNum = 0;
+
+ //if(number != null)
+ //{
+ blockBuffer.append(bulletText);
+ //listNum = 1;
+ //}
+
+ //for(;listNum < lvl._xst.length; listNum++)
+ //{
+ // addText(lvl._xst[listNum], blockBuffer);
+ //}
+
+
+ switch (lvl._ixchFollow)
+ {
+ case 0:
+ addText('\u0009', blockBuffer);
+ break;
+ case 1:
+ addText(' ', blockBuffer);
+ break;
+ }
+
+ closeLine(blockBuffer);
+ for(int x = 0; x < len; x++)
+ {
+ ChpxNode charNode = (ChpxNode)charRuns.get(x);
+ byte[] chpx = charNode.getChpx();
+ CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet);
+
+
+ addCharacterProperties(chp, blockBuffer);
+
+ int charStart = Math.max(charNode.getStart(), currentNode.getStart());
+ int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd());
+ Vector textRuns = findProperties(charStart, charEnd, _text.root);
+ int textRunLen = textRuns.size();
+ for(int y = 0; y < textRunLen; y++)
+ {
+ TextPiece piece = (TextPiece)textRuns.get(y);
+ charStart = Math.max(charStart, piece.getStart());
+ charEnd = Math.min(charEnd, piece.getEnd());
+
+ if(piece.usesUnicode())
+ {
+ addUnicodeText(charStart, charEnd, blockBuffer);
+ }
+ else
+ {
+ addText(charStart, charEnd, blockBuffer);
+ }
+ closeLine(blockBuffer);
+ }
+ }
+ closeBlock(blockBuffer);
+ }
+
+ private void addParagraphContent(StringBuffer blockBuffer, PAP pap,
+ PapxNode currentNode, int start, int end,
+ StyleDescription std)
+ {
+ addParagraphProperties(pap, blockBuffer);
+
+ Vector charRuns = findProperties(Math.max(currentNode.getStart(), start),
+ Math.min(currentNode.getEnd(), end),
+ _characterTable.root);
+ int len = charRuns.size();
+
+ for(int x = 0; x < len; x++)
+ {
+ ChpxNode charNode = (ChpxNode)charRuns.get(x);
+ byte[] chpx = charNode.getChpx();
+ CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet);
+
+ addCharacterProperties(chp, blockBuffer);
+
+ int charStart = Math.max(charNode.getStart(), currentNode.getStart());
+ int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd());
+ Vector textRuns = findProperties(charStart, charEnd, _text.root);
+ int textRunLen = textRuns.size();
+ for(int y = 0; y < textRunLen; y++)
+ {
+ TextPiece piece = (TextPiece)textRuns.get(y);
+ charStart = Math.max(charStart, piece.getStart());
+ charEnd = Math.min(charEnd, piece.getEnd());
+
+ if(piece.usesUnicode())
+ {
+ addUnicodeText(charStart, charEnd, blockBuffer);
+ }
+ else
+ {
+ addText(charStart, charEnd, blockBuffer);
+ }
+ closeLine(blockBuffer);
+ }
+ }
+ closeBlock(blockBuffer);
+ }
+ private void addText(int start, int end, StringBuffer buf)
+ {
+ for(int x = start; x < end; x++)
+ {
+ char ch = '?';
+
+
+ ch = (char)_header[x];
+
+ addText(ch, buf);
+ }
+ }
+ private void addText(char ch, StringBuffer buf)
+ {
+ int num = 0xffff & ch;
+ if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') || ch == '_' || ch == ' ' || ch == '-' || ch == '.' || ch == '$')
+ {
+ buf.append(ch);
+ }
+ else if(num == 0x07 && _cellBuffer != null)
+ {
+
+ if(_cells == null)
+ {
+ _cells = new Vector();
+ }
+ closeLine(_cellBuffer);
+ closeBlock(_cellBuffer);
+ _cells.add(_cellBuffer.toString());
+ _cellBuffer = null;
+
+ }
+
+ else
+ {
+ /** @todo handle special characters */
+ if(num < 0x20)
+ num=0x20;
+ buf.append("&#");
+ buf.append(num);
+ buf.append(';');
+ }
+ }
+ private void addUnicodeText(int start, int end, StringBuffer buf)
+ {
+ for(int x = start; x < end; x += 2)
+ {
+ char ch = Utils.getUnicodeCharacter(_header, x);
+ //if(ch < 0x0020)
+ //{
+ // _bodyBuffer.append('?');
+ //}
+ //else
+ //{
+ addText(ch, buf);
+ //}
+ }
+ }
+ private void addParagraphProperties(PAP pap, StringBuffer buf)
+ {
+ buf.append("<fo:block ");
+ buf.append("text-align=\"" + getTextAlignment(pap._jc) + "\"\r\n");
+ buf.append("linefeed-treatment=\"preserve\" ");
+ buf.append("white-space-collapse=\"false\" ");
+
+ if(pap._fKeep > 0)
+ {
+ buf.append("keep-together.within-page=\"always\"\r\n");
+ }
+ if(pap._fKeepFollow > 0)
+ {
+ buf.append("keep-with-next.within-page=\"always\"\r\n");
+ }
+ if(pap._fPageBreakBefore > 0)
+ {
+ buf.append("break-before=\"page\"\r\n");
+ }
+ if(pap._fNoAutoHyph == 0)
+ {
+ buf.append("hyphenate=\"true\"\r\n");
+ }
+ else
+ {
+ buf.append("hyphenate=\"false\"\r\n");
+ }
+ if(pap._dxaLeft > 0)
+ {
+ buf.append("start-indent=\"" + ((float)pap._dxaLeft)/1440.0f + "in\"\r\n");
+ }
+ if(pap._dxaRight > 0)
+ {
+ buf.append("end-indent=\"" + ((float)pap._dxaRight)/1440.0f + "in\"\r\n");
+ }
+ if(pap._dxaLeft1 != 0)
+ {
+ buf.append("text-indent=\"" + ((float)pap._dxaLeft1)/1440.0f + "in\"\r\n");
+ }
+ if(pap._lspd[1] == 0)
+ {
+ //buf.append("line-height=\"" + ((float)pap._lspd[0])/1440.0f + "in\"\r\n");
+ }
+ addBorder(buf, pap._brcTop, "top");
+ addBorder(buf, pap._brcBottom, "bottom");
+ addBorder(buf, pap._brcLeft, "left");
+ addBorder(buf, pap._brcRight, "right");
+
+ buf.append(">");
+
+ }
+
+ private void addCharacterProperties(CHP chp, StringBuffer buf)
+ {
+ buf.append("<fo:inline ");
+ buf.append("font-family=\"" + _fonts.getFont(chp._ftcAscii) + "\" ");
+ buf.append("font-size=\"" + (chp._hps / 2) + "pt\" ");
+ buf.append("color=\"" + getColor(chp._ico) + "\" ");
+ //not supported by fop
+ //buf.append("letter-spacing=\"" + ((double)chp._dxaSpace)/1440.0f + "in\" ");
+
+ addBorder(buf, chp._brc, "top");
+ addBorder(buf, chp._brc, "bottom");
+ addBorder(buf, chp._brc, "left");
+ addBorder(buf, chp._brc, "right");
+
+ if(chp._italic)
+ {
+ buf.append("font-style=\"italic\" ");
+ }
+ if(chp._bold)
+ {
+ buf.append("font-weight=\"bold\" ");
+ }
+ if(chp._fSmallCaps)
+ {
+ buf.append("font-variant=\"small-caps\" ");
+ }
+ if(chp._fCaps)
+ {
+ buf.append("text-transform=\"uppercase\" ");
+ }
+ if(chp._fStrike || chp._fDStrike)
+ {
+ buf.append("text-decoration=\"line-through\" ");
+ }
+ if(chp._fShadow)
+ {
+ int size = chp._hps/24;
+ buf.append("text-shadow=\"" + size + "pt\"");
+ }
+ if(chp._fLowerCase)
+ {
+ buf.append("text-transform=\"lowercase\" ");
+ }
+ if(chp._kul > 0)
+ {
+ buf.append("text-decoration=\"underline\" ");
+ }
+ if(chp._highlighted)
+ {
+ buf.append("background-color=\"" + getColor(chp._icoHighlight) + "\" ");
+ }
+ if(chp._paddingStart != 0)
+ {
+ buf.append("padding-start=\"" + (float)chp._paddingStart/1440.0f + "in\" ");
+ }
+ if(chp._paddingEnd != 0)
+ {
+ buf.append("padding-end=\"" + (float)chp._paddingEnd/1440.0f + "in\" ");
+ }
+ buf.append(">");
+ }
+ private void addStaticContent(String flowName, HeaderFooter content)
+ {
+ _bodyBuffer.append("<fo:static-content flow-name=\"" + flowName + "\">");
+ //_bodyBuffer.append("<fo:float float=\"before\">");
+ addBlockContent(content.getStart(), content.getEnd(),_text, _paragraphTable, _characterTable);
+ //_bodyBuffer.append("</fo:float>");
+ _bodyBuffer.append("</fo:static-content>");
+
+ }
+ private String getBulletText(LVL lvl, PAP pap)
+ {
+ StringBuffer bulletBuffer = new StringBuffer();
+ for(int x = 0; x < lvl._xst.length; x++)
+ {
+ if(lvl._xst[x] < 9)
+ {
+ LVL numLevel = _listTables.getLevel(pap._ilfo, lvl._xst[x]);
+ int num = numLevel._iStartAt;
+ if(lvl == numLevel)
+ {
+ numLevel._iStartAt++;
+ }
+ else if(num > 1)
+ {
+ num--;
+ }
+ bulletBuffer.append(NumberFormatter.getNumber(num, lvl._nfc));
+
+ }
+ else
+ {
+ bulletBuffer.append(lvl._xst[x]);
+ }
+
+ }
+ return bulletBuffer.toString();
+ }
+ /**
+ * finds all chpx's that are between start and end
+ */
+ private Vector findProperties(int start, int end, BTreeSet.BTreeNode root)
+ {
+ Vector results = new Vector();
+ BTreeSet.Entry[] entries = root.entries;
+
+ for(int x = 0; x < entries.length; x++)
+ {
+ if(entries[x] != null)
+ {
+ BTreeSet.BTreeNode child = entries[x].child;
+ PropertyNode xNode = (PropertyNode)entries[x].element;
+ if(xNode != null)
+ {
+ int xStart = xNode.getStart();
+ int xEnd = xNode.getEnd();
+ if(xStart < end)
+ {
+ if(xStart >= start)
+ {
+ if(child != null)
+ {
+ Vector beforeItems = findProperties(start, end, child);
+ results.addAll(beforeItems);
+ }
+ results.add(xNode);
+ }
+ else if(start < xEnd)
+ {
+ results.add(xNode);
+ //break;
+ }
+ }
+ else
+ {
+ if(child != null)
+ {
+ Vector beforeItems = findProperties(start, end, child);
+ results.addAll(beforeItems);
+ }
+ break;
+ }
+ }
+ else if(child != null)
+ {
+ Vector afterItems = findProperties(start, end, child);
+ results.addAll(afterItems);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ return results;
+ }
+ private void openPage(String page, String type)
+ {
+ _bodyBuffer.append("<fo:page-sequence master-reference=\"" + page + "\">\r\n");
+ }
+ private void openFlow()
+ {
+ _bodyBuffer.append("<fo:flow flow-name=\"xsl-region-body\">\r\n");
+ }
+ private void closeFlow()
+ {
+ _bodyBuffer.append("</fo:flow>\r\n");
+ }
+ private void closePage()
+ {
+ _bodyBuffer.append("</fo:page-sequence>\r\n");
+ }
+ private void closeLine(StringBuffer buf)
+ {
+ buf.append("</fo:inline>");
+ }
+ private void closeBlock(StringBuffer buf)
+ {
+ buf.append("</fo:block>\r\n");
+ }
+ private Vector findPAPProperties(int start, int end, BTreeSet.BTreeNode root)
+ {
+ Vector results = new Vector();
+ BTreeSet.Entry[] entries = root.entries;
+
+ for(int x = 0; x < entries.length; x++)
+ {
+ if(entries[x] != null)
+ {
+ BTreeSet.BTreeNode child = entries[x].child;
+ PapxNode papxNode = (PapxNode)entries[x].element;
+ if(papxNode != null)
+ {
+ int papxStart = papxNode.getStart();
+ if(papxStart < end)
+ {
+ if(papxStart >= start)
+ {
+ if(child != null)
+ {
+ Vector beforeItems = findPAPProperties(start, end, child);
+ results.addAll(beforeItems);
+ }
+ results.add(papxNode);
+ }
+ }
+ else
+ {
+ if(child != null)
+ {
+ Vector beforeItems = findPAPProperties(start, end, child);
+ results.addAll(beforeItems);
+ }
+ break;
+ }
+ }
+ else if(child != null)
+ {
+ Vector afterItems = findPAPProperties(start, end, child);
+ results.addAll(afterItems);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ return results;
+ }
+
+ private String createPageMaster(SEP sep, String type, int section,
+ String regionBefore, String regionAfter)
+ {
+ float height = ((float)sep._yaPage)/1440.0f;
+ float width = ((float)sep._xaPage)/1440.0f;
+ float leftMargin = ((float)sep._dxaLeft)/1440.0f;
+ float rightMargin = ((float)sep._dxaRight)/1440.0f;
+ float topMargin = ((float)sep._dyaTop)/1440.0f;
+ float bottomMargin = ((float)sep._dyaBottom)/1440.0f;
+
+ //add these to the header
+ String thisPage = type + "-page" + section;
+
+ _headerBuffer.append("<fo:simple-page-master master-name=\"" +
+ thisPage + "\"\r\n");
+ _headerBuffer.append("page-height=\"" + height + "in\"\r\n");
+ _headerBuffer.append("page-width=\"" + width + "in\"\r\n");
+ _headerBuffer.append(">\r\n");
+
+
+
+ _headerBuffer.append("<fo:region-body ");
+ //top right bottom left
+
+ _headerBuffer.append("margin=\"" + topMargin + "in " + rightMargin + "in " +
+ bottomMargin + "in " + leftMargin + "in\"\r\n");
+
+ //String style = null;
+ //String color = null;
+ addBorder(_headerBuffer, sep._brcTop, "top");
+ addBorder(_headerBuffer, sep._brcBottom, "bottom");
+ addBorder(_headerBuffer, sep._brcLeft, "left");
+ addBorder(_headerBuffer, sep._brcRight, "right");
+
+ if(sep._ccolM1 > 0)
+ {
+ _headerBuffer.append("column-count=\"" + (sep._ccolM1 + 1) + "\" ");
+ if(sep._fEvenlySpaced)
+ {
+ _headerBuffer.append("column-gap=\"" + ((float)(sep._dxaColumns))/1440.0f + "in\"");
+ }
+ else
+ {
+ _headerBuffer.append("column-gap=\"0.25in\"");
+ }
+ }
+ _headerBuffer.append("/>\r\n");
+
+ if(regionBefore != null)
+ {
+ _headerBuffer.append(regionBefore);
+ }
+ if(regionAfter != null)
+ {
+ _headerBuffer.append(regionAfter);
+ }
+
+ _headerBuffer.append("</fo:simple-page-master>\r\n");
+ return thisPage;
+ }
+ private void addBorder(StringBuffer buf, short[] brc, String where)
+ {
+ if((brc[0] & 0xff00) != 0 && brc[0] != -1)
+ {
+ int type = (brc[0] & 0xff00) >> 8;
+ float width = ((float)(brc[0] & 0x00ff))/8.0f;
+ String style = getBorderStyle(brc[0]);
+ String color = getColor(brc[1] & 0x00ff);
+ String thickness = getBorderThickness(brc[0]);
+ buf.append("border-" + where + "-style=\"" + style + "\"\r\n");
+ buf.append("border-" + where + "-color=\"" + color + "\"\r\n");
+ buf.append("border-" + where + "-width=\"" + width + "pt\"\r\n");
+ }
+ }
+ public void closeDoc()
+ {
+ _headerBuffer.append("</fo:layout-master-set>");
+ _bodyBuffer.append("</fo:root>");
+ //_headerBuffer.append();
+
+ //test code
+ try
+ {
+ OutputStreamWriter test = new OutputStreamWriter(new FileOutputStream("/home/andy/test.xml"), "8859_1");
+ test.write(_headerBuffer.toString());
+ test.write(_bodyBuffer.toString());
+ test.flush();
+ test.close();
+ }
+ catch(Throwable t)
+ {
+ t.printStackTrace();
+ }
+ }
+ private String getBorderThickness(int style)
+ {
+ switch(style)
+ {
+ case 1:
+ return "medium";
+ case 2:
+ return "thick";
+ case 3:
+ return "medium";
+ case 5:
+ return "thin";
+ default:
+ return "medium";
+ }
+ }
+
+
+ private String getColor(int ico)
+ {
+ switch(ico)
+ {
+ case 1:
+ return "black";
+ case 2:
+ return "blue";
+ case 3:
+ return "cyan";
+ case 4:
+ return "green";
+ case 5:
+ return "magenta";
+ case 6:
+ return "red";
+ case 7:
+ return "yellow";
+ case 8:
+ return "white";
+ case 9:
+ return "darkblue";
+ case 10:
+ return "darkcyan";
+ case 11:
+ return "darkgreen";
+ case 12:
+ return "darkmagenta";
+ case 13:
+ return "darkred";
+ case 14:
+ return "darkyellow";
+ case 15:
+ return "darkgray";
+ case 16:
+ return "lightgray";
+ default:
+ return "black";
+ }
+ }
+
+ private String getBorderStyle(int type)
+ {
+
+ switch(type)
+ {
+ case 1:
+ case 2:
+ return "solid";
+ case 3:
+ return "double";
+ case 5:
+ return "solid";
+ case 6:
+ return "dotted";
+ case 7:
+ case 8:
+ return "dashed";
+ case 9:
+ return "dotted";
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ return "double";
+ case 20:
+ return "solid";
+ case 21:
+ return "double";
+ case 22:
+ return "dashed";
+ case 23:
+ return "dashed";
+ case 24:
+ return "ridge";
+ case 25:
+ return "grooved";
+ default:
+ return "solid";
+ }
+ }
+ private void createListTables(byte[] tableStream)
+ {
+
+
+ int lfoOffset = Utils.convertBytesToInt(_header, 0x2ea);
+ int lfoSize = Utils.convertBytesToInt(_header, 0x2ee);
+ byte[] plflfo = new byte[lfoSize];
+
+ System.arraycopy(tableStream, lfoOffset, plflfo, 0, lfoSize);
+
+ int lstOffset = Utils.convertBytesToInt(_header, 0x2e2);
+ int lstSize = Utils.convertBytesToInt(_header, 0x2e2);
+ if(lstOffset > 0 && lstSize > 0)
+ {
+ lstSize = lfoOffset - lstOffset;
+ byte[] plcflst = new byte[lstSize];
+ System.arraycopy(tableStream, lstOffset, plcflst, 0, lstSize);
+ _listTables = new ListTables(plcflst, plflfo);
+ }
+
+ }
+ private void createStyleSheet(byte[] tableStream)
+ {
+ int stshIndex = Utils.convertBytesToInt(_header, 0xa2);
+ int stshSize = Utils.convertBytesToInt(_header, 0xa6);
+ byte[] stsh = new byte[stshSize];
+ System.arraycopy(tableStream, stshIndex, stsh, 0, stshSize);
+
+ _styleSheet = new StyleSheet(stsh);
+
+ }
+ private void createFontTable(byte[] tableStream)
+ {
+ int fontTableIndex = Utils.convertBytesToInt(_header, 0x112);
+ int fontTableSize = Utils.convertBytesToInt(_header, 0x116);
+ byte[] fontTable = new byte[fontTableSize];
+ System.arraycopy(tableStream, fontTableIndex, fontTable, 0, fontTableSize);
+ _fonts = new FontTable(fontTable);
+ }
+
+ private byte[] createBufferFromBBD(int startBlock) throws IOException
+ {
+
+ int[] blockChain = readChain(_big_block_depot, startBlock);
+ byte[] streamBuffer = new byte[512 * blockChain.length];
+
+
+ for(int x = 0; x < blockChain.length; x++)
+ {
+ byte[] bigBlock = new byte[512];
+ seek((blockChain[x] + 1) * 512);
+ read(bigBlock);
+ System.arraycopy(bigBlock, 0, streamBuffer, x * 512, 512);
+ }
+ return streamBuffer;
+
+ }
+ private void overrideCellBorder(int row, int col, int height,
+ int width, TC tc, TAP tap)
+ {
+
+ if(row == 0)
+ {
+ if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
+ {
+ tc._brcTop = tap._brcTop;
+ }
+ if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
+ {
+ tc._brcBottom = tap._brcHorizontal;
+ }
+ }
+ else if(row == (height - 1))
+ {
+ if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
+ {
+ tc._brcTop = tap._brcHorizontal;
+ }
+ if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
+ {
+ tc._brcBottom = tap._brcBottom;
+ }
+ }
+ else
+ {
+ if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
+ {
+ tc._brcTop = tap._brcHorizontal;
+ }
+ if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
+ {
+ tc._brcBottom = tap._brcHorizontal;
+ }
+ }
+ if(col == 0)
+ {
+ if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
+ {
+ tc._brcLeft = tap._brcLeft;
+ }
+ if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
+ {
+ tc._brcRight = tap._brcVertical;
+ }
+ }
+ else if(col == (width - 1))
+ {
+ if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
+ {
+ tc._brcLeft = tap._brcVertical;
+ }
+ if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
+ {
+ tc._brcRight = tap._brcRight;
+ }
+ }
+ else
+ {
+ if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
+ {
+ tc._brcLeft = tap._brcVertical;
+ }
+ if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
+ {
+ tc._brcRight = tap._brcVertical;
+ }
+ }
+ }
+ private void printTable()
+ {
+ if(_table != null)
+ {
+ int size = _table.size();
+
+ //local buffers for the table
+ StringBuffer tableHeaderBuffer = new StringBuffer();
+ StringBuffer tableBodyBuffer = new StringBuffer();
+
+ for(int x = 0; x < size; x++)
+ {
+ StringBuffer rowBuffer = tableBodyBuffer;
+ TableRow row = (TableRow)_table.get(x);
+ TAP tap = row.getTAP();
+ Vector cells = row.getCells();
+
+ if(tap._fTableHeader)
+ {
+ rowBuffer = tableHeaderBuffer;
+ }
+ rowBuffer.append("<fo:table-row ");
+ if(tap._dyaRowHeight > 0)
+ {
+ rowBuffer.append("height=\"" + ((float)tap._dyaRowHeight)/1440.0f + "in\" ");
+ }
+ if(tap._fCantSplit)
+ {
+ rowBuffer.append("keep-together=\"always\" ");
+ }
+ rowBuffer.append(">");
+ //add cells
+ for(int y = 0; y < tap._itcMac; y++)
+ {
+ TC tc = tap._rgtc[y];
+ overrideCellBorder(x, y, size, tap._itcMac, tc, tap);
+ rowBuffer.append("<fo:table-cell ");
+ rowBuffer.append("width=\"" + ((float)(tap._rgdxaCenter[y+1] - tap._rgdxaCenter[y]))/1440.0f + "in\" ");
+ rowBuffer.append("padding-start=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" ");
+ rowBuffer.append("padding-end=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" ");
+ addBorder(rowBuffer, tc._brcTop, "top");
+ addBorder(rowBuffer, tc._brcLeft, "left");
+ addBorder(rowBuffer, tc._brcBottom, "bottom");
+ addBorder(rowBuffer, tc._brcRight, "right");
+ rowBuffer.append(">");
+ rowBuffer.append((String)cells.get(y));
+ rowBuffer.append("</fo:table-cell>");
+ }
+ rowBuffer.append("</fo:table-row>");
+ }
+ StringBuffer tableBuffer = new StringBuffer();
+ tableBuffer.append("<fo:table>");
+ if(tableHeaderBuffer.length() > 0)
+ {
+ tableBuffer.append("<fo:table-header>");
+ tableBuffer.append(tableHeaderBuffer.toString());
+ tableBuffer.append("</fo:table-header>");
+ }
+ tableBuffer.append("<fo:table-body>");
+ tableBuffer.append(tableBodyBuffer.toString());
+ tableBuffer.append("</fo:table-body>");
+ tableBuffer.append("</fo:table>");
+ _bodyBuffer.append(tableBuffer.toString());
+ _table = null;
+ }
+ }
+ private void initPclfHdd(byte[] tableStream)
+ {
+ int size = Utils.convertBytesToInt(_header, 0xf6);
+ int pos = Utils.convertBytesToInt(_header, 0xf2);
+
+ _plcfHdd = new byte[size];
+
+ System.arraycopy(tableStream, pos, _plcfHdd, 0, size);
+ }
+
+
+
+
+}
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class DOP
+{
+
+ public boolean _fFacingPages;
+ public int _fpc;
+ public int _epc;
+ public int _rncFtn;
+ public int _nFtn;
+ public int _rncEdn;
+ public int _nEdn;
+
+ public DOP()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class LFO
+{
+ int _lsid;
+ int _clfolvl;
+ LFOLVL[] _levels;
+
+ public LFO()
+ {
+
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class LFOLVL
+{
+ int _iStartAt;
+ int _ilvl;
+ boolean _fStartAt;
+ boolean _fFormatting;
+ LVL _override;
+
+ public LFOLVL()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class LST
+{
+ int _lsid;
+ int _tplc;
+ byte[] _rgistd = new byte[18];
+ boolean _fSimpleList;
+ LVL[] _levels;
+
+ public LST()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+
+public class LVL
+{
+ public int _iStartAt;
+ public byte _nfc;
+ byte _jc;
+ boolean _fLegal;
+ boolean _fNoRestart;
+ boolean _fPrev;
+ boolean _fPrevSpace;
+ boolean _fWord6;
+ public byte[] _rgbxchNums = new byte[9];
+ public byte _ixchFollow;
+ public byte[] _chpx;
+ public byte[] _papx;
+ public char[] _xst;
+ public short _istd;
+
+ //byte _cbGrpprlChpx;
+ //byte _cbGrpprlPapx;
+
+
+ public LVL()
+ {
+ }
+ public Object clone()
+ {
+ LVL obj = null;
+ try
+ {
+ obj = (LVL)super.clone();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ return obj;
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.data;
+
+import java.util.*;
+
+import org.apache.poi.hdf.extractor.*;
+
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class ListTables
+{
+
+ LFO[] _pllfo;
+ Hashtable _lists = new Hashtable();
+
+ public ListTables(byte[] plcflst, byte[] plflfo)
+ {
+ initLST(plcflst);
+ initLFO(plflfo);
+ }
+ public LVL getLevel(int list, int level)
+ {
+
+ LFO override = _pllfo[list - 1];
+
+ for(int x = 0; x < override._clfolvl; x++)
+ {
+ if(override._levels[x]._ilvl == level)
+ {
+ LFOLVL lfolvl = override._levels[x];
+ if(lfolvl._fFormatting)
+ {
+ LST lst = (LST)_lists.get(new Integer(override._lsid));
+ LVL lvl = lfolvl._override;
+ lvl._istd = Utils.convertBytesToShort(lst._rgistd, level * 2);
+ return lvl;
+ }
+ else if(lfolvl._fStartAt)
+ {
+ LST lst = (LST)_lists.get(new Integer(override._lsid));
+ LVL lvl = lst._levels[level];
+ LVL newLvl = (LVL)lvl.clone();
+ newLvl._istd = Utils.convertBytesToShort(lst._rgistd, level * 2);
+ newLvl._iStartAt = lfolvl._iStartAt;
+ return newLvl;
+ }
+ }
+ }
+
+ LST lst = (LST)_lists.get(new Integer(override._lsid));
+ LVL lvl = lst._levels[level];
+ lvl._istd = Utils.convertBytesToShort(lst._rgistd, level * 2);
+ return lvl;
+
+
+ }
+ private void initLST(byte[] plcflst)
+ {
+ short length = Utils.convertBytesToShort(plcflst, 0);
+ int nextLevelOffset = 0;
+ //LST[] lstArray = new LST[length];
+ for(int x = 0; x < length; x++)
+ {
+ LST lst = new LST();
+ lst._lsid = Utils.convertBytesToInt(plcflst, 2 + (x * 28));
+ lst._tplc = Utils.convertBytesToInt(plcflst, 2 + 4 + (x * 28));
+ System.arraycopy(plcflst, 2 + 8 + (x * 28), lst._rgistd, 0, 18);
+ byte code = plcflst[2 + 26 + (x * 28)];
+ lst._fSimpleList = StyleSheet.getFlag(code & 0x01);
+ //lstArray[x] = lst;
+ _lists.put(new Integer(lst._lsid), lst);
+
+ if(lst._fSimpleList)
+ {
+ lst._levels = new LVL[1];
+ }
+ else
+ {
+ lst._levels = new LVL[9];
+ }
+
+ for(int y = 0; y < lst._levels.length; y++)
+ {
+ int offset = 2 + (length * 28) + nextLevelOffset;
+ lst._levels[y] = new LVL();
+ nextLevelOffset += createLVL(plcflst, offset, lst._levels[y]);
+ }
+ }
+
+
+ }
+ private void initLFO(byte[] plflfo)
+ {
+ int lfoSize = Utils.convertBytesToInt(plflfo, 0);
+ _pllfo = new LFO[lfoSize];
+ for(int x = 0; x < lfoSize; x++)
+ {
+ LFO nextLFO = new LFO();
+ nextLFO._lsid = Utils.convertBytesToInt(plflfo, 4 + (x * 16));
+ nextLFO._clfolvl = plflfo[4 + 12 + (x * 16)];
+ nextLFO._levels = new LFOLVL[nextLFO._clfolvl];
+ _pllfo[x] = nextLFO;
+ }
+
+ int lfolvlOffset = (lfoSize * 16) + 4;
+ int lvlOffset = 0;
+ int lfolvlNum = 0;
+ for(int x = 0; x < lfoSize; x++)
+ {
+ for(int y = 0; y < _pllfo[x]._clfolvl; y++)
+ {
+ int offset = lfolvlOffset + (lfolvlNum * 8) + lvlOffset;
+ LFOLVL lfolvl = new LFOLVL();
+ lfolvl._iStartAt = Utils.convertBytesToInt(plflfo, offset);
+ lfolvl._ilvl = Utils.convertBytesToInt(plflfo, offset + 4);
+ lfolvl._fStartAt = StyleSheet.getFlag(lfolvl._ilvl & 0x10);
+ lfolvl._fFormatting = StyleSheet.getFlag(lfolvl._ilvl & 0x20);
+ lfolvl._ilvl = (lfolvl._ilvl & (byte)0x0f);
+ lfolvlNum++;
+
+ if(lfolvl._fFormatting)
+ {
+ offset = lfolvlOffset + (lfolvlNum * 12) + lvlOffset;
+ lfolvl._override = new LVL();
+ lvlOffset += createLVL(plflfo, offset, lfolvl._override);
+ }
+ _pllfo[x]._levels[y] = lfolvl;
+ }
+ }
+ }
+ private int createLVL(byte[] data, int offset, LVL lvl)
+ {
+
+ lvl._iStartAt = Utils.convertBytesToInt(data, offset);
+ lvl._nfc = data[offset + 4];
+ int code = Utils.convertBytesToInt(data, offset + 5);
+ lvl._jc = (byte)(code & 0x03);
+ lvl._fLegal = StyleSheet.getFlag(code & 0x04);
+ lvl._fNoRestart = StyleSheet.getFlag(code & 0x08);
+ lvl._fPrev = StyleSheet.getFlag(code & 0x10);
+ lvl._fPrevSpace = StyleSheet.getFlag(code & 0x20);
+ lvl._fWord6 = StyleSheet.getFlag(code & 0x40);
+ System.arraycopy(data, offset + 6, lvl._rgbxchNums, 0, 9);
+ lvl._ixchFollow = data[offset + 15];
+ int chpxSize = data[offset + 24];
+ int papxSize = data[offset + 25];
+ lvl._chpx = new byte[chpxSize];
+ lvl._papx = new byte[papxSize];
+ System.arraycopy(data, offset + 28, lvl._papx, 0, papxSize);
+ System.arraycopy(data, offset + 28 + papxSize, lvl._chpx, 0, chpxSize);
+ offset += 28 + papxSize + chpxSize;//modify offset
+ int xstSize = Utils.convertBytesToShort(data, offset);
+ lvl._xst = new char[xstSize];
+
+ offset += 2;
+ for(int x = 0; x < xstSize; x++)
+ {
+ lvl._xst[x] = (char)Utils.convertBytesToShort(data, offset + (x * 2));
+ }
+ return 28 + papxSize + chpxSize + 2 + (xstSize * 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+import java.util.*;
+
+
+/*
+ * A B-Tree like implementation of the java.util.Set inteface. This is a modifiable set
+ * and thus allows elements to be added and removed. An instance of java.util.Comparator
+ * must be provided at construction else all Objects added to the set must implement
+ * java.util.Comparable and must be comparable to one another. No duplicate elements
+ * will be allowed in any BTreeSet in accordance with the specifications of the Set interface.
+ * Any attempt to add a null element will result in an IllegalArgumentException being thrown.
+ * The java.util.Iterator returned by the iterator method guarantees the elements returned
+ * are in ascending order. The Iterator.remove() method is supported.
+ * Comment me
+ *
+ * @author Ryan Ackley
+ *
+*/
+
+public class BTreeSet extends AbstractSet implements Set {
+
+ /*
+ * Instance Variables
+ */
+ public BTreeNode root;
+ private Comparator comparator = null;
+ private int order;
+ private int size = 0;
+
+ /*
+ * Constructors
+ * A no-arg constructor is supported in accordance with the specifications of the
+ * java.util.Collections interface. If the order for the B-Tree is not specified
+ * at construction it defaults to 32.
+ */
+
+ public BTreeSet() {
+ this(6); // Default order for a BTreeSet is 32
+ }
+
+ public BTreeSet(Collection c) {
+ this(6); // Default order for a BTreeSet is 32
+ addAll(c);
+ }
+
+ public BTreeSet(int order) {
+ this(order, null);
+ }
+
+ public BTreeSet(int order, Comparator comparator) {
+ this.order = order;
+ this.comparator = comparator;
+ root = new BTreeNode(null);
+ }
+
+
+ /*
+ * Public Methods
+ */
+ public boolean add(Object x) throws IllegalArgumentException {
+ if (x == null) throw new IllegalArgumentException();
+ return root.insert(x, -1);
+ }
+
+ public boolean contains(Object x) {
+ return root.includes(x);
+ }
+
+ public boolean remove(Object x) {
+ if (x == null) return false;
+ return root.delete(x, -1);
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public void clear() {
+ root = new BTreeNode(null);
+ size = 0;
+ }
+
+ public java.util.Iterator iterator() {
+ return new Iterator();
+ }
+
+
+ /*
+ * Private methods
+ */
+ private int compare(Object x, Object y) {
+ return (comparator == null ? ((Comparable)x).compareTo(y) : comparator.compare(x, y));
+ }
+
+
+
+ /*
+ * Inner Classes
+ */
+
+ /*
+ * Guarantees that the Objects are returned in ascending order. Due to the volatile
+ * structure of a B-Tree (many splits, steals and merges can happen in a single call to remove)
+ * this Iterator does not attempt to track any concurrent changes that are happening to
+ * it's BTreeSet. Therefore, after every call to BTreeSet.remove or BTreeSet.add a new
+ * Iterator should be constructed. If no new Iterator is constructed than there is a
+ * chance of receiving a NullPointerException. The Iterator.delete method is supported.
+ */
+
+ private class Iterator implements java.util.Iterator {
+ private int index = 0;
+ private Stack parentIndex = new Stack(); // Contains all parentIndicies for currentNode
+ private Object lastReturned = null;
+ private Object next;
+ private BTreeNode currentNode;
+
+ Iterator() {
+ currentNode = firstNode();
+ next = nextElement();
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public Object next() {
+ if (next == null) throw new NoSuchElementException();
+
+ lastReturned = next;
+ next = nextElement();
+ return lastReturned;
+ }
+
+ public void remove() {
+ if (lastReturned == null) throw new NoSuchElementException();
+
+ BTreeSet.this.remove(lastReturned);
+ lastReturned = null;
+ }
+
+ private BTreeNode firstNode() {
+ BTreeNode temp = BTreeSet.this.root;
+
+ while (temp.entries[0].child != null) {
+ temp = temp.entries[0].child;
+ parentIndex.push(new Integer(0));
+ }
+
+ return temp;
+ }
+
+ private Object nextElement() {
+ if (currentNode.isLeaf()) {
+ if (index < currentNode.nrElements) return currentNode.entries[index++].element;
+
+ else if (!parentIndex.empty()) { //All elements have been returned, return successor of lastReturned if it exists
+ currentNode = currentNode.parent;
+ index = ((Integer)parentIndex.pop()).intValue();
+
+ while (index == currentNode.nrElements) {
+ if (parentIndex.empty()) break;
+ currentNode = currentNode.parent;
+ index = ((Integer)parentIndex.pop()).intValue();
+ }
+
+ if (index == currentNode.nrElements) return null; //Reached root and he has no more children
+ return currentNode.entries[index++].element;
+ }
+
+ else { //Your a leaf and the root
+ if (index == currentNode.nrElements) return null;
+ return currentNode.entries[index++].element;
+ }
+ }
+
+ else { //Your not a leaf so simply find and return the successor of lastReturned
+ currentNode = currentNode.entries[index].child;
+ parentIndex.push(new Integer(index));
+
+ while (currentNode.entries[0].child != null) {
+ currentNode = currentNode.entries[0].child;
+ parentIndex.push(new Integer(0));
+ }
+
+ index = 1;
+ return currentNode.entries[0].element;
+ }
+ }
+ }
+
+
+ public static class Entry {
+
+ public Object element;
+ public BTreeNode child;
+ }
+
+
+ public class BTreeNode {
+
+ public Entry[] entries;
+ public BTreeNode parent;
+ private int nrElements = 0;
+ private final int MIN = (BTreeSet.this.order - 1) / 2;
+
+ BTreeNode(BTreeNode parent) {
+ this.parent = parent;
+ entries = new Entry[BTreeSet.this.order];
+ entries[0] = new Entry();
+ }
+
+ boolean insert(Object x, int parentIndex) {
+ if (isFull()) { // If full, you must split and promote splitNode before inserting
+ Object splitNode = entries[nrElements / 2].element;
+ BTreeNode rightSibling = split();
+
+ if (isRoot()) { // Grow a level
+ splitRoot(splitNode, this, rightSibling);
+ // Determine where to insert
+ if (BTreeSet.this.compare(x, BTreeSet.this.root.entries[0].element) < 0) insert(x, 0);
+ else rightSibling.insert(x, 1);
+ }
+
+ else { // Promote splitNode
+ parent.insertSplitNode(splitNode, this, rightSibling, parentIndex);
+ if (BTreeSet.this.compare(x, parent.entries[parentIndex].element) < 0) return insert(x, parentIndex);
+ else return rightSibling.insert(x, parentIndex + 1);
+ }
+ }
+
+ else if (isLeaf()) { // If leaf, simply insert the non-duplicate element
+ int insertAt = childToInsertAt(x, true);
+ if (insertAt == -1) return false; // Determine if the element already exists
+ else {
+ insertNewElement(x, insertAt);
+ BTreeSet.this.size++;
+ return true;
+ }
+ }
+
+ else { // If not full and not leaf recursively find correct node to insert at
+ int insertAt = childToInsertAt(x, true);
+ return (insertAt == -1 ? false : entries[insertAt].child.insert(x, insertAt));
+ }
+ return false;
+ }
+
+ boolean includes(Object x) {
+ int index = childToInsertAt(x, true);
+ if (index == -1) return true;
+ if (entries[index] == null || entries[index].child == null) return false;
+ return entries[index].child.includes(x);
+ }
+
+ boolean delete(Object x, int parentIndex) {
+ int i = childToInsertAt(x, true);
+ int priorParentIndex = parentIndex;
+ BTreeNode temp = this;
+ if (i != -1) {
+ do {
+ if (temp.entries[i] == null || temp.entries[i].child == null) return false;
+ temp = temp.entries[i].child;
+ priorParentIndex = parentIndex;
+ parentIndex = i;
+ i = temp.childToInsertAt(x, true);
+ } while (i != -1);
+ } // Now temp contains element to delete and temp's parentIndex is parentIndex
+
+ if (temp.isLeaf()) { // If leaf and have more than MIN elements, simply delete
+ if (temp.nrElements > MIN) {
+ temp.deleteElement(x);
+ BTreeSet.this.size--;
+ return true;
+ }
+
+ else { // If leaf and have less than MIN elements, than prepare the BTreeSet for deletion
+ temp.prepareForDeletion(parentIndex);
+ temp.deleteElement(x);
+ BTreeSet.this.size--;
+ temp.fixAfterDeletion(priorParentIndex);
+ return true;
+ }
+ }
+
+ else { // Only delete at leaf so first switch with successor than delete
+ temp.switchWithSuccessor(x);
+ parentIndex = temp.childToInsertAt(x, false) + 1;
+ return temp.entries[parentIndex].child.delete(x, parentIndex);
+ }
+ }
+
+
+ private boolean isFull() { return nrElements == (BTreeSet.this.order - 1); }
+
+ private boolean isLeaf() { return entries[0].child == null; }
+
+ private boolean isRoot() { return parent == null; }
+
+ /*
+ * Splits a BTreeNode into two BTreeNodes, removing the splitNode from the
+ * calling BTreeNode.
+ */
+ private BTreeNode split() {
+ BTreeNode rightSibling = new BTreeNode(parent);
+ int index = nrElements / 2;
+ entries[index++].element = null;
+
+ for (int i = 0, nr = nrElements; index <= nr; i++, index++) {
+ rightSibling.entries[i] = entries[index];
+ if (rightSibling.entries[i] != null && rightSibling.entries[i].child != null)
+ rightSibling.entries[i].child.parent = rightSibling;
+ entries[index] = null;
+ nrElements--;
+ rightSibling.nrElements++;
+ }
+
+ rightSibling.nrElements--; // Need to correct for copying the last Entry which has a null element and a child
+ return rightSibling;
+ }
+
+ /*
+ * Creates a new BTreeSet.root which contains only the splitNode and pointers
+ * to it's left and right child.
+ */
+ private void splitRoot(Object splitNode, BTreeNode left, BTreeNode right) {
+ BTreeNode newRoot = new BTreeNode(null);
+ newRoot.entries[0].element = splitNode;
+ newRoot.entries[0].child = left;
+ newRoot.entries[1] = new Entry();
+ newRoot.entries[1].child = right;
+ newRoot.nrElements = 1;
+ left.parent = right.parent = newRoot;
+ BTreeSet.this.root = newRoot;
+ }
+
+ private void insertSplitNode(Object splitNode, BTreeNode left, BTreeNode right, int insertAt) {
+ for (int i = nrElements; i >= insertAt; i--) entries[i + 1] = entries[i];
+
+ entries[insertAt] = new Entry();
+ entries[insertAt].element = splitNode;
+ entries[insertAt].child = left;
+ entries[insertAt + 1].child = right;
+
+ nrElements++;
+ }
+
+ private void insertNewElement(Object x, int insertAt) {
+
+ for (int i = nrElements; i > insertAt; i--) entries[i] = entries[i - 1];
+
+ entries[insertAt] = new Entry();
+ entries[insertAt].element = x;
+
+ nrElements++;
+ }
+
+ /*
+ * Possibly a deceptive name for a pretty cool method. Uses binary search
+ * to determine the postion in entries[] in which to traverse to find the correct
+ * BTreeNode in which to insert a new element. If the element exists in the calling
+ * BTreeNode than -1 is returned. When the parameter position is true and the element
+ * is present in the calling BTreeNode -1 is returned, if position is false and the
+ * element is contained in the calling BTreeNode than the position of the element
+ * in entries[] is returned.
+ */
+ private int childToInsertAt(Object x, boolean position) {
+ int index = nrElements / 2;
+
+ if (entries[index] == null || entries[index].element == null) return index;
+
+ int lo = 0, hi = nrElements - 1;
+ while (lo <= hi) {
+ if (BTreeSet.this.compare(x, entries[index].element) > 0) {
+ lo = index + 1;
+ index = (hi + lo) / 2;
+ }
+ else {
+ hi = index - 1;
+ index = (hi + lo) / 2;
+ }
+ }
+
+ hi++;
+ if (entries[hi] == null || entries[hi].element == null) return hi;
+ return (!position ? hi : BTreeSet.this.compare(x, entries[hi].element) == 0 ? -1 : hi);
+ }
+
+
+ private void deleteElement(Object x) {
+ int index = childToInsertAt(x, false);
+ for (; index < (nrElements - 1); index++) entries[index] = entries[index + 1];
+
+ if (nrElements == 1) entries[index] = new Entry(); // This is root and it is empty
+ else entries[index] = null;
+
+ nrElements--;
+ }
+
+ private void prepareForDeletion(int parentIndex) {
+ if (isRoot()) return; // Don't attempt to steal or merge if your the root
+
+ // If not root then try to steal left
+ else if (parentIndex != 0 && parent.entries[parentIndex - 1].child.nrElements > MIN) {
+ stealLeft(parentIndex);
+ return;
+ }
+
+ // If not root and can't steal left try to steal right
+ else if (parentIndex < entries.length && parent.entries[parentIndex + 1] != null && parent.entries[parentIndex + 1].child != null && parent.entries[parentIndex + 1].child.nrElements > MIN) {
+ stealRight(parentIndex);
+ return;
+ }
+
+ // If not root and can't steal left or right then try to merge left
+ else if (parentIndex != 0) {
+ mergeLeft(parentIndex);
+ return;
+ }
+
+ // If not root and can't steal left or right and can't merge left you must be able to merge right
+ else mergeRight(parentIndex);
+ }
+
+ private void fixAfterDeletion(int parentIndex) {
+ if (isRoot() || parent.isRoot()) return; // No fixing needed
+
+ if (parent.nrElements < MIN) { // If parent lost it's n/2 element repair it
+ BTreeNode temp = parent;
+ temp.prepareForDeletion(parentIndex);
+ if (temp.parent == null) return; // Root changed
+ if (!temp.parent.isRoot() && temp.parent.nrElements < MIN) { // If need be recurse
+ BTreeNode x = temp.parent.parent;
+ int i = 0;
+ // Find parent's parentIndex
+ for (; i < entries.length; i++) if (x.entries[i].child == temp.parent) break;
+ temp.parent.fixAfterDeletion(i);
+ }
+ }
+ }
+
+ private void switchWithSuccessor(Object x) {
+ int index = childToInsertAt(x, false);
+ BTreeNode temp = entries[index + 1].child;
+ while (temp.entries[0] != null && temp.entries[0].child != null) temp = temp.entries[0].child;
+ Object successor = temp.entries[0].element;
+ temp.entries[0].element = entries[index].element;
+ entries[index].element = successor;
+ }
+
+ /*
+ * This method is called only when the BTreeNode has the minimum number of elements,
+ * has a leftSibling, and the leftSibling has more than the minimum number of elements.
+ */
+ private void stealLeft(int parentIndex) {
+ BTreeNode p = parent;
+ BTreeNode ls = parent.entries[parentIndex - 1].child;
+
+ if (isLeaf()) { // When stealing from leaf to leaf don't worry about children
+ int add = childToInsertAt(p.entries[parentIndex - 1].element, true);
+ insertNewElement(p.entries[parentIndex - 1].element, add);
+ p.entries[parentIndex - 1].element = ls.entries[ls.nrElements - 1].element;
+ ls.entries[ls.nrElements - 1] = null;
+ ls.nrElements--;
+ }
+
+ else { // Was called recursively to fix an undermanned parent
+ entries[0].element = p.entries[parentIndex - 1].element;
+ p.entries[parentIndex - 1].element = ls.entries[ls.nrElements - 1].element;
+ entries[0].child = ls.entries[ls.nrElements].child;
+ entries[0].child.parent = this;
+ ls.entries[ls.nrElements] = null;
+ ls.entries[ls.nrElements - 1].element = null;
+ nrElements++;
+ ls.nrElements--;
+ }
+ }
+
+ /*
+ * This method is called only when stealLeft can't be called, the BTreeNode
+ * has the minimum number of elements, has a rightSibling, and the rightSibling
+ * has more than the minimum number of elements.
+ */
+ private void stealRight(int parentIndex) {
+ BTreeNode p = parent;
+ BTreeNode rs = p.entries[parentIndex + 1].child;
+
+ if (isLeaf()) { // When stealing from leaf to leaf don't worry about children
+ entries[nrElements] = new Entry();
+ entries[nrElements].element = p.entries[parentIndex].element;
+ p.entries[parentIndex].element = rs.entries[0].element;
+ for (int i = 0; i < rs.nrElements; i++) rs.entries[i] = rs.entries[i + 1];
+ rs.entries[rs.nrElements - 1] = null;
+ nrElements++;
+ rs.nrElements--;
+ }
+
+ else { // Was called recursively to fix an undermanned parent
+ for (int i = 0; i <= nrElements; i++) entries[i] = entries[i + 1];
+ entries[nrElements].element = p.entries[parentIndex].element;
+ p.entries[parentIndex].element = rs.entries[0].element;
+ entries[nrElements + 1] = new Entry();
+ entries[nrElements + 1].child = rs.entries[0].child;
+ entries[nrElements + 1].child.parent = this;
+ for (int i = 0; i <= rs.nrElements; i++) rs.entries[i] = rs.entries[i + 1];
+ rs.entries[rs.nrElements] = null;
+ nrElements++;
+ rs.nrElements--;
+ }
+ }
+
+ /*
+ * This method is called only when stealLeft and stealRight could not be called,
+ * the BTreeNode has the minimum number of elements, has a leftSibling, and the
+ * leftSibling has more than the minimum number of elements. If after completion
+ * parent has fewer than the minimum number of elements than the parents entries[0]
+ * slot is left empty in anticipation of a recursive call to stealLeft, stealRight,
+ * mergeLeft, or mergeRight to fix the parent. All of the before-mentioned methods
+ * expect the parent to be in such a condition.
+ */
+ private void mergeLeft(int parentIndex) {
+ BTreeNode p = parent;
+ BTreeNode ls = p.entries[parentIndex - 1].child;
+
+ if (isLeaf()) { // Don't worry about children
+ int add = childToInsertAt(p.entries[parentIndex - 1].element, true);
+ insertNewElement(p.entries[parentIndex - 1].element, add); // Could have been a successor switch
+ p.entries[parentIndex - 1].element = null;
+
+ for (int i = nrElements - 1, nr = ls.nrElements; i >= 0; i--)
+ entries[i + nr] = entries[i];
+
+ for (int i = ls.nrElements - 1; i >= 0; i--) {
+ entries[i] = ls.entries[i];
+ nrElements++;
+ }
+
+ if (p.nrElements == MIN && p != BTreeSet.this.root) {
+
+ for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x--, y--)
+ p.entries[x] = p.entries[y];
+ p.entries[0] = new Entry();
+ p.entries[0].child = ls; //So p doesn't think it's a leaf this will be deleted in the next recursive call
+ }
+
+ else {
+
+ for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
+ p.entries[x] = p.entries[y];
+ p.entries[p.nrElements] = null;
+ }
+
+ p.nrElements--;
+
+ if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
+ BTreeSet.this.root = this;
+ parent = null;
+ }
+ }
+
+ else { // I'm not a leaf but fixing the tree structure
+ entries[0].element = p.entries[parentIndex - 1].element;
+ entries[0].child = ls.entries[ls.nrElements].child;
+ nrElements++;
+
+ for (int x = nrElements, nr = ls.nrElements; x >= 0; x--)
+ entries[x + nr] = entries[x];
+
+ for (int x = ls.nrElements - 1; x >= 0; x--) {
+ entries[x] = ls.entries[x];
+ entries[x].child.parent = this;
+ nrElements++;
+ }
+
+ if (p.nrElements == MIN && p != BTreeSet.this.root) { // Push everything to the right
+ for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x++, y++){
+ System.out.println(x + " " + y);
+ p.entries[x] = p.entries[y];}
+ p.entries[0] = new Entry();
+ }
+
+ else { // Either p.nrElements > MIN or p == BTreeSet.this.root so push everything to the left
+ for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
+ p.entries[x] = p.entries[y];
+ p.entries[p.nrElements] = null;
+ }
+
+ p.nrElements--;
+
+ if (p.isRoot() && p.nrElements == 0) { // p == BTreeSet.this.root and it's empty
+ BTreeSet.this.root = this;
+ parent = null;
+ }
+ }
+ }
+
+ /*
+ * This method is called only when stealLeft, stealRight, and mergeLeft could not be called,
+ * the BTreeNode has the minimum number of elements, has a rightSibling, and the
+ * rightSibling has more than the minimum number of elements. If after completion
+ * parent has fewer than the minimum number of elements than the parents entries[0]
+ * slot is left empty in anticipation of a recursive call to stealLeft, stealRight,
+ * mergeLeft, or mergeRight to fix the parent. All of the before-mentioned methods
+ * expect the parent to be in such a condition.
+ */
+ private void mergeRight(int parentIndex) {
+ BTreeNode p = parent;
+ BTreeNode rs = p.entries[parentIndex + 1].child;
+
+ if (isLeaf()) { // Don't worry about children
+ entries[nrElements] = new Entry();
+ entries[nrElements].element = p.entries[parentIndex].element;
+ nrElements++;
+ for (int i = 0, nr = nrElements; i < rs.nrElements; i++, nr++) {
+ entries[nr] = rs.entries[i];
+ nrElements++;
+ }
+ p.entries[parentIndex].element = p.entries[parentIndex + 1].element;
+ if (p.nrElements == MIN && p != BTreeSet.this.root) {
+ for (int x = parentIndex + 1, y = parentIndex; y >= 0; x--, y--)
+ p.entries[x] = p.entries[y];
+ p.entries[0] = new Entry();
+ p.entries[0].child = rs; // So it doesn't think it's a leaf, this child will be deleted in the next recursive call
+ }
+
+ else {
+ for (int x = parentIndex + 1, y = parentIndex + 2; y <= p.nrElements; x++, y++)
+ p.entries[x] = p.entries[y];
+ p.entries[p.nrElements] = null;
+ }
+
+ p.nrElements--;
+ if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
+ BTreeSet.this.root = this;
+ parent = null;
+ }
+ }
+
+ else { // It's not a leaf
+
+ entries[nrElements].element = p.entries[parentIndex].element;
+ nrElements++;
+
+ for (int x = nrElements + 1, y = 0; y <= rs.nrElements; x++, y++) {
+ entries[x] = rs.entries[y];
+ rs.entries[y].child.parent = this;
+ nrElements++;
+ }
+ nrElements--;
+
+ p.entries[++parentIndex].child = this;
+
+ if (p.nrElements == MIN && p != BTreeSet.this.root) {
+ for (int x = parentIndex - 1, y = parentIndex - 2; y >= 0; x--, y--)
+ p.entries[x] = p.entries[y];
+ p.entries[0] = new Entry();
+ }
+
+ else {
+ for (int x = parentIndex - 1, y = parentIndex; y <= p.nrElements; x++, y++)
+ p.entries[x] = p.entries[y];
+ p.entries[p.nrElements] = null;
+ }
+
+ p.nrElements--;
+
+ if (p.isRoot() && p.nrElements == 0) { // It's the root and it's empty
+ BTreeSet.this.root = this;
+ parent = null;
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class ChpxNode extends PropertyNode
+{
+
+
+ public ChpxNode(int fcStart, int fcEnd, byte[] chpx)
+ {
+ super(fcStart, fcEnd, chpx);
+ }
+ public byte[] getChpx()
+ {
+ return super.getGrpprl();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class NumberFormatter
+{
+ private final static int ARABIC = 0;
+ private final static int UPPER_ROMAN = 1;
+ private final static int LOWER_ROMAN = 2;
+ private final static int UPPER_LETTER = 3;
+ private final static int LOWER_LETTER = 4;
+ private final static int ORDINAL = 5;
+
+ private static String[] _arabic = new String[] {"1", "2", "3", "4", "5", "6",
+ "7", "8", "9", "10", "11", "12",
+ "13", "14", "15", "16", "17", "18",
+ "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28",
+ "29", "30", "31", "32", "33",
+ "34", "35", "36", "37", "38",
+ "39", "40", "41", "42", "43",
+ "44", "45", "46", "47", "48",
+ "49", "50", "51", "52", "53"};
+ private static String[] _roman = new String[]{"i", "ii", "iii", "iv", "v", "vi",
+ "vii", "viii", "ix", "x", "xi", "xii",
+ "xiii","xiv", "xv", "xvi", "xvii",
+ "xviii", "xix", "xx", "xxi", "xxii",
+ "xxiii", "xxiv", "xxv", "xxvi",
+ "xxvii", "xxviii", "xxix", "xxx",
+ "xxxi", "xxxii", "xxxiii", "xxxiv",
+ "xxxv", "xxxvi", "xxxvii", "xxxvii",
+ "xxxviii", "xxxix", "xl", "xli", "xlii",
+ "xliii", "xliv", "xlv", "xlvi", "xlvii",
+ "xlviii", "xlix", "l"};
+ private static String[] _letter = new String[]{"a", "b", "c", "d", "e", "f", "g",
+ "h", "i", "j", "k", "l", "m", "n",
+ "o", "p", "q", "r", "s", "t", "u",
+ "v", "x", "y", "z"};
+ public NumberFormatter()
+ {
+ }
+ public static String getNumber(int num, int style)
+ {
+ switch(style)
+ {
+ case ARABIC:
+ return _arabic[num - 1];
+ case UPPER_ROMAN:
+ return _roman[num-1].toUpperCase();
+ case LOWER_ROMAN:
+ return _roman[num-1];
+ case UPPER_LETTER:
+ return _letter[num-1].toUpperCase();
+ case LOWER_LETTER:
+ return _letter[num-1];
+ case ORDINAL:
+ return _arabic[num - 1];
+ default:
+ return _arabic[num - 1];
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class PapxNode extends PropertyNode
+{
+
+
+ public PapxNode(int fcStart, int fcEnd, byte[] papx)
+ {
+ super(fcStart, fcEnd, papx);
+ }
+ public byte[] getPapx()
+ {
+ return super.getGrpprl();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class PropertyNode implements Comparable
+{
+ private byte[] _grpprl;
+ private int _fcStart;
+ private int _fcEnd;
+
+ public PropertyNode(int fcStart, int fcEnd, byte[] grpprl)
+ {
+ _fcStart = fcStart;
+ _fcEnd = fcEnd;
+ _grpprl = grpprl;
+ }
+ public int getStart()
+ {
+ return _fcStart;
+ }
+ public int getEnd()
+ {
+ return _fcEnd;
+ }
+ protected byte[] getGrpprl()
+ {
+ return _grpprl;
+ }
+ public int compareTo(Object o)
+ {
+ int fcStart = ((PropertyNode)o).getStart();
+ if(_fcStart == fcStart)
+ {
+ return 0;
+ }
+ else if(_fcStart < fcStart)
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache POI" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache POI", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+
+package org.apache.poi.hdf.extractor.util;
+
+/**
+ * Comment me
+ *
+ * @author Ryan Ackley
+ */
+
+public class SepxNode extends PropertyNode
+{
+
+ int _index;
+
+ public SepxNode(int index, int start, int end, byte[] sepx)
+ {
+ super(start, end, sepx);
+ }
+ public byte[] getSepx()
+ {
+ return getGrpprl();
+ }
+
+ public int compareTo(Object obj) {
+ return 0;
+ }
+
+}
\ No newline at end of file