Mercurial > projects > dwt-addons
annotate dwtx/jface/text/projection/ProjectionMapping.d @ 134:51e6e63f930e
Regex fix for casts
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 24 Aug 2008 01:46:20 +0200 |
parents | 7d818bd32d63 |
children | 6dcb0baaa031 |
rev | line source |
---|---|
129 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2008 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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.jface.text.projection.ProjectionMapping; | |
14 | |
131 | 15 import dwtx.jface.text.projection.ChildDocumentManager; // packageimport |
16 import dwtx.jface.text.projection.SegmentUpdater; // packageimport | |
17 import dwtx.jface.text.projection.Segment; // packageimport | |
18 import dwtx.jface.text.projection.ProjectionDocument; // packageimport | |
19 import dwtx.jface.text.projection.FragmentUpdater; // packageimport | |
20 import dwtx.jface.text.projection.ProjectionDocumentEvent; // packageimport | |
21 import dwtx.jface.text.projection.ChildDocument; // packageimport | |
22 import dwtx.jface.text.projection.IMinimalMapping; // packageimport | |
23 import dwtx.jface.text.projection.Fragment; // packageimport | |
24 import dwtx.jface.text.projection.ProjectionTextStore; // packageimport | |
25 import dwtx.jface.text.projection.ProjectionDocumentManager; // packageimport | |
26 | |
27 | |
129 | 28 import dwt.dwthelper.utils; |
29 | |
30 | |
31 import dwtx.core.runtime.Assert; | |
32 import dwtx.jface.text.BadLocationException; | |
33 import dwtx.jface.text.BadPositionCategoryException; | |
34 import dwtx.jface.text.IDocument; | |
35 import dwtx.jface.text.IDocumentInformationMapping; | |
36 import dwtx.jface.text.IDocumentInformationMappingExtension; | |
37 import dwtx.jface.text.IDocumentInformationMappingExtension2; | |
38 import dwtx.jface.text.IRegion; | |
39 import dwtx.jface.text.Position; | |
40 import dwtx.jface.text.Region; | |
41 | |
42 | |
43 /** | |
44 * Internal class. Do not use. Only public for testing purposes. | |
45 * <p> | |
46 * Implementation of {@link dwtx.jface.text.IDocumentInformationMapping} | |
47 * for the projection mapping between a master and a slave document. | |
48 * | |
49 * @since 3.0 | |
50 * @noinstantiate This class is not intended to be instantiated by clients. | |
51 * @noextend This class is not intended to be subclassed by clients. | |
52 */ | |
53 public class ProjectionMapping : IDocumentInformationMapping , IDocumentInformationMappingExtension, IDocumentInformationMappingExtension2, IMinimalMapping { | |
54 | |
55 private static final int LEFT= -1; | |
56 private static final int NONE= 0; | |
57 private static final int RIGHT= +1; | |
58 | |
59 /** The master document */ | |
60 private IDocument fMasterDocument; | |
61 /** The position category used to manage the projection fragments inside the master document */ | |
62 private String fFragmentsCategory; | |
63 /** The projection document */ | |
64 private IDocument fSlaveDocument; | |
65 /** The position category to manage the projection segments inside the slave document. */ | |
66 private String fSegmentsCategory; | |
67 /** Cached segments */ | |
68 private Position[] fCachedSegments; | |
69 /** Cached fragments */ | |
70 private Position[] fCachedFragments; | |
71 | |
72 /** | |
73 * Creates a new mapping between the given parent document and the given projection document. | |
74 * | |
75 * @param masterDocument the master document | |
76 * @param fragmentsCategory the position category of the parent document used to manage the projected regions | |
77 * @param slaveDocument the slave document | |
78 * @param segmentsCategory the position category of the projection document used to manage the fragments | |
79 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
80 public this(IDocument masterDocument, String fragmentsCategory, IDocument slaveDocument, String segmentsCategory) { |
129 | 81 fMasterDocument= masterDocument; |
82 fFragmentsCategory= fragmentsCategory; | |
83 fSlaveDocument= slaveDocument; | |
84 fSegmentsCategory= segmentsCategory; | |
85 } | |
86 | |
87 /** | |
88 * Notifies this projection mapping that there was a projection change. | |
89 */ | |
90 public void projectionChanged() { | |
91 fCachedSegments= null; | |
92 fCachedFragments= null; | |
93 } | |
94 | |
95 private Position[] getSegments() { | |
96 if (fCachedSegments is null) { | |
97 try { | |
98 fCachedSegments= fSlaveDocument.getPositions(fSegmentsCategory); | |
99 } catch (BadPositionCategoryException e) { | |
100 return new Position[0]; | |
101 } | |
102 } | |
103 return fCachedSegments; | |
104 } | |
105 | |
106 private Position[] getFragments() { | |
107 if (fCachedFragments is null) { | |
108 try { | |
109 fCachedFragments= fMasterDocument.getPositions(fFragmentsCategory); | |
110 } catch (BadPositionCategoryException e) { | |
111 return new Position[0]; | |
112 } | |
113 } | |
114 return fCachedFragments; | |
115 } | |
116 | |
117 private int findSegmentIndex(int offset) throws BadLocationException { | |
118 Position[] segments= getSegments(); | |
119 if (segments.length is 0) { | |
120 if (offset > 0) | |
121 throw new BadLocationException(); | |
122 return -1; | |
123 } | |
124 | |
125 try { | |
126 int index= fSlaveDocument.computeIndexInCategory(fSegmentsCategory, offset); | |
127 if (index is segments.length && offset > exclusiveEnd(segments[index-1])) | |
128 throw new BadLocationException(); | |
129 | |
130 if (index < segments.length && offset is segments[index].offset) | |
131 return index; | |
132 | |
133 if (index > 0) | |
134 index--; | |
135 | |
136 return index; | |
137 | |
138 } catch (BadPositionCategoryException e) { | |
139 throw new IllegalStateException(); | |
140 } | |
141 } | |
142 | |
143 private Segment findSegment(int offset) throws BadLocationException { | |
144 | |
145 checkImageOffset(offset); | |
146 | |
147 int index= findSegmentIndex(offset); | |
148 if (index is -1) { | |
149 | |
150 Segment s= new Segment(0, 0); | |
151 Fragment f= new Fragment(0, 0); | |
152 s.fragment= f; | |
153 f.segment= s; | |
154 return s; | |
155 } | |
156 | |
157 Position[] segments= getSegments(); | |
134 | 158 return cast(Segment) segments[index]; |
129 | 159 } |
160 | |
161 /** | |
162 * Computes the fragment index given an origin offset. Returns the index of | |
163 * the fragment that contains <code>offset</code>, or <code>-1</code> | |
164 * if no fragment contains <code>offset</code>. | |
165 * <p> | |
166 * If <code>extensionDirection</code> is set to <code>RIGHT</code> or | |
167 * <code>LEFT</code>, the next fragment in that direction is returned if | |
168 * there is no fragment containing <code>offset</code>. Note that if | |
169 * <code>offset</code> occurs before any fragment and | |
170 * <code>extensionDirection</code> is <code>LEFT</code>, | |
171 * <code>-1</code> is also returned. The same applies for an offset after | |
172 * the last fragment and <code>extensionDirection</code> set to | |
173 * <code>RIGHT</code>. | |
174 * </p> | |
175 * | |
176 * @param offset an origin offset | |
177 * @param extensionDirection the direction in which to extend the search, or | |
178 * <code>NONE</code> | |
179 * @return the index of the fragment containing <code>offset</code>, or | |
180 * <code>-1</code> | |
181 * @throws BadLocationException if the index is not valid on the master | |
182 * document | |
183 */ | |
184 private int findFragmentIndex(int offset, int extensionDirection) throws BadLocationException { | |
185 try { | |
186 | |
187 Position[] fragments= getFragments(); | |
188 if (fragments.length is 0) | |
189 return -1; | |
190 | |
191 int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, offset); | |
192 | |
193 if (index < fragments.length && offset is fragments[index].offset) | |
194 return index; | |
195 | |
196 if (0 < index && index <= fragments.length && fragments[index - 1].includes(offset)) | |
197 return index - 1; | |
198 | |
199 switch (extensionDirection) { | |
200 case LEFT: | |
201 return index - 1; | |
202 case RIGHT: | |
203 if (index < fragments.length) | |
204 return index; | |
205 } | |
206 | |
207 return -1; | |
208 | |
209 } catch (BadPositionCategoryException e) { | |
210 throw new IllegalStateException(); | |
211 } | |
212 } | |
213 | |
214 private Fragment findFragment(int offset) throws BadLocationException { | |
215 checkOriginOffset(offset); | |
216 | |
217 int index= findFragmentIndex(offset, NONE); | |
218 Position[] fragments= getFragments(); | |
219 if (index is -1) { | |
220 if (fragments.length > 0) { | |
134 | 221 Fragment last= cast(Fragment) fragments[fragments.length - 1]; |
129 | 222 if (exclusiveEnd(last) is offset) |
223 return last; | |
224 } | |
225 return null; | |
226 } | |
134 | 227 return cast(Fragment) fragments[index]; |
129 | 228 } |
229 | |
230 /** | |
231 * Returns the image region for <code>originRegion</code>. | |
232 * | |
233 * @param originRegion the region to get the image for | |
234 * @param exact if <code>true</code>, the begin and end offsets of | |
235 * <code>originRegion</code> must be projected, otherwise | |
236 * <code>null</code> is returned. If <code>false</code>, the | |
237 * begin and end range that is not visible is simply clipped. | |
238 * @param takeClosestImage if <code>false</code>, <code>null</code> is | |
239 * returned if <code>originRegion</code> is completely invisible. | |
240 * If <code>true</code>, the zero-length region is returned that | |
241 * "covers" the hidden origin region | |
242 * @return the image region of <code>originRegion</code> | |
243 * @throws BadLocationException if the region is not a valid origin region | |
244 */ | |
245 private IRegion toImageRegion(IRegion originRegion, bool exact, bool takeClosestImage) throws BadLocationException { | |
246 if (originRegion.getLength() is 0 && !takeClosestImage) { | |
247 int imageOffset= toImageOffset(originRegion.getOffset()); | |
248 return imageOffset is -1 ? null : new Region(imageOffset, 0); | |
249 } | |
250 | |
251 Fragment[] fragments= findFragments(originRegion, exact, takeClosestImage); | |
252 if (fragments is null) { | |
253 if (takeClosestImage) { | |
254 // originRegion may before the first or after the last fragment | |
255 Position[] allFragments= getFragments(); | |
256 if (allFragments.length > 0) { | |
257 // before the first | |
258 if (exclusiveEnd(originRegion) <= allFragments[0].getOffset()) | |
259 return new Region(0, 0); | |
260 // after last | |
261 Position last= allFragments[allFragments.length - 1]; | |
262 if (originRegion.getOffset() >= exclusiveEnd(last)) | |
134 | 263 return new Region(exclusiveEnd((cast(Fragment) last).segment), 0); |
129 | 264 } |
265 return new Region(0, 0); | |
266 } | |
267 return null; | |
268 } | |
269 | |
270 int imageOffset, exclusiveImageEndOffset; | |
271 | |
272 // translate start offset | |
273 int relative= originRegion.getOffset() - fragments[0].getOffset(); | |
274 if (relative < 0) { | |
275 Assert.isTrue(!exact); | |
276 relative= 0; | |
277 } | |
278 imageOffset= fragments[0].segment.getOffset() + relative; | |
279 | |
280 // translate end offset | |
281 relative= exclusiveEnd(originRegion) - fragments[1].getOffset(); | |
282 if (relative > fragments[1].getLength()) { | |
283 Assert.isTrue(!exact); | |
284 relative= fragments[1].getLength(); | |
285 } | |
286 exclusiveImageEndOffset= fragments[1].segment.getOffset() + relative; | |
287 | |
288 return new Region(imageOffset, exclusiveImageEndOffset - imageOffset); | |
289 } | |
290 | |
291 /** | |
292 * Returns the two fragments containing the begin and end offsets of | |
293 * <code>originRegion</code>. | |
294 * | |
295 * @param originRegion the region to get the fragments for | |
296 * @param exact if <code>true</code>, only the fragments that contain the | |
297 * begin and end offsets are returned; if <code>false</code>, the | |
298 * first fragment after the begin offset and the last fragment before | |
299 * the end offset are returned if the offsets are not projected | |
300 * @param takeClosestImage if <code>true</code>, the method will return | |
301 * fragments also if <code>originRegion</code> completely lies in | |
302 * an unprojected region. | |
303 * @return the two fragments containing the begin and end offset of | |
304 * <code>originRegion</code>, or <code>null</code> if these do | |
305 * not exist | |
306 * @throws BadLocationException if the region is not a valid origin region | |
307 */ | |
308 private Fragment[] findFragments(IRegion originRegion, bool exact, bool takeClosestImage) throws BadLocationException { | |
309 Position[] fragments= getFragments(); | |
310 if (fragments.length is 0) | |
311 return null; | |
312 | |
313 checkOriginRegion(originRegion); | |
314 | |
315 int startFragmentIdx= findFragmentIndex(originRegion.getOffset(), exact ? NONE : RIGHT); | |
316 if (startFragmentIdx is -1) | |
317 return null; | |
318 | |
319 int endFragmentIdx= findFragmentIndex(inclusiveEnd(originRegion), exact ? NONE : LEFT); | |
320 if (!takeClosestImage && startFragmentIdx > endFragmentIdx || endFragmentIdx is -1) | |
321 return null; | |
322 | |
134 | 323 Fragment[] result= {cast(Fragment) fragments[startFragmentIdx], cast(Fragment) fragments[endFragmentIdx]}; |
129 | 324 return result; |
325 } | |
326 | |
327 private IRegion createOriginStartRegion(Segment image, int offsetShift) { | |
328 return new Region(image.fragment.getOffset() + offsetShift, image.fragment.getLength() - offsetShift); | |
329 } | |
330 | |
331 private IRegion createOriginRegion(Segment image) { | |
332 return new Region(image.fragment.getOffset(), image.fragment.getLength()); | |
333 } | |
334 | |
335 private IRegion createOriginEndRegion(Segment image, int lengthReduction) { | |
336 return new Region(image.fragment.getOffset(), image.fragment.getLength() - lengthReduction); | |
337 } | |
338 | |
339 private IRegion createImageStartRegion(Fragment origin, int offsetShift) { | |
340 int shift= offsetShift > 0 ? offsetShift : 0; | |
341 return new Region(origin.segment.getOffset() + shift, origin.segment.getLength() - shift); | |
342 } | |
343 | |
344 private IRegion createImageRegion(Fragment origin) { | |
345 return new Region(origin.segment.getOffset(), origin.segment.getLength()); | |
346 } | |
347 | |
348 private IRegion createImageEndRegion(Fragment origin, int lengthReduction) { | |
349 int reduction= lengthReduction > 0 ? lengthReduction : 0; | |
350 return new Region(origin.segment.getOffset(), origin.segment.getLength() - reduction); | |
351 } | |
352 | |
353 private IRegion createOriginStartRegion(Fragment origin, int offsetShift) { | |
354 int shift= offsetShift > 0 ? offsetShift : 0; | |
355 return new Region(origin.getOffset() + shift, origin.getLength() - shift); | |
356 } | |
357 | |
358 private IRegion createOriginRegion(Fragment origin) { | |
359 return new Region(origin.getOffset(), origin.getLength()); | |
360 } | |
361 | |
362 private IRegion createOriginEndRegion(Fragment origin, int lengthReduction) { | |
363 int reduction= lengthReduction > 0 ? lengthReduction : 0; | |
364 return new Region(origin.getOffset(), origin.getLength() - reduction); | |
365 } | |
366 | |
367 private IRegion getIntersectingRegion(IRegion left, IRegion right) { | |
368 int offset= Math.max(left.getOffset(), right.getOffset()); | |
369 int exclusiveEndOffset= Math.min(exclusiveEnd(left), exclusiveEnd(right)); | |
370 if (exclusiveEndOffset < offset) | |
371 return null; | |
372 return new Region(offset, exclusiveEndOffset - offset); | |
373 } | |
374 | |
375 /* | |
376 * @see dwtx.jface.text.IDocumentInformationMapping#getCoverage() | |
377 */ | |
378 public IRegion getCoverage() { | |
379 Position[] fragments= getFragments(); | |
380 if (fragments !is null && fragments.length > 0) { | |
381 Position first=fragments[0]; | |
382 Position last= fragments[fragments.length -1]; | |
383 return new Region(first.offset, exclusiveEnd(last) - first.offset); | |
384 } | |
385 return new Region(0, 0); | |
386 } | |
387 | |
388 /* | |
389 * @see dwtx.jface.text.IDocumentInformationMapping#toOriginOffset(int) | |
390 */ | |
391 public int toOriginOffset(int imageOffset) throws BadLocationException { | |
392 Segment segment= findSegment(imageOffset); | |
393 int relative= imageOffset - segment.offset; | |
394 return segment.fragment.offset + relative; | |
395 } | |
396 | |
397 /* | |
398 * @see dwtx.jface.text.IDocumentInformationMapping#toOriginRegion(dwtx.jface.text.IRegion) | |
399 */ | |
400 public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException { | |
401 int imageOffset= imageRegion.getOffset(); | |
402 int imageLength= imageRegion.getLength(); | |
403 | |
404 if (imageLength is 0) { | |
405 if (imageOffset is 0) { | |
406 Position[] fragments= getFragments(); | |
407 if (fragments.length is 0 || (fragments.length is 1 && fragments[0].getOffset() is 0 && fragments[0].getLength() is 0)) | |
408 return new Region(0, fMasterDocument.getLength()); | |
409 } | |
410 return new Region(toOriginOffset(imageOffset), 0); | |
411 } | |
412 | |
413 int originOffset= toOriginOffset(imageOffset); | |
414 int inclusiveImageEndOffset= imageOffset + imageLength -1; | |
415 int inclusiveOriginEndOffset= toOriginOffset(inclusiveImageEndOffset); | |
416 | |
417 return new Region(originOffset, (inclusiveOriginEndOffset + 1) - originOffset); | |
418 } | |
419 | |
420 /* | |
421 * @see dwtx.jface.text.IDocumentInformationMapping#toOriginLines(int) | |
422 */ | |
423 public IRegion toOriginLines(int imageLine) throws BadLocationException { | |
424 IRegion imageRegion= fSlaveDocument.getLineInformation(imageLine); | |
425 IRegion originRegion= toOriginRegion(imageRegion); | |
426 | |
427 int originStartLine= fMasterDocument.getLineOfOffset(originRegion.getOffset()); | |
428 if (originRegion.getLength() is 0) | |
429 return new Region(originStartLine, 1); | |
430 | |
431 int originEndLine= fMasterDocument.getLineOfOffset(inclusiveEnd(originRegion)); | |
432 return new Region(originStartLine, (originEndLine + 1) - originStartLine); | |
433 } | |
434 | |
435 /* | |
436 * @see dwtx.jface.text.IDocumentInformationMapping#toOriginLine(int) | |
437 */ | |
438 public int toOriginLine(int imageLine) throws BadLocationException { | |
439 IRegion lines= toOriginLines(imageLine); | |
440 return (lines.getLength() > 1 ? -1 : lines.getOffset()); | |
441 } | |
442 | |
443 /* | |
444 * @see dwtx.jface.text.IDocumentInformationMapping#toImageOffset(int) | |
445 */ | |
446 public int toImageOffset(int originOffset) throws BadLocationException { | |
447 Fragment fragment= findFragment(originOffset); | |
448 if (fragment !is null) { | |
449 int relative= originOffset - fragment.offset; | |
450 return fragment.segment.offset + relative; | |
451 } | |
452 return -1; | |
453 } | |
454 | |
455 /* | |
456 * @see dwtx.jface.text.IDocumentInformationMappingExtension#toExactImageRegion(dwtx.jface.text.IRegion) | |
457 */ | |
458 public IRegion toExactImageRegion(IRegion originRegion) throws BadLocationException { | |
459 return toImageRegion(originRegion, true, false); | |
460 } | |
461 | |
462 /* | |
463 * @see dwtx.jface.text.IDocumentInformationMapping#toImageRegion(dwtx.jface.text.IRegion) | |
464 */ | |
465 public IRegion toImageRegion(IRegion originRegion) throws BadLocationException { | |
466 return toImageRegion(originRegion, false, false); | |
467 } | |
468 | |
469 /* | |
470 * @see dwtx.jface.text.IDocumentInformationMappingExtension2#toClosestImageRegion(dwtx.jface.text.IRegion) | |
471 * @since 3.1 | |
472 */ | |
473 public IRegion toClosestImageRegion(IRegion originRegion) throws BadLocationException { | |
474 return toImageRegion(originRegion, false, true); | |
475 } | |
476 | |
477 /* | |
478 * @see dwtx.jface.text.IDocumentInformationMapping#toImageLine(int) | |
479 */ | |
480 public int toImageLine(int originLine) throws BadLocationException { | |
481 IRegion originRegion= fMasterDocument.getLineInformation(originLine); | |
482 IRegion imageRegion= toImageRegion(originRegion); | |
483 if (imageRegion is null) { | |
484 int imageOffset= toImageOffset(originRegion.getOffset()); | |
485 if (imageOffset > -1) | |
486 imageRegion= new Region(imageOffset, 0); | |
487 else | |
488 return -1; | |
489 } | |
490 | |
491 int startLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset()); | |
492 if (imageRegion.getLength() is 0) | |
493 return startLine; | |
494 | |
495 int endLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset() + imageRegion.getLength()); | |
496 if (endLine !is startLine) | |
497 throw new IllegalStateException(); | |
498 | |
499 return startLine; | |
500 } | |
501 | |
502 /* | |
503 * @see dwtx.jface.text.IDocumentInformationMapping#toClosestImageLine(int) | |
504 */ | |
505 public int toClosestImageLine(int originLine) throws BadLocationException { | |
506 try { | |
507 | |
508 int imageLine= toImageLine(originLine); | |
509 if (imageLine > -1) | |
510 return imageLine; | |
511 | |
512 Position[] fragments= getFragments(); | |
513 if (fragments.length is 0) | |
514 return -1; | |
515 | |
516 IRegion originLineRegion= fMasterDocument.getLineInformation(originLine); | |
517 int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, originLineRegion.getOffset()); | |
518 | |
519 if (0 < index && index < fragments.length) { | |
134 | 520 Fragment left= cast(Fragment) fragments[index - 1]; |
129 | 521 int leftDistance= originLineRegion.getOffset() - (exclusiveEnd(left)); |
134 | 522 Fragment right= cast(Fragment) fragments[index]; |
129 | 523 int rightDistance= right.getOffset() - (exclusiveEnd(originLineRegion)); |
524 | |
525 if (leftDistance <= rightDistance) | |
526 originLine= fMasterDocument.getLineOfOffset(left.getOffset() + Math.max(left.getLength() - 1, 0)); | |
527 else | |
528 originLine= fMasterDocument.getLineOfOffset(right.getOffset()); | |
529 | |
530 } else if (index is 0) { | |
134 | 531 Fragment right= cast(Fragment) fragments[index]; |
129 | 532 originLine= fMasterDocument.getLineOfOffset(right.getOffset()); |
533 } else if (index is fragments.length) { | |
134 | 534 Fragment left= cast(Fragment) fragments[index - 1]; |
129 | 535 originLine= fMasterDocument.getLineOfOffset(exclusiveEnd(left)); |
536 } | |
537 | |
538 return toImageLine(originLine); | |
539 | |
540 } catch (BadPositionCategoryException x) { | |
541 } | |
542 | |
543 return -1; | |
544 } | |
545 | |
546 /* | |
547 * @see dwtx.jface.text.IDocumentInformationMappingExtension#toExactOriginRegions(dwtx.jface.text.IRegion) | |
548 */ | |
549 public IRegion[] toExactOriginRegions(IRegion imageRegion) throws BadLocationException { | |
550 | |
551 if (imageRegion.getLength() is 0) | |
552 return new IRegion[] { new Region(toOriginOffset(imageRegion.getOffset()), 0) }; | |
553 | |
554 int endOffset= exclusiveEnd(imageRegion); | |
555 Position[] segments= getSegments(); | |
556 int firstIndex= findSegmentIndex(imageRegion.getOffset()); | |
557 int lastIndex= findSegmentIndex(endOffset - 1); | |
558 | |
559 int resultLength= lastIndex - firstIndex + 1; | |
560 IRegion[] result= new IRegion[resultLength]; | |
561 | |
562 // first | |
134 | 563 result[0]= createOriginStartRegion(cast(Segment) segments[firstIndex], imageRegion.getOffset() - segments[firstIndex].getOffset()); |
129 | 564 // middles |
565 for (int i= 1; i < resultLength - 1; i++) | |
134 | 566 result[i]= createOriginRegion(cast(Segment) segments[firstIndex + i]); |
129 | 567 // last |
134 | 568 Segment last= cast(Segment) segments[lastIndex]; |
129 | 569 int segmentEndOffset= exclusiveEnd(last); |
570 IRegion lastRegion= createOriginEndRegion(last, segmentEndOffset - endOffset); | |
571 if (resultLength > 1) { | |
572 // first !is last | |
573 result[resultLength - 1]= lastRegion; | |
574 } else { | |
575 // merge first and last | |
576 IRegion intersection= getIntersectingRegion(result[0], lastRegion); | |
577 if (intersection is null) | |
578 result= new IRegion[0]; | |
579 else | |
580 result[0]= intersection; | |
581 } | |
582 | |
583 return result; | |
584 } | |
585 | |
586 /* | |
587 * @see dwtx.jface.text.IDocumentInformationMappingExtension#getImageLength() | |
588 */ | |
589 public int getImageLength() { | |
590 Position[] segments= getSegments(); | |
591 int length= 0; | |
592 for (int i= 0; i < segments.length; i++) | |
593 length += segments[i].length; | |
594 return length; | |
595 } | |
596 | |
597 /* | |
598 * @see dwtx.jface.text.IDocumentInformationMappingExtension#toExactImageRegions(dwtx.jface.text.IRegion) | |
599 */ | |
600 public IRegion[] toExactImageRegions(IRegion originRegion) throws BadLocationException { | |
601 | |
602 int offset= originRegion.getOffset(); | |
603 if (originRegion.getLength() is 0) { | |
604 int imageOffset= toImageOffset(offset); | |
605 return imageOffset > -1 ? new IRegion[] { new Region(imageOffset, 0) } : null; | |
606 } | |
607 | |
608 int endOffset= exclusiveEnd(originRegion); | |
609 Position[] fragments= getFragments(); | |
610 int firstIndex= findFragmentIndex(offset, RIGHT); | |
611 int lastIndex= findFragmentIndex(endOffset - 1, LEFT); | |
612 | |
613 if (firstIndex is -1 || firstIndex > lastIndex) | |
614 return null; | |
615 | |
616 int resultLength= lastIndex - firstIndex + 1; | |
617 IRegion[] result= new IRegion[resultLength]; | |
618 | |
619 // first | |
134 | 620 result[0]= createImageStartRegion(cast(Fragment) fragments[firstIndex], offset - fragments[firstIndex].getOffset()); |
129 | 621 // middles |
622 for (int i= 1; i < resultLength - 1; i++) | |
134 | 623 result[i]= createImageRegion(cast(Fragment) fragments[firstIndex + i]); |
129 | 624 // last |
134 | 625 Fragment last= cast(Fragment) fragments[lastIndex]; |
129 | 626 int fragmentEndOffset= exclusiveEnd(last); |
627 IRegion lastRegion= createImageEndRegion(last, fragmentEndOffset - endOffset); | |
628 if (resultLength > 1) { | |
629 // first !is last | |
630 result[resultLength - 1]= lastRegion; | |
631 } else { | |
632 // merge first and last | |
633 IRegion intersection= getIntersectingRegion(result[0], lastRegion); | |
634 if (intersection is null) | |
635 return null; | |
636 result[0]= intersection; | |
637 } | |
638 | |
639 return result; | |
640 } | |
641 | |
642 /* | |
643 * @see dwtx.jface.text.IDocumentInformationMappingExtension#getExactCoverage(dwtx.jface.text.IRegion) | |
644 */ | |
645 public IRegion[] getExactCoverage(IRegion originRegion) throws BadLocationException { | |
646 | |
647 int originOffset= originRegion.getOffset(); | |
648 int originLength= originRegion.getLength(); | |
649 | |
650 if (originLength is 0) { | |
651 int imageOffset= toImageOffset(originOffset); | |
652 return imageOffset > -1 ? new IRegion[] { new Region(originOffset, 0) } : null; | |
653 } | |
654 | |
655 int endOffset= originOffset + originLength; | |
656 Position[] fragments= getFragments(); | |
657 int firstIndex= findFragmentIndex(originOffset, RIGHT); | |
658 int lastIndex= findFragmentIndex(endOffset - 1, LEFT); | |
659 | |
660 if (firstIndex is -1 || firstIndex > lastIndex) | |
661 return null; | |
662 | |
663 int resultLength= lastIndex - firstIndex + 1; | |
664 IRegion[] result= new IRegion[resultLength]; | |
665 | |
666 // first | |
134 | 667 result[0]= createOriginStartRegion(cast(Fragment) fragments[firstIndex], originOffset - fragments[firstIndex].getOffset()); |
129 | 668 // middles |
669 for (int i= 1; i < resultLength - 1; i++) | |
134 | 670 result[i]= createOriginRegion(cast(Fragment) fragments[firstIndex + i]); |
129 | 671 // last |
134 | 672 Fragment last= cast(Fragment) fragments[lastIndex]; |
129 | 673 int fragmentEndOffset= exclusiveEnd(last); |
674 IRegion lastRegion= createOriginEndRegion(last, fragmentEndOffset - endOffset); | |
675 if (resultLength > 1) { | |
676 // first !is last | |
677 result[resultLength - 1]= lastRegion; | |
678 } else { | |
679 // merge first and last | |
680 IRegion intersection= getIntersectingRegion(result[0], lastRegion); | |
681 if (intersection is null) | |
682 return null; | |
683 result[0]= intersection; | |
684 } | |
685 | |
686 return result; | |
687 } | |
688 | |
689 private final void checkOriginRegion(IRegion originRegion) throws BadLocationException { | |
690 int offset= originRegion.getOffset(); | |
691 int endOffset= inclusiveEnd(originRegion); | |
692 int max= fMasterDocument.getLength(); | |
693 if (offset < 0 || offset > max || endOffset < 0 || endOffset > max) | |
694 throw new BadLocationException(); | |
695 } | |
696 | |
697 private final void checkOriginOffset(int originOffset) throws BadLocationException { | |
698 if (originOffset < 0 || originOffset > fMasterDocument.getLength()) | |
699 throw new BadLocationException(); | |
700 } | |
701 | |
702 private final void checkImageOffset(int imageOffset) throws BadLocationException { | |
703 if (imageOffset < 0 || imageOffset > getImageLength()) | |
704 throw new BadLocationException(); | |
705 } | |
706 | |
707 private final int exclusiveEnd(Position position) { | |
708 return position.offset + position.length; | |
709 } | |
710 | |
711 private final int exclusiveEnd(IRegion region) { | |
712 return region.getOffset() + region.getLength(); | |
713 } | |
714 | |
715 private final int inclusiveEnd(IRegion region) { | |
716 int length= region.getLength(); | |
717 if (length is 0) | |
718 return region.getOffset(); | |
719 return region.getOffset() + length - 1; | |
720 } | |
721 | |
722 | |
723 } |