Mercurial > projects > dwt-addons
annotate dwtx/jface/text/rules/DefaultPartitioner.d @ 160:3678e4f1a766
toHash, toString
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Wed, 27 Aug 2008 02:07:22 +0200 |
parents | f70d9508c95c |
children | 1a5b8f8129df |
rev | line source |
---|---|
129 | 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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.jface.text.rules.DefaultPartitioner; | |
14 | |
131 | 15 import dwtx.jface.text.rules.FastPartitioner; // packageimport |
16 import dwtx.jface.text.rules.ITokenScanner; // packageimport | |
17 import dwtx.jface.text.rules.Token; // packageimport | |
18 import dwtx.jface.text.rules.RuleBasedScanner; // packageimport | |
19 import dwtx.jface.text.rules.EndOfLineRule; // packageimport | |
20 import dwtx.jface.text.rules.WordRule; // packageimport | |
21 import dwtx.jface.text.rules.WhitespaceRule; // packageimport | |
22 import dwtx.jface.text.rules.WordPatternRule; // packageimport | |
23 import dwtx.jface.text.rules.IPredicateRule; // packageimport | |
24 import dwtx.jface.text.rules.NumberRule; // packageimport | |
25 import dwtx.jface.text.rules.SingleLineRule; // packageimport | |
26 import dwtx.jface.text.rules.PatternRule; // packageimport | |
27 import dwtx.jface.text.rules.IWordDetector; // packageimport | |
28 import dwtx.jface.text.rules.RuleBasedDamagerRepairer; // packageimport | |
29 import dwtx.jface.text.rules.ICharacterScanner; // packageimport | |
30 import dwtx.jface.text.rules.IRule; // packageimport | |
31 import dwtx.jface.text.rules.DefaultDamagerRepairer; // packageimport | |
32 import dwtx.jface.text.rules.IToken; // packageimport | |
33 import dwtx.jface.text.rules.IPartitionTokenScanner; // packageimport | |
34 import dwtx.jface.text.rules.MultiLineRule; // packageimport | |
35 import dwtx.jface.text.rules.RuleBasedPartitioner; // packageimport | |
36 import dwtx.jface.text.rules.RuleBasedPartitionScanner; // packageimport | |
37 import dwtx.jface.text.rules.BufferedRuleBasedScanner; // packageimport | |
38 import dwtx.jface.text.rules.IWhitespaceDetector; // packageimport | |
39 | |
40 | |
129 | 41 import dwt.dwthelper.utils; |
42 | |
43 | |
153
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
150
diff
changeset
|
44 import dwtx.dwtxhelper.Collection; |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
150
diff
changeset
|
45 |
129 | 46 |
47 import dwtx.core.runtime.Assert; | |
48 import dwtx.jface.text.BadLocationException; | |
49 import dwtx.jface.text.BadPositionCategoryException; | |
50 import dwtx.jface.text.DefaultPositionUpdater; | |
51 import dwtx.jface.text.DocumentEvent; | |
52 import dwtx.jface.text.DocumentRewriteSession; | |
53 import dwtx.jface.text.IDocument; | |
54 import dwtx.jface.text.IDocumentPartitioner; | |
55 import dwtx.jface.text.IDocumentPartitionerExtension; | |
56 import dwtx.jface.text.IDocumentPartitionerExtension2; | |
57 import dwtx.jface.text.IDocumentPartitionerExtension3; | |
58 import dwtx.jface.text.IRegion; | |
59 import dwtx.jface.text.ITypedRegion; | |
60 import dwtx.jface.text.Position; | |
61 import dwtx.jface.text.Region; | |
62 import dwtx.jface.text.TextUtilities; | |
63 import dwtx.jface.text.TypedPosition; | |
64 import dwtx.jface.text.TypedRegion; | |
65 | |
66 | |
67 | |
68 /** | |
69 * A standard implementation of a document partitioner. It uses a partition | |
70 * token scanner to scan the document and to determine the document's | |
71 * partitioning. The tokens returned by the scanner are supposed to return the | |
72 * partition type as their data. The partitioner remembers the document's | |
73 * partitions in the document itself rather than maintaining its own data | |
74 * structure. | |
75 * | |
76 * @see IPartitionTokenScanner | |
77 * @since 2.0 | |
78 * @deprecated As of 3.1, replaced by {@link dwtx.jface.text.rules.FastPartitioner} instead | |
79 */ | |
80 public class DefaultPartitioner : IDocumentPartitioner, IDocumentPartitionerExtension, IDocumentPartitionerExtension2, IDocumentPartitionerExtension3 { | |
81 | |
82 /** | |
83 * The position category this partitioner uses to store the document's partitioning information. | |
84 * @deprecated As of 3.0, use <code>getManagingPositionCategories()</code> instead. | |
85 */ | |
146 | 86 public const static String CONTENT_TYPES_CATEGORY= "__content_types_category"; //$NON-NLS-1$ |
129 | 87 |
88 | |
89 /** The partitioner's scanner */ | |
90 protected IPartitionTokenScanner fScanner; | |
91 /** The legal content types of this partitioner */ | |
92 protected String[] fLegalContentTypes; | |
93 /** The partitioner's document */ | |
94 protected IDocument fDocument; | |
95 /** The document length before a document change occurred */ | |
96 protected int fPreviousDocumentLength; | |
97 /** The position updater used to for the default updating of partitions */ | |
98 protected DefaultPositionUpdater fPositionUpdater; | |
99 /** The offset at which the first changed partition starts */ | |
100 protected int fStartOffset; | |
101 /** The offset at which the last changed partition ends */ | |
102 protected int fEndOffset; | |
103 /**The offset at which a partition has been deleted */ | |
104 protected int fDeleteOffset; | |
105 /** | |
106 * The position category this partitioner uses to store the document's partitioning information. | |
107 * @since 3.0 | |
108 */ | |
109 private String fPositionCategory; | |
110 /** | |
111 * The active document rewrite session. | |
112 * @since 3.1 | |
113 */ | |
114 private DocumentRewriteSession fActiveRewriteSession; | |
115 /** | |
116 * Flag indicating whether this partitioner has been initialized. | |
117 * @since 3.1 | |
118 */ | |
119 private bool fIsInitialized= false; | |
120 | |
121 /** | |
122 * Creates a new partitioner that uses the given scanner and may return | |
123 * partitions of the given legal content types. | |
124 * | |
125 * @param scanner the scanner this partitioner is supposed to use | |
126 * @param legalContentTypes the legal content types of this partitioner | |
127 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
128 public this(IPartitionTokenScanner scanner, String[] legalContentTypes) { |
129 | 129 fScanner= scanner; |
130 fLegalContentTypes= TextUtilities.copy(legalContentTypes); | |
160 | 131 fPositionCategory= CONTENT_TYPES_CATEGORY + toHash(); |
129 | 132 fPositionUpdater= new DefaultPositionUpdater(fPositionCategory); |
133 } | |
134 | |
135 /* | |
136 * @see dwtx.jface.text.IDocumentPartitionerExtension2#getManagingPositionCategories() | |
137 * @since 3.0 | |
138 */ | |
139 public String[] getManagingPositionCategories() { | |
150 | 140 return [ fPositionCategory ]; |
129 | 141 } |
142 | |
143 /* | |
144 * @see dwtx.jface.text.IDocumentPartitioner#connect(dwtx.jface.text.IDocument) | |
145 */ | |
146 public void connect(IDocument document) { | |
147 connect(document, false); | |
148 } | |
149 | |
150 /* | |
151 * @see dwtx.jface.text.IDocumentPartitionerExtension3#connect(dwtx.jface.text.IDocument, bool) | |
152 * @since 3.1 | |
153 */ | |
154 public void connect(IDocument document, bool delayInitialization) { | |
155 Assert.isNotNull(document); | |
156 Assert.isTrue(!document.containsPositionCategory(fPositionCategory)); | |
157 | |
158 fDocument= document; | |
159 fDocument.addPositionCategory(fPositionCategory); | |
160 | |
161 fIsInitialized= false; | |
162 if (!delayInitialization) | |
163 checkInitialization(); | |
164 } | |
165 | |
166 /* | |
167 * @since 3.1 | |
168 */ | |
169 protected final void checkInitialization() { | |
170 if (!fIsInitialized) | |
171 initialize(); | |
172 } | |
173 | |
174 /** | |
175 * Performs the initial partitioning of the partitioner's document. | |
176 */ | |
177 protected void initialize() { | |
178 fIsInitialized= true; | |
179 fScanner.setRange(fDocument, 0, fDocument.getLength()); | |
180 | |
181 try { | |
182 IToken token= fScanner.nextToken(); | |
183 while (!token.isEOF()) { | |
184 | |
185 String contentType= getTokenContentType(token); | |
186 | |
187 if (isSupportedContentType(contentType)) { | |
188 TypedPosition p= new TypedPosition(fScanner.getTokenOffset(), fScanner.getTokenLength(), contentType); | |
189 fDocument.addPosition(fPositionCategory, p); | |
190 } | |
191 | |
192 token= fScanner.nextToken(); | |
193 } | |
194 } catch (BadLocationException x) { | |
195 // cannot happen as offsets come from scanner | |
196 } catch (BadPositionCategoryException x) { | |
197 // cannot happen if document has been connected before | |
198 } | |
199 } | |
200 | |
201 /* | |
202 * @see IDocumentPartitioner#disconnect() | |
203 */ | |
204 public void disconnect() { | |
205 | |
206 Assert.isTrue(fDocument.containsPositionCategory(fPositionCategory)); | |
207 | |
208 try { | |
209 fDocument.removePositionCategory(fPositionCategory); | |
210 } catch (BadPositionCategoryException x) { | |
211 // can not happen because of Assert | |
212 } | |
213 } | |
214 | |
215 /* | |
216 * @see IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent) | |
217 */ | |
218 public void documentAboutToBeChanged(DocumentEvent e) { | |
219 if (fIsInitialized) { | |
220 | |
221 Assert.isTrue(e.getDocument() is fDocument); | |
222 | |
223 fPreviousDocumentLength= e.getDocument().getLength(); | |
224 fStartOffset= -1; | |
225 fEndOffset= -1; | |
226 fDeleteOffset= -1; | |
227 } | |
228 } | |
229 | |
230 /* | |
231 * @see IDocumentPartitioner#documentChanged(DocumentEvent) | |
232 */ | |
233 public bool documentChanged(DocumentEvent e) { | |
234 if (fIsInitialized) { | |
235 IRegion region= documentChanged2(e); | |
236 return (region !is null); | |
237 } | |
238 return false; | |
239 } | |
240 | |
241 /** | |
242 * Helper method for tracking the minimal region containing all partition changes. | |
243 * If <code>offset</code> is smaller than the remembered offset, <code>offset</code> | |
244 * will from now on be remembered. If <code>offset + length</code> is greater than | |
245 * the remembered end offset, it will be remembered from now on. | |
246 * | |
247 * @param offset the offset | |
248 * @param length the length | |
249 */ | |
250 private void rememberRegion(int offset, int length) { | |
251 // remember start offset | |
252 if (fStartOffset is -1) | |
253 fStartOffset= offset; | |
254 else if (offset < fStartOffset) | |
255 fStartOffset= offset; | |
256 | |
257 // remember end offset | |
258 int endOffset= offset + length; | |
259 if (fEndOffset is -1) | |
260 fEndOffset= endOffset; | |
261 else if (endOffset > fEndOffset) | |
262 fEndOffset= endOffset; | |
263 } | |
264 | |
265 /** | |
266 * Remembers the given offset as the deletion offset. | |
267 * | |
268 * @param offset the offset | |
269 */ | |
270 private void rememberDeletedOffset(int offset) { | |
271 fDeleteOffset= offset; | |
272 } | |
273 | |
274 /** | |
275 * Creates the minimal region containing all partition changes using the | |
276 * remembered offset, end offset, and deletion offset. | |
277 * | |
278 * @return the minimal region containing all the partition changes | |
279 */ | |
280 private IRegion createRegion() { | |
281 if (fDeleteOffset is -1) { | |
282 if (fStartOffset is -1 || fEndOffset is -1) | |
283 return null; | |
284 return new Region(fStartOffset, fEndOffset - fStartOffset); | |
285 } else if (fStartOffset is -1 || fEndOffset is -1) { | |
286 return new Region(fDeleteOffset, 0); | |
287 } else { | |
288 int offset= Math.min(fDeleteOffset, fStartOffset); | |
289 int endOffset= Math.max(fDeleteOffset, fEndOffset); | |
290 return new Region(offset, endOffset - offset); | |
291 } | |
292 } | |
293 | |
294 /* | |
295 * @see IDocumentPartitionerExtension#documentChanged2(DocumentEvent) | |
296 * @since 2.0 | |
297 */ | |
298 public IRegion documentChanged2(DocumentEvent e) { | |
299 | |
300 if (!fIsInitialized) | |
301 return null; | |
302 | |
303 try { | |
304 | |
305 IDocument d= e.getDocument(); | |
306 Position[] category= d.getPositions(fPositionCategory); | |
307 IRegion line= d.getLineInformationOfOffset(e.getOffset()); | |
308 int reparseStart= line.getOffset(); | |
309 int partitionStart= -1; | |
310 String contentType= null; | |
311 int newLength= e.getText() is null ? 0 : e.getText().length(); | |
312 | |
313 int first= d.computeIndexInCategory(fPositionCategory, reparseStart); | |
314 if (first > 0) { | |
134 | 315 TypedPosition partition= cast(TypedPosition) category[first - 1]; |
129 | 316 if (partition.includes(reparseStart)) { |
317 partitionStart= partition.getOffset(); | |
318 contentType= partition.getType(); | |
319 if (e.getOffset() is partition.getOffset() + partition.getLength()) | |
320 reparseStart= partitionStart; | |
321 -- first; | |
322 } else if (reparseStart is e.getOffset() && reparseStart is partition.getOffset() + partition.getLength()) { | |
323 partitionStart= partition.getOffset(); | |
324 contentType= partition.getType(); | |
325 reparseStart= partitionStart; | |
326 -- first; | |
327 } else { | |
328 partitionStart= partition.getOffset() + partition.getLength(); | |
329 contentType= IDocument.DEFAULT_CONTENT_TYPE; | |
330 } | |
331 } | |
332 | |
333 fPositionUpdater.update(e); | |
334 for (int i= first; i < category.length; i++) { | |
335 Position p= category[i]; | |
336 if (p.isDeleted) { | |
337 rememberDeletedOffset(e.getOffset()); | |
338 break; | |
339 } | |
340 } | |
341 category= d.getPositions(fPositionCategory); | |
342 | |
343 fScanner.setPartialRange(d, reparseStart, d.getLength() - reparseStart, contentType, partitionStart); | |
344 | |
345 int lastScannedPosition= reparseStart; | |
346 IToken token= fScanner.nextToken(); | |
347 | |
348 while (!token.isEOF()) { | |
349 | |
350 contentType= getTokenContentType(token); | |
351 | |
352 if (!isSupportedContentType(contentType)) { | |
353 token= fScanner.nextToken(); | |
354 continue; | |
355 } | |
356 | |
357 int start= fScanner.getTokenOffset(); | |
358 int length= fScanner.getTokenLength(); | |
359 | |
360 lastScannedPosition= start + length - 1; | |
361 | |
362 // remove all affected positions | |
363 while (first < category.length) { | |
134 | 364 TypedPosition p= cast(TypedPosition) category[first]; |
129 | 365 if (lastScannedPosition >= p.offset + p.length || |
366 (p.overlapsWith(start, length) && | |
367 (!d.containsPosition(fPositionCategory, start, length) || | |
368 !contentType.equals(p.getType())))) { | |
369 | |
370 rememberRegion(p.offset, p.length); | |
371 d.removePosition(fPositionCategory, p); | |
372 ++ first; | |
373 | |
374 } else | |
375 break; | |
376 } | |
377 | |
378 // if position already exists and we have scanned at least the | |
379 // area covered by the event, we are done | |
380 if (d.containsPosition(fPositionCategory, start, length)) { | |
381 if (lastScannedPosition >= e.getOffset() + newLength) | |
382 return createRegion(); | |
383 ++ first; | |
384 } else { | |
385 // insert the new type position | |
386 try { | |
387 d.addPosition(fPositionCategory, new TypedPosition(start, length, contentType)); | |
388 rememberRegion(start, length); | |
389 } catch (BadPositionCategoryException x) { | |
390 } catch (BadLocationException x) { | |
391 } | |
392 } | |
393 | |
394 token= fScanner.nextToken(); | |
395 } | |
396 | |
397 | |
398 // remove all positions behind lastScannedPosition since there aren't any further types | |
399 if (lastScannedPosition !is reparseStart) { | |
400 // if this condition is not met, nothing has been scanned because of a deletion | |
401 ++ lastScannedPosition; | |
402 } | |
403 first= d.computeIndexInCategory(fPositionCategory, lastScannedPosition); | |
404 category= d.getPositions(fPositionCategory); | |
405 | |
406 TypedPosition p; | |
407 while (first < category.length) { | |
134 | 408 p= cast(TypedPosition) category[first++]; |
129 | 409 d.removePosition(fPositionCategory, p); |
410 rememberRegion(p.offset, p.length); | |
411 } | |
412 | |
413 } catch (BadPositionCategoryException x) { | |
414 // should never happen on connected documents | |
415 } catch (BadLocationException x) { | |
416 } | |
417 | |
418 return createRegion(); | |
419 } | |
420 | |
421 | |
422 /** | |
423 * Returns the position in the partitoner's position category which is | |
424 * close to the given offset. This is, the position has either an offset which | |
425 * is the same as the given offset or an offset which is smaller than the given | |
426 * offset. This method profits from the knowledge that a partitioning is | |
427 * a ordered set of disjoint position. | |
428 * | |
429 * @param offset the offset for which to search the closest position | |
430 * @return the closest position in the partitioner's category | |
431 */ | |
432 protected TypedPosition findClosestPosition(int offset) { | |
433 | |
434 try { | |
435 | |
436 int index= fDocument.computeIndexInCategory(fPositionCategory, offset); | |
437 Position[] category= fDocument.getPositions(fPositionCategory); | |
438 | |
439 if (category.length is 0) | |
440 return null; | |
441 | |
442 if (index < category.length) { | |
443 if (offset is category[index].offset) | |
134 | 444 return cast(TypedPosition) category[index]; |
129 | 445 } |
446 | |
447 if (index > 0) | |
448 index--; | |
449 | |
134 | 450 return cast(TypedPosition) category[index]; |
129 | 451 |
452 } catch (BadPositionCategoryException x) { | |
453 } catch (BadLocationException x) { | |
454 } | |
455 | |
456 return null; | |
457 } | |
458 | |
459 | |
460 /* | |
461 * @see IDocumentPartitioner#getContentType(int) | |
462 */ | |
463 public String getContentType(int offset) { | |
464 checkInitialization(); | |
465 | |
466 TypedPosition p= findClosestPosition(offset); | |
467 if (p !is null && p.includes(offset)) | |
468 return p.getType(); | |
469 | |
470 return IDocument.DEFAULT_CONTENT_TYPE; | |
471 } | |
472 | |
473 /* | |
474 * @see IDocumentPartitioner#getPartition(int) | |
475 */ | |
476 public ITypedRegion getPartition(int offset) { | |
477 checkInitialization(); | |
478 | |
479 try { | |
480 | |
481 Position[] category = fDocument.getPositions(fPositionCategory); | |
482 | |
483 if (category is null || category.length is 0) | |
484 return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE); | |
485 | |
486 int index= fDocument.computeIndexInCategory(fPositionCategory, offset); | |
487 | |
488 if (index < category.length) { | |
489 | |
134 | 490 TypedPosition next= cast(TypedPosition) category[index]; |
129 | 491 |
492 if (offset is next.offset) | |
493 return new TypedRegion(next.getOffset(), next.getLength(), next.getType()); | |
494 | |
495 if (index is 0) | |
496 return new TypedRegion(0, next.offset, IDocument.DEFAULT_CONTENT_TYPE); | |
497 | |
134 | 498 TypedPosition previous= cast(TypedPosition) category[index - 1]; |
129 | 499 if (previous.includes(offset)) |
500 return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType()); | |
501 | |
502 int endOffset= previous.getOffset() + previous.getLength(); | |
503 return new TypedRegion(endOffset, next.getOffset() - endOffset, IDocument.DEFAULT_CONTENT_TYPE); | |
504 } | |
505 | |
134 | 506 TypedPosition previous= cast(TypedPosition) category[category.length - 1]; |
129 | 507 if (previous.includes(offset)) |
508 return new TypedRegion(previous.getOffset(), previous.getLength(), previous.getType()); | |
509 | |
510 int endOffset= previous.getOffset() + previous.getLength(); | |
511 return new TypedRegion(endOffset, fDocument.getLength() - endOffset, IDocument.DEFAULT_CONTENT_TYPE); | |
512 | |
513 } catch (BadPositionCategoryException x) { | |
514 } catch (BadLocationException x) { | |
515 } | |
516 | |
517 return new TypedRegion(0, fDocument.getLength(), IDocument.DEFAULT_CONTENT_TYPE); | |
518 } | |
519 | |
520 /* | |
521 * @see IDocumentPartitioner#computePartitioning(int, int) | |
522 */ | |
523 public ITypedRegion[] computePartitioning(int offset, int length) { | |
524 return computePartitioning(offset, length, false); | |
525 } | |
526 | |
527 /* | |
528 * @see IDocumentPartitioner#getLegalContentTypes() | |
529 */ | |
530 public String[] getLegalContentTypes() { | |
531 return TextUtilities.copy(fLegalContentTypes); | |
532 } | |
533 | |
534 /** | |
535 * Returns whether the given type is one of the legal content types. | |
536 * | |
537 * @param contentType the content type to check | |
538 * @return <code>true</code> if the content type is a legal content type | |
539 */ | |
540 protected bool isSupportedContentType(String contentType) { | |
541 if (contentType !is null) { | |
542 for (int i= 0; i < fLegalContentTypes.length; i++) { | |
543 if (fLegalContentTypes[i].equals(contentType)) | |
544 return true; | |
545 } | |
546 } | |
547 | |
548 return false; | |
549 } | |
550 | |
551 /** | |
552 * Returns a content type encoded in the given token. If the token's | |
553 * data is not <code>null</code> and a string it is assumed that | |
554 * it is the encoded content type. | |
555 * | |
556 * @param token the token whose content type is to be determined | |
557 * @return the token's content type | |
558 */ | |
559 protected String getTokenContentType(IToken token) { | |
560 Object data= token.getData(); | |
138 | 561 if ( cast(String)data ) |
134 | 562 return cast(String) data; |
129 | 563 return null; |
564 } | |
565 | |
566 /* zero-length partition support */ | |
567 | |
568 /* | |
569 * @see dwtx.jface.text.IDocumentPartitionerExtension2#getContentType(int) | |
570 * @since 3.0 | |
571 */ | |
572 public String getContentType(int offset, bool preferOpenPartitions) { | |
573 return getPartition(offset, preferOpenPartitions).getType(); | |
574 } | |
575 | |
576 /* | |
577 * @see dwtx.jface.text.IDocumentPartitionerExtension2#getPartition(int) | |
578 * @since 3.0 | |
579 */ | |
580 public ITypedRegion getPartition(int offset, bool preferOpenPartitions) { | |
581 ITypedRegion region= getPartition(offset); | |
582 if (preferOpenPartitions) { | |
583 if (region.getOffset() is offset && !region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE)) { | |
584 if (offset > 0) { | |
585 region= getPartition(offset - 1); | |
586 if (region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE)) | |
587 return region; | |
588 } | |
589 return new TypedRegion(offset, 0, IDocument.DEFAULT_CONTENT_TYPE); | |
590 } | |
591 } | |
592 return region; | |
593 } | |
594 | |
595 /* | |
596 * @see dwtx.jface.text.IDocumentPartitionerExtension2#computePartitioning(int, int, bool) | |
597 * @since 3.0 | |
598 */ | |
599 public ITypedRegion[] computePartitioning(int offset, int length, bool includeZeroLengthPartitions) { | |
600 checkInitialization(); | |
601 List list= new ArrayList(); | |
602 | |
603 try { | |
604 | |
605 int endOffset= offset + length; | |
606 | |
607 Position[] category= fDocument.getPositions(fPositionCategory); | |
608 | |
609 TypedPosition previous= null, current= null; | |
610 int start, end, gapOffset; | |
611 Position gap= new Position(0); | |
612 | |
613 int startIndex= getFirstIndexEndingAfterOffset(category, offset); | |
614 int endIndex= getFirstIndexStartingAfterOffset(category, endOffset); | |
615 for (int i= startIndex; i < endIndex; i++) { | |
616 | |
134 | 617 current= cast(TypedPosition) category[i]; |
129 | 618 |
619 gapOffset= (previous !is null) ? previous.getOffset() + previous.getLength() : 0; | |
620 gap.setOffset(gapOffset); | |
621 gap.setLength(current.getOffset() - gapOffset); | |
622 if ((includeZeroLengthPartitions && overlapsOrTouches(gap, offset, length)) || | |
623 (gap.getLength() > 0 && gap.overlapsWith(offset, length))) { | |
624 start= Math.max(offset, gapOffset); | |
625 end= Math.min(endOffset, gap.getOffset() + gap.getLength()); | |
626 list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE)); | |
627 } | |
628 | |
629 if (current.overlapsWith(offset, length)) { | |
630 start= Math.max(offset, current.getOffset()); | |
631 end= Math.min(endOffset, current.getOffset() + current.getLength()); | |
632 list.add(new TypedRegion(start, end - start, current.getType())); | |
633 } | |
634 | |
635 previous= current; | |
636 } | |
637 | |
638 if (previous !is null) { | |
639 gapOffset= previous.getOffset() + previous.getLength(); | |
640 gap.setOffset(gapOffset); | |
641 gap.setLength(fDocument.getLength() - gapOffset); | |
642 if ((includeZeroLengthPartitions && overlapsOrTouches(gap, offset, length)) || | |
643 (gap.getLength() > 0 && gap.overlapsWith(offset, length))) { | |
644 start= Math.max(offset, gapOffset); | |
645 end= Math.min(endOffset, fDocument.getLength()); | |
646 list.add(new TypedRegion(start, end - start, IDocument.DEFAULT_CONTENT_TYPE)); | |
647 } | |
648 } | |
649 | |
650 if (list.isEmpty()) | |
651 list.add(new TypedRegion(offset, length, IDocument.DEFAULT_CONTENT_TYPE)); | |
652 | |
653 } catch (BadPositionCategoryException x) { | |
654 } | |
655 | |
656 TypedRegion[] result= new TypedRegion[list.size()]; | |
657 list.toArray(result); | |
658 return result; | |
659 } | |
660 | |
661 /** | |
662 * Returns <code>true</code> if the given ranges overlap with or touch each other. | |
663 * | |
664 * @param gap the first range | |
665 * @param offset the offset of the second range | |
666 * @param length the length of the second range | |
667 * @return <code>true</code> if the given ranges overlap with or touch each other | |
668 * @since 3.0 | |
669 */ | |
670 private bool overlapsOrTouches(Position gap, int offset, int length) { | |
671 return gap.getOffset() <= offset + length && offset <= gap.getOffset() + gap.getLength(); | |
672 } | |
673 | |
674 /** | |
675 * Returns the index of the first position which ends after the given offset. | |
676 * | |
677 * @param positions the positions in linear order | |
678 * @param offset the offset | |
679 * @return the index of the first position which ends after the offset | |
680 * | |
681 * @since 3.0 | |
682 */ | |
683 private int getFirstIndexEndingAfterOffset(Position[] positions, int offset) { | |
684 int i= -1, j= positions.length; | |
685 while (j - i > 1) { | |
686 int k= (i + j) >> 1; | |
687 Position p= positions[k]; | |
688 if (p.getOffset() + p.getLength() > offset) | |
689 j= k; | |
690 else | |
691 i= k; | |
692 } | |
693 return j; | |
694 } | |
695 | |
696 /** | |
697 * Returns the index of the first position which starts at or after the given offset. | |
698 * | |
699 * @param positions the positions in linear order | |
700 * @param offset the offset | |
701 * @return the index of the first position which starts after the offset | |
702 * | |
703 * @since 3.0 | |
704 */ | |
705 private int getFirstIndexStartingAfterOffset(Position[] positions, int offset) { | |
706 int i= -1, j= positions.length; | |
707 while (j - i > 1) { | |
708 int k= (i + j) >> 1; | |
709 Position p= positions[k]; | |
710 if (p.getOffset() >= offset) | |
711 j= k; | |
712 else | |
713 i= k; | |
714 } | |
715 return j; | |
716 } | |
717 | |
718 /* | |
719 * @see dwtx.jface.text.IDocumentPartitionerExtension3#startRewriteSession(dwtx.jface.text.DocumentRewriteSession) | |
720 * @since 3.1 | |
721 */ | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
722 public void startRewriteSession(DocumentRewriteSession session) { |
129 | 723 if (fActiveRewriteSession !is null) |
724 throw new IllegalStateException(); | |
725 fActiveRewriteSession= session; | |
726 } | |
727 | |
728 /* | |
729 * @see dwtx.jface.text.IDocumentPartitionerExtension3#stopRewriteSession(dwtx.jface.text.DocumentRewriteSession) | |
730 * @since 3.1 | |
731 */ | |
732 public void stopRewriteSession(DocumentRewriteSession session) { | |
733 if (fActiveRewriteSession is session) | |
734 flushRewriteSession(); | |
735 } | |
736 | |
737 /* | |
738 * @see dwtx.jface.text.IDocumentPartitionerExtension3#getActiveRewriteSession() | |
739 * @since 3.1 | |
740 */ | |
741 public DocumentRewriteSession getActiveRewriteSession() { | |
742 return fActiveRewriteSession; | |
743 } | |
744 | |
745 /** | |
746 * Flushes the active rewrite session. | |
747 * | |
748 * @since 3.1 | |
749 */ | |
750 protected final void flushRewriteSession() { | |
751 fActiveRewriteSession= null; | |
752 | |
753 // remove all position belonging to the partitioner position category | |
754 try { | |
755 fDocument.removePositionCategory(fPositionCategory); | |
756 } catch (BadPositionCategoryException x) { | |
757 } | |
758 fDocument.addPositionCategory(fPositionCategory); | |
759 | |
760 fIsInitialized= false; | |
761 } | |
762 } |