KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hdf > extractor > WordDocument


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18
19
20 package org.apache.poi.hdf.extractor;
21
22
23 import org.apache.poi.hdf.extractor.util.*;
24 import org.apache.poi.hdf.extractor.data.*;
25 import java.util.*;
26 import java.io.*;
27 import javax.swing.*;
28
29 import java.awt.*;
30
31 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
32 import org.apache.poi.poifs.filesystem.POIFSDocument;
33 import org.apache.poi.poifs.filesystem.DocumentEntry;
34
35 import org.apache.poi.util.LittleEndian;
36
37 /**
38  * This class contains the main functionality for the Word file "reader". Much
39  * of the code in this class is based on the Word 97 document file format. Only
40  * works for non-complex files
41  *
42  * @author Ryan Ackley
43  */

44
45 public class WordDocument
46 {
47   /** byte buffer containing the main Document stream*/
48   byte[] _header;
49   /** contains all style information for this document see Word 97 Doc spec*/
50   StyleSheet _styleSheet;
51   /** contains All list information for this document*/
52   ListTables _listTables;
53   /** contains global Document properties for this document*/
54   DOP _docProps = new DOP();
55
56   int _currentList = -1;
57   int _tableSize;
58   int _sectionCounter = 1;
59   /** fonts available for this document*/
60   FontTable _fonts;
61
62   /** document's text blocks*/
63   BTreeSet _text = new BTreeSet();
64   /** document's character runs */
65   BTreeSet _characterTable = new BTreeSet();
66   /** document's paragraphs*/
67   BTreeSet _paragraphTable = new BTreeSet();
68   /** doucment's sections*/
69   BTreeSet _sectionTable = new BTreeSet();
70
71   /** used for XSL-FO conversion*/
72   StringBuffer JavaDoc _headerBuffer = new StringBuffer JavaDoc();
73   /** used for XSL-FO conversion*/
74   StringBuffer JavaDoc _bodyBuffer = new StringBuffer JavaDoc();
75   /** used for XSL-FO table conversion*/
76   StringBuffer JavaDoc _cellBuffer;
77   /** used for XSL-FO table conversion*/
78   ArrayList _cells;
79   /** used for XSL-FO table conversion*/
80   ArrayList _table;
81
82   /** document's header and footer information*/
83   byte[] _plcfHdd;
84
85   /** starting position of text in main document stream*/
86   int _fcMin;
87   /** length of main document text stream*/
88   int _ccpText;
89   /** length of footnotes text*/
90   int _ccpFtn;
91
92   /** The name of the file to write to */
93   private static String JavaDoc _outName;
94
95   /** OLE stuff*/
96   private InputStream istream;
97   /** OLE stuff*/
98   private POIFSFileSystem filesystem;
99
100   //used internally
101
private static int HEADER_EVEN_INDEX = 0;
102   private static int HEADER_ODD_INDEX = 1;
103   private static int FOOTER_EVEN_INDEX = 2;
104   private static int FOOTER_ODD_INDEX = 3;
105   private static int HEADER_FIRST_INDEX = 4;
106   private static int FOOTER_FIRST_INDEX = 5;
107
108   /**
109    * right now this function takes one parameter: a Word file, and outputs an
110    * XSL-FO document at c:\test.xml (this is hardcoded)
111    */

112   public static void main(String JavaDoc args[])
113   {
114       /*try
115       {
116         WordDocument file = new WordDocument(args[0], "r");
117         Writer out = new BufferedWriter(new FileWriter(args[1]));
118         file.writeAllText(out);
119         out.flush();
120         out.close();
121       }
122       catch(Throwable t)
123       {
124         t.printStackTrace();
125       }*/

126       try
127       {
128           _outName = args[1];
129           WordDocument file = new WordDocument(args[0]);
130           file.closeDoc();
131       }
132       catch(Exception JavaDoc e)
133       {
134           e.printStackTrace();
135       }
136       System.exit(0);
137   }
138   /**
139    * Spits out the document text
140    *
141    * @param out The Writer to write the text to.
142    * @throws IOException if there is a problem while reading from the file or
143    * writing out the text.
144    */

145   public void writeAllText(Writer out) throws IOException
146   {
147     int textStart = Utils.convertBytesToInt(_header, 0x18);
148     int textEnd = Utils.convertBytesToInt(_header, 0x1c);
149     ArrayList textPieces = findProperties(textStart, textEnd, _text.root);
150     int size = textPieces.size();
151
152     for(int x = 0; x < size; x++)
153     {
154       TextPiece nextPiece = (TextPiece)textPieces.get(x);
155       int start = nextPiece.getStart();
156       int end = nextPiece.getEnd();
157       boolean unicode = nextPiece.usesUnicode();
158       int add = 1;
159
160       if(unicode)
161       {
162         add = 2;
163         char ch;
164         for(int y = start; y < end; y += add)
165         {
166       ch = (char)Utils.convertBytesToShort(_header, y);
167       out.write(ch);
168         }
169       }
170       else
171       {
172     String JavaDoc sText = new String JavaDoc(_header, start, end-start);
173     out.write(sText);
174       }
175     }
176   }
177   /**
178    * Constructs a Word document from fileName. Parses the document and places
179    * all the important stuff into data structures.
180    *
181    * @param fileName The name of the file to read.
182    * @throws IOException if there is a problem while parsing the document.
183    */

184   public WordDocument(String JavaDoc fileName) throws IOException
185   {
186     this(new FileInputStream(fileName));
187   }
188   
189   public WordDocument(InputStream inputStream) throws IOException
190   {
191         //do Ole stuff
192
istream = inputStream;
193         filesystem = new POIFSFileSystem(istream);
194
195         //get important stuff from the Header block and parse all the
196
//data structures
197
readFIB();
198
199         //get the SEPS for the main document text
200
ArrayList sections = findProperties(_fcMin, _fcMin + _ccpText, _sectionTable.root);
201
202         //iterate through sections, paragraphs, and character runs doing what
203
//you will with the data.
204
int size = sections.size();
205         for(int x = 0; x < size; x++)
206         {
207           SepxNode node = (SepxNode)sections.get(x);
208           int start = node.getStart();
209           int end = node.getEnd();
210           SEP sep = (SEP)StyleSheet.uncompressProperty(node.getSepx(), new SEP(), _styleSheet);
211           writeSection(Math.max(_fcMin, start), Math.min(_fcMin + _ccpText, end), sep, _text, _paragraphTable, _characterTable, _styleSheet);
212         }
213         //finish
214
istream.close();
215
216   }
217   /**
218    * Extracts the main document stream from the POI file then hands off to other
219    * functions that parse other areas.
220    *
221    * @throws IOException
222    */

223   private void readFIB() throws IOException
224   {
225       //get the main document stream
226
DocumentEntry headerProps =
227         (DocumentEntry)filesystem.getRoot().getEntry("WordDocument");
228
229       //I call it the header but its also the main document stream
230
_header = new byte[headerProps.getSize()];
231       filesystem.createDocumentInputStream("WordDocument").read(_header);
232
233       //Get the information we need from the header
234
int info = LittleEndian.getShort(_header, 0xa);
235
236       _fcMin = LittleEndian.getInt(_header, 0x18);
237       _ccpText = LittleEndian.getInt(_header, 0x4c);
238       _ccpFtn = LittleEndian.getInt(_header, 0x50);
239
240       int charPLC = LittleEndian.getInt(_header, 0xfa);
241       int charPlcSize = LittleEndian.getInt(_header, 0xfe);
242       int parPLC = LittleEndian.getInt(_header, 0x102);
243       int parPlcSize = LittleEndian.getInt(_header, 0x106);
244       boolean useTable1 = (info & 0x200) != 0;
245
246       //process the text and formatting properties
247
processComplexFile(useTable1, charPLC, charPlcSize, parPLC, parPlcSize);
248   }
249
250   /**
251    * Extracts the correct Table stream from the POI filesystem then hands off to
252    * other functions to process text and formatting info. the name is based on
253    * the fact that in Word 8(97) all text (not character or paragraph formatting)
254    * is stored in complex format.
255    *
256    * @param useTable1 boolean that specifies if we should use table1 or table0
257    * @param charTable offset in table stream of character property bin table
258    * @param charPlcSize size of character property bin table
259    * @param parTable offset in table stream of paragraph property bin table.
260    * @param parPlcSize size of paragraph property bin table.
261    * @return boolean indocating success of
262    * @throws IOException
263    */

264   private void processComplexFile(boolean useTable1, int charTable,
265                                      int charPlcSize, int parTable, int parPlcSize) throws IOException
266   {
267
268       //get the location of the piece table
269
int complexOffset = LittleEndian.getInt(_header, 0x1a2);
270
271       String JavaDoc tablename=null;
272       DocumentEntry tableEntry = null;
273       if(useTable1)
274       {
275           tablename="1Table";
276       }
277       else
278       {
279           tablename="0Table";
280       }
281       tableEntry = (DocumentEntry)filesystem.getRoot().getEntry(tablename);
282
283       //load the table stream into a buffer
284
int size = tableEntry.getSize();
285       byte[] tableStream = new byte[size];
286       filesystem.createDocumentInputStream(tablename).read(tableStream);
287
288       //init the DOP for this document
289
initDocProperties(tableStream);
290       //load the header/footer raw data for this document
291
initPclfHdd(tableStream);
292       //parse out the text locations
293
findText(tableStream, complexOffset);
294       //parse out text formatting
295
findFormatting(tableStream, charTable, charPlcSize, parTable, parPlcSize);
296
297   }
298   /**
299    * Goes through the piece table and parses out the info regarding the text
300    * blocks. For Word 97 and greater all text is stored in the "complex" way
301    * because of unicode.
302    *
303    * @param tableStream buffer containing the main table stream.
304    * @param beginning of the complex data.
305    * @throws IOException
306    */

307   private void findText(byte[] tableStream, int complexOffset) throws IOException
308   {
309     //actual text
310
int pos = complexOffset;
311     //skips through the prms before we reach the piece table. These contain data
312
//for actual fast saved files
313
while(tableStream[pos] == 1)
314     {
315         pos++;
316         int skip = LittleEndian.getShort(tableStream, pos);
317         pos += 2 + skip;
318     }
319     if(tableStream[pos] != 2)
320     {
321         throw new IOException("corrupted Word file");
322     }
323     else
324     {
325         //parse out the text pieces
326
int pieceTableSize = LittleEndian.getInt(tableStream, ++pos);
327         pos += 4;
328         int pieces = (pieceTableSize - 4) / 12;
329         for (int x = 0; x < pieces; x++)
330         {
331             int filePos = LittleEndian.getInt(tableStream, pos + ((pieces + 1) * 4) + (x * 8) + 2);
332             boolean unicode = false;
333             if ((filePos & 0x40000000) == 0)
334             {
335                 unicode = true;
336             }
337             else
338             {
339                 unicode = false;
340                 filePos &= ~(0x40000000);//gives me FC in doc stream
341
filePos /= 2;
342             }
343             int totLength = LittleEndian.getInt(tableStream, pos + (x + 1) * 4) -
344                             LittleEndian.getInt(tableStream, pos + (x * 4));
345
346             TextPiece piece = new TextPiece(filePos, totLength, unicode);
347             _text.add(piece);
348
349         }
350
351     }
352   }
353
354   /**
355    * Does all of the formatting parsing
356    *
357    * @param tableStream Main table stream buffer.
358    * @param charOffset beginning of the character bin table.
359    * @param chrPlcSize size of the char bin table.
360    * @param parOffset offset of the paragraph bin table.
361    * @param size of the paragraph bin table.
362    */

363   private void findFormatting(byte[] tableStream, int charOffset,
364                               int charPlcSize, int parOffset, int parPlcSize) throws IOException
365   {
366       openDoc();
367       createStyleSheet(tableStream);
368       createListTables(tableStream);
369       createFontTable(tableStream);
370
371       //find character runs
372
//Get all the chpx info and store it
373

374       int arraySize = (charPlcSize - 4)/8;
375
376       //first we must go through the bin table and find the fkps
377
for(int x = 0; x < arraySize; x++)
378       {
379
380
381           //get page number(has nothing to do with document page)
382
//containing the chpx for the paragraph
383
int PN = LittleEndian.getInt(tableStream, charOffset + (4 * (arraySize + 1) + (4 * x)));
384
385           byte[] fkp = new byte[512];
386           System.arraycopy(_header, (PN * 512), fkp, 0, 512);
387           //take each fkp and get the chpxs
388
int crun = Utils.convertUnsignedByteToInt(fkp[511]);
389           for(int y = 0; y < crun; y++)
390           {
391               //get the beginning fc of each paragraph text run
392
int fcStart = LittleEndian.getInt(fkp, y * 4);
393               int fcEnd = LittleEndian.getInt(fkp, (y+1) * 4);
394               //get the offset in fkp of the papx for this paragraph
395
int chpxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + y]);
396
397               //optimization if offset == 0 use "Normal" style
398
if(chpxOffset == 0)
399
400               {
401                 _characterTable.add(new ChpxNode(fcStart, fcEnd, new byte[0]));
402                 continue;
403               }
404
405               int size = Utils.convertUnsignedByteToInt(fkp[chpxOffset]);
406
407               byte[] chpx = new byte[size];
408               System.arraycopy(fkp, ++chpxOffset, chpx, 0, size);
409               //_papTable.put(new Integer(fcStart), papx);
410
_characterTable.add(new ChpxNode(fcStart, fcEnd, chpx));
411           }
412
413       }
414
415       //find paragraphs
416
arraySize = (parPlcSize - 4)/8;
417       //first we must go through the bin table and find the fkps
418
for(int x = 0; x < arraySize; x++)
419       {
420           int PN = LittleEndian.getInt(tableStream, parOffset + (4 * (arraySize + 1) + (4 * x)));
421
422           byte[] fkp = new byte[512];
423           System.arraycopy(_header, (PN * 512), fkp, 0, 512);
424           //take each fkp and get the paps
425
int crun = Utils.convertUnsignedByteToInt(fkp[511]);
426           for(int y = 0; y < crun; y++)
427           {
428               //get the beginning fc of each paragraph text run
429
int fcStart = LittleEndian.getInt(fkp, y * 4);
430               int fcEnd = LittleEndian.getInt(fkp, (y+1) * 4);
431               //get the offset in fkp of the papx for this paragraph
432
int papxOffset = 2 * Utils.convertUnsignedByteToInt(fkp[((crun + 1) * 4) + (y * 13)]);
433               int size = 2 * Utils.convertUnsignedByteToInt(fkp[papxOffset]);
434               if(size == 0)
435               {
436                   size = 2 * Utils.convertUnsignedByteToInt(fkp[++papxOffset]);
437               }
438               else
439               {
440                   size--;
441               }
442
443               byte[] papx = new byte[size];
444               System.arraycopy(fkp, ++papxOffset, papx, 0, size);
445               _paragraphTable.add(new PapxNode(fcStart, fcEnd, papx));
446
447           }
448
449       }
450
451       //find sections
452
int fcMin = Utils.convertBytesToInt(_header, 0x18);
453       int plcfsedFC = Utils.convertBytesToInt(_header, 0xca);
454       int plcfsedSize = Utils.convertBytesToInt(_header, 0xce);
455       byte[] plcfsed = new byte[plcfsedSize];
456       System.arraycopy(tableStream, plcfsedFC, plcfsed, 0, plcfsedSize);
457
458       arraySize = (plcfsedSize - 4)/16;
459
460       //openDoc();
461

462       for(int x = 0; x < arraySize; x++)
463       {
464           int sectionStart = Utils.convertBytesToInt(plcfsed, x * 4) + fcMin;
465           int sectionEnd = Utils.convertBytesToInt(plcfsed, (x+1) * 4) + fcMin;
466           int sepxStart = Utils.convertBytesToInt(plcfsed, 4 * (arraySize + 1) + (x * 12) + 2);
467           int sepxSize = Utils.convertBytesToShort(_header, sepxStart);
468           byte[] sepx = new byte[sepxSize];
469           System.arraycopy(_header, sepxStart + 2, sepx, 0, sepxSize);
470           SepxNode node = new SepxNode(x + 1, sectionStart, sectionEnd, sepx);
471           _sectionTable.add(node);
472       }
473
474
475   }
476
477   public void openDoc()
478   {
479     _headerBuffer.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r\n");
480     _headerBuffer.append("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\r\n");
481     _headerBuffer.append("<fo:layout-master-set>\r\n");
482
483   }
484   private HeaderFooter findSectionHdrFtr(int type, int index)
485   {
486     if(_plcfHdd.length < 50)
487     {
488       return new HeaderFooter(0,0,0);
489     }
490     int start = _fcMin + _ccpText + _ccpFtn;
491     int end = start;
492     int arrayIndex = 0;
493
494     switch(type)
495     {
496       case HeaderFooter.HEADER_EVEN:
497            arrayIndex = (HEADER_EVEN_INDEX + (index * 6));
498            break;
499       case HeaderFooter.FOOTER_EVEN:
500            arrayIndex = (FOOTER_EVEN_INDEX + (index * 6));
501            break;
502       case HeaderFooter.HEADER_ODD:
503            arrayIndex = (HEADER_ODD_INDEX + (index * 6));
504            break;
505       case HeaderFooter.FOOTER_ODD:
506            arrayIndex = (FOOTER_ODD_INDEX + (index * 6));
507            break;
508       case HeaderFooter.HEADER_FIRST:
509            arrayIndex = (HEADER_FIRST_INDEX + (index * 6));
510            break;
511       case HeaderFooter.FOOTER_FIRST:
512            arrayIndex = (FOOTER_FIRST_INDEX + (index * 6));
513            break;
514     }
515     start += Utils.convertBytesToInt(_plcfHdd, (arrayIndex * 4));
516     end += Utils.convertBytesToInt(_plcfHdd, (arrayIndex + 1) * 4);
517
518     HeaderFooter retValue = new HeaderFooter(type, start, end);
519
520     if((end - start) == 0 && index > 1)
521     {
522       retValue = findSectionHdrFtr(type, index - 1);
523     }
524     return retValue;
525   }
526   /**
527    * inits this document DOP structure.
528    *
529    * @param tableStream The documents table stream.
530    */

531   private void initDocProperties(byte[] tableStream)
532   {
533     int pos = LittleEndian.getInt(_header, 0x192);
534     int size = LittleEndian.getInt(_header, 0x196);
535     byte[] dop = new byte[size];
536
537     System.arraycopy(tableStream, pos, dop, 0, size);
538
539     _docProps._fFacingPages = (dop[0] & 0x1) > 0;
540     _docProps._fpc = (dop[0] & 0x60) >> 5;
541
542     short num = LittleEndian.getShort(dop, 2);
543     _docProps._rncFtn = (num & 0x3);
544     _docProps._nFtn = (short)(num & 0xfffc) >> 2;
545     num = LittleEndian.getShort(dop, 52);
546     _docProps._rncEdn = num & 0x3;
547     _docProps._nEdn = (short)(num & 0xfffc) >> 2;
548     num = LittleEndian.getShort(dop, 54);
549     _docProps._epc = num & 0x3;
550   }
551
552   public void writeSection(int start, int end, SEP sep, BTreeSet text,
553                            BTreeSet paragraphTable, BTreeSet characterTable,
554                            StyleSheet stylesheet)
555   {
556
557     HeaderFooter titleHeader = findSectionHdrFtr(HeaderFooter.HEADER_FIRST, _sectionCounter);
558     HeaderFooter titleFooter = findSectionHdrFtr(HeaderFooter.FOOTER_FIRST, _sectionCounter);
559     HeaderFooter oddHeader = findSectionHdrFtr(HeaderFooter.HEADER_ODD, _sectionCounter);
560     HeaderFooter evenHeader = findSectionHdrFtr(HeaderFooter.HEADER_EVEN, _sectionCounter);
561     HeaderFooter oddFooter = findSectionHdrFtr(HeaderFooter.FOOTER_ODD, _sectionCounter);
562     HeaderFooter evenFooter = findSectionHdrFtr(HeaderFooter.FOOTER_EVEN, _sectionCounter);
563
564     String JavaDoc titlePage = null;
565     String JavaDoc evenPage = null;
566     String JavaDoc oddPage = null;
567     String JavaDoc regPage = null;
568
569     String JavaDoc sequenceName = null;
570
571     /*if(sep._fTitlePage)
572     {
573       titlePage = createPageMaster(sep, "first", _sectionCounter, createRegion("before", "title-header"), createRegion("after", "title-footer"));
574
575       if(!titleHeader.isEmpty())
576       {
577         addStaticContent("title-header" + _sectionCounter, titleHeader);
578       }
579       if(!titleFooter.isEmpty())
580       {
581         addStaticContent("title-footer" + _sectionCounter, titleFooter);
582       }
583     }*/

584
585     if(_docProps._fFacingPages)
586     {
587       if(sep._fTitlePage)
588       {
589         String JavaDoc before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter);
590         String JavaDoc after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter);
591         titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
592       }
593       String JavaDoc before = createRegion(true, evenHeader, sep, "even-header" + _sectionCounter);
594       String JavaDoc after = createRegion(false, evenFooter, sep, "even-footer" + _sectionCounter);
595       evenPage = createPageMaster(sep, "even", _sectionCounter, before, after);
596       before = createRegion(true, oddHeader, sep, "odd-header" + _sectionCounter);
597       after = createRegion(false, oddFooter, sep, "odd-footer" + _sectionCounter);
598       oddPage = createPageMaster(sep, "odd", _sectionCounter, before, after);
599       sequenceName = createEvenOddPageSequence(titlePage, evenPage, oddPage, _sectionCounter);
600
601       openPage(sequenceName, "reference");
602
603       if(sep._fTitlePage)
604       {
605
606
607         if(!titleHeader.isEmpty())
608         {
609           addStaticContent("title-header" + _sectionCounter, titleHeader);
610         }
611         if(!titleFooter.isEmpty())
612         {
613           addStaticContent("title-footer" + _sectionCounter, titleFooter);
614         }
615       }
616
617       //handle the headers and footers for odd and even pages
618
if(!oddHeader.isEmpty())
619       {
620         addStaticContent("odd-header" + _sectionCounter, oddHeader);
621       }
622       if(!oddFooter.isEmpty())
623       {
624         addStaticContent("odd-footer" + _sectionCounter, oddFooter);
625       }
626       if(!evenHeader.isEmpty())
627       {
628         addStaticContent("even-header" + _sectionCounter, evenHeader);
629       }
630       if(!evenFooter.isEmpty())
631       {
632         addStaticContent("even-footer" + _sectionCounter, evenFooter);
633       }
634       openFlow();
635       addBlockContent(start, end, text, paragraphTable, characterTable);
636       closeFlow();
637       closePage();
638     }
639     else
640     {
641       /*if(sep._fTitlePage)
642       {
643         String before = createRegion(true, titleHeader, sep);
644         String after = createRegion(false, titleFooter, sep);
645         titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
646       }*/

647       String JavaDoc before = createRegion(true, oddHeader, sep, null);
648       String JavaDoc after = createRegion(false, oddFooter, sep, null);
649       regPage = createPageMaster(sep, "page", _sectionCounter, before, after);
650
651       if(sep._fTitlePage)
652       {
653         before = createRegion(true, titleHeader, sep, "title-header" + _sectionCounter);
654         after = createRegion(false, titleFooter, sep, "title-footer" + _sectionCounter);
655         titlePage = createPageMaster(sep, "first", _sectionCounter, before, after);
656         sequenceName = createPageSequence(titlePage, regPage, _sectionCounter);
657         openPage(sequenceName, "reference");
658
659         if(!titleHeader.isEmpty())
660         {
661           addStaticContent("title-header" + _sectionCounter, titleHeader);
662         }
663         if(!titleFooter.isEmpty())
664         {
665           addStaticContent("title-footer" + _sectionCounter, titleFooter);
666         }
667       }
668       else
669       {
670         openPage(regPage, "name");
671       }
672       if(!oddHeader.isEmpty())
673       {
674         addStaticContent("xsl-region-before", oddHeader);
675       }
676       if(!oddFooter.isEmpty())
677       {
678         addStaticContent("xsl-region-after", oddFooter);
679       }
680       openFlow();
681       addBlockContent(start, end, text, paragraphTable, characterTable);
682       closeFlow();
683       closePage();
684     }
685     _sectionCounter++;
686   }
687
688   private int calculateHeaderHeight(int start, int end, int pageWidth)
689   {
690     ArrayList paragraphs = findProperties(start, end, _paragraphTable.root);
691     int size = paragraphs.size();
692     ArrayList lineHeights = new ArrayList();
693     //StyleContext context = StyleContext.getDefaultStyleContext();
694

695     for(int x = 0; x < size; x++)
696     {
697       PapxNode node = (PapxNode)paragraphs.get(x);
698       int parStart = Math.max(node.getStart(), start);
699       int parEnd = Math.min(node.getEnd(), end);
700
701       int lineWidth = 0;
702       int maxHeight = 0;
703
704       ArrayList textRuns = findProperties(parStart, parEnd, _characterTable.root);
705       int charSize = textRuns.size();
706
707       //StringBuffer lineBuffer = new StringBuffer();
708
for(int y = 0; y < charSize; y++)
709       {
710         ChpxNode charNode = (ChpxNode)textRuns.get(y);
711         int istd = Utils.convertBytesToShort(node.getPapx(), 0);
712         StyleDescription sd = _styleSheet.getStyleDescription(istd);
713         CHP chp = (CHP)StyleSheet.uncompressProperty(charNode.getChpx(), sd.getCHP(), _styleSheet);
714
715         //get Font info
716
//FontMetrics metrics = getFontMetrics(chp, context);
717

718         int height = 10;//metrics.getHeight();
719
maxHeight = Math.max(maxHeight, height);
720
721         int charStart = Math.max(parStart, charNode.getStart());
722         int charEnd = Math.min(parEnd, charNode.getEnd());
723
724         ArrayList text = findProperties(charStart, charEnd, _text.root);
725
726         int textSize = text.size();
727         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
728         for(int z = 0; z < textSize; z++)
729         {
730
731           TextPiece piece = (TextPiece)text.get(z);
732           int textStart = Math.max(piece.getStart(), charStart);
733           int textEnd = Math.min(piece.getEnd(), charEnd);
734
735           if(piece.usesUnicode())
736           {
737             addUnicodeText(textStart, textEnd, buf);
738           }
739           else
740           {
741             addText(textStart, textEnd, buf);
742           }
743         }
744
745         String JavaDoc tempString = buf.toString();
746         lineWidth += 10 * tempString.length();//metrics.stringWidth(tempString);
747
if(lineWidth > pageWidth)
748         {
749           lineHeights.add(new Integer JavaDoc(maxHeight));
750           maxHeight = 0;
751           lineWidth = 0;
752         }
753       }
754       lineHeights.add(new Integer JavaDoc(maxHeight));
755     }
756     int sum = 0;
757     size = lineHeights.size();
758     for(int x = 0; x < size; x++)
759     {
760       Integer JavaDoc height = (Integer JavaDoc)lineHeights.get(x);
761       sum += height.intValue();
762     }
763
764     return sum;
765   }
766 /* private FontMetrics getFontMetrics(CHP chp, StyleContext context)
767   {
768     String fontName = _fonts.getFont(chp._ftcAscii);
769     int style = 0;
770     if(chp._bold)
771     {
772       style |= Font.BOLD;
773     }
774     if(chp._italic)
775     {
776       style |= Font.ITALIC;
777     }
778
779     Font font = new Font(fontName, style, chp._hps/2);
780
781
782     return context.getFontMetrics(font);
783   }*/

784   private String JavaDoc createRegion(boolean before, HeaderFooter header, SEP sep, String JavaDoc name)
785   {
786     if(header.isEmpty())
787     {
788       return "";
789     }
790     String JavaDoc region = "region-name=\"" + name + "\"";
791     if(name == null)
792     {
793       region = "";
794     }
795     int height = calculateHeaderHeight(header.getStart(), header.getEnd(), sep._xaPage/20);
796     int marginTop = 0;
797     int marginBottom = 0;
798     int extent = 0;
799     String JavaDoc where = null;
800     String JavaDoc align = null;
801
802     if(before)
803     {
804       where = "before";
805       align = "before";
806       marginTop = sep._dyaHdrTop/20;
807       extent = height + marginTop;
808       sep._dyaTop = Math.max(extent*20, sep._dyaTop);
809     }
810     else
811     {
812       where = "after";
813       align = "after";
814       marginBottom = sep._dyaHdrBottom/20;
815       extent = height + marginBottom;
816       sep._dyaBottom = Math.max(extent*20, sep._dyaBottom);
817     }
818
819     int marginLeft = sep._dxaLeft/20;
820     int marginRight = sep._dxaRight/20;
821
822     return "<fo:region-" + where + " display-align=\"" + align + "\" extent=\"" +
823              extent + "pt\" padding-left=\"" + marginLeft + "pt\" padding-right=\"" +
824              marginRight + "pt\" padding-top=\"" + marginTop + "pt\" padding-bottom=\"" +
825              marginBottom + "pt\" " + region + "/>";
826
827   }
828   private String JavaDoc createRegion(String JavaDoc where, String JavaDoc name)
829   {
830     return "<fo:region-" + where + " overflow=\"scroll\" region-name=\"" + name + "\"/>";
831   }
832   private String JavaDoc createEvenOddPageSequence(String JavaDoc titlePage, String JavaDoc evenPage, String JavaDoc oddPage, int counter)
833   {
834     String JavaDoc name = "my-sequence" + counter;
835     _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> ");
836     _headerBuffer.append("<fo:repeatable-page-master-alternatives>");
837     if(titlePage != null)
838     {
839       _headerBuffer.append("<fo:conditional-page-master-reference " +
840                            "page-position=\"first\" master-reference=\"" +
841                             titlePage + "\"/>");
842     }
843     _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"odd\" ");
844     _headerBuffer.append("master-reference=\""+ oddPage + "\"/> ");
845     _headerBuffer.append("<fo:conditional-page-master-reference odd-or-even=\"even\" ");
846     _headerBuffer.append("master-reference=\"" + evenPage + "\"/> ");
847     _headerBuffer.append("</fo:repeatable-page-master-alternatives>");
848     _headerBuffer.append("</fo:page-sequence-master>");
849     return name;
850   }
851   private String JavaDoc createPageSequence(String JavaDoc titlePage, String JavaDoc regPage, int counter)
852   {
853     String JavaDoc name = null;
854     if(titlePage != null)
855     {
856       name = "my-sequence" + counter;
857       _headerBuffer.append("<fo:page-sequence-master master-name=\"" + name + "\"> ");
858       _headerBuffer.append("<fo:single-page-master-reference master-reference=\"" + titlePage + "\"/>");
859       _headerBuffer.append("<fo:repeatable-page-master-reference master-reference=\"" + regPage + "\"/>");
860       _headerBuffer.append("</fo:page-sequence-master>");
861     }
862     return name;
863   }
864   private void addBlockContent(int start, int end, BTreeSet text,
865                               BTreeSet paragraphTable, BTreeSet characterTable)
866   {
867
868     BTreeSet.BTreeNode root = paragraphTable.root;
869     ArrayList pars = findProperties(start, end, root);
870     //root = characterTable.root;
871
int size = pars.size();
872
873     for(int c = 0; c < size; c++)
874     {
875       PapxNode currentNode = (PapxNode)pars.get(c);
876       createParagraph(start, end, currentNode, characterTable, text);
877     }
878     //closePage();
879
}
880   private String JavaDoc getTextAlignment(byte jc)
881   {
882     switch(jc)
883     {
884       case 0:
885         return "start";
886       case 1:
887         return "center";
888       case 2:
889         return "end";
890       case 3:
891         return "justify";
892       default:
893         return "left";
894     }
895   }
896   private void createParagraph(int start, int end, PapxNode currentNode,
897                                BTreeSet characterTable, BTreeSet text)
898   {
899     StringBuffer JavaDoc blockBuffer = _bodyBuffer;
900     byte[] papx = currentNode.getPapx();
901     int istd = Utils.convertBytesToShort(papx, 0);
902     StyleDescription std = _styleSheet.getStyleDescription(istd);
903     PAP pap = (PAP)StyleSheet.uncompressProperty(papx, std.getPAP(), _styleSheet);
904
905     //handle table cells
906
if(pap._fInTable > 0)
907     {
908       if(pap._fTtp == 0)
909       {
910         if(_cellBuffer == null)
911         {
912           _cellBuffer = new StringBuffer JavaDoc();
913         }
914         blockBuffer = _cellBuffer;
915       }
916       else
917       {
918         if(_table == null)
919         {
920           _table = new ArrayList();
921         }
922         TAP tap = (TAP)StyleSheet.uncompressProperty(papx, new TAP(), _styleSheet);
923         TableRow nextRow = new TableRow(_cells, tap);
924         _table.add(nextRow);
925         _cells = null;
926         return;
927       }
928     }
929     else
930     {
931       //just prints out any table that is stored in _table
932
printTable();
933     }
934
935     if(pap._ilfo > 0)
936     {
937       LVL lvl = _listTables.getLevel(pap._ilfo, pap._ilvl);
938       addListParagraphContent(lvl, blockBuffer, pap, currentNode, start, end, std);
939     }
940     else
941     {
942       addParagraphContent(blockBuffer, pap, currentNode, start, end, std);
943     }
944
945   }
946
947   private void addListParagraphContent(LVL lvl, StringBuffer JavaDoc blockBuffer, PAP pap,
948                                        PapxNode currentNode, int start, int end,
949                                        StyleDescription std)
950   {
951     pap = (PAP)StyleSheet.uncompressProperty(lvl._papx, pap, _styleSheet, false);
952
953     addParagraphProperties(pap, blockBuffer);
954
955     ArrayList charRuns = findProperties(Math.max(currentNode.getStart(), start),
956                                      Math.min(currentNode.getEnd(), end),
957                                      _characterTable.root);
958     int len = charRuns.size();
959
960     CHP numChp = (CHP)StyleSheet.uncompressProperty(((ChpxNode)charRuns.get(len-1)).getChpx(), std.getCHP(), _styleSheet);
961
962     numChp = (CHP)StyleSheet.uncompressProperty(lvl._chpx, numChp, _styleSheet);
963
964     //StyleContext context = StyleContext.getDefaultStyleContext();
965
//FontMetrics metrics = getFontMetrics(numChp, context);
966
int indent = -1 * pap._dxaLeft1;
967     String JavaDoc bulletText = getBulletText(lvl, pap);
968
969     indent = indent - (bulletText.length() * 10) * 20;//(metrics.stringWidth(bulletText) * 20);
970

971     if(indent > 0)
972     {
973       numChp._paddingEnd = (short)indent;
974     }
975
976     addCharacterProperties(numChp, blockBuffer);
977     int listNum = 0;
978
979     //if(number != null)
980
//{
981
blockBuffer.append(bulletText);
982       //listNum = 1;
983
//}
984

985     //for(;listNum < lvl._xst.length; listNum++)
986
//{
987
// addText(lvl._xst[listNum], blockBuffer);
988
//}
989

990
991     switch (lvl._ixchFollow)
992     {
993       case 0:
994         addText('\u0009', blockBuffer);
995         break;
996       case 1:
997         addText(' ', blockBuffer);
998         break;
999     }
1000
1001    closeLine(blockBuffer);
1002    for(int x = 0; x < len; x++)
1003    {
1004      ChpxNode charNode = (ChpxNode)charRuns.get(x);
1005      byte[] chpx = charNode.getChpx();
1006      CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet);
1007
1008
1009      addCharacterProperties(chp, blockBuffer);
1010
1011      int charStart = Math.max(charNode.getStart(), currentNode.getStart());
1012      int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd());
1013      ArrayList textRuns = findProperties(charStart, charEnd, _text.root);
1014      int textRunLen = textRuns.size();
1015      for(int y = 0; y < textRunLen; y++)
1016      {
1017        TextPiece piece = (TextPiece)textRuns.get(y);
1018        charStart = Math.max(charStart, piece.getStart());
1019        charEnd = Math.min(charEnd, piece.getEnd());
1020
1021        if(piece.usesUnicode())
1022        {
1023          addUnicodeText(charStart, charEnd, blockBuffer);
1024        }
1025        else
1026        {
1027          addText(charStart, charEnd, blockBuffer);
1028        }
1029        closeLine(blockBuffer);
1030      }
1031    }
1032    closeBlock(blockBuffer);
1033  }
1034
1035  private void addParagraphContent(StringBuffer JavaDoc blockBuffer, PAP pap,
1036                                   PapxNode currentNode, int start, int end,
1037                                   StyleDescription std)
1038  {
1039    addParagraphProperties(pap, blockBuffer);
1040
1041    ArrayList charRuns = findProperties(Math.max(currentNode.getStart(), start),
1042                                     Math.min(currentNode.getEnd(), end),
1043                                     _characterTable.root);
1044    int len = charRuns.size();
1045
1046    for(int x = 0; x < len; x++)
1047    {
1048      ChpxNode charNode = (ChpxNode)charRuns.get(x);
1049      byte[] chpx = charNode.getChpx();
1050      CHP chp = (CHP)StyleSheet.uncompressProperty(chpx, std.getCHP(), _styleSheet);
1051
1052      addCharacterProperties(chp, blockBuffer);
1053
1054      int charStart = Math.max(charNode.getStart(), currentNode.getStart());
1055      int charEnd = Math.min(charNode.getEnd(), currentNode.getEnd());
1056      ArrayList textRuns = findProperties(charStart, charEnd, _text.root);
1057      int textRunLen = textRuns.size();
1058      for(int y = 0; y < textRunLen; y++)
1059      {
1060        TextPiece piece = (TextPiece)textRuns.get(y);
1061        charStart = Math.max(charStart, piece.getStart());
1062        charEnd = Math.min(charEnd, piece.getEnd());
1063
1064        if(piece.usesUnicode())
1065        {
1066          addUnicodeText(charStart, charEnd, blockBuffer);
1067        }
1068        else
1069        {
1070          addText(charStart, charEnd, blockBuffer);
1071        }
1072        closeLine(blockBuffer);
1073      }
1074    }
1075    closeBlock(blockBuffer);
1076  }
1077  private void addText(int start, int end, StringBuffer JavaDoc buf)
1078  {
1079    for(int x = start; x < end; x++)
1080    {
1081      char ch = '?';
1082
1083
1084      ch = (char)_header[x];
1085
1086      addText(ch, buf);
1087    }
1088  }
1089  private void addText(char ch, StringBuffer JavaDoc buf)
1090  {
1091    int num = 0xffff & ch;
1092    if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
1093      (ch >= '0' && ch <= '9') || ch == '_' || ch == ' ' || ch == '-' || ch == '.' || ch == '$')
1094    {
1095      buf.append(ch);
1096    }
1097    else if(num == 0x07 && _cellBuffer != null)
1098    {
1099
1100      if(_cells == null)
1101      {
1102        _cells = new ArrayList();
1103      }
1104      closeLine(_cellBuffer);
1105      closeBlock(_cellBuffer);
1106      _cells.add(_cellBuffer.toString());
1107      _cellBuffer = null;
1108
1109    }
1110
1111    else
1112    {
1113      /** @todo handle special characters */
1114      if(num < 0x20)
1115      num=0x20;
1116      buf.append("&#");
1117      buf.append(num);
1118      buf.append(';');
1119    }
1120  }
1121  private void addUnicodeText(int start, int end, StringBuffer JavaDoc buf)
1122  {
1123    for(int x = start; x < end; x += 2)
1124    {
1125      char ch = Utils.getUnicodeCharacter(_header, x);
1126      //if(ch < 0x0020)
1127
//{
1128
// _bodyBuffer.append('?');
1129
//}
1130
//else
1131
//{
1132
addText(ch, buf);
1133      //}
1134
}
1135  }
1136  private void addParagraphProperties(PAP pap, StringBuffer JavaDoc buf)
1137  {
1138    buf.append("<fo:block ");
1139    buf.append("text-align=\"" + getTextAlignment(pap._jc) + "\"\r\n");
1140    buf.append("linefeed-treatment=\"preserve\" ");
1141    buf.append("white-space-collapse=\"false\" ");
1142
1143    if(pap._fKeep > 0)
1144    {
1145      buf.append("keep-together.within-page=\"always\"\r\n");
1146    }
1147    if(pap._fKeepFollow > 0)
1148    {
1149      buf.append("keep-with-next.within-page=\"always\"\r\n");
1150    }
1151    if(pap._fPageBreakBefore > 0)
1152    {
1153      buf.append("break-before=\"page\"\r\n");
1154    }
1155    if(pap._fNoAutoHyph == 0)
1156    {
1157      buf.append("hyphenate=\"true\"\r\n");
1158    }
1159    else
1160    {
1161      buf.append("hyphenate=\"false\"\r\n");
1162    }
1163    if(pap._dxaLeft > 0)
1164    {
1165      buf.append("start-indent=\"" + ((float)pap._dxaLeft)/1440.0f + "in\"\r\n");
1166    }
1167    if(pap._dxaRight > 0)
1168    {
1169      buf.append("end-indent=\"" + ((float)pap._dxaRight)/1440.0f + "in\"\r\n");
1170    }
1171    if(pap._dxaLeft1 != 0)
1172    {
1173      buf.append("text-indent=\"" + ((float)pap._dxaLeft1)/1440.0f + "in\"\r\n");
1174    }
1175    if(pap._lspd[1] == 0)
1176    {
1177      //buf.append("line-height=\"" + ((float)pap._lspd[0])/1440.0f + "in\"\r\n");
1178
}
1179    addBorder(buf, pap._brcTop, "top");
1180    addBorder(buf, pap._brcBottom, "bottom");
1181    addBorder(buf, pap._brcLeft, "left");
1182    addBorder(buf, pap._brcRight, "right");
1183
1184    buf.append(">");
1185
1186  }
1187
1188  private void addCharacterProperties(CHP chp, StringBuffer JavaDoc buf)
1189  {
1190    buf.append("<fo:inline ");
1191    buf.append("font-family=\"" + _fonts.getFont(chp._ftcAscii) + "\" ");
1192    buf.append("font-size=\"" + (chp._hps / 2) + "pt\" ");
1193    buf.append("color=\"" + getColor(chp._ico) + "\" ");
1194    //not supported by fop
1195
//buf.append("letter-spacing=\"" + ((double)chp._dxaSpace)/1440.0f + "in\" ");
1196

1197    addBorder(buf, chp._brc, "top");
1198    addBorder(buf, chp._brc, "bottom");
1199    addBorder(buf, chp._brc, "left");
1200    addBorder(buf, chp._brc, "right");
1201
1202    if(chp._italic)
1203    {
1204      buf.append("font-style=\"italic\" ");
1205    }
1206    if(chp._bold)
1207    {
1208      buf.append("font-weight=\"bold\" ");
1209    }
1210    if(chp._fSmallCaps)
1211    {
1212      buf.append("font-variant=\"small-caps\" ");
1213    }
1214    if(chp._fCaps)
1215    {
1216      buf.append("text-transform=\"uppercase\" ");
1217    }
1218    if(chp._fStrike || chp._fDStrike)
1219    {
1220      buf.append("text-decoration=\"line-through\" ");
1221    }
1222    if(chp._fShadow)
1223    {
1224      int size = chp._hps/24;
1225      buf.append("text-shadow=\"" + size + "pt\"");
1226    }
1227    if(chp._fLowerCase)
1228    {
1229      buf.append("text-transform=\"lowercase\" ");
1230    }
1231    if(chp._kul > 0)
1232    {
1233      buf.append("text-decoration=\"underline\" ");
1234    }
1235    if(chp._highlighted)
1236    {
1237      buf.append("background-color=\"" + getColor(chp._icoHighlight) + "\" ");
1238    }
1239    if(chp._paddingStart != 0)
1240    {
1241      buf.append("padding-start=\"" + (float)chp._paddingStart/1440.0f + "in\" ");
1242    }
1243    if(chp._paddingEnd != 0)
1244    {
1245      buf.append("padding-end=\"" + (float)chp._paddingEnd/1440.0f + "in\" ");
1246    }
1247    buf.append(">");
1248  }
1249  private void addStaticContent(String JavaDoc flowName, HeaderFooter content)
1250  {
1251    _bodyBuffer.append("<fo:static-content flow-name=\"" + flowName + "\">");
1252    //_bodyBuffer.append("<fo:float float=\"before\">");
1253
addBlockContent(content.getStart(), content.getEnd(),_text, _paragraphTable, _characterTable);
1254    //_bodyBuffer.append("</fo:float>");
1255
_bodyBuffer.append("</fo:static-content>");
1256
1257  }
1258  private String JavaDoc getBulletText(LVL lvl, PAP pap)
1259  {
1260    StringBuffer JavaDoc bulletBuffer = new StringBuffer JavaDoc();
1261    for(int x = 0; x < lvl._xst.length; x++)
1262    {
1263      if(lvl._xst[x] < 9)
1264      {
1265        LVL numLevel = _listTables.getLevel(pap._ilfo, lvl._xst[x]);
1266        int num = numLevel._iStartAt;
1267        if(lvl == numLevel)
1268        {
1269          numLevel._iStartAt++;
1270        }
1271        else if(num > 1)
1272        {
1273          num--;
1274        }
1275        bulletBuffer.append(NumberFormatter.getNumber(num, lvl._nfc));
1276
1277      }
1278      else
1279      {
1280        bulletBuffer.append(lvl._xst[x]);
1281      }
1282
1283    }
1284    return bulletBuffer.toString();
1285  }
1286  /**
1287   * finds all chpx's that are between start and end
1288   */

1289  private ArrayList findProperties(int start, int end, BTreeSet.BTreeNode root)
1290  {
1291    ArrayList results = new ArrayList();
1292    BTreeSet.Entry[] entries = root.entries;
1293
1294    for(int x = 0; x < entries.length; x++)
1295    {
1296      if(entries[x] != null)
1297      {
1298        BTreeSet.BTreeNode child = entries[x].child;
1299        PropertyNode xNode = (PropertyNode)entries[x].element;
1300        if(xNode != null)
1301        {
1302          int xStart = xNode.getStart();
1303          int xEnd = xNode.getEnd();
1304          if(xStart < end)
1305          {
1306            if(xStart >= start)
1307            {
1308              if(child != null)
1309              {
1310                ArrayList beforeItems = findProperties(start, end, child);
1311                results.addAll(beforeItems);
1312              }
1313              results.add(xNode);
1314            }
1315            else if(start < xEnd)
1316            {
1317              results.add(xNode);
1318              //break;
1319
}
1320          }
1321          else
1322          {
1323            if(child != null)
1324            {
1325              ArrayList beforeItems = findProperties(start, end, child);
1326              results.addAll(beforeItems);
1327            }
1328            break;
1329          }
1330        }
1331        else if(child != null)
1332        {
1333          ArrayList afterItems = findProperties(start, end, child);
1334          results.addAll(afterItems);
1335        }
1336      }
1337      else
1338      {
1339        break;
1340      }
1341    }
1342    return results;
1343  }
1344  private void openPage(String JavaDoc page, String JavaDoc type)
1345  {
1346    _bodyBuffer.append("<fo:page-sequence master-reference=\"" + page + "\">\r\n");
1347  }
1348  private void openFlow()
1349  {
1350    _bodyBuffer.append("<fo:flow flow-name=\"xsl-region-body\">\r\n");
1351  }
1352  private void closeFlow()
1353  {
1354    _bodyBuffer.append("</fo:flow>\r\n");
1355  }
1356  private void closePage()
1357  {
1358    _bodyBuffer.append("</fo:page-sequence>\r\n");
1359  }
1360  private void closeLine(StringBuffer JavaDoc buf)
1361  {
1362    buf.append("</fo:inline>");
1363  }
1364  private void closeBlock(StringBuffer JavaDoc buf)
1365  {
1366    buf.append("</fo:block>\r\n");
1367  }
1368  private ArrayList findPAPProperties(int start, int end, BTreeSet.BTreeNode root)
1369  {
1370    ArrayList results = new ArrayList();
1371    BTreeSet.Entry[] entries = root.entries;
1372
1373    for(int x = 0; x < entries.length; x++)
1374    {
1375      if(entries[x] != null)
1376      {
1377        BTreeSet.BTreeNode child = entries[x].child;
1378        PapxNode papxNode = (PapxNode)entries[x].element;
1379        if(papxNode != null)
1380        {
1381          int papxStart = papxNode.getStart();
1382          if(papxStart < end)
1383          {
1384            if(papxStart >= start)
1385            {
1386              if(child != null)
1387              {
1388                ArrayList beforeItems = findPAPProperties(start, end, child);
1389                results.addAll(beforeItems);
1390              }
1391              results.add(papxNode);
1392            }
1393          }
1394          else
1395          {
1396            if(child != null)
1397            {
1398              ArrayList beforeItems = findPAPProperties(start, end, child);
1399              results.addAll(beforeItems);
1400            }
1401            break;
1402          }
1403        }
1404        else if(child != null)
1405        {
1406          ArrayList afterItems = findPAPProperties(start, end, child);
1407          results.addAll(afterItems);
1408        }
1409      }
1410      else
1411      {
1412        break;
1413      }
1414    }
1415    return results;
1416  }
1417
1418  private String JavaDoc createPageMaster(SEP sep, String JavaDoc type, int section,
1419                                  String JavaDoc regionBefore, String JavaDoc regionAfter)
1420  {
1421    float height = ((float)sep._yaPage)/1440.0f;
1422    float width = ((float)sep._xaPage)/1440.0f;
1423    float leftMargin = ((float)sep._dxaLeft)/1440.0f;
1424    float rightMargin = ((float)sep._dxaRight)/1440.0f;
1425    float topMargin = ((float)sep._dyaTop)/1440.0f;
1426    float bottomMargin = ((float)sep._dyaBottom)/1440.0f;
1427
1428    //add these to the header
1429
String JavaDoc thisPage = type + "-page" + section;
1430
1431    _headerBuffer.append("<fo:simple-page-master master-name=\"" +
1432                        thisPage + "\"\r\n");
1433    _headerBuffer.append("page-height=\"" + height + "in\"\r\n");
1434    _headerBuffer.append("page-width=\"" + width + "in\"\r\n");
1435    _headerBuffer.append(">\r\n");
1436
1437
1438
1439    _headerBuffer.append("<fo:region-body ");
1440    //top right bottom left
1441

1442    _headerBuffer.append("margin=\"" + topMargin + "in " + rightMargin + "in " +
1443                         bottomMargin + "in " + leftMargin + "in\"\r\n");
1444
1445    //String style = null;
1446
//String color = null;
1447
addBorder(_headerBuffer, sep._brcTop, "top");
1448    addBorder(_headerBuffer, sep._brcBottom, "bottom");
1449    addBorder(_headerBuffer, sep._brcLeft, "left");
1450    addBorder(_headerBuffer, sep._brcRight, "right");
1451
1452    if(sep._ccolM1 > 0)
1453    {
1454      _headerBuffer.append("column-count=\"" + (sep._ccolM1 + 1) + "\" ");
1455      if(sep._fEvenlySpaced)
1456      {
1457        _headerBuffer.append("column-gap=\"" + ((float)(sep._dxaColumns))/1440.0f + "in\"");
1458      }
1459      else
1460      {
1461        _headerBuffer.append("column-gap=\"0.25in\"");
1462      }
1463    }
1464    _headerBuffer.append("/>\r\n");
1465
1466    if(regionBefore != null)
1467    {
1468      _headerBuffer.append(regionBefore);
1469    }
1470    if(regionAfter != null)
1471    {
1472      _headerBuffer.append(regionAfter);
1473    }
1474
1475    _headerBuffer.append("</fo:simple-page-master>\r\n");
1476    return thisPage;
1477  }
1478  private void addBorder(StringBuffer JavaDoc buf, short[] brc, String JavaDoc where)
1479  {
1480    if((brc[0] & 0xff00) != 0 && brc[0] != -1)
1481    {
1482      int type = (brc[0] & 0xff00) >> 8;
1483      float width = ((float)(brc[0] & 0x00ff))/8.0f;
1484      String JavaDoc style = getBorderStyle(brc[0]);
1485      String JavaDoc color = getColor(brc[1] & 0x00ff);
1486      String JavaDoc thickness = getBorderThickness(brc[0]);
1487      buf.append("border-" + where + "-style=\"" + style + "\"\r\n");
1488      buf.append("border-" + where + "-color=\"" + color + "\"\r\n");
1489      buf.append("border-" + where + "-width=\"" + width + "pt\"\r\n");
1490    }
1491  }
1492  public void closeDoc()
1493  {
1494    _headerBuffer.append("</fo:layout-master-set>");
1495    _bodyBuffer.append("</fo:root>");
1496    //_headerBuffer.append();
1497

1498    //test code
1499
try
1500    {
1501      OutputStreamWriter test = new OutputStreamWriter(new FileOutputStream(_outName), "8859_1");
1502      test.write(_headerBuffer.toString());
1503      test.write(_bodyBuffer.toString());
1504      test.flush();
1505      test.close();
1506    }
1507    catch(Throwable JavaDoc t)
1508    {
1509      t.printStackTrace();
1510    }
1511  }
1512  private String JavaDoc getBorderThickness(int style)
1513  {
1514    switch(style)
1515    {
1516      case 1:
1517        return "medium";
1518      case 2:
1519        return "thick";
1520      case 3:
1521        return "medium";
1522      case 5:
1523        return "thin";
1524      default:
1525        return "medium";
1526    }
1527  }
1528
1529
1530  private String JavaDoc getColor(int ico)
1531  {
1532    switch(ico)
1533    {
1534      case 1:
1535        return "black";
1536      case 2:
1537        return "blue";
1538      case 3:
1539        return "cyan";
1540      case 4:
1541        return "green";
1542      case 5:
1543        return "magenta";
1544      case 6:
1545        return "red";
1546      case 7:
1547        return "yellow";
1548      case 8:
1549        return "white";
1550      case 9:
1551        return "darkblue";
1552      case 10:
1553        return "darkcyan";
1554      case 11:
1555        return "darkgreen";
1556      case 12:
1557        return "darkmagenta";
1558      case 13:
1559        return "darkred";
1560      case 14:
1561        return "darkyellow";
1562      case 15:
1563        return "darkgray";
1564      case 16:
1565        return "lightgray";
1566      default:
1567        return "black";
1568    }
1569  }
1570
1571  private String JavaDoc getBorderStyle(int type)
1572  {
1573
1574    switch(type)
1575    {
1576      case 1:
1577      case 2:
1578        return "solid";
1579      case 3:
1580        return "double";
1581      case 5:
1582        return "solid";
1583      case 6:
1584        return "dotted";
1585      case 7:
1586      case 8:
1587        return "dashed";
1588      case 9:
1589        return "dotted";
1590      case 10:
1591      case 11:
1592      case 12:
1593      case 13:
1594      case 14:
1595      case 15:
1596      case 16:
1597      case 17:
1598      case 18:
1599      case 19:
1600        return "double";
1601      case 20:
1602        return "solid";
1603      case 21:
1604        return "double";
1605      case 22:
1606        return "dashed";
1607      case 23:
1608        return "dashed";
1609      case 24:
1610        return "ridge";
1611      case 25:
1612        return "grooved";
1613      default:
1614        return "solid";
1615    }
1616  }
1617  /**
1618   * creates the List data
1619   *
1620   * @param tableStream Main table stream buffer.
1621   */

1622  private void createListTables(byte[] tableStream)
1623  {
1624
1625
1626    int lfoOffset = LittleEndian.getInt(_header, 0x2ea);
1627    int lfoSize = LittleEndian.getInt(_header, 0x2ee);
1628    byte[] plflfo = new byte[lfoSize];
1629
1630    System.arraycopy(tableStream, lfoOffset, plflfo, 0, lfoSize);
1631
1632    int lstOffset = LittleEndian.getInt(_header, 0x2e2);
1633    int lstSize = LittleEndian.getInt(_header, 0x2e2);
1634    if(lstOffset > 0 && lstSize > 0)
1635    {
1636      lstSize = lfoOffset - lstOffset;
1637      byte[] plcflst = new byte[lstSize];
1638      System.arraycopy(tableStream, lstOffset, plcflst, 0, lstSize);
1639      _listTables = new ListTables(plcflst, plflfo);
1640    }
1641
1642  }
1643  /**
1644   * Creates the documents StyleSheet
1645   *
1646   * @param tableStream Main table stream buffer.
1647   *
1648   */

1649  private void createStyleSheet(byte[] tableStream)
1650  {
1651      int stshIndex = LittleEndian.getInt(_header, 0xa2);
1652      int stshSize = LittleEndian.getInt(_header, 0xa6);
1653      byte[] stsh = new byte[stshSize];
1654      System.arraycopy(tableStream, stshIndex, stsh, 0, stshSize);
1655
1656      _styleSheet = new StyleSheet(stsh);
1657
1658  }
1659  /**
1660   * creates the Font table
1661   *
1662   * @param tableStream Main table stream buffer.
1663   */

1664  private void createFontTable(byte[] tableStream)
1665  {
1666    int fontTableIndex = LittleEndian.getInt(_header, 0x112);
1667    int fontTableSize = LittleEndian.getInt(_header, 0x116);
1668    byte[] fontTable = new byte[fontTableSize];
1669    System.arraycopy(tableStream, fontTableIndex, fontTable, 0, fontTableSize);
1670    _fonts = new FontTable(fontTable);
1671  }
1672
1673
1674  private void overrideCellBorder(int row, int col, int height,
1675                                  int width, TC tc, TAP tap)
1676  {
1677
1678    if(row == 0)
1679    {
1680      if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
1681      {
1682        tc._brcTop = tap._brcTop;
1683      }
1684      if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
1685      {
1686        tc._brcBottom = tap._brcHorizontal;
1687      }
1688    }
1689    else if(row == (height - 1))
1690    {
1691      if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
1692      {
1693        tc._brcTop = tap._brcHorizontal;
1694      }
1695      if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
1696      {
1697        tc._brcBottom = tap._brcBottom;
1698      }
1699    }
1700    else
1701    {
1702      if(tc._brcTop[0] == 0 || tc._brcTop[0] == -1)
1703      {
1704        tc._brcTop = tap._brcHorizontal;
1705      }
1706      if(tc._brcBottom[0] == 0 || tc._brcBottom[0] == -1)
1707      {
1708        tc._brcBottom = tap._brcHorizontal;
1709      }
1710    }
1711    if(col == 0)
1712    {
1713      if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
1714      {
1715        tc._brcLeft = tap._brcLeft;
1716      }
1717      if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
1718      {
1719        tc._brcRight = tap._brcVertical;
1720      }
1721    }
1722    else if(col == (width - 1))
1723    {
1724      if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
1725      {
1726        tc._brcLeft = tap._brcVertical;
1727      }
1728      if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
1729      {
1730        tc._brcRight = tap._brcRight;
1731      }
1732    }
1733    else
1734    {
1735      if(tc._brcLeft[0] == 0 || tc._brcLeft[0] == -1)
1736      {
1737        tc._brcLeft = tap._brcVertical;
1738      }
1739      if(tc._brcRight[0] == 0 || tc._brcRight[0] == -1)
1740      {
1741        tc._brcRight = tap._brcVertical;
1742      }
1743    }
1744  }
1745  private void printTable()
1746  {
1747    if(_table != null)
1748    {
1749      int size = _table.size();
1750
1751      //local buffers for the table
1752
StringBuffer JavaDoc tableHeaderBuffer = new StringBuffer JavaDoc();
1753      StringBuffer JavaDoc tableBodyBuffer = new StringBuffer JavaDoc();
1754
1755      for(int x = 0; x < size; x++)
1756      {
1757        StringBuffer JavaDoc rowBuffer = tableBodyBuffer;
1758        TableRow row = (TableRow)_table.get(x);
1759        TAP tap = row.getTAP();
1760        ArrayList cells = row.getCells();
1761
1762        if(tap._fTableHeader)
1763        {
1764          rowBuffer = tableHeaderBuffer;
1765        }
1766        rowBuffer.append("<fo:table-row ");
1767        if(tap._dyaRowHeight > 0)
1768        {
1769          rowBuffer.append("height=\"" + ((float)tap._dyaRowHeight)/1440.0f + "in\" ");
1770        }
1771        if(tap._fCantSplit)
1772        {
1773          rowBuffer.append("keep-together=\"always\" ");
1774        }
1775        rowBuffer.append(">");
1776        //add cells
1777
for(int y = 0; y < tap._itcMac; y++)
1778        {
1779          TC tc = tap._rgtc[y];
1780          overrideCellBorder(x, y, size, tap._itcMac, tc, tap);
1781          rowBuffer.append("<fo:table-cell ");
1782          rowBuffer.append("width=\"" + ((float)(tap._rgdxaCenter[y+1] - tap._rgdxaCenter[y]))/1440.0f + "in\" ");
1783          rowBuffer.append("padding-start=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" ");
1784          rowBuffer.append("padding-end=\"" + ((float)tap._dxaGapHalf)/1440.0f + "in\" ");
1785          addBorder(rowBuffer, tc._brcTop, "top");
1786          addBorder(rowBuffer, tc._brcLeft, "left");
1787          addBorder(rowBuffer, tc._brcBottom, "bottom");
1788          addBorder(rowBuffer, tc._brcRight, "right");
1789          rowBuffer.append(">");
1790          rowBuffer.append((String JavaDoc)cells.get(y));
1791          rowBuffer.append("</fo:table-cell>");
1792        }
1793        rowBuffer.append("</fo:table-row>");
1794      }
1795      StringBuffer JavaDoc tableBuffer = new StringBuffer JavaDoc();
1796      tableBuffer.append("<fo:table>");
1797      if(tableHeaderBuffer.length() > 0)
1798      {
1799        tableBuffer.append("<fo:table-header>");
1800        tableBuffer.append(tableHeaderBuffer.toString());
1801        tableBuffer.append("</fo:table-header>");
1802      }
1803      tableBuffer.append("<fo:table-body>");
1804      tableBuffer.append(tableBodyBuffer.toString());
1805      tableBuffer.append("</fo:table-body>");
1806      tableBuffer.append("</fo:table>");
1807      _bodyBuffer.append(tableBuffer.toString());
1808      _table = null;
1809    }
1810  }
1811  private void initPclfHdd(byte[] tableStream)
1812  {
1813    int size = Utils.convertBytesToInt(_header, 0xf6);
1814    int pos = Utils.convertBytesToInt(_header, 0xf2);
1815
1816    _plcfHdd = new byte[size];
1817
1818    System.arraycopy(tableStream, pos, _plcfHdd, 0, size);
1819  }
1820
1821
1822
1823
1824}
1825
Popular Tags