Source Code Cross Referenced for ChunkCache.java in  » Swing-Library » jEdit » org » gjt » sp » jedit » textarea » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jEdit » org.gjt.sp.jedit.textarea 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ChunkCache.java - Intermediate layer between token lists from a TokenMarker
003:         * and what you see on screen
004:         * :tabSize=8:indentSize=8:noTabs=false:
005:         * :folding=explicit:collapseFolds=1:
006:         *
007:         * Copyright (C) 2001, 2005 Slava Pestov
008:         *
009:         * This program is free software; you can redistribute it and/or
010:         * modify it under the terms of the GNU General Public License
011:         * as published by the Free Software Foundation; either version 2
012:         * of the License, or any later version.
013:         *
014:         * This program is distributed in the hope that it will be useful,
015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017:         * GNU General Public License for more details.
018:         *
019:         * You should have received a copy of the GNU General Public License
020:         * along with this program; if not, write to the Free Software
021:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
022:         */
023:
024:        package org.gjt.sp.jedit.textarea;
025:
026:        //{{{ Imports
027:        import java.util.*;
028:        import org.gjt.sp.jedit.buffer.JEditBuffer;
029:        import org.gjt.sp.jedit.Debug;
030:        import org.gjt.sp.jedit.syntax.*;
031:        import org.gjt.sp.util.Log;
032:
033:        //}}}
034:
035:        /**
036:         * Manages low-level text display tasks - the visible lines in the TextArea.
037:         * 
038:         * 
039:         *
040:         * @author Slava Pestov
041:         * @version $Id: ChunkCache.java 8271 2006-12-28 08:05:51Z kpouer $
042:         */
043:        class ChunkCache {
044:            //{{{ ChunkCache constructor
045:            ChunkCache(TextArea textArea) {
046:                this .textArea = textArea;
047:                out = new ArrayList<Chunk>();
048:                tokenHandler = new DisplayTokenHandler();
049:            } //}}}
050:
051:            //{{{ getMaxHorizontalScrollWidth() method
052:            /**
053:             * Returns the max line width of the textarea.
054:             * It will check all lines the first invalid line.
055:             *
056:             * @return the max line width
057:             */
058:            int getMaxHorizontalScrollWidth() {
059:                int max = 0;
060:                for (int i = 0; i < firstInvalidLine; i++) {
061:                    LineInfo info = lineInfo[i];
062:                    if (info.width > max)
063:                        max = info.width;
064:                }
065:                return max;
066:            } //}}}
067:
068:            //{{{ getScreenLineOfOffset() method
069:            /**
070:             * @param line physical line number of document 
071:             * @param offset number of characters from the left of the line. 
072:             * @return number of pixels from the left of the textArea where the
073:             * cursor should be
074:             */
075:            int getScreenLineOfOffset(int line, int offset) {
076:                if (lineInfo.length == 0)
077:                    return -1;
078:                if (line < textArea.getFirstPhysicalLine())
079:                    return -1;
080:                if (line == textArea.getFirstPhysicalLine()
081:                        && offset < getLineInfo(0).offset)
082:                    return -1;
083:                if (line > textArea.getLastPhysicalLine())
084:                    return -1;
085:
086:                if (line == lastScreenLineP) {
087:                    LineInfo last = getLineInfo(lastScreenLine);
088:
089:                    if (offset >= last.offset
090:                            && offset < last.offset + last.length) {
091:                        return lastScreenLine;
092:                    }
093:                }
094:
095:                int screenLine = -1;
096:
097:                // Find the screen line containing this offset
098:                for (int i = 0; i < textArea.getVisibleLines(); i++) {
099:                    LineInfo info = getLineInfo(i);
100:                    if (info.physicalLine > line) {
101:                        // line is invisible?
102:                        return i - 1;
103:                        //return -1;
104:                    }
105:                    if (info.physicalLine == line) {
106:                        if (offset >= info.offset
107:                                && offset < info.offset + info.length) {
108:                            screenLine = i;
109:                            break;
110:                        }
111:                    }
112:                }
113:
114:                if (screenLine == -1)
115:                    return -1;
116:
117:                lastScreenLineP = line;
118:                lastScreenLine = screenLine;
119:
120:                return screenLine;
121:            } //}}}
122:
123:            //{{{ recalculateVisibleLines() method
124:            /**
125:             * Recalculate visible lines.
126:             * This is called when the TextArea geometry is changed or when the font is changed.
127:             */
128:            void recalculateVisibleLines() {
129:                LineInfo[] newLineInfo = new LineInfo[textArea
130:                        .getVisibleLines()];
131:
132:                int start;
133:                if (lineInfo == null)
134:                    start = 0;
135:                else {
136:                    start = Math.min(lineInfo.length, newLineInfo.length);
137:                    System.arraycopy(lineInfo, 0, newLineInfo, 0, start);
138:                }
139:
140:                for (int i = start; i < newLineInfo.length; i++)
141:                    newLineInfo[i] = new LineInfo();
142:
143:                lineInfo = newLineInfo;
144:
145:                lastScreenLine = lastScreenLineP = -1;
146:            } //}}}
147:
148:            //{{{ setBuffer() method
149:            void setBuffer(JEditBuffer buffer) {
150:                this .buffer = buffer;
151:                lastScreenLine = lastScreenLineP = -1;
152:            } //}}}
153:
154:            //{{{ scrollDown() method
155:            void scrollDown(int amount) {
156:                int visibleLines = textArea.getVisibleLines();
157:
158:                System.arraycopy(lineInfo, amount, lineInfo, 0, visibleLines
159:                        - amount);
160:
161:                for (int i = visibleLines - amount; i < visibleLines; i++) {
162:                    lineInfo[i] = new LineInfo();
163:                }
164:
165:                firstInvalidLine -= amount;
166:                if (firstInvalidLine < 0)
167:                    firstInvalidLine = 0;
168:
169:                if (Debug.CHUNK_CACHE_DEBUG) {
170:                    System.err.println("f > t.f: only " + amount
171:                            + " need updates");
172:                }
173:
174:                lastScreenLine = lastScreenLineP = -1;
175:            } //}}}
176:
177:            //{{{ scrollUp() method
178:            void scrollUp(int amount) {
179:                System.arraycopy(lineInfo, 0, lineInfo, amount, textArea
180:                        .getVisibleLines()
181:                        - amount);
182:
183:                for (int i = 0; i < amount; i++) {
184:                    lineInfo[i] = new LineInfo();
185:                }
186:
187:                // don't try this at home
188:                int oldFirstInvalidLine = firstInvalidLine;
189:                firstInvalidLine = 0;
190:                updateChunksUpTo(amount);
191:                firstInvalidLine = oldFirstInvalidLine + amount;
192:                if (firstInvalidLine > textArea.getVisibleLines())
193:                    firstInvalidLine = textArea.getVisibleLines();
194:
195:                if (Debug.CHUNK_CACHE_DEBUG) {
196:                    Log.log(Log.DEBUG, this , "f > t.f: only " + amount
197:                            + " need updates");
198:                }
199:
200:                lastScreenLine = lastScreenLineP = -1;
201:            } //}}}
202:
203:            //{{{ invalidateAll() method
204:            void invalidateAll() {
205:                firstInvalidLine = 0;
206:                lastScreenLine = lastScreenLineP = -1;
207:            } //}}}
208:
209:            //{{{ invalidateChunksFrom() method
210:            void invalidateChunksFrom(int screenLine) {
211:                if (Debug.CHUNK_CACHE_DEBUG)
212:                    Log.log(Log.DEBUG, this , "Invalidate from " + screenLine);
213:                firstInvalidLine = Math.min(screenLine, firstInvalidLine);
214:
215:                if (screenLine <= lastScreenLine)
216:                    lastScreenLine = lastScreenLineP = -1;
217:            } //}}}
218:
219:            //{{{ invalidateChunksFromPhys() method
220:            void invalidateChunksFromPhys(int physicalLine) {
221:                for (int i = 0; i < firstInvalidLine; i++) {
222:                    LineInfo info = lineInfo[i];
223:                    if (info.physicalLine == -1
224:                            || info.physicalLine >= physicalLine) {
225:                        firstInvalidLine = i;
226:                        if (i <= lastScreenLine)
227:                            lastScreenLine = lastScreenLineP = -1;
228:                        break;
229:                    }
230:                }
231:            } //}}}
232:
233:            //{{{ getLineInfo() method
234:            LineInfo getLineInfo(int screenLine) {
235:                updateChunksUpTo(screenLine);
236:                return lineInfo[screenLine];
237:            } //}}}
238:
239:            //{{{ getLineSubregionCount() method
240:            int getLineSubregionCount(int physicalLine) {
241:                if (!textArea.softWrap)
242:                    return 1;
243:
244:                out.clear();
245:                lineToChunkList(physicalLine, out);
246:
247:                int size = out.size();
248:                if (size == 0)
249:                    return 1;
250:                else
251:                    return size;
252:            } //}}}
253:
254:            //{{{ getSubregionOfOffset() method
255:            /**
256:             * Returns the subregion containing the specified offset. A subregion
257:             * is a subset of a physical line. Each screen line corresponds to one
258:             * subregion. Unlike the {@link #getScreenLineOfOffset(int, int)} method,
259:             * this method works with non-visible lines too.
260:             *
261:             * @param offset the offset
262:             * @param lineInfos a lineInfos array. Usualy the array is the result of
263:             *	{@link #getLineInfosForPhysicalLine(int)} call
264:             *
265:             * @return the subregion of the offset, or -1 if the offset was not in one of the given lineInfos
266:             */
267:            static int getSubregionOfOffset(int offset, LineInfo[] lineInfos) {
268:                for (int i = 0; i < lineInfos.length; i++) {
269:                    LineInfo info = lineInfos[i];
270:                    if (offset >= info.offset
271:                            && offset < info.offset + info.length)
272:                        return i;
273:                }
274:
275:                return -1;
276:            } //}}}
277:
278:            //{{{ xToSubregionOffset() method
279:            /**
280:             * Converts an x co-ordinate within a subregion into an offset from the
281:             * start of that subregion.
282:             * @param physicalLine The physical line number
283:             * @param subregion The subregion; if -1, then this is the last
284:             * subregion.
285:             * @param x The x co-ordinate
286:             * @param round Round up to next character if x is past the middle of a
287:             * character?
288:             */
289:            int xToSubregionOffset(int physicalLine, int subregion, int x,
290:                    boolean round) {
291:                LineInfo[] infos = getLineInfosForPhysicalLine(physicalLine);
292:                if (subregion == -1)
293:                    subregion += infos.length;
294:                return xToSubregionOffset(infos[subregion], x, round);
295:            } //}}}
296:
297:            //{{{ xToSubregionOffset() method
298:            /**
299:             * Converts an x co-ordinate within a subregion into an offset from the
300:             * start of that subregion.
301:             * @param info The line info object
302:             * @param x The x co-ordinate
303:             * @param round Round up to next character if x is past the middle of a
304:             * character?
305:             */
306:            static int xToSubregionOffset(LineInfo info, int x, boolean round) {
307:                int offset = Chunk.xToOffset(info.chunks, x, round);
308:                if (offset == -1 || offset == info.offset + info.length)
309:                    offset = info.offset + info.length - 1;
310:
311:                return offset;
312:            } //}}}
313:
314:            //{{{ subregionOffsetToX() method
315:            /**
316:             * Converts an offset within a subregion into an x co-ordinate.
317:             * @param physicalLine The physical line
318:             * @param offset The offset
319:             */
320:            int subregionOffsetToX(int physicalLine, int offset) {
321:                LineInfo[] infos = getLineInfosForPhysicalLine(physicalLine);
322:                LineInfo info = infos[getSubregionOfOffset(offset, infos)];
323:                return subregionOffsetToX(info, offset);
324:            } //}}}
325:
326:            //{{{ subregionOffsetToX() method
327:            /**
328:             * Converts an offset within a subregion into an x co-ordinate.
329:             * @param info The line info object
330:             * @param offset The offset
331:             */
332:            static int subregionOffsetToX(LineInfo info, int offset) {
333:                return (int) Chunk.offsetToX(info.chunks, offset);
334:            } //}}}
335:
336:            //{{{ getSubregionStartOffset() method
337:            /**
338:             * Returns the start offset of the specified subregion of the specified
339:             * physical line.
340:             * @param line The physical line number
341:             * @param offset An offset
342:             */
343:            int getSubregionStartOffset(int line, int offset) {
344:                LineInfo[] lineInfos = getLineInfosForPhysicalLine(line);
345:                LineInfo info = lineInfos[getSubregionOfOffset(offset,
346:                        lineInfos)];
347:                return textArea.getLineStartOffset(info.physicalLine)
348:                        + info.offset;
349:            } //}}}
350:
351:            //{{{ getSubregionEndOffset() method
352:            /**
353:             * Returns the end offset of the specified subregion of the specified
354:             * physical line.
355:             * @param line The physical line number
356:             * @param offset An offset
357:             */
358:            int getSubregionEndOffset(int line, int offset) {
359:                LineInfo[] lineInfos = getLineInfosForPhysicalLine(line);
360:                LineInfo info = lineInfos[getSubregionOfOffset(offset,
361:                        lineInfos)];
362:                return textArea.getLineStartOffset(info.physicalLine)
363:                        + info.offset + info.length;
364:            } //}}}
365:
366:            //{{{ getBelowPosition() method
367:            /**
368:             * @param physicalLine The physical line number
369:             * @param offset The offset
370:             * @param x The location
371:             * @param ignoreWrap If true, behave as if soft wrap is off even if it
372:             * is on
373:             */
374:            int getBelowPosition(int physicalLine, int offset, int x,
375:                    boolean ignoreWrap) {
376:                LineInfo[] lineInfos = getLineInfosForPhysicalLine(physicalLine);
377:
378:                int subregion = getSubregionOfOffset(offset, lineInfos);
379:
380:                if (subregion != lineInfos.length - 1 && !ignoreWrap) {
381:                    return textArea.getLineStartOffset(physicalLine)
382:                            + xToSubregionOffset(lineInfos[subregion + 1], x,
383:                                    true);
384:                } else {
385:                    int nextLine = textArea.displayManager
386:                            .getNextVisibleLine(physicalLine);
387:
388:                    if (nextLine == -1)
389:                        return -1;
390:                    else {
391:                        return textArea.getLineStartOffset(nextLine)
392:                                + xToSubregionOffset(nextLine, 0, x, true);
393:                    }
394:                }
395:            } //}}}
396:
397:            //{{{ getAbovePosition() method
398:            /**
399:             * @param physicalLine The physical line number
400:             * @param offset The offset
401:             * @param x The location
402:             * @param ignoreWrap If true, behave as if soft wrap is off even if it
403:             * is on
404:             */
405:            int getAbovePosition(int physicalLine, int offset, int x,
406:                    boolean ignoreWrap) {
407:                LineInfo[] lineInfos = getLineInfosForPhysicalLine(physicalLine);
408:
409:                int subregion = getSubregionOfOffset(offset, lineInfos);
410:
411:                if (subregion != 0 && !ignoreWrap) {
412:                    return textArea.getLineStartOffset(physicalLine)
413:                            + xToSubregionOffset(lineInfos[subregion - 1], x,
414:                                    true);
415:                } else {
416:                    int prevLine = textArea.displayManager
417:                            .getPrevVisibleLine(physicalLine);
418:
419:                    if (prevLine == -1)
420:                        return -1;
421:                    else {
422:                        return textArea.getLineStartOffset(prevLine)
423:                                + xToSubregionOffset(prevLine, -1, x, true);
424:                    }
425:                }
426:            } //}}}
427:
428:            //{{{ needFullRepaint() method
429:            /**
430:             * The needFullRepaint variable becomes true when the number of screen
431:             * lines in a physical line changes.
432:             */
433:            boolean needFullRepaint() {
434:                boolean retVal = needFullRepaint;
435:                needFullRepaint = false;
436:                return retVal;
437:            } //}}}
438:
439:            //{{{ getLineInfosForPhysicalLine() method
440:            LineInfo[] getLineInfosForPhysicalLine(int physicalLine) {
441:                out.clear();
442:
443:                if (!buffer.isLoading())
444:                    lineToChunkList(physicalLine, out);
445:
446:                if (out.isEmpty())
447:                    out.add(null);
448:
449:                List<LineInfo> returnValue = new ArrayList<LineInfo>(out.size());
450:                getLineInfosForPhysicalLine(physicalLine, returnValue);
451:                return returnValue.toArray(new LineInfo[out.size()]);
452:            } //}}}
453:
454:            //{{{ Private members
455:
456:            //{{{ Instance variables
457:            private final TextArea textArea;
458:            private JEditBuffer buffer;
459:            /**
460:             * The lineInfo array. There is LineInfo for each line that is visible in the textArea.
461:             * it can be resized by {@link #recalculateVisibleLines()}.
462:             * The content is valid from 0 to {@link #firstInvalidLine}
463:             */
464:            private LineInfo[] lineInfo;
465:            private final List<Chunk> out;
466:
467:            /** The first invalid line. All lines before this one are valid. */
468:            private int firstInvalidLine;
469:            private int lastScreenLineP;
470:            private int lastScreenLine;
471:
472:            private boolean needFullRepaint;
473:
474:            private final DisplayTokenHandler tokenHandler;
475:
476:            //}}}
477:
478:            //{{{ getLineInfosForPhysicalLine() method
479:            private void getLineInfosForPhysicalLine(int physicalLine,
480:                    List<LineInfo> list) {
481:                for (int i = 0; i < out.size(); i++) {
482:                    Chunk chunks = out.get(i);
483:                    LineInfo info = new LineInfo();
484:                    info.physicalLine = physicalLine;
485:                    if (i == 0) {
486:                        info.firstSubregion = true;
487:                        info.offset = 0;
488:                    } else
489:                        info.offset = chunks.offset;
490:
491:                    if (i == out.size() - 1) {
492:                        info.lastSubregion = true;
493:                        info.length = textArea.getLineLength(physicalLine)
494:                                - info.offset + 1;
495:                    } else {
496:                        info.length = out.get(i + 1).offset - info.offset;
497:                    }
498:
499:                    info.chunks = chunks;
500:
501:                    list.add(info);
502:                }
503:            } //}}}
504:
505:            //{{{ getFirstScreenLine() method
506:            /**
507:             * Find a valid line closest to the last screen line.
508:             */
509:            private int getFirstScreenLine() {
510:                for (int i = firstInvalidLine - 1; i >= 0; i--) {
511:                    if (lineInfo[i].lastSubregion)
512:                        return i + 1;
513:                }
514:
515:                return 0;
516:            } //}}}
517:
518:            //{{{ getUpdateStartLine() method
519:            /**
520:             * Return a physical line number.
521:             */
522:            private int getUpdateStartLine(int firstScreenLine) {
523:                // for the first line displayed, take its physical line to be
524:                // the text area's first physical line
525:                if (firstScreenLine == 0) {
526:                    return textArea.getFirstPhysicalLine();
527:                }
528:                // otherwise, determine the next visible line
529:                else {
530:                    int prevPhysLine = lineInfo[firstScreenLine - 1].physicalLine;
531:                    // if -1, the empty space at the end of the text area
532:                    // when the buffer has less lines than are visible
533:                    if (prevPhysLine == -1)
534:                        return -1;
535:                    else {
536:                        return textArea.displayManager
537:                                .getNextVisibleLine(prevPhysLine);
538:                    }
539:                }
540:            } //}}}
541:
542:            //{{{ updateChunksUpTo() method
543:            private void updateChunksUpTo(int lastScreenLine) {
544:                // this method is a nightmare
545:                if (lastScreenLine >= lineInfo.length)
546:                    throw new ArrayIndexOutOfBoundsException(lastScreenLine);
547:
548:                // if one line's chunks are invalid, remaining lines are also
549:                // invalid
550:                if (lastScreenLine < firstInvalidLine)
551:                    return;
552:
553:                int firstScreenLine = getFirstScreenLine();
554:                int physicalLine = getUpdateStartLine(firstScreenLine);
555:
556:                if (Debug.CHUNK_CACHE_DEBUG) {
557:                    Log.log(Log.DEBUG, this , "Updating chunks from "
558:                            + firstScreenLine + " to " + lastScreenLine);
559:                }
560:
561:                // Note that we rely on the fact that when a physical line is
562:                // invalidated, all screen lines/subregions of that line are
563:                // invalidated as well. See below comment for code that tries
564:                // to uphold this assumption.
565:
566:                out.clear();
567:
568:                int offset = 0;
569:                int length = 0;
570:
571:                for (int i = firstScreenLine; i <= lastScreenLine; i++) {
572:                    LineInfo info = lineInfo[i];
573:
574:                    Chunk chunks;
575:
576:                    // get another line of chunks
577:                    if (out.isEmpty()) {
578:                        // unless this is the first time, increment
579:                        // the line number
580:                        if (physicalLine != -1 && i != firstScreenLine) {
581:                            physicalLine = textArea.displayManager
582:                                    .getNextVisibleLine(physicalLine);
583:                        }
584:
585:                        // empty space
586:                        if (physicalLine == -1) {
587:                            info.chunks = null;
588:                            info.physicalLine = -1;
589:                            // fix the bug where the horiz.
590:                            // scroll bar was not updated
591:                            // after creating a new file.
592:                            info.width = 0;
593:                            continue;
594:                        }
595:
596:                        // chunk the line.
597:                        lineToChunkList(physicalLine, out);
598:
599:                        info.firstSubregion = true;
600:
601:                        int screenLines;
602:
603:                        // if the line has no text, out.size() == 0
604:                        if (out.isEmpty()) {
605:                            screenLines = 1;
606:
607:                            if (i == 0) {
608:                                if (textArea.displayManager.firstLine.skew > 0) {
609:                                    Log
610:                                            .log(
611:                                                    Log.ERROR,
612:                                                    this ,
613:                                                    "BUG: skew="
614:                                                            + textArea.displayManager.firstLine.skew
615:                                                            + ",out.size()="
616:                                                            + out.size());
617:                                    textArea.displayManager.firstLine.skew = 0;
618:                                    needFullRepaint = true;
619:                                    lastScreenLine = lineInfo.length - 1;
620:                                }
621:                            }
622:                            chunks = null;
623:                            offset = 0;
624:                            length = 1;
625:                        }
626:                        // otherwise, the number of subregions
627:                        else {
628:                            screenLines = out.size();
629:
630:                            if (i == 0) {
631:                                int skew = textArea.displayManager.firstLine.skew;
632:                                if (skew >= out.size()) {
633:                                    Log.log(Log.ERROR, this , "BUG: skew="
634:                                            + skew + ",out.size()="
635:                                            + out.size());
636:                                    skew = 0;
637:                                    needFullRepaint = true;
638:                                    lastScreenLine = lineInfo.length - 1;
639:                                } else if (skew > 0) {
640:                                    info.firstSubregion = false;
641:                                    for (int j = 0; j < skew; j++)
642:                                        out.remove(0);
643:                                }
644:                            }
645:                            chunks = out.remove(0);
646:                            offset = chunks.offset;
647:                            if (!out.isEmpty())
648:                                length = out.get(0).offset - offset;
649:                            else
650:                                length = textArea.getLineLength(physicalLine)
651:                                        - offset + 1;
652:                        }
653:                    } else {
654:                        info.firstSubregion = false;
655:
656:                        chunks = out.remove(0);
657:                        offset = chunks.offset;
658:                        if (!out.isEmpty())
659:                            length = out.get(0).offset - offset;
660:                        else
661:                            length = textArea.getLineLength(physicalLine)
662:                                    - offset + 1;
663:                    }
664:
665:                    boolean lastSubregion = out.isEmpty();
666:
667:                    if (i == lastScreenLine
668:                            && lastScreenLine != lineInfo.length - 1) {
669:                        /* if the user changes the syntax token at the
670:                         * end of a line, need to do a full repaint. */
671:                        if (tokenHandler.getLineContext() != info.lineContext) {
672:                            lastScreenLine++;
673:                            needFullRepaint = true;
674:                        }
675:                        /* If this line has become longer or shorter
676:                         * (in which case the new physical line number
677:                         * is different from the cached one) we need to:
678:                         * - continue updating past the last line
679:                         * - advise the text area to repaint
680:                         * On the other hand, if the line wraps beyond
681:                         * lastScreenLine, we need to keep updating the
682:                         * chunk list to ensure proper alignment of
683:                         * invalidation flags (see start of method) */
684:                        else if (info.physicalLine != physicalLine
685:                                || info.lastSubregion != lastSubregion) {
686:                            lastScreenLine++;
687:                            needFullRepaint = true;
688:                        }
689:                        /* We only cache entire physical lines at once;
690:                         * don't want to split a physical line into
691:                         * screen lines and only have some valid. */
692:                        else if (!out.isEmpty())
693:                            lastScreenLine++;
694:                    }
695:
696:                    info.physicalLine = physicalLine;
697:                    info.lastSubregion = lastSubregion;
698:                    info.offset = offset;
699:                    info.length = length;
700:                    info.chunks = chunks;
701:                    info.lineContext = tokenHandler.getLineContext();
702:                }
703:
704:                firstInvalidLine = Math.max(lastScreenLine + 1,
705:                        firstInvalidLine);
706:            } //}}}
707:
708:            //{{{ lineToChunkList() method
709:            private void lineToChunkList(int physicalLine, List<Chunk> out) {
710:                TextAreaPainter painter = textArea.getPainter();
711:
712:                tokenHandler.init(painter.getStyles(), painter
713:                        .getFontRenderContext(), painter, out,
714:                        textArea.softWrap ? textArea.wrapMargin : 0.0f);
715:                buffer.markTokens(physicalLine, tokenHandler);
716:            } //}}}
717:
718:            //}}}
719:
720:            //{{{ LineInfo class
721:            /** The informations on a line. (for fast access) */
722:            static class LineInfo {
723:                int physicalLine;
724:                int offset;
725:                int length;
726:                boolean firstSubregion;
727:                boolean lastSubregion;
728:                Chunk chunks;
729:                /** The line width. */
730:                int width;
731:                TokenMarker.LineContext lineContext;
732:            } //}}}
733:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.