~ubuntu-branches/ubuntu/vivid/drmips/vivid-backports

« back to all changes in this revision

Viewing changes to src/pc/DrMIPS/src/org/fife/ui/rsyntaxtextarea/RSyntaxDocument.java

  • Committer: Package Import Robot
  • Author(s): Bruno Nova
  • Date: 2014-09-27 12:24:17 UTC
  • Revision ID: package-import@ubuntu.com-20140927122417-2gadkwt9k0u7j4zu
Tags: upstream-1.2.3
Import upstream version 1.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * 10/16/2004
 
3
 *
 
4
 * RSyntaxDocument.java - A document capable of syntax highlighting, used by
 
5
 * RSyntaxTextArea.
 
6
 * 
 
7
 * This library is distributed under a modified BSD license.  See the included
 
8
 * RSyntaxTextArea.License.txt file for details.
 
9
 */
 
10
package org.fife.ui.rsyntaxtextarea;
 
11
 
 
12
import java.awt.event.ActionEvent;
 
13
import java.io.IOException;
 
14
import java.io.ObjectInputStream;
 
15
import javax.swing.Action;
 
16
import javax.swing.event.*;
 
17
import javax.swing.text.*;
 
18
 
 
19
import org.fife.ui.rsyntaxtextarea.modes.AbstractMarkupTokenMaker;
 
20
import org.fife.ui.rtextarea.RDocument;
 
21
import org.fife.util.DynamicIntArray;
 
22
 
 
23
 
 
24
/**
 
25
 * The document used by {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextArea}.
 
26
 * This document is like <code>javax.swing.text.PlainDocument</code> except that
 
27
 * it also keeps track of syntax highlighting in the document.  It has a "style"
 
28
 * attribute associated with it that determines how syntax highlighting is done
 
29
 * (i.e., what language is being highlighted).<p>
 
30
 *
 
31
 * Instances of <code>RSyntaxTextArea</code> will only accept instances of
 
32
 * <code>RSyntaxDocument</code>, since it is this document that keeps
 
33
 * track of syntax highlighting.  All others will cause an exception to be
 
34
 * thrown.<p>
 
35
 *
 
36
 * To change the language being syntax highlighted at any time, you merely have
 
37
 * to call {@link #setSyntaxStyle}.  Other than that, this document can be
 
38
 * treated like any other save one caveat:  all <code>DocumentEvent</code>s of
 
39
 * type <code>CHANGE</code> use their offset and length values to represent the
 
40
 * first and last lines, respectively, that have had their syntax coloring
 
41
 * change.  This is really a hack to increase the speed of the painting code
 
42
 * and should really be corrected, but oh well. 
 
43
 *
 
44
 * @author Robert Futrell
 
45
 * @version 1.0
 
46
 */
 
47
public class RSyntaxDocument extends RDocument implements SyntaxConstants {
 
48
 
 
49
        /**
 
50
         * Creates a {@link TokenMaker} appropriate for a given programming
 
51
         * language.
 
52
         */
 
53
        private transient TokenMakerFactory tokenMakerFactory;
 
54
 
 
55
        /**
 
56
         * Splits text into tokens for the current programming language.
 
57
         */
 
58
        private transient TokenMaker tokenMaker;
 
59
 
 
60
        /**
 
61
         * The current syntax style.  Only cached to keep this class serializable.
 
62
         */
 
63
        private String syntaxStyle;
 
64
 
 
65
        /**
 
66
         * Array of values representing the "last token type" on each line.  This
 
67
         * is used in cases such as multi-line comments:  if the previous line
 
68
         * ended with an (unclosed) multi-line comment, we can use this knowledge
 
69
         * and start the current line's syntax highlighting in multi-line comment
 
70
         * state.
 
71
         */
 
72
        protected transient DynamicIntArray lastTokensOnLines;
 
73
 
 
74
        private transient int lastLine = -1;
 
75
        private transient Token cachedTokenList;
 
76
        private transient int useCacheCount = 0;
 
77
        private transient int tokenRetrievalCount = 0;
 
78
 
 
79
        private transient Segment s;
 
80
 
 
81
        /**
 
82
         * If this is set to <code>true</code>, debug information about how much
 
83
         * token caching is helping is printed to stdout.
 
84
         */
 
85
        private static final boolean DEBUG_TOKEN_CACHING = false;
 
86
 
 
87
 
 
88
        /**
 
89
         * Constructs a plain text document.  A default root element is created,
 
90
         * and the tab size set to 5.
 
91
         *
 
92
         * @param syntaxStyle The syntax highlighting scheme to use.
 
93
         */
 
94
        public RSyntaxDocument(String syntaxStyle) {
 
95
                this(null, syntaxStyle);
 
96
        }
 
97
 
 
98
 
 
99
        /**
 
100
         * Constructs a plain text document.  A default root element is created,
 
101
         * and the tab size set to 5.
 
102
         *
 
103
         * @param tmf The <code>TokenMakerFactory</code> for this document.  If
 
104
         *        this is <code>null</code>, a default factory is used.
 
105
         * @param syntaxStyle The syntax highlighting scheme to use.
 
106
         */
 
107
        public RSyntaxDocument(TokenMakerFactory tmf, String syntaxStyle) {
 
108
                putProperty(tabSizeAttribute, Integer.valueOf(5));
 
109
                lastTokensOnLines = new DynamicIntArray(400);
 
110
                lastTokensOnLines.add(Token.NULL); // Initial (empty) line.
 
111
                s = new Segment();
 
112
                setTokenMakerFactory(tmf);
 
113
                setSyntaxStyle(syntaxStyle);
 
114
        }
 
115
 
 
116
 
 
117
        /**
 
118
         * Alerts all listeners to this document of an insertion.  This is
 
119
         * overridden so we can update our syntax highlighting stuff.<p>
 
120
         * The syntax highlighting stuff has to be here instead of in
 
121
         * <code>insertUpdate</code> because <code>insertUpdate</code> is not
 
122
         * called by the undo/redo actions, but this method is.
 
123
         *
 
124
         * @param e The change.
 
125
         */
 
126
        @Override
 
127
        protected void fireInsertUpdate(DocumentEvent e) {
 
128
 
 
129
                cachedTokenList = null;
 
130
 
 
131
                /*
 
132
                 * Now that the text is actually inserted into the content and
 
133
                 * element structure, we can update our token elements and "last
 
134
                 * tokens on lines" structure.
 
135
                 */
 
136
 
 
137
                Element lineMap = getDefaultRootElement();
 
138
                DocumentEvent.ElementChange change = e.getChange(lineMap);
 
139
                Element[] added = change==null ? null : change.getChildrenAdded();
 
140
 
 
141
                int numLines = lineMap.getElementCount();
 
142
                int line = lineMap.getElementIndex(e.getOffset());
 
143
                int previousLine = line - 1;
 
144
                int previousTokenType = (previousLine>-1 ?
 
145
                                        lastTokensOnLines.get(previousLine) : Token.NULL);
 
146
 
 
147
                // If entire lines were added...
 
148
                if (added!=null && added.length>0) {
 
149
 
 
150
                        Element[] removed = change.getChildrenRemoved();
 
151
                        int numRemoved = removed!=null ? removed.length : 0;
 
152
 
 
153
                        int endBefore = line + added.length - numRemoved;
 
154
                        //System.err.println("... adding lines: " + line + " - " + (endBefore-1));
 
155
                        //System.err.println("... ... added: " + added.length + ", removed:" + numRemoved);
 
156
                        for (int i=line; i<endBefore; i++) {
 
157
 
 
158
                                setSharedSegment(i); // Loads line i's text into s.
 
159
 
 
160
                                int tokenType = tokenMaker.getLastTokenTypeOnLine(s, previousTokenType);
 
161
                                lastTokensOnLines.add(i, tokenType);
 
162
                                //System.err.println("--------- lastTokensOnLines.size() == " + lastTokensOnLines.getSize());
 
163
 
 
164
                                previousTokenType = tokenType;
 
165
 
 
166
                        } // End of for (int i=line; i<endBefore; i++).
 
167
 
 
168
                        // Update last tokens for lines below until they stop changing.
 
169
                        updateLastTokensBelow(endBefore, numLines, previousTokenType);
 
170
 
 
171
                } // End of if (added!=null && added.length>0).
 
172
 
 
173
                // Otherwise, text was inserted on a single line...
 
174
                else {
 
175
 
 
176
                        // Update last tokens for lines below until they stop changing.
 
177
                        updateLastTokensBelow(line, numLines, previousTokenType);
 
178
 
 
179
                } // End of else.
 
180
 
 
181
                // Let all listeners know about the insertion.
 
182
                super.fireInsertUpdate(e);
 
183
 
 
184
        }
 
185
 
 
186
 
 
187
        /**
 
188
         * This method is called AFTER the content has been inserted into the
 
189
         * document and the element structure has been updated.<p>
 
190
         * The syntax-highlighting updates need to be done here (as opposed to
 
191
         * an override of <code>postRemoveUpdate</code>) as this method is called
 
192
         * in response to undo/redo events, whereas <code>postRemoveUpdate</code>
 
193
         * is not.<p>
 
194
         * Now that the text is actually inserted into the content and element
 
195
         * structure, we can update our token elements and "last tokens on
 
196
         * lines" structure.
 
197
         *
 
198
         * @param chng The change that occurred.
 
199
         * @see #removeUpdate
 
200
         */
 
201
        @Override
 
202
        protected void fireRemoveUpdate(DocumentEvent chng) {
 
203
 
 
204
                cachedTokenList =  null;
 
205
                Element lineMap = getDefaultRootElement();
 
206
                int numLines = lineMap.getElementCount();
 
207
 
 
208
                DocumentEvent.ElementChange change = chng.getChange(lineMap);
 
209
                Element[] removed = change==null ? null : change.getChildrenRemoved();
 
210
 
 
211
                // If entire lines were removed...
 
212
                if (removed!=null && removed.length>0) {
 
213
 
 
214
                        int line = change.getIndex();   // First line entirely removed.
 
215
                        int previousLine = line - 1;    // Line before that.
 
216
                        int previousTokenType = (previousLine>-1 ?
 
217
                                        lastTokensOnLines.get(previousLine) : Token.NULL);
 
218
 
 
219
                        Element[] added = change.getChildrenAdded();
 
220
                        int numAdded = added==null ? 0 : added.length;
 
221
 
 
222
                        // Remove the cached last-token values for the removed lines.
 
223
                        int endBefore = line + removed.length - numAdded;
 
224
                        //System.err.println("... removing lines: " + line + " - " + (endBefore-1));
 
225
                        //System.err.println("... added: " + numAdded + ", removed: " + removed.length);
 
226
 
 
227
                        lastTokensOnLines.removeRange(line, endBefore); // Removing values for lines [line-(endBefore-1)].
 
228
                        //System.err.println("--------- lastTokensOnLines.size() == " + lastTokensOnLines.getSize());
 
229
 
 
230
                        // Update last tokens for lines below until they've stopped changing.
 
231
                        updateLastTokensBelow(line, numLines, previousTokenType);
 
232
 
 
233
                } // End of if (removed!=null && removed.size()>0).
 
234
 
 
235
                // Otherwise, text was removed from just one line...
 
236
                else {
 
237
 
 
238
                        int line = lineMap.getElementIndex(chng.getOffset());
 
239
                        if (line>=lastTokensOnLines.getSize())
 
240
                                return; // If we're editing the last line in a document...
 
241
 
 
242
                        int previousLine = line - 1;
 
243
                        int previousTokenType = (previousLine>-1 ?
 
244
                                        lastTokensOnLines.get(previousLine) : Token.NULL);
 
245
                        //System.err.println("previousTokenType for line : " + previousLine + " is " + previousTokenType);
 
246
                        // Update last tokens for lines below until they've stopped changing.
 
247
                        updateLastTokensBelow(line, numLines, previousTokenType);
 
248
 
 
249
                }
 
250
 
 
251
                // Let all of our listeners know about the removal.
 
252
                super.fireRemoveUpdate(chng);
 
253
 
 
254
        }
 
255
 
 
256
 
 
257
        /**
 
258
         * Returns the closest {@link TokenTypes "standard" token type} for a given
 
259
         * "internal" token type (e.g. one whose value is <code>&lt; 0</code>).
 
260
         *
 
261
         * @param type The token type.
 
262
         * @return The closest "standard" token type.  If a mapping is not defined
 
263
         *         for this language, then <code>type</code> is returned.
 
264
         */
 
265
        public int getClosestStandardTokenTypeForInternalType(int type) {
 
266
                return tokenMaker.getClosestStandardTokenTypeForInternalType(type);
 
267
        }
 
268
 
 
269
 
 
270
        /**
 
271
         * Returns whether closing markup tags should be automatically completed.
 
272
         * This method only returns <code>true</code> if
 
273
         * {@link #getLanguageIsMarkup()} also returns <code>true</code>.
 
274
         *
 
275
         * @return Whether markup closing tags should be automatically completed.
 
276
         * @see #getLanguageIsMarkup()
 
277
         */
 
278
        public boolean getCompleteMarkupCloseTags() {
 
279
                // TODO: Remove terrible dependency on AbstractMarkupTokenMaker
 
280
                return getLanguageIsMarkup() &&
 
281
                                ((AbstractMarkupTokenMaker)tokenMaker).getCompleteCloseTags();
 
282
        }
 
283
 
 
284
 
 
285
        /**
 
286
         * Returns whether the current programming language uses curly braces
 
287
         * ('<tt>{</tt>' and '<tt>}</tt>') to denote code blocks.
 
288
         *
 
289
         * @return Whether curly braces denote code blocks.
 
290
         */
 
291
        public boolean getCurlyBracesDenoteCodeBlocks() {
 
292
                return tokenMaker.getCurlyBracesDenoteCodeBlocks();
 
293
        }
 
294
 
 
295
 
 
296
        /**
 
297
         * Returns whether the current language is a markup language, such as
 
298
         * HTML, XML or PHP.
 
299
         *
 
300
         * @return Whether the current language is a markup language.
 
301
         */
 
302
        public boolean getLanguageIsMarkup() {
 
303
                return tokenMaker.isMarkupLanguage();
 
304
        }
 
305
 
 
306
 
 
307
        /**
 
308
         * Returns the token type of the last token on the given line.
 
309
         *
 
310
         * @param line The line to inspect.
 
311
         * @return The token type of the last token on the specified line.  If
 
312
         *         the line is invalid, an exception is thrown.
 
313
         */
 
314
        public int getLastTokenTypeOnLine(int line) {
 
315
                return lastTokensOnLines.get(line);
 
316
        }
 
317
 
 
318
 
 
319
        /**
 
320
         * Returns the text to place at the beginning and end of a
 
321
         * line to "comment" it in the current programming language.
 
322
         *
 
323
         * @return The start and end strings to add to a line to "comment"
 
324
         *         it out.  A <code>null</code> value for either means there
 
325
         *         is no string to add for that part.  A value of
 
326
         *         <code>null</code> for the array means this language
 
327
         *         does not support commenting/uncommenting lines.
 
328
         */
 
329
        public String[] getLineCommentStartAndEnd() {
 
330
                return tokenMaker.getLineCommentStartAndEnd();
 
331
        }
 
332
 
 
333
 
 
334
        /**
 
335
         * Returns whether tokens of the specified type should have "mark
 
336
         * occurrences" enabled for the current programming language.
 
337
         *
 
338
         * @param type The token type.
 
339
         * @return Whether tokens of this type should have "mark occurrences"
 
340
         *         enabled.
 
341
         */
 
342
        boolean getMarkOccurrencesOfTokenType(int type) {
 
343
                return tokenMaker.getMarkOccurrencesOfTokenType(type);
 
344
        }
 
345
 
 
346
 
 
347
        /**
 
348
         * Returns the occurrence marker for the current language.
 
349
         *
 
350
         * @return The occurrence marker.
 
351
         */
 
352
        OccurrenceMarker getOccurrenceMarker() {
 
353
                return tokenMaker.getOccurrenceMarker();
 
354
        }
 
355
 
 
356
 
 
357
        /**
 
358
         * This method returns whether auto indentation should be done if Enter
 
359
         * is pressed at the end of the specified line.
 
360
         *
 
361
         * @param line The line to check.
 
362
         * @return Whether an extra indentation should be done.
 
363
         */
 
364
        public boolean getShouldIndentNextLine(int line) {
 
365
                Token t = getTokenListForLine(line);
 
366
                t = t.getLastNonCommentNonWhitespaceToken();
 
367
                return tokenMaker.getShouldIndentNextLineAfter(t);
 
368
        }
 
369
 
 
370
 
 
371
        /**
 
372
         * Returns a token list for the specified segment of text representing
 
373
         * the specified line number.  This method is basically a wrapper for
 
374
         * <code>tokenMaker.getTokenList</code> that takes into account the last
 
375
         * token on the previous line to assure token accuracy.
 
376
         *
 
377
         * @param line The line number of <code>text</code> in the document, >= 0.
 
378
         * @return A token list representing the specified line.
 
379
         */
 
380
        public final Token getTokenListForLine(int line) {
 
381
 
 
382
                tokenRetrievalCount++;
 
383
                if (line==lastLine && cachedTokenList!=null) {
 
384
                        if (DEBUG_TOKEN_CACHING) {
 
385
                                useCacheCount++;
 
386
                                System.err.println("--- Using cached line; ratio now: " +
 
387
                                                useCacheCount + "/" + tokenRetrievalCount);
 
388
                        }
 
389
                        return cachedTokenList;
 
390
                }
 
391
                lastLine = line;
 
392
                
 
393
                Element map = getDefaultRootElement();
 
394
                Element elem = map.getElement(line);
 
395
                int startOffset = elem.getStartOffset();
 
396
                //int endOffset = (line==map.getElementCount()-1 ? elem.getEndOffset() - 1:
 
397
                //                                                                      elem.getEndOffset() - 1);
 
398
                int endOffset = elem.getEndOffset() - 1; // Why always "-1"?
 
399
                try {
 
400
                        getText(startOffset,endOffset-startOffset, s);
 
401
                } catch (BadLocationException ble) {
 
402
                        ble.printStackTrace();
 
403
                        return null;
 
404
                }
 
405
                int initialTokenType = line==0 ? Token.NULL :
 
406
                                                                getLastTokenTypeOnLine(line-1);
 
407
 
 
408
                //return tokenMaker.getTokenList(s, initialTokenType, startOffset);
 
409
                cachedTokenList = tokenMaker.getTokenList(s, initialTokenType, startOffset);
 
410
                return cachedTokenList;
 
411
 
 
412
        }
 
413
 
 
414
 
 
415
        boolean insertBreakSpecialHandling(ActionEvent e) {
 
416
                Action a = tokenMaker.getInsertBreakAction();
 
417
                if (a!=null) {
 
418
                        a.actionPerformed(e);
 
419
                        return true;
 
420
                }
 
421
                return false;
 
422
        }
 
423
 
 
424
 
 
425
        /**
 
426
         * Deserializes a document.
 
427
         *
 
428
         * @param in The stream to read from.
 
429
         * @throws ClassNotFoundException
 
430
         * @throws IOException
 
431
         */
 
432
        private void readObject(ObjectInputStream in)
 
433
                                                throws ClassNotFoundException, IOException {
 
434
 
 
435
                in.defaultReadObject();
 
436
 
 
437
                // Install default TokenMakerFactory.  To support custom TokenMakers,
 
438
                // both JVM's should install default TokenMakerFactories that support
 
439
                // the language they want to use beforehand.
 
440
                setTokenMakerFactory(null);
 
441
 
 
442
                // Handle other transient stuff
 
443
                this.s = new Segment();
 
444
                int lineCount = getDefaultRootElement().getElementCount();
 
445
                lastTokensOnLines = new DynamicIntArray(lineCount);
 
446
                setSyntaxStyle(syntaxStyle); // Actually install (transient) TokenMaker
 
447
 
 
448
        }
 
449
 
 
450
 
 
451
        /**
 
452
         * Makes our private <code>Segment s</code> point to the text in our
 
453
         * document referenced by the specified element.  Note that
 
454
         * <code>line</code> MUST be a valid line number in the document.
 
455
         *
 
456
         * @param line The line number you want to get.
 
457
         */
 
458
        private final void setSharedSegment(int line) {
 
459
 
 
460
                Element map = getDefaultRootElement();
 
461
                //int numLines = map.getElementCount();
 
462
 
 
463
                Element element = map.getElement(line);
 
464
                if (element==null)
 
465
                        throw new InternalError("Invalid line number: " + line);
 
466
                int startOffset = element.getStartOffset();
 
467
                //int endOffset = (line==numLines-1 ?
 
468
                //                      element.getEndOffset()-1 : element.getEndOffset() - 1);
 
469
                int endOffset = element.getEndOffset()-1; // Why always "-1"?
 
470
                try {
 
471
                        getText(startOffset, endOffset-startOffset, s);
 
472
                } catch (BadLocationException ble) {
 
473
                        throw new InternalError("Text range not in document: " +
 
474
                                                                startOffset + "-" + endOffset);
 
475
                }
 
476
 
 
477
        }
 
478
 
 
479
 
 
480
        /**
 
481
         * Sets the syntax style being used for syntax highlighting in this
 
482
         * document.  What styles are supported by a document is determined by its
 
483
         * {@link TokenMakerFactory}.  By default, all <code>RSyntaxDocument</code>s
 
484
         * support all languages built into <code>RSyntaxTextArea</code>. 
 
485
         *
 
486
         * @param styleKey The new style to use, such as
 
487
         *        {@link SyntaxConstants#SYNTAX_STYLE_JAVA}.  If this style is not
 
488
         *        known or supported by this document, then
 
489
         *        {@link SyntaxConstants#SYNTAX_STYLE_NONE} is used.
 
490
         * @see #setSyntaxStyle(TokenMaker)
 
491
         */
 
492
        public void setSyntaxStyle(String styleKey) {
 
493
                tokenMaker = tokenMakerFactory.getTokenMaker(styleKey);
 
494
                updateSyntaxHighlightingInformation();
 
495
                this.syntaxStyle = styleKey;
 
496
        }
 
497
 
 
498
 
 
499
        /**
 
500
         * Sets the syntax style being used for syntax highlighting in this
 
501
         * document.  You should call this method if you've created a custom token
 
502
         * maker for a language not normally supported by
 
503
         * <code>RSyntaxTextArea</code>.
 
504
         *
 
505
         * @param tokenMaker The new token maker to use.
 
506
         * @see #setSyntaxStyle(String)
 
507
         */
 
508
        public void setSyntaxStyle(TokenMaker tokenMaker) {
 
509
                this.tokenMaker = tokenMaker;
 
510
                updateSyntaxHighlightingInformation();
 
511
        }
 
512
 
 
513
 
 
514
        /**
 
515
         * Sets the token maker factory used by this document.
 
516
         *
 
517
         * @param tmf The <code>TokenMakerFactory</code> for this document.  If
 
518
         *        this is <code>null</code>, a default factory is used.
 
519
         */
 
520
        public void setTokenMakerFactory(TokenMakerFactory tmf) {
 
521
                tokenMakerFactory = tmf!=null ? tmf :
 
522
                        TokenMakerFactory.getDefaultInstance();
 
523
        }
 
524
 
 
525
 
 
526
        /**
 
527
         * Loops through the last-tokens-on-lines array from a specified point
 
528
         * onward, updating last-token values until they stop changing.  This
 
529
         * should be called when lines are updated/inserted/removed, as doing
 
530
         * so may cause lines below to change color.
 
531
         *
 
532
         * @param line The first line to check for a change in last-token value.
 
533
         * @param numLines The number of lines in the document.
 
534
         * @param previousTokenType The last-token value of the line just before
 
535
         *        <code>line</code>.
 
536
         * @return The last line that needs repainting.
 
537
         */
 
538
        private int updateLastTokensBelow(int line, int numLines, int previousTokenType) {
 
539
 
 
540
                int firstLine = line;
 
541
 
 
542
                // Loop through all lines past our starting point.  Update even the last
 
543
                // line's info, even though there aren't any lines after it that depend
 
544
                // on it changing for them to be changed, as its state may be used
 
545
                // elsewhere in the library.
 
546
                int end = numLines;
 
547
                //System.err.println("--- end==" + end + " (numLines==" + numLines + ")");
 
548
                while (line<end) {
 
549
 
 
550
                        setSharedSegment(line); // Sets s's text to that of line 'line' in the document.
 
551
 
 
552
                        int oldTokenType = lastTokensOnLines.get(line);
 
553
                        int newTokenType = tokenMaker.getLastTokenTypeOnLine(s, previousTokenType);
 
554
                        //System.err.println("---------------- line " + line + "; oldTokenType==" + oldTokenType + ", newTokenType==" + newTokenType + ", s=='" + s + "'");
 
555
 
 
556
                        // If this line's end-token value didn't change, stop here.  Note
 
557
                        // that we're saying this line needs repainting; this is because
 
558
                        // the beginning of this line did indeed change color, but the
 
559
                        // end didn't.
 
560
                        if (oldTokenType==newTokenType) {
 
561
                                //System.err.println("... ... ... repainting lines " + firstLine + "-" + line);
 
562
                                fireChangedUpdate(new DefaultDocumentEvent(firstLine, line, DocumentEvent.EventType.CHANGE));
 
563
                                return line;
 
564
                        }
 
565
 
 
566
                        // If the line's end-token value did change, update it and
 
567
                        // keep going.
 
568
                        // NOTE: "setUnsafe" is okay here as the bounds checking was
 
569
                        // already done in lastTokensOnLines.get(line) above.
 
570
                        lastTokensOnLines.setUnsafe(line, newTokenType);
 
571
                        previousTokenType = newTokenType;
 
572
                        line++;
 
573
 
 
574
                } // End of while (line<numLines).
 
575
 
 
576
                // If any lines had their token types changed, fire a changed update
 
577
                // for them.  The view will repaint the area covered by the lines.
 
578
                // FIXME:  We currently cheat and send the line range that needs to be
 
579
                // repainted as the "offset and length" of the change, since this is
 
580
                // what the view needs.  We really should send the actual offset and
 
581
                // length.
 
582
                if (line>firstLine) {
 
583
                        //System.err.println("... ... ... repainting lines " + firstLine + "-" + line);
 
584
                        fireChangedUpdate(new DefaultDocumentEvent(firstLine, line,
 
585
                                                                DocumentEvent.EventType.CHANGE));
 
586
                }
 
587
 
 
588
                return line;
 
589
 
 
590
        }
 
591
 
 
592
 
 
593
        /**
 
594
         * Updates internal state information; e.g. the "last tokens on lines"
 
595
         * data.  After this, a changed update is fired to let listeners know that
 
596
         * the document's structure has changed.<p>
 
597
         *
 
598
         * This is called internally whenever the syntax style changes.
 
599
         */
 
600
        protected void updateSyntaxHighlightingInformation() {
 
601
 
 
602
                // Reinitialize the "last token on each line" array.  Note that since
 
603
                // the actual text in the document isn't changing, the number of lines
 
604
                // is the same.
 
605
                Element map = getDefaultRootElement();
 
606
                int numLines = map.getElementCount();
 
607
                int lastTokenType = Token.NULL;
 
608
                for (int i=0; i<numLines; i++) {
 
609
                        setSharedSegment(i);
 
610
                        lastTokenType = tokenMaker.getLastTokenTypeOnLine(s, lastTokenType);
 
611
                        lastTokensOnLines.set(i, lastTokenType);
 
612
                }
 
613
 
 
614
                // Let everybody know that syntax styles have (probably) changed.
 
615
                fireChangedUpdate(new DefaultDocumentEvent(
 
616
                                                0, numLines-1, DocumentEvent.EventType.CHANGE));
 
617
 
 
618
        }
 
619
 
 
620
 
 
621
}
 
 
b'\\ No newline at end of file'