KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hwpf > usermodel > Range


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

16
17
18
19 package org.apache.poi.hwpf.usermodel;
20
21
22 import org.apache.poi.util.LittleEndian;
23
24 import org.apache.poi.hwpf.HWPFDocument;
25
26 import org.apache.poi.hwpf.usermodel.CharacterRun;
27 import org.apache.poi.hwpf.usermodel.Paragraph;
28 import org.apache.poi.hwpf.usermodel.ParagraphProperties;
29 import org.apache.poi.hwpf.usermodel.Section;
30
31 import org.apache.poi.hwpf.model.PropertyNode;
32 import org.apache.poi.hwpf.model.StyleSheet;
33 import org.apache.poi.hwpf.model.StyleDescription;
34 import org.apache.poi.hwpf.model.CHPBinTable;
35 import org.apache.poi.hwpf.model.CHPX;
36 import org.apache.poi.hwpf.model.PAPX;
37 import org.apache.poi.hwpf.model.SEPX;
38 import org.apache.poi.hwpf.model.PAPBinTable;
39 import org.apache.poi.hwpf.model.SectionTable;
40 import org.apache.poi.hwpf.model.TextPieceTable;
41 import org.apache.poi.hwpf.model.TextPiece;
42 import org.apache.poi.hwpf.model.ListTables;
43
44 import org.apache.poi.hwpf.sprm.CharacterSprmUncompressor;
45 import org.apache.poi.hwpf.sprm.CharacterSprmCompressor;
46 import org.apache.poi.hwpf.sprm.SectionSprmUncompressor;
47 import org.apache.poi.hwpf.sprm.ParagraphSprmUncompressor;
48 import org.apache.poi.hwpf.sprm.ParagraphSprmCompressor;
49 import org.apache.poi.hwpf.sprm.SprmBuffer;
50
51
52 import java.util.List JavaDoc;
53 import java.util.ArrayList JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.NoSuchElementException JavaDoc;
56 import java.io.UnsupportedEncodingException JavaDoc;
57 import java.lang.ref.WeakReference JavaDoc;
58
59 /**
60  * This class is the central class of the HWPF object model. All properties
61  * that apply to a range of characters in a Word document extend this class.
62  *
63  * It is possible to insert text and/or properties at the beginning or end of a
64  * range.
65  *
66  * Ranges are only valid if there hasn't been an insert in a prior Range since
67  * the Range's creation. Once an element (text, paragraph, etc.) has been
68  * inserted into a Range, subsequent Ranges become unstable.
69  *
70  * @author Ryan Ackley
71  */

72 public class Range
73 {
74
75   public static final int TYPE_PARAGRAPH = 0;
76   public static final int TYPE_CHARACTER= 1;
77   public static final int TYPE_SECTION = 2;
78   public static final int TYPE_TEXT = 3;
79   public static final int TYPE_LISTENTRY = 4;
80   public static final int TYPE_TABLE = 5;
81   public static final int TYPE_UNDEFINED = 6;
82
83   /** Needed so inserts and deletes will ripple up through containing Ranges */
84   private WeakReference JavaDoc _parent;
85
86   /** The starting character offset of this range.*/
87   protected int _start;
88
89   /** The ending character offset of this range.*/
90   protected int _end;
91
92   /** The document this range blongs to.*/
93   protected HWPFDocument _doc;
94
95   /** Have we loaded the section indexes yet*/
96   boolean _sectionRangeFound;
97
98   /** All sections that belong to the document this Range belongs to.*/
99   protected List JavaDoc _sections;
100
101   /** The start index in the sections list for this Range*/
102   protected int _sectionStart;
103
104   /** The end index in the sections list for this Range.*/
105   protected int _sectionEnd;
106
107   /** Have we loaded the paragraph indexes yet.*/
108   protected boolean _parRangeFound;
109
110   /** All paragraphs that belong to the document this Range belongs to.*/
111   protected List JavaDoc _paragraphs;
112
113   /** The start index in the paragraphs list for this Range*/
114   protected int _parStart;
115
116   /** The end index in the paragraphs list for this Range.*/
117   protected int _parEnd;
118
119   /** Have we loaded the characterRun indexes yet.*/
120   protected boolean _charRangeFound;
121
122   /** All CharacterRuns that belong to the document this Range belongs to.*/
123   protected List JavaDoc _characters;
124
125   /** The start index in the characterRuns list for this Range*/
126   protected int _charStart;
127
128   /** The end index in the characterRuns list for this Range. */
129   protected int _charEnd;
130
131   /** Have we loaded the Text indexes yet*/
132   protected boolean _textRangeFound;
133
134   /** All text pieces that belong to the document this Range belongs to.*/
135   protected List JavaDoc _text;
136
137   /** The start index in the text list for this Range.*/
138   protected int _textStart;
139
140   /** The end index in the text list for this Range.*/
141   protected int _textEnd;
142
143 // protected Range()
144
// {
145
//
146
// }
147

148   /**
149    * Used to construct a Range from a document. This is generally used to
150    * create a Range that spans the whole document.
151    *
152    * @param start Starting character offset of the range.
153    * @param end Ending character offset of the range.
154    * @param doc The HWPFDocument the range is based on.
155    */

156   public Range(int start, int end, HWPFDocument doc)
157   {
158     _start = start;
159     _end = end;
160     _doc = doc;
161     _sections = _doc.getSectionTable().getSections();
162     _paragraphs = _doc.getParagraphTable().getParagraphs();
163     _characters = _doc.getCharacterTable().getTextRuns();
164     _text = _doc.getTextTable().getTextPieces();
165     _parent = new WeakReference JavaDoc(null);
166   }
167
168
169   /**
170    * Used to create Ranges that are children of other Ranges.
171    *
172    * @param start Starting character offset of the range.
173    * @param end Ending character offset of the range.
174    * @param parent The parent this range belongs to.
175    */

176   protected Range(int start, int end, Range parent)
177   {
178     _start = start;
179     _end = end;
180     _doc = parent._doc;
181     _sections = parent._sections;
182     _paragraphs = parent._paragraphs;
183     _characters = parent._characters;
184     _text = parent._text;
185     _parent = new WeakReference JavaDoc(parent);
186   }
187
188   /**
189    * Constructor used to build a Range from indexes in one of its internal
190    * lists.
191    *
192    * @param startIdx The starting index in the list.
193    * @param endIdx The ending index in the list.
194    * @param idxType The list type.
195    * @param parent The parent Range this range belongs to.
196    */

197   protected Range(int startIdx, int endIdx, int idxType, Range parent)
198   {
199     _doc = parent._doc;
200     _sections = parent._sections;
201     _paragraphs = parent._paragraphs;
202     _characters = parent._characters;
203     _text = parent._text;
204     _parent = new WeakReference JavaDoc(parent);
205
206     switch (idxType)
207     {
208       case TYPE_PARAGRAPH:
209         _parStart = parent._parStart + startIdx;
210         _parEnd = parent._parStart + endIdx;
211         _start = ((PropertyNode)_paragraphs.get(_parStart)).getStart();
212         _end = ((PropertyNode)_paragraphs.get(_parEnd)).getEnd();
213         _parRangeFound = true;
214         break;
215       case TYPE_CHARACTER:
216         _charStart = parent._charStart + startIdx;
217         _charEnd = parent._charStart + endIdx;
218         _start = ((PropertyNode)_characters.get(_charStart)).getStart();
219         _end = ((PropertyNode)_characters.get(_charEnd)).getEnd();
220         _charRangeFound = true;
221         break;
222      case TYPE_SECTION:
223         _sectionStart = parent._sectionStart + startIdx;
224         _sectionEnd = parent._sectionStart + endIdx;
225         _start = ((PropertyNode)_sections.get(_sectionStart)).getStart();
226         _end = ((PropertyNode)_sections.get(_sectionEnd)).getEnd();
227         _sectionRangeFound = true;
228         break;
229      case TYPE_TEXT:
230         _textStart = parent._textStart + startIdx;
231         _textEnd = parent._textStart + endIdx;
232         _start = ((PropertyNode)_text.get(_textStart)).getStart();
233         _end = ((PropertyNode)_text.get(_textEnd)).getEnd();
234         _textRangeFound = true;
235         break;
236     }
237   }
238
239   /**
240    * Gets the text that this Range contains.
241    *
242    * @return The text for this range.
243    */

244   public String JavaDoc text()
245   {
246     initText();
247
248     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
249
250     for (int x = _textStart; x < _textEnd; x++)
251     {
252       TextPiece piece = (TextPiece)_text.get(x);
253       int start = _start > piece.getStart() ? _start - piece.getStart() : 0;
254       int end = _end <= piece.getEnd() ? _end - piece.getStart() : piece.getEnd() - piece.getStart();
255
256       if(piece.usesUnicode()) // convert the byte pointers to char pointers
257
{
258         start/=2;
259         end/=2;
260       }
261       sb.append(piece.getStringBuffer().substring(start, end));
262     }
263     return sb.toString();
264   }
265
266   /**
267    * Used to get the number of sections in a range. If this range is smaller
268    * than a section, it will return 1 for its containing section.
269    *
270    * @return The number of sections in this range.
271    */

272   public int numSections()
273   {
274     initSections();
275     return _sectionEnd - _sectionStart;
276   }
277
278   /**
279    * Used to get the number of paragraphs in a range. If this range is smaller
280    * than a paragraph, it will return 1 for its containing paragraph.
281    *
282    * @return The number of paragraphs in this range.
283    */

284
285   public int numParagraphs()
286   {
287     initParagraphs();
288     return _parEnd - _parStart;
289   }
290
291   /**
292    *
293    * @return The number of characterRuns in this range.
294    */

295
296   public int numCharacterRuns()
297   {
298     initCharacterRuns();
299     return _charEnd - _charStart;
300   }
301
302   /**
303    * Inserts text into the front of this range.
304    *
305    * @param text The text to insert
306    * @return The character run that text was inserted into.
307    */

308   public CharacterRun insertBefore(String JavaDoc text)
309     //throws UnsupportedEncodingException
310
{
311     initAll();
312
313     TextPiece tp = (TextPiece)_text.get(_textStart);
314     StringBuffer JavaDoc sb = (StringBuffer JavaDoc)tp.getStringBuffer();
315
316     // Since this is the first item in our list, it is safe to assume that
317
// _start >= tp.getStart()
318
int insertIndex = _start - tp.getStart();
319     sb.insert(insertIndex, text);
320     int adjustedLength = _doc.getTextTable().adjustForInsert(_textStart, text.length());
321     _doc.getCharacterTable().adjustForInsert(_charStart, adjustedLength);
322     _doc.getParagraphTable().adjustForInsert(_parStart, adjustedLength);
323     _doc.getSectionTable().adjustForInsert(_sectionStart, adjustedLength);
324     adjustForInsert(text.length());
325
326     return getCharacterRun(0);
327   }
328
329   /**
330    * Inserts text onto the end of this range
331    *
332    * @param text The text to insert
333    * @return The character run the text was inserted into.
334    */

335   public CharacterRun insertAfter(String JavaDoc text)
336   {
337     initAll();
338
339     int listIndex = _textEnd - 1;
340     TextPiece tp = (TextPiece)_text.get(listIndex);
341     StringBuffer JavaDoc sb = (StringBuffer JavaDoc)tp.getStringBuffer();
342
343     int insertIndex = _end - tp.getStart();
344
345     if (tp.getStringBuffer().charAt(_end - 1) == '\r' && text.charAt(0) != '\u0007')
346     {
347       insertIndex--;
348     }
349     sb.insert(insertIndex, text);
350     int adjustedLength = _doc.getTextTable().adjustForInsert(listIndex, text.length());
351     _doc.getCharacterTable().adjustForInsert(_charEnd - 1, adjustedLength);
352     _doc.getParagraphTable().adjustForInsert(_parEnd - 1, adjustedLength);
353     _doc.getSectionTable().adjustForInsert(_sectionEnd - 1, adjustedLength);
354     adjustForInsert(text.length());
355
356     return getCharacterRun(numCharacterRuns() - 1);
357
358   }
359
360   /**
361    * Inserts text into the front of this range and it gives that text the
362    * CharacterProperties specified in props.
363    *
364    * @param text The text to insert.
365    * @param props The CharacterProperties to give the text.
366    * @return A new CharacterRun that has the given text and properties and is n
367    * ow a part of the document.
368    */

369   public CharacterRun insertBefore(String JavaDoc text, CharacterProperties props)
370     //throws UnsupportedEncodingException
371
{
372     initAll();
373     PAPX papx = (PAPX)_paragraphs.get(_parStart);
374     short istd = papx.getIstd();
375
376     StyleSheet ss = _doc.getStyleSheet();
377     CharacterProperties baseStyle = ss.getCharacterStyle(istd);
378     byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle);
379     SprmBuffer buf = new SprmBuffer(grpprl);
380     _doc.getCharacterTable().insert(_charStart, _start, buf);
381
382     return insertBefore(text);
383   }
384
385   /**
386    * Inserts text onto the end of this range and gives that text the
387    * CharacterProperties specified in props.
388    *
389    * @param text The text to insert.
390    * @param props The CharacterProperties to give the text.
391    * @return A new CharacterRun that has the given text and properties and is n
392    * ow a part of the document.
393    */

394   public CharacterRun insertAfter(String JavaDoc text, CharacterProperties props)
395     //throws UnsupportedEncodingException
396
{
397     initAll();
398     PAPX papx = (PAPX)_paragraphs.get(_parEnd - 1);
399     short istd = papx.getIstd();
400
401     StyleSheet ss = _doc.getStyleSheet();
402     CharacterProperties baseStyle = ss.getCharacterStyle(istd);
403     byte[] grpprl = CharacterSprmCompressor.compressCharacterProperty(props, baseStyle);
404     SprmBuffer buf = new SprmBuffer(grpprl);
405     _doc.getCharacterTable().insert(_charEnd, _end, buf);
406     _charEnd++;
407     return insertAfter(text);
408   }
409
410   /**
411    * Inserts and empty paragraph into the front of this range.
412    *
413    * @param props The properties that the new paragraph will have.
414    * @param styleIndex The index into the stylesheet for the new paragraph.
415    * @return The newly inserted paragraph.
416    */

417   public Paragraph insertBefore(ParagraphProperties props, int styleIndex)
418     //throws UnsupportedEncodingException
419
{
420    return this.insertBefore(props, styleIndex, "\r");
421   }
422
423   /**
424    * Inserts a paragraph into the front of this range. The paragraph will
425    * contain one character run that has the default properties for the
426    * paragraph's style.
427    *
428    * It is necessary for the text to end with the character '\r'
429    *
430    * @param props The paragraph's properties.
431    * @param styleIndex The index of the paragraph's style in the style sheet.
432    * @param text The text to insert.
433    * @return A newly inserted paragraph.
434    */

435   protected Paragraph insertBefore(ParagraphProperties props, int styleIndex, String JavaDoc text)
436     //throws UnsupportedEncodingException
437
{
438     initAll();
439     StyleSheet ss = _doc.getStyleSheet();
440     ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex);
441     CharacterProperties baseChp = ss.getCharacterStyle(styleIndex);
442
443     byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle);
444     byte[] withIndex = new byte[grpprl.length + LittleEndian.SHORT_SIZE];
445     LittleEndian.putShort(withIndex, (short)styleIndex);
446     System.arraycopy(grpprl, 0, withIndex, LittleEndian.SHORT_SIZE, grpprl.length);
447     SprmBuffer buf = new SprmBuffer(withIndex);
448
449     _doc.getParagraphTable().insert(_parStart, _start, buf);
450     insertBefore(text, baseChp);
451     return getParagraph(0);
452   }
453
454   /**
455    * Inserts and empty paragraph into the end of this range.
456    *
457    * @param props The properties that the new paragraph will have.
458    * @param styleIndex The index into the stylesheet for the new paragraph.
459    * @return The newly inserted paragraph.
460    */

461
462   public Paragraph insertAfter(ParagraphProperties props, int styleIndex)
463     //throws UnsupportedEncodingException
464
{
465     return this.insertAfter(props, styleIndex, "\r");
466   }
467
468   /**
469   * Inserts a paragraph into the end of this range. The paragraph will
470   * contain one character run that has the default properties for the
471   * paragraph's style.
472   *
473   * It is necessary for the text to end with the character '\r'
474   *
475   * @param props The paragraph's properties.
476   * @param styleIndex The index of the paragraph's style in the style sheet.
477   * @param text The text to insert.
478   * @return A newly inserted paragraph.
479   */

480   protected Paragraph insertAfter(ParagraphProperties props, int styleIndex, String JavaDoc text)
481     //throws UnsupportedEncodingException
482
{
483     initAll();
484     StyleSheet ss = _doc.getStyleSheet();
485     ParagraphProperties baseStyle = ss.getParagraphStyle(styleIndex);
486     CharacterProperties baseChp = ss.getCharacterStyle(styleIndex);
487
488     byte[] grpprl = ParagraphSprmCompressor.compressParagraphProperty(props, baseStyle);
489     byte[] withIndex = new byte[grpprl.length + LittleEndian.SHORT_SIZE];
490     LittleEndian.putShort(withIndex, (short)styleIndex);
491     System.arraycopy(grpprl, 0, withIndex, LittleEndian.SHORT_SIZE, grpprl.length);
492     SprmBuffer buf = new SprmBuffer(withIndex);
493
494     _doc.getParagraphTable().insert(_parEnd, _end, buf);
495     _parEnd++;
496     insertAfter(text, baseChp);
497     return getParagraph(numParagraphs() - 1);
498   }
499
500   public void delete()
501   {
502     initAll();
503
504     int numSections = _sections.size();
505     int numRuns = _characters.size();
506     int numParagraphs = _paragraphs.size();
507
508     for (int x = _charStart; x < numRuns; x++)
509     {
510       CHPX chpx = (CHPX)_characters.get(x);
511       chpx.adjustForDelete(_start, _end - _start);
512     }
513
514     for (int x = _parStart; x < numParagraphs; x++)
515     {
516       PAPX papx = (PAPX)_paragraphs.get(x);
517       papx.adjustForDelete(_start, _end - _start);
518     }
519
520     for (int x = _sectionStart; x < numSections; x++)
521     {
522       SEPX sepx = (SEPX)_sections.get(x);
523       sepx.adjustForDelete(_start, _end - _start);
524     }
525   }
526
527   /**
528    * Inserts a simple table into the beginning of this range. The number of
529    * columns is determined by the TableProperties passed into this function.
530    *
531    * @param props The table properties for the table.
532    * @param rows The number of rows.
533    * @return The empty Table that is now part of the document.
534    */

535   public Table insertBefore(TableProperties props, int rows)
536   {
537     ParagraphProperties parProps = new ParagraphProperties();
538     parProps.setFInTable((byte)1);
539     parProps.setTableLevel((byte)1);
540
541     int columns = props.getItcMac();
542     for (int x = 0; x < rows; x++)
543     {
544       Paragraph cell = this.insertBefore(parProps, StyleSheet.NIL_STYLE);
545       cell.insertAfter(String.valueOf('\u0007'));
546       for(int y = 1; y < columns; y++)
547       {
548         cell = cell.insertAfter(parProps, StyleSheet.NIL_STYLE);
549         cell.insertAfter(String.valueOf('\u0007'));
550       }
551       cell = cell.insertAfter(parProps, StyleSheet.NIL_STYLE, String.valueOf('\u0007'));
552       cell.setTableRowEnd(props);
553     }
554     return new Table(_start, _start + (rows * (columns + 1)), this, 1);
555   }
556
557   /**
558    * Inserts a list into the beginning of this range.
559    *
560    * @param props The properties of the list entry. All list entries are
561    * paragraphs.
562    * @param listID The id of the list that contains the properties.
563    * @param level The indentation level of the list.
564    * @param styleIndex The base style's index in the stylesheet.
565    * @return The empty ListEntry that is now part of the document.
566    */

567   public ListEntry insertBefore(ParagraphProperties props, int listID, int level, int styleIndex)
568   {
569     ListTables lt = _doc.getListTables();
570     if (lt.getLevel(listID, level) == null)
571     {
572       throw new NoSuchElementException JavaDoc("The specified list and level do not exist");
573     }
574
575     int ilfo = lt.getOverrideIndexFromListID(listID);
576     props.setIlfo(ilfo);
577     props.setIlvl((byte)level);
578
579     return (ListEntry)insertBefore(props, styleIndex);
580   }
581
582   /**
583    * Inserts a list into the beginning of this range.
584    *
585    * @param props The properties of the list entry. All list entries are
586    * paragraphs.
587    * @param listID The id of the list that contains the properties.
588    * @param level The indentation level of the list.
589    * @param styleIndex The base style's index in the stylesheet.
590    * @return The empty ListEntry that is now part of the document.
591    */

592   public ListEntry insertAfter(ParagraphProperties props, int listID, int level, int styleIndex)
593   {
594     ListTables lt = _doc.getListTables();
595     if (lt.getLevel(listID, level) == null)
596     {
597       throw new NoSuchElementException JavaDoc("The specified list and level do not exist");
598     }
599     int ilfo = lt.getOverrideIndexFromListID(listID);
600     props.setIlfo(ilfo);
601     props.setIlvl((byte)level);
602
603     return (ListEntry)insertAfter(props, styleIndex);
604   }
605
606
607   /**
608    * Gets the character run at index. The index is relative to this range.
609    *
610    * @param index The index of the character run to get.
611    * @return The character run at the specified index in this range.
612    */

613   public CharacterRun getCharacterRun(int index)
614   {
615     initCharacterRuns();
616     CHPX chpx = (CHPX)_characters.get(index + _charStart);
617
618     int[] point = findRange(_paragraphs, _parStart, Math.max(chpx.getStart(), _start),
619                               chpx.getEnd());
620     PAPX papx = (PAPX)_paragraphs.get(point[0]);
621     short istd = papx.getIstd();
622
623     CharacterRun chp = new CharacterRun(chpx, _doc.getStyleSheet(), istd, this);
624
625     return chp;
626   }
627
628   /**
629    * Gets the section at index. The index is relative to this range.
630    *
631    * @param index The index of the section to get.
632    * @return The section at the specified index in this range.
633    */

634   public Section getSection(int index)
635   {
636     initSections();
637     SEPX sepx = (SEPX)_sections.get(index + _sectionStart);
638     Section sep = new Section(sepx, this);
639     return sep;
640   }
641
642   /**
643    * Gets the paragraph at index. The index is relative to this range.
644    *
645    * @param index The index of the paragraph to get.
646    * @return The paragraph at the specified index in this range.
647    */

648
649   public Paragraph getParagraph(int index)
650   {
651     initParagraphs();
652     PAPX papx = (PAPX)_paragraphs.get(index + _parStart);
653
654     ParagraphProperties props = papx.getParagraphProperties(_doc.getStyleSheet());
655     Paragraph pap = null;
656     if (props.getIlfo() > 0)
657     {
658       pap = new ListEntry(papx, this, _doc.getListTables());
659     }
660     else
661     {
662       pap = new Paragraph(papx, this);
663     }
664
665     return pap;
666   }
667
668   /**
669    * This method is used to determine the type. Handy for switch statements
670    * compared to the instanceof operator.
671    *
672    * @return A TYPE constant.
673    */

674   public int type()
675   {
676     return TYPE_UNDEFINED;
677   }
678
679   /**
680    * Gets the table that starts with paragraph. In a Word file, a table consists
681    * of a group of paragraphs with certain flags set.
682    *
683    * @param paragraph The paragraph that is the first paragraph in the table.
684    * @return The table that starts with paragraph
685    */

686   public Table getTable(Paragraph paragraph)
687   {
688     if (!paragraph.isInTable())
689     {
690       throw new IllegalArgumentException JavaDoc("This paragraph doesn't belong to a table");
691     }
692
693     Range r = (Range)paragraph;
694     if (r._parent.get() != this)
695     {
696       throw new IllegalArgumentException JavaDoc("This paragraph is not a child of this range");
697     }
698
699     r.initAll();
700     int tableEnd = r._parEnd;
701
702     if (r._parStart != 0 && getParagraph(r._parStart - 1).isInTable()
703         && getParagraph(r._parStart - 1)._sectionEnd >= r._sectionStart)
704     {
705       throw new IllegalArgumentException JavaDoc("This paragraph is not the first one in the table");
706     }
707
708     int limit = _paragraphs.size();
709     for (; tableEnd < limit; tableEnd++)
710     {
711        if (!getParagraph(tableEnd).isInTable())
712       {
713         break;
714       }
715     }
716
717     initAll();
718     if (tableEnd > _parEnd)
719     {
720       throw new ArrayIndexOutOfBoundsException JavaDoc("The table's bounds fall outside of this Range");
721     }
722     return new Table(r._parStart, tableEnd, r._doc.getRange(), paragraph.getTableLevel());
723   }
724
725   /**
726    * loads all of the list indexes.
727    */

728   protected void initAll()
729   {
730     initText();
731     initCharacterRuns();
732     initParagraphs();
733     initSections();
734   }
735
736   /**
737    * inits the paragraph list indexes.
738    */

739   private void initParagraphs()
740   {
741     if (!_parRangeFound)
742     {
743       int[] point = findRange(_paragraphs, _parStart, _start, _end);
744       _parStart = point[0];
745       _parEnd = point[1];
746       _parRangeFound = true;
747     }
748   }
749
750   /**
751    * inits the character run list indexes.
752    */

753   private void initCharacterRuns()
754   {
755     if (!_charRangeFound)
756     {
757       int[] point = findRange(_characters, _charStart, _start, _end);
758       _charStart = point[0];
759       _charEnd = point[1];
760       _charRangeFound = true;
761     }
762   }
763
764   /**
765    * inits the text piece list indexes.
766    */

767   private void initText()
768   {
769     if (!_textRangeFound)
770     {
771       int[] point = findRange(_text, _textStart, _start, _end);
772       _textStart = point[0];
773       _textEnd = point[1];
774       _textRangeFound = true;
775     }
776   }
777
778   /**
779    * inits the section list indexes.
780    */

781   private void initSections()
782   {
783     if (!_sectionRangeFound)
784     {
785       int[] point = findRange(_sections, _sectionStart, _start, _end);
786       _sectionStart = point[0];
787       _sectionEnd = point[1];
788       _sectionRangeFound = true;
789     }
790   }
791
792   /**
793    * Used to find the list indexes of a particular property.
794    *
795    * @param rpl A list of property nodes.
796    * @param min A hint on where to start looking.
797    * @param start The starting character offset.
798    * @param end The ending character offset.
799    * @return An int array of length 2. The first int is the start index and the
800    * second int is the end index.
801    */

802   private int[] findRange(List JavaDoc rpl, int min, int start, int end)
803   {
804     int x = min;
805     PropertyNode node = (PropertyNode)rpl.get(x);
806     while(node.getEnd() <= start && x < rpl.size()-1)
807     {
808       x++;
809       node = (PropertyNode)rpl.get(x);
810     }
811
812     int y = x;
813     node = (PropertyNode)rpl.get(y);
814     while(node.getEnd() < end && y < rpl.size()-1)
815     {
816       y++;
817       node = (PropertyNode)rpl.get(y);
818     }
819     return new int[]{x, y + 1};
820   }
821
822   /**
823    * resets the list indexes.
824    */

825   private void reset()
826   {
827     _textRangeFound = false;
828     _charRangeFound = false;
829     _parRangeFound = false;
830     _sectionRangeFound = false;
831   }
832
833   /**
834    * adjust this range after an insert happens.
835    * @param length the length to adjust for
836    */

837   private void adjustForInsert(int length)
838   {
839     _end += length;
840     reset();
841     Range parent = (Range)_parent.get();
842     if (parent != null)
843     {
844       parent.adjustForInsert(length);
845     }
846   }
847
848 }
849
Popular Tags