KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > projection > ProjectionMapping


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text.projection;
12
13
14 import org.eclipse.core.runtime.Assert;
15
16 import org.eclipse.jface.text.BadLocationException;
17 import org.eclipse.jface.text.BadPositionCategoryException;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.IDocumentInformationMapping;
20 import org.eclipse.jface.text.IDocumentInformationMappingExtension;
21 import org.eclipse.jface.text.IDocumentInformationMappingExtension2;
22 import org.eclipse.jface.text.IRegion;
23 import org.eclipse.jface.text.Position;
24 import org.eclipse.jface.text.Region;
25
26
27 /**
28  * Internal class. Do not use. Only public for testing purposes.
29  * <p>
30  * Implementation of {@link org.eclipse.jface.text.IDocumentInformationMapping}
31  * for the projection mapping between a master and a slave document.
32  *
33  * @since 3.0
34  */

35 public class ProjectionMapping implements IDocumentInformationMapping , IDocumentInformationMappingExtension, IDocumentInformationMappingExtension2, IMinimalMapping {
36
37     private static final int LEFT= -1;
38     private static final int NONE= 0;
39     private static final int RIGHT= +1;
40
41     /** The master document */
42     private IDocument fMasterDocument;
43     /** The position category used to manage the projection fragments inside the master document */
44     private String JavaDoc fFragmentsCategory;
45     /** The projection document */
46     private IDocument fSlaveDocument;
47     /** The position category to manage the projection segments inside the slave document. */
48     private String JavaDoc fSegmentsCategory;
49     /** Cached segments */
50     private Position[] fCachedSegments;
51     /** Cached fragments */
52     private Position[] fCachedFragments;
53
54     /**
55      * Creates a new mapping between the given parent document and the given projection document.
56      *
57      * @param masterDocument the master document
58      * @param fragmentsCategory the position category of the parent document used to manage the projected regions
59      * @param slaveDocument the slave document
60      * @param segmentsCategory the position category of the projection document used to manage the fragments
61      */

62     public ProjectionMapping(IDocument masterDocument, String JavaDoc fragmentsCategory, IDocument slaveDocument, String JavaDoc segmentsCategory) {
63         fMasterDocument= masterDocument;
64         fFragmentsCategory= fragmentsCategory;
65         fSlaveDocument= slaveDocument;
66         fSegmentsCategory= segmentsCategory;
67     }
68
69     /**
70      * Notifies this projection mapping that there was a projection change.
71      */

72     public void projectionChanged() {
73         fCachedSegments= null;
74         fCachedFragments= null;
75     }
76
77     private Position[] getSegments() {
78         if (fCachedSegments == null) {
79             try {
80                 fCachedSegments= fSlaveDocument.getPositions(fSegmentsCategory);
81             } catch (BadPositionCategoryException e) {
82                 return new Position[0];
83             }
84         }
85         return fCachedSegments;
86     }
87
88     private Position[] getFragments() {
89         if (fCachedFragments == null) {
90             try {
91                 fCachedFragments= fMasterDocument.getPositions(fFragmentsCategory);
92             } catch (BadPositionCategoryException e) {
93                 return new Position[0];
94             }
95         }
96         return fCachedFragments;
97     }
98
99     private int findSegmentIndex(int offset) throws BadLocationException {
100         Position[] segments= getSegments();
101         if (segments.length == 0) {
102             if (offset > 0)
103                 throw new BadLocationException();
104             return -1;
105         }
106
107         try {
108             int index= fSlaveDocument.computeIndexInCategory(fSegmentsCategory, offset);
109             if (index == segments.length && offset > exclusiveEnd(segments[index-1]))
110                 throw new BadLocationException();
111
112             if (index < segments.length && offset == segments[index].offset)
113                 return index;
114
115             if (index > 0)
116                 index--;
117
118             return index;
119
120         } catch (BadPositionCategoryException e) {
121             throw new IllegalStateException JavaDoc();
122         }
123     }
124
125     private Segment findSegment(int offset) throws BadLocationException {
126
127         checkImageOffset(offset);
128
129         int index= findSegmentIndex(offset);
130         if (index == -1) {
131
132             Segment s= new Segment(0, 0);
133             Fragment f= new Fragment(0, 0);
134             s.fragment= f;
135             f.segment= s;
136             return s;
137         }
138
139         Position[] segments= getSegments();
140         return (Segment) segments[index];
141     }
142
143     /**
144      * Computes the fragment index given an origin offset. Returns the index of
145      * the fragment that contains <code>offset</code>, or <code>-1</code>
146      * if no fragment contains <code>offset</code>.
147      * <p>
148      * If <code>extensionDirection</code> is set to <code>RIGHT</code> or
149      * <code>LEFT</code>, the next fragment in that direction is returned if
150      * there is no fragment containing <code>offset</code>. Note that if
151      * <code>offset</code> occurs before any fragment and
152      * <code>extensionDirection</code> is <code>LEFT</code>,
153      * <code>-1</code> is also returned. The same applies for an offset after
154      * the last fragment and <code>extensionDirection</code> set to
155      * <code>RIGHT</code>.
156      * </p>
157      *
158      * @param offset an origin offset
159      * @param extensionDirection the direction in which to extend the search, or
160      * <code>NONE</code>
161      * @return the index of the fragment containing <code>offset</code>, or
162      * <code>-1</code>
163      * @throws BadLocationException if the index is not valid on the master
164      * document
165      */

166     private int findFragmentIndex(int offset, int extensionDirection) throws BadLocationException {
167         try {
168
169             Position[] fragments= getFragments();
170             if (fragments.length == 0)
171                 return -1;
172
173             int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, offset);
174
175             if (index < fragments.length && offset == fragments[index].offset)
176                 return index;
177
178             if (0 < index && index <= fragments.length && fragments[index - 1].includes(offset))
179                 return index - 1;
180
181             switch (extensionDirection) {
182                 case LEFT:
183                     return index - 1;
184                 case RIGHT:
185                     if (index < fragments.length)
186                         return index;
187             }
188
189             return -1;
190
191         } catch (BadPositionCategoryException e) {
192             throw new IllegalStateException JavaDoc();
193         }
194     }
195
196     private Fragment findFragment(int offset) throws BadLocationException {
197         checkOriginOffset(offset);
198
199         int index= findFragmentIndex(offset, NONE);
200         Position[] fragments= getFragments();
201         if (index == -1) {
202             if (fragments.length > 0) {
203                 Fragment last= (Fragment) fragments[fragments.length - 1];
204                 if (exclusiveEnd(last) == offset)
205                     return last;
206             }
207             return null;
208         }
209         return (Fragment) fragments[index];
210     }
211
212     /**
213      * Returns the image region for <code>originRegion</code>.
214      *
215      * @param originRegion the region to get the image for
216      * @param exact if <code>true</code>, the begin and end offsets of
217      * <code>originRegion</code> must be projected, otherwise
218      * <code>null</code> is returned. If <code>false</code>, the
219      * begin and end range that is not visible is simply clipped.
220      * @param takeClosestImage if <code>false</code>, <code>null</code> is
221      * returned if <code>originRegion</code> is completely invisible.
222      * If <code>true</code>, the zero-length region is returned that
223      * "covers" the hidden origin region
224      * @return the image region of <code>originRegion</code>
225      * @throws BadLocationException if the region is not a valid origin region
226      */

227     private IRegion toImageRegion(IRegion originRegion, boolean exact, boolean takeClosestImage) throws BadLocationException {
228         if (originRegion.getLength() == 0 && !takeClosestImage) {
229             int imageOffset= toImageOffset(originRegion.getOffset());
230             return imageOffset == -1 ? null : new Region(imageOffset, 0);
231         }
232
233         Fragment[] fragments= findFragments(originRegion, exact, takeClosestImage);
234         if (fragments == null) {
235             if (takeClosestImage) {
236                 // originRegion may before the first or after the last fragment
237
Position[] allFragments= getFragments();
238                 if (allFragments.length > 0) {
239                     // before the first
240
if (exclusiveEnd(originRegion) <= allFragments[0].getOffset())
241                         return new Region(0, 0);
242                     // after last
243
Position last= allFragments[allFragments.length - 1];
244                     if (originRegion.getOffset() >= exclusiveEnd(last))
245                         return new Region(exclusiveEnd(((Fragment) last).segment), 0);
246                 }
247                 return new Region(0, 0);
248             }
249             return null;
250         }
251
252         int imageOffset, exclusiveImageEndOffset;
253
254         // translate start offset
255
int relative= originRegion.getOffset() - fragments[0].getOffset();
256         if (relative < 0) {
257             Assert.isTrue(!exact);
258             relative= 0;
259         }
260         imageOffset= fragments[0].segment.getOffset() + relative;
261
262         // translate end offset
263
relative= exclusiveEnd(originRegion) - fragments[1].getOffset();
264         if (relative > fragments[1].getLength()) {
265             Assert.isTrue(!exact);
266             relative= fragments[1].getLength();
267         }
268         exclusiveImageEndOffset= fragments[1].segment.getOffset() + relative;
269
270         return new Region(imageOffset, exclusiveImageEndOffset - imageOffset);
271     }
272
273     /**
274      * Returns the two fragments containing the begin and end offsets of
275      * <code>originRegion</code>.
276      *
277      * @param originRegion the region to get the fragments for
278      * @param exact if <code>true</code>, only the fragments that contain the
279      * begin and end offsets are returned; if <code>false</code>, the
280      * first fragment after the begin offset and the last fragment before
281      * the end offset are returned if the offsets are not projected
282      * @param takeClosestImage if <code>true</code>, the method will return
283      * fragments also if <code>originRegion</code> completely lies in
284      * an unprojected region.
285      * @return the two fragments containing the begin and end offset of
286      * <code>originRegion</code>, or <code>null</code> if these do
287      * not exist
288      * @throws BadLocationException if the region is not a valid origin region
289      */

290     private Fragment[] findFragments(IRegion originRegion, boolean exact, boolean takeClosestImage) throws BadLocationException {
291         Position[] fragments= getFragments();
292         if (fragments.length == 0)
293             return null;
294
295         checkOriginRegion(originRegion);
296
297         int startFragmentIdx= findFragmentIndex(originRegion.getOffset(), exact ? NONE : RIGHT);
298         if (startFragmentIdx == -1)
299             return null;
300
301         int endFragmentIdx= findFragmentIndex(inclusiveEnd(originRegion), exact ? NONE : LEFT);
302         if (!takeClosestImage && startFragmentIdx > endFragmentIdx || endFragmentIdx == -1)
303             return null;
304
305         Fragment[] result= {(Fragment) fragments[startFragmentIdx], (Fragment) fragments[endFragmentIdx]};
306         return result;
307     }
308
309     private IRegion createOriginStartRegion(Segment image, int offsetShift) {
310         return new Region(image.fragment.getOffset() + offsetShift, image.fragment.getLength() - offsetShift);
311     }
312
313     private IRegion createOriginRegion(Segment image) {
314         return new Region(image.fragment.getOffset(), image.fragment.getLength());
315     }
316
317     private IRegion createOriginEndRegion(Segment image, int lengthReduction) {
318         return new Region(image.fragment.getOffset(), image.fragment.getLength() - lengthReduction);
319     }
320
321     private IRegion createImageStartRegion(Fragment origin, int offsetShift) {
322         int shift= offsetShift > 0 ? offsetShift : 0;
323         return new Region(origin.segment.getOffset() + shift, origin.segment.getLength() - shift);
324     }
325
326     private IRegion createImageRegion(Fragment origin) {
327         return new Region(origin.segment.getOffset(), origin.segment.getLength());
328     }
329
330     private IRegion createImageEndRegion(Fragment origin, int lengthReduction) {
331         int reduction= lengthReduction > 0 ? lengthReduction : 0;
332         return new Region(origin.segment.getOffset(), origin.segment.getLength() - reduction);
333     }
334
335     private IRegion createOriginStartRegion(Fragment origin, int offsetShift) {
336         int shift= offsetShift > 0 ? offsetShift : 0;
337         return new Region(origin.getOffset() + shift, origin.getLength() - shift);
338     }
339
340     private IRegion createOriginRegion(Fragment origin) {
341         return new Region(origin.getOffset(), origin.getLength());
342     }
343
344     private IRegion createOriginEndRegion(Fragment origin, int lengthReduction) {
345         int reduction= lengthReduction > 0 ? lengthReduction : 0;
346         return new Region(origin.getOffset(), origin.getLength() - reduction);
347     }
348
349     private IRegion getIntersectingRegion(IRegion left, IRegion right) {
350         int offset= Math.max(left.getOffset(), right.getOffset());
351         int exclusiveEndOffset= Math.min(exclusiveEnd(left), exclusiveEnd(right));
352         if (exclusiveEndOffset < offset)
353             return null;
354         return new Region(offset, exclusiveEndOffset - offset);
355     }
356
357     /*
358      * @see org.eclipse.jface.text.IDocumentInformationMapping#getCoverage()
359      */

360     public IRegion getCoverage() {
361         Position[] fragments= getFragments();
362         if (fragments != null && fragments.length > 0) {
363             Position first=fragments[0];
364             Position last= fragments[fragments.length -1];
365             return new Region(first.offset, exclusiveEnd(last) - first.offset);
366         }
367         return new Region(0, 0);
368     }
369
370     /*
371      * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginOffset(int)
372      */

373     public int toOriginOffset(int imageOffset) throws BadLocationException {
374         Segment segment= findSegment(imageOffset);
375         int relative= imageOffset - segment.offset;
376         return segment.fragment.offset + relative;
377     }
378
379     /*
380      * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginRegion(org.eclipse.jface.text.IRegion)
381      */

382     public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException {
383         int imageOffset= imageRegion.getOffset();
384         int imageLength= imageRegion.getLength();
385
386         if (imageLength == 0) {
387             if (imageOffset == 0) {
388                 Position[] fragments= getFragments();
389                 if (fragments.length == 0 || (fragments.length == 1 && fragments[0].getOffset() == 0 && fragments[0].getLength() == 0))
390                     return new Region(0, fMasterDocument.getLength());
391             }
392             return new Region(toOriginOffset(imageOffset), 0);
393         }
394
395         int originOffset= toOriginOffset(imageOffset);
396         int inclusiveImageEndOffset= imageOffset + imageLength -1;
397         int inclusiveOriginEndOffset= toOriginOffset(inclusiveImageEndOffset);
398
399         return new Region(originOffset, (inclusiveOriginEndOffset + 1) - originOffset);
400     }
401
402     /*
403      * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLines(int)
404      */

405     public IRegion toOriginLines(int imageLine) throws BadLocationException {
406         IRegion imageRegion= fSlaveDocument.getLineInformation(imageLine);
407         IRegion originRegion= toOriginRegion(imageRegion);
408
409         int originStartLine= fMasterDocument.getLineOfOffset(originRegion.getOffset());
410         if (originRegion.getLength() == 0)
411             return new Region(originStartLine, 1);
412
413         int originEndLine= fMasterDocument.getLineOfOffset(inclusiveEnd(originRegion));
414         return new Region(originStartLine, (originEndLine + 1) - originStartLine);
415     }
416
417     /*
418      * @see org.eclipse.jface.text.IDocumentInformationMapping#toOriginLine(int)
419      */

420     public int toOriginLine(int imageLine) throws BadLocationException {
421         IRegion lines= toOriginLines(imageLine);
422         return (lines.getLength() > 1 ? -1 : lines.getOffset());
423     }
424
425     /*
426      * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageOffset(int)
427      */

428     public int toImageOffset(int originOffset) throws BadLocationException {
429         Fragment fragment= findFragment(originOffset);
430         if (fragment != null) {
431             int relative= originOffset - fragment.offset;
432             return fragment.segment.offset + relative;
433         }
434         return -1;
435     }
436
437     /*
438      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension#toExactImageRegion(org.eclipse.jface.text.IRegion)
439      */

440     public IRegion toExactImageRegion(IRegion originRegion) throws BadLocationException {
441         return toImageRegion(originRegion, true, false);
442     }
443
444     /*
445      * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageRegion(org.eclipse.jface.text.IRegion)
446      */

447     public IRegion toImageRegion(IRegion originRegion) throws BadLocationException {
448         return toImageRegion(originRegion, false, false);
449     }
450
451     /*
452      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension2#toClosestImageRegion(org.eclipse.jface.text.IRegion)
453      * @since 3.1
454      */

455     public IRegion toClosestImageRegion(IRegion originRegion) throws BadLocationException {
456         return toImageRegion(originRegion, false, true);
457     }
458
459     /*
460      * @see org.eclipse.jface.text.IDocumentInformationMapping#toImageLine(int)
461      */

462     public int toImageLine(int originLine) throws BadLocationException {
463         IRegion originRegion= fMasterDocument.getLineInformation(originLine);
464         IRegion imageRegion= toImageRegion(originRegion);
465         if (imageRegion == null) {
466             int imageOffset= toImageOffset(originRegion.getOffset());
467             if (imageOffset > -1)
468                 imageRegion= new Region(imageOffset, 0);
469             else
470                 return -1;
471         }
472
473         int startLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset());
474         if (imageRegion.getLength() == 0)
475             return startLine;
476
477         int endLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset() + imageRegion.getLength());
478         if (endLine != startLine)
479             throw new IllegalStateException JavaDoc();
480
481         return startLine;
482     }
483
484     /*
485      * @see org.eclipse.jface.text.IDocumentInformationMapping#toClosestImageLine(int)
486      */

487     public int toClosestImageLine(int originLine) throws BadLocationException {
488         try {
489
490             int imageLine= toImageLine(originLine);
491             if (imageLine > -1)
492                 return imageLine;
493
494             Position[] fragments= getFragments();
495             if (fragments.length == 0)
496                 return -1;
497
498             IRegion originLineRegion= fMasterDocument.getLineInformation(originLine);
499             int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, originLineRegion.getOffset());
500
501             if (0 < index && index < fragments.length) {
502                 Fragment left= (Fragment) fragments[index - 1];
503                 int leftDistance= originLineRegion.getOffset() - (exclusiveEnd(left));
504                 Fragment right= (Fragment) fragments[index];
505                 int rightDistance= right.getOffset() - (exclusiveEnd(originLineRegion));
506
507                 if (leftDistance <= rightDistance)
508                     originLine= fMasterDocument.getLineOfOffset(left.getOffset() + Math.max(left.getLength() - 1, 0));
509                 else
510                     originLine= fMasterDocument.getLineOfOffset(right.getOffset());
511
512             } else if (index == 0) {
513                 Fragment right= (Fragment) fragments[index];
514                 originLine= fMasterDocument.getLineOfOffset(right.getOffset());
515             } else if (index == fragments.length) {
516                 Fragment left= (Fragment) fragments[index - 1];
517                 originLine= fMasterDocument.getLineOfOffset(exclusiveEnd(left));
518             }
519
520             return toImageLine(originLine);
521
522         } catch (BadPositionCategoryException x) {
523         }
524
525         return -1;
526     }
527
528     /*
529      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension#toExactOriginRegions(org.eclipse.jface.text.IRegion)
530      */

531     public IRegion[] toExactOriginRegions(IRegion imageRegion) throws BadLocationException {
532
533         if (imageRegion.getLength() == 0)
534             return new IRegion[] { new Region(toOriginOffset(imageRegion.getOffset()), 0) };
535
536         int endOffset= exclusiveEnd(imageRegion);
537         Position[] segments= getSegments();
538         int firstIndex= findSegmentIndex(imageRegion.getOffset());
539         int lastIndex= findSegmentIndex(endOffset - 1);
540
541         int resultLength= lastIndex - firstIndex + 1;
542         IRegion[] result= new IRegion[resultLength];
543
544         // first
545
result[0]= createOriginStartRegion((Segment) segments[firstIndex], imageRegion.getOffset() - segments[firstIndex].getOffset());
546         // middles
547
for (int i= 1; i < resultLength - 1; i++)
548             result[i]= createOriginRegion((Segment) segments[firstIndex + i]);
549         // last
550
Segment last= (Segment) segments[lastIndex];
551         int segmentEndOffset= exclusiveEnd(last);
552         IRegion lastRegion= createOriginEndRegion(last, segmentEndOffset - endOffset);
553         if (resultLength > 1) {
554             // first != last
555
result[resultLength - 1]= lastRegion;
556         } else {
557             // merge first and last
558
IRegion intersection= getIntersectingRegion(result[0], lastRegion);
559             if (intersection == null)
560                 result= new IRegion[0];
561             else
562                 result[0]= intersection;
563         }
564
565         return result;
566     }
567
568     /*
569      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension#getImageLength()
570      */

571     public int getImageLength() {
572         Position[] segments= getSegments();
573         int length= 0;
574         for (int i= 0; i < segments.length; i++)
575             length += segments[i].length;
576         return length;
577     }
578
579     /*
580      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension#toExactImageRegions(org.eclipse.jface.text.IRegion)
581      */

582     public IRegion[] toExactImageRegions(IRegion originRegion) throws BadLocationException {
583
584         int offset= originRegion.getOffset();
585         if (originRegion.getLength() == 0) {
586             int imageOffset= toImageOffset(offset);
587             return imageOffset > -1 ? new IRegion[] { new Region(imageOffset, 0) } : null;
588         }
589
590         int endOffset= exclusiveEnd(originRegion);
591         Position[] fragments= getFragments();
592         int firstIndex= findFragmentIndex(offset, RIGHT);
593         int lastIndex= findFragmentIndex(endOffset - 1, LEFT);
594
595         if (firstIndex == -1 || firstIndex > lastIndex)
596             return null;
597
598         int resultLength= lastIndex - firstIndex + 1;
599         IRegion[] result= new IRegion[resultLength];
600
601         // first
602
result[0]= createImageStartRegion((Fragment) fragments[firstIndex], offset - fragments[firstIndex].getOffset());
603         // middles
604
for (int i= 1; i < resultLength - 1; i++)
605             result[i]= createImageRegion((Fragment) fragments[firstIndex + i]);
606         // last
607
Fragment last= (Fragment) fragments[lastIndex];
608         int fragmentEndOffset= exclusiveEnd(last);
609         IRegion lastRegion= createImageEndRegion(last, fragmentEndOffset - endOffset);
610         if (resultLength > 1) {
611             // first != last
612
result[resultLength - 1]= lastRegion;
613         } else {
614             // merge first and last
615
IRegion intersection= getIntersectingRegion(result[0], lastRegion);
616             if (intersection == null)
617                 return null;
618             result[0]= intersection;
619         }
620
621         return result;
622     }
623
624     /*
625      * @see org.eclipse.jface.text.IDocumentInformationMappingExtension#getExactCoverage(org.eclipse.jface.text.IRegion)
626      */

627     public IRegion[] getExactCoverage(IRegion originRegion) throws BadLocationException {
628
629         int originOffset= originRegion.getOffset();
630         int originLength= originRegion.getLength();
631
632         if (originLength == 0) {
633             int imageOffset= toImageOffset(originOffset);
634             return imageOffset > -1 ? new IRegion[] { new Region(originOffset, 0) } : null;
635         }
636
637         int endOffset= originOffset + originLength;
638         Position[] fragments= getFragments();
639         int firstIndex= findFragmentIndex(originOffset, RIGHT);
640         int lastIndex= findFragmentIndex(endOffset - 1, LEFT);
641
642         if (firstIndex == -1 || firstIndex > lastIndex)
643             return null;
644
645         int resultLength= lastIndex - firstIndex + 1;
646         IRegion[] result= new IRegion[resultLength];
647
648         // first
649
result[0]= createOriginStartRegion((Fragment) fragments[firstIndex], originOffset - fragments[firstIndex].getOffset());
650         // middles
651
for (int i= 1; i < resultLength - 1; i++)
652             result[i]= createOriginRegion((Fragment) fragments[firstIndex + i]);
653         // last
654
Fragment last= (Fragment) fragments[lastIndex];
655         int fragmentEndOffset= exclusiveEnd(last);
656         IRegion lastRegion= createOriginEndRegion(last, fragmentEndOffset - endOffset);
657         if (resultLength > 1) {
658             // first != last
659
result[resultLength - 1]= lastRegion;
660         } else {
661             // merge first and last
662
IRegion intersection= getIntersectingRegion(result[0], lastRegion);
663             if (intersection == null)
664                 return null;
665             result[0]= intersection;
666         }
667
668         return result;
669     }
670
671     private final void checkOriginRegion(IRegion originRegion) throws BadLocationException {
672         int offset= originRegion.getOffset();
673         int endOffset= inclusiveEnd(originRegion);
674         int max= fMasterDocument.getLength();
675         if (offset < 0 || offset > max || endOffset < 0 || endOffset > max)
676             throw new BadLocationException();
677     }
678
679     private final void checkOriginOffset(int originOffset) throws BadLocationException {
680         if (originOffset < 0 || originOffset > fMasterDocument.getLength())
681             throw new BadLocationException();
682     }
683
684     private final void checkImageOffset(int imageOffset) throws BadLocationException {
685         if (imageOffset < 0 || imageOffset > getImageLength())
686             throw new BadLocationException();
687     }
688
689     private final int exclusiveEnd(Position position) {
690         return position.offset + position.length;
691     }
692
693     private final int exclusiveEnd(IRegion region) {
694         return region.getOffset() + region.getLength();
695     }
696
697     private final int inclusiveEnd(IRegion region) {
698         int length= region.getLength();
699         if (length == 0)
700             return region.getOffset();
701         return region.getOffset() + length - 1;
702     }
703
704
705 }
706
Popular Tags