FileDocCategorySizeDatePackage
WordDocument.javaAPI DocApache Poi 3.0.155167Mon Jan 01 18:55:24 GMT 2007org.apache.poi.hdf.extractor

WordDocument

public class WordDocument extends Object
This class contains the main functionality for the Word file "reader". Much of the code in this class is based on the Word 97 document file format. Only works for non-complex files
author
Ryan Ackley

Fields Summary
byte[]
_header
byte buffer containing the main Document stream
StyleSheet
_styleSheet
contains all style information for this document see Word 97 Doc spec
ListTables
_listTables
contains All list information for this document
DOP
_docProps
contains global Document properties for this document
int
_currentList
int
_tableSize
int
_sectionCounter
FontTable
_fonts
fonts available for this document
BTreeSet
_text
document's text blocks
BTreeSet
_characterTable
document's character runs
BTreeSet
_paragraphTable
document's paragraphs
BTreeSet
_sectionTable
doucment's sections
StringBuffer
_headerBuffer
used for XSL-FO conversion
StringBuffer
_bodyBuffer
used for XSL-FO conversion
StringBuffer
_cellBuffer
used for XSL-FO table conversion
ArrayList
_cells
used for XSL-FO table conversion
ArrayList
_table
used for XSL-FO table conversion
byte[]
_plcfHdd
document's header and footer information
int
_fcMin
starting position of text in main document stream
int
_ccpText
length of main document text stream
int
_ccpFtn
length of footnotes text
private static String
_outName
The name of the file to write to
private InputStream
istream
OLE stuff
private POIFSFileSystem
filesystem
OLE stuff
private static int
HEADER_EVEN_INDEX
private static int
HEADER_ODD_INDEX
private static int
FOOTER_EVEN_INDEX
private static int
FOOTER_ODD_INDEX
private static int
HEADER_FIRST_INDEX
private static int
FOOTER_FIRST_INDEX
Constructors Summary
public WordDocument(String fileName)
Constructs a Word document from fileName. Parses the document and places all the important stuff into data structures.

param
fileName The name of the file to read.
throws
IOException if there is a problem while parsing the document.

  	this(new FileInputStream(fileName));
  
public WordDocument(InputStream inputStream)

        //do Ole stuff
        istream = inputStream;
        filesystem = new POIFSFileSystem(istream);

        //get important stuff from the Header block and parse all the
        //data structures
        readFIB();

        //get the SEPS for the main document text
        ArrayList sections = findProperties(_fcMin, _fcMin + _ccpText, _sectionTable.root);

        //iterate through sections, paragraphs, and character runs doing what
        //you will with the data.
        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);
        }
        //finish
        istream.close();

  
Methods Summary
private voidaddBlockContent(int start, int end, org.apache.poi.hdf.extractor.util.BTreeSet text, org.apache.poi.hdf.extractor.util.BTreeSet paragraphTable, org.apache.poi.hdf.extractor.util.BTreeSet characterTable)


    BTreeSet.BTreeNode root = paragraphTable.root;
    ArrayList 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 voidaddBorder(java.lang.StringBuffer buf, short[] brc, java.lang.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");
    }
  
private voidaddCharacterProperties(org.apache.poi.hdf.extractor.CHP chp, java.lang.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 voidaddListParagraphContent(org.apache.poi.hdf.extractor.data.LVL lvl, java.lang.StringBuffer blockBuffer, org.apache.poi.hdf.extractor.PAP pap, org.apache.poi.hdf.extractor.util.PapxNode currentNode, int start, int end, org.apache.poi.hdf.extractor.StyleDescription std)

    pap = (PAP)StyleSheet.uncompressProperty(lvl._papx, pap, _styleSheet, false);

    addParagraphProperties(pap, blockBuffer);

    ArrayList 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());
      ArrayList 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 voidaddParagraphContent(java.lang.StringBuffer blockBuffer, org.apache.poi.hdf.extractor.PAP pap, org.apache.poi.hdf.extractor.util.PapxNode currentNode, int start, int end, org.apache.poi.hdf.extractor.StyleDescription std)

    addParagraphProperties(pap, blockBuffer);

    ArrayList 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());
      ArrayList 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 voidaddParagraphProperties(org.apache.poi.hdf.extractor.PAP pap, java.lang.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 voidaddStaticContent(java.lang.String flowName, org.apache.poi.hdf.extractor.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 voidaddText(int start, int end, java.lang.StringBuffer buf)

    for(int x = start; x < end; x++)
    {
      char ch = '?";


      ch = (char)_header[x];

      addText(ch, buf);
    }
  
private voidaddText(char ch, java.lang.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 ArrayList();
      }
      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 voidaddUnicodeText(int start, int end, java.lang.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 intcalculateHeaderHeight(int start, int end, int pageWidth)

    ArrayList paragraphs = findProperties(start, end, _paragraphTable.root);
    int size = paragraphs.size();
    ArrayList lineHeights = new ArrayList();
    //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;

      ArrayList 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());

        ArrayList 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 voidcloseBlock(java.lang.StringBuffer buf)

    buf.append("</fo:block>\r\n");
  
public voidcloseDoc()

    _headerBuffer.append("</fo:layout-master-set>");
    _bodyBuffer.append("</fo:root>");
    //_headerBuffer.append();

    //test code
    try
    {
      OutputStreamWriter test = new OutputStreamWriter(new FileOutputStream(_outName), "8859_1");
      test.write(_headerBuffer.toString());
      test.write(_bodyBuffer.toString());
      test.flush();
      test.close();
    }
    catch(Throwable t)
    {
      t.printStackTrace();
    }
  
private voidcloseFlow()

    _bodyBuffer.append("</fo:flow>\r\n");
  
private voidcloseLine(java.lang.StringBuffer buf)

    buf.append("</fo:inline>");
  
private voidclosePage()

    _bodyBuffer.append("</fo:page-sequence>\r\n");
  
private java.lang.StringcreateEvenOddPageSequence(java.lang.String titlePage, java.lang.String evenPage, java.lang.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 voidcreateFontTable(byte[] tableStream)
creates the Font table

param
tableStream Main table stream buffer.

    int fontTableIndex = LittleEndian.getInt(_header, 0x112);
    int fontTableSize = LittleEndian.getInt(_header, 0x116);
    byte[] fontTable = new byte[fontTableSize];
    System.arraycopy(tableStream, fontTableIndex, fontTable, 0, fontTableSize);
    _fonts = new FontTable(fontTable);
  
private voidcreateListTables(byte[] tableStream)
creates the List data

param
tableStream Main table stream buffer.



    int lfoOffset = LittleEndian.getInt(_header, 0x2ea);
    int lfoSize = LittleEndian.getInt(_header, 0x2ee);
    byte[] plflfo = new byte[lfoSize];

    System.arraycopy(tableStream, lfoOffset, plflfo, 0, lfoSize);

    int lstOffset = LittleEndian.getInt(_header, 0x2e2);
    int lstSize = LittleEndian.getInt(_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 java.lang.StringcreatePageMaster(org.apache.poi.hdf.extractor.SEP sep, java.lang.String type, int section, java.lang.String regionBefore, java.lang.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 java.lang.StringcreatePageSequence(java.lang.String titlePage, java.lang.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 voidcreateParagraph(int start, int end, org.apache.poi.hdf.extractor.util.PapxNode currentNode, org.apache.poi.hdf.extractor.util.BTreeSet characterTable, org.apache.poi.hdf.extractor.util.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 ArrayList();
        }
        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 java.lang.StringcreateRegion(boolean before, org.apache.poi.hdf.extractor.HeaderFooter header, org.apache.poi.hdf.extractor.SEP sep, java.lang.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\" "+region+"/>";
// org.apache.fop.fo.expr.PropertyException: 
// Border and padding for region "xsl-region-before" must be '0' 
// (See 6.4.13 in XSL 1.0).
//             extent + "pt\" padding-left=\"" + marginLeft + "pt\" padding-right=\"" +
//             marginRight + "pt\" padding-top=\"" + marginTop + "pt\" padding-bottom=\"" +
//             marginBottom + "pt\" " + region + "/>";

  
private java.lang.StringcreateRegion(java.lang.String where, java.lang.String name)

    return "<fo:region-" + where + " overflow=\"scroll\" region-name=\"" + name + "\"/>";
  
private voidcreateStyleSheet(byte[] tableStream)
Creates the documents StyleSheet

param
tableStream Main table stream buffer.

      int stshIndex = LittleEndian.getInt(_header, 0xa2);
      int stshSize = LittleEndian.getInt(_header, 0xa6);
      byte[] stsh = new byte[stshSize];
      System.arraycopy(tableStream, stshIndex, stsh, 0, stshSize);

      _styleSheet = new StyleSheet(stsh);

  
private voidfindFormatting(byte[] tableStream, int charOffset, int charPlcSize, int parOffset, int parPlcSize)
Does all of the formatting parsing

param
tableStream Main table stream buffer.
param
charOffset beginning of the character bin table.
param
chrPlcSize size of the char bin table.
param
parOffset offset of the paragraph bin table.
param
size of the paragraph bin table.

      openDoc();
      createStyleSheet(tableStream);
      createListTables(tableStream);
      createFontTable(tableStream);

      //find character runs
      //Get all the chpx info and store it

      int arraySize = (charPlcSize - 4)/8;

      //first we must go through the bin table and find the fkps
      for(int x = 0; x < arraySize; x++)
      {


          //get page number(has nothing to do with document page)
          //containing the chpx for the paragraph
          int PN = LittleEndian.getInt(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 chpxs
          int crun = Utils.convertUnsignedByteToInt(fkp[511]);
          for(int y = 0; y < crun; y++)
          {
              //get the beginning fc of each paragraph text run
              int fcStart = LittleEndian.getInt(fkp, y * 4);
              int fcEnd = LittleEndian.getInt(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 = LittleEndian.getInt(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 = LittleEndian.getInt(fkp, y * 4);
              int fcEnd = LittleEndian.getInt(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);
      }


  
private java.util.ArrayListfindPAPProperties(int start, int end, org.apache.poi.hdf.extractor.util.BTreeSet$BTreeNode root)

    ArrayList results = new ArrayList();
    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)
              {
                ArrayList beforeItems = findPAPProperties(start, end, child);
                results.addAll(beforeItems);
              }
              results.add(papxNode);
            }
          }
          else
          {
            if(child != null)
            {
              ArrayList beforeItems = findPAPProperties(start, end, child);
              results.addAll(beforeItems);
            }
            break;
          }
        }
        else if(child != null)
        {
          ArrayList afterItems = findPAPProperties(start, end, child);
          results.addAll(afterItems);
        }
      }
      else
      {
        break;
      }
    }
    return results;
  
private java.util.ArrayListfindProperties(int start, int end, org.apache.poi.hdf.extractor.util.BTreeSet$BTreeNode root)
finds all chpx's that are between start and end

    ArrayList results = new ArrayList();
    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)
              {
                ArrayList beforeItems = findProperties(start, end, child);
                results.addAll(beforeItems);
              }
              results.add(xNode);
            }
            else if(start < xEnd)
            {
              results.add(xNode);
              //break;
            }
          }
          else
          {
            if(child != null)
            {
              ArrayList beforeItems = findProperties(start, end, child);
              results.addAll(beforeItems);
            }
            break;
          }
        }
        else if(child != null)
        {
          ArrayList afterItems = findProperties(start, end, child);
          results.addAll(afterItems);
        }
      }
      else
      {
        break;
      }
    }
    return results;
  
private org.apache.poi.hdf.extractor.HeaderFooterfindSectionHdrFtr(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 voidfindText(byte[] tableStream, int complexOffset)
Goes through the piece table and parses out the info regarding the text blocks. For Word 97 and greater all text is stored in the "complex" way because of unicode.

param
tableStream buffer containing the main table stream.
param
beginning of the complex data.
throws
IOException

    //actual text
    int pos = complexOffset;
    //skips through the prms before we reach the piece table. These contain data
    //for actual fast saved files
    while(tableStream[pos] == 1)
    {
        pos++;
        int skip = LittleEndian.getShort(tableStream, pos);
        pos += 2 + skip;
    }
    if(tableStream[pos] != 2)
    {
        throw new IOException("corrupted Word file");
    }
    else
    {
        //parse out the text pieces
        int pieceTableSize = LittleEndian.getInt(tableStream, ++pos);
        pos += 4;
        int pieces = (pieceTableSize - 4) / 12;
        for (int x = 0; x < pieces; x++)
        {
            int filePos = LittleEndian.getInt(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 = LittleEndian.getInt(tableStream, pos + (x + 1) * 4) -
                            LittleEndian.getInt(tableStream, pos + (x * 4));

            TextPiece piece = new TextPiece(filePos, totLength, unicode);
            _text.add(piece);

        }

    }
  
private java.lang.StringgetBorderStyle(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 java.lang.StringgetBorderThickness(int style)

    switch(style)
    {
      case 1:
        return "medium";
      case 2:
        return "thick";
      case 3:
        return "medium";
      case 5:
        return "thin";
      default:
        return "medium";
    }
  
private java.lang.StringgetBulletText(org.apache.poi.hdf.extractor.data.LVL lvl, org.apache.poi.hdf.extractor.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();
  
private java.lang.StringgetColor(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 java.lang.StringgetTextAlignment(byte jc)

    switch(jc)
    {
      case 0:
        return "start";
      case 1:
        return "center";
      case 2:
        return "end";
      case 3:
        return "justify";
      default:
        return "left";
    }
  
private voidinitDocProperties(byte[] tableStream)
inits this document DOP structure.

param
tableStream The documents table stream.

    int pos = LittleEndian.getInt(_header, 0x192);
    int size = LittleEndian.getInt(_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 = LittleEndian.getShort(dop, 2);
    _docProps._rncFtn = (num & 0x3);
    _docProps._nFtn = (short)(num & 0xfffc) >> 2;
    num = LittleEndian.getShort(dop, 52);
    _docProps._rncEdn = num & 0x3;
    _docProps._nEdn = (short)(num & 0xfffc) >> 2;
    num = LittleEndian.getShort(dop, 54);
    _docProps._epc = num & 0x3;
  
private voidinitPclfHdd(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);
  
public static voidmain(java.lang.String[] args)
right now this function takes one parameter: a Word file, and outputs an XSL-FO document at c:\test.xml (this is hardcoded)


                           
      
  
      /*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
      {
          _outName = args[1];
          WordDocument file = new WordDocument(args[0]);
          file.closeDoc();
      }
      catch(Exception e)
      {
          e.printStackTrace();
      }
      System.exit(0);
  
public voidopenDoc()

    _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");

  
private voidopenFlow()

    _bodyBuffer.append("<fo:flow flow-name=\"xsl-region-body\">\r\n");
  
private voidopenPage(java.lang.String page, java.lang.String type)

    _bodyBuffer.append("<fo:page-sequence master-reference=\"" + page + "\">\r\n");
  
private voidoverrideCellBorder(int row, int col, int height, int width, org.apache.poi.hdf.extractor.TC tc, org.apache.poi.hdf.extractor.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 voidprintTable()

    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();
        ArrayList 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 voidprocessComplexFile(boolean useTable1, int charTable, int charPlcSize, int parTable, int parPlcSize)
Extracts the correct Table stream from the POI filesystem then hands off to other functions to process text and formatting info. the name is based on the fact that in Word 8(97) all text (not character or paragraph formatting) is stored in complex format.

param
useTable1 boolean that specifies if we should use table1 or table0
param
charTable offset in table stream of character property bin table
param
charPlcSize size of character property bin table
param
parTable offset in table stream of paragraph property bin table.
param
parPlcSize size of paragraph property bin table.
return
boolean indocating success of
throws
IOException


      //get the location of the piece table
      int complexOffset = LittleEndian.getInt(_header, 0x1a2);

      String tablename=null;
      DocumentEntry tableEntry = null;
      if(useTable1)
      {
          tablename="1Table";
      }
      else
      {
          tablename="0Table";
      }
      tableEntry = (DocumentEntry)filesystem.getRoot().getEntry(tablename);

      //load the table stream into a buffer
      int size = tableEntry.getSize();
      byte[] tableStream = new byte[size];
      filesystem.createDocumentInputStream(tablename).read(tableStream);

      //init the DOP for this document
      initDocProperties(tableStream);
      //load the header/footer raw data for this document
      initPclfHdd(tableStream);
      //parse out the text locations
      findText(tableStream, complexOffset);
      //parse out text formatting
      findFormatting(tableStream, charTable, charPlcSize, parTable, parPlcSize);

  
private voidreadFIB()
Extracts the main document stream from the POI file then hands off to other functions that parse other areas.

throws
IOException

      //get the main document stream
      DocumentEntry headerProps =
        (DocumentEntry)filesystem.getRoot().getEntry("WordDocument");

      //I call it the header but its also the main document stream
      _header = new byte[headerProps.getSize()];
      filesystem.createDocumentInputStream("WordDocument").read(_header);

      //Get the information we need from the header
      int info = LittleEndian.getShort(_header, 0xa);

      _fcMin = LittleEndian.getInt(_header, 0x18);
      _ccpText = LittleEndian.getInt(_header, 0x4c);
      _ccpFtn = LittleEndian.getInt(_header, 0x50);

      int charPLC = LittleEndian.getInt(_header, 0xfa);
      int charPlcSize = LittleEndian.getInt(_header, 0xfe);
      int parPLC = LittleEndian.getInt(_header, 0x102);
      int parPlcSize = LittleEndian.getInt(_header, 0x106);
      boolean useTable1 = (info & 0x200) != 0;

      //process the text and formatting properties
      processComplexFile(useTable1, charPLC, charPlcSize, parPLC, parPlcSize);
  
public voidwriteAllText(java.io.Writer out)
Spits out the document text

param
out The Writer to write the text to.
throws
IOException if there is a problem while reading from the file or writing out the text.

    int textStart = Utils.convertBytesToInt(_header, 0x18);
    int textEnd = Utils.convertBytesToInt(_header, 0x1c);
    ArrayList 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)
        {
	  ch = (char)Utils.convertBytesToShort(_header, y);
	  out.write(ch);
        }
      }
      else
      {
	String sText = new String(_header, start, end-start);
	out.write(sText);
      }
    }
  
public voidwriteSection(int start, int end, org.apache.poi.hdf.extractor.SEP sep, org.apache.poi.hdf.extractor.util.BTreeSet text, org.apache.poi.hdf.extractor.util.BTreeSet paragraphTable, org.apache.poi.hdf.extractor.util.BTreeSet characterTable, org.apache.poi.hdf.extractor.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++;