Source Code Cross Referenced for DocOp.java in  » Swing-Library » abeille-forms-designer » org » netbeans » editor » 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 » abeille forms designer » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *                 Sun Public License Notice
0003:         * 
0004:         * The contents of this file are subject to the Sun Public License
0005:         * Version 1.0 (the "License"). You may not use this file except in
0006:         * compliance with the License. A copy of the License is available at
0007:         * http://www.sun.com/
0008:         * 
0009:         * The Original Code is NetBeans. The Initial Developer of the Original
0010:         * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
0011:         * Microsystems, Inc. All Rights Reserved.
0012:         */
0013:
0014:        package org.netbeans.editor;
0015:
0016:        import javax.swing.text.AbstractDocument;
0017:        import javax.swing.text.BadLocationException;
0018:        import javax.swing.text.Position;
0019:        import javax.swing.text.Segment;
0020:        import javax.swing.undo.AbstractUndoableEdit;
0021:        import javax.swing.undo.CannotRedoException;
0022:        import javax.swing.undo.CannotUndoException;
0023:        import javax.swing.undo.UndoableEdit;
0024:
0025:        /**
0026:         * Document operations. This class enhances basic marks operations by
0027:         * interaction with the data of the document. All mark operations should go
0028:         * through this class. This class implements <tt>AbstractDocument.Content</tt>
0029:         * interface. BOL means Begin of Line position. EOL means End of Line position.
0030:         * 
0031:         * @author Miloslav Metelka
0032:         * @version 1.00
0033:         */
0034:
0035:        class DocOp implements  AbstractDocument.Content {
0036:
0037:            /** Number of line cache entries */
0038:            private static final int CACHE_LEN = 5;
0039:
0040:            private static final String WRONG_POSITION = "Wrong position "; // NOI18N
0041:
0042:            private static final String DOC_LEN = ". Document length is "; // NOI18N
0043:
0044:            /**
0045:             * Default mark distance for inserting to the document. If the insert is
0046:             * made then the distance between nearest marks around insertion point is
0047:             * checked and if it's greater than the max mark distance then another
0048:             * mark(s) are inserted.
0049:             */
0050:            private int MARK_DISTANCE;
0051:
0052:            /**
0053:             * Maximum mark distance. When there is an insertion done in document and
0054:             * the distance between marks get greater than this value, another mark will
0055:             * be inserted.
0056:             */
0057:            private int MAX_MARK_DISTANCE;
0058:
0059:            /**
0060:             * Minimum mark distance for removals. When there is a removal done in
0061:             * document and it makes the marks to get closer than this value, then the
0062:             * second mark will be removed.
0063:             */
0064:            private int MIN_MARK_DISTANCE;
0065:
0066:            /**
0067:             * Size of one batch for updating syntax marks. It's used in two cases. When
0068:             * the prepareSyntax() is called it may be necessary to update the state
0069:             * infos of the syntax marks that were not updated yet. In this case the
0070:             * SYNTAX_UPDATE_BATCH_SIZE is the minimum area after the required position
0071:             * that will be updated (required length is often 0 so this prevents
0072:             * updating marks one by one). The other case is when insert or remove is
0073:             * performed it's not clear how many marks will it be necessary to update so
0074:             * it serves as the batching constant in this case.
0075:             */
0076:            private int SYNTAX_UPDATE_BATCH_SIZE;
0077:
0078:            /** Document cache */
0079:            private DocCache cache;
0080:
0081:            /** Document cache support */
0082:            private DocCacheSupport cacheSupport;
0083:
0084:            /** Document marks handling */
0085:            DocMarks marks;
0086:
0087:            /** Document */
0088:            private BaseDocument doc;
0089:
0090:            /** Document len */
0091:            private int docLen;
0092:
0093:            /** End of current line forward finder */
0094:            private FinderFactory.EOLFwdFinder eolFwdFinder;
0095:
0096:            /** Current line begining backward finder */
0097:            private FinderFactory.BOLBwdFinder bolBwdFinder;
0098:
0099:            /** Find both BOL and EOL one or more lines forward in text */
0100:            private FinderFactory.BEOLLineFwdFinder beolLineFwdFinder;
0101:
0102:            /** Find both BOL and EOL when position is known */
0103:            private FinderFactory.BEOLPosFwdFinder beolPosFwdFinder;
0104:
0105:            /** Finder for visual x-coord to position conversion */
0106:            private FinderFactory.VisColPosFwdFinder visColPosFwdFinder;
0107:
0108:            /** Finder for position to x-coord conversion */
0109:            private FinderFactory.PosVisColFwdFinder posVisColFwdFinder;
0110:
0111:            /** Line and column information cache */
0112:            private CacheEntry lineCache[];
0113:
0114:            /**
0115:             * End of document mark. This mark should speed up getting the line number
0116:             * of the end of document so that the cache fragment doesn't have to move.
0117:             */
0118:            private Mark endMark;
0119:
0120:            /**
0121:             * Mark that is inserted at the end of line (better said after the end of
0122:             * line) where the insertion currently occurs. The mark is possibly moved
0123:             * and/or updated before the insertion/removal occurs. Then after the
0124:             * insertion/removal is done mark syntax state is checked again. If it's the
0125:             * same as before it's not necessary to paint the next line after insertion.
0126:             * If it's not the same the painting must continue till the syntax mark with
0127:             * matching state.
0128:             */
0129:            MarkFactory.SyntaxMark eolMark;
0130:
0131:            /**
0132:             * Position of the end of the already scanned area. When the initial read is
0133:             * performed, it's set to zero. The <tt>prepareSyntax()</tt> updates this
0134:             * position if necessary. The value -1 means that either the document is
0135:             * empty or all the syntax marks are already up-to-date. It happens by
0136:             * requesting the scanning at the end of the document or after the first
0137:             * modification. The particular value means that all the syntax marks
0138:             * including those right at the position given by the value of the variable
0139:             * are up-to-date even if there would be more than one mark right at that
0140:             * position.
0141:             */
0142:            private int updatedAreaEnd = -1;
0143:
0144:            /** Renderer for doing syntax mark updates after insertion/removal. */
0145:            private SyntaxUpdateRenderer suRenderer;
0146:
0147:            /**
0148:             * First syntax mark that is laying in the left direction from the update
0149:             * point.
0150:             */
0151:            private MarkFactory.SyntaxMark leftUpdateMark;
0152:
0153:            /** Statistics */
0154:            int statCacheHit;
0155:            int statCacheMiss;
0156:
0157:            /**
0158:             * Construct new document marks operations. Since this class uses both cache
0159:             * and marks both these classes must be already created in document.
0160:             */
0161:            DocOp() {
0162:                marks = new DocMarks();
0163:                marks.startMark.setOp(this );
0164:
0165:                cacheSupport = new MemCacheSupport();
0166:                cache = new DocCache(cacheSupport, 2048, true); // !!!
0167:
0168:                // initialize cache
0169:                lineCache = new CacheEntry[CACHE_LEN];
0170:                for (int i = 0; i < CACHE_LEN; i++) {
0171:                    lineCache[i] = new CacheEntry();
0172:                }
0173:
0174:                // create necessary finders
0175:                bolBwdFinder = new FinderFactory.BOLBwdFinder();
0176:                eolFwdFinder = new FinderFactory.EOLFwdFinder();
0177:                beolLineFwdFinder = new FinderFactory.BEOLLineFwdFinder();
0178:                beolPosFwdFinder = new FinderFactory.BEOLPosFwdFinder();
0179:                visColPosFwdFinder = new FinderFactory.VisColPosFwdFinder();
0180:                posVisColFwdFinder = new FinderFactory.PosVisColFwdFinder();
0181:
0182:                // init endMark and eolMark
0183:                try {
0184:
0185:                    endMark = insertMark(docLen, false);
0186:                    eolMark = new MarkFactory.SyntaxMark() {
0187:                        protected void removeUpdateAction(int pos, int len) {
0188:                            // prevent default removing of this mark
0189:                        }
0190:                    };
0191:                    insertMark(eolMark, docLen);
0192:                } catch (BadLocationException e) {
0193:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0194:                        e.printStackTrace();
0195:                    }
0196:                } catch (InvalidMarkException e) {
0197:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0198:                        e.printStackTrace();
0199:                    }
0200:                }
0201:
0202:                // create shared syntax update renderer
0203:                suRenderer = new SyntaxUpdateRenderer();
0204:            }
0205:
0206:            void setDocument(BaseDocument doc) {
0207:                this .doc = doc;
0208:                MARK_DISTANCE = ((Integer) doc
0209:                        .getProperty(SettingsNames.MARK_DISTANCE)).intValue();
0210:                MAX_MARK_DISTANCE = ((Integer) doc
0211:                        .getProperty(SettingsNames.MAX_MARK_DISTANCE))
0212:                        .intValue();
0213:                MIN_MARK_DISTANCE = ((Integer) doc
0214:                        .getProperty(SettingsNames.MIN_MARK_DISTANCE))
0215:                        .intValue();
0216:                SYNTAX_UPDATE_BATCH_SIZE = ((Integer) doc
0217:                        .getProperty(SettingsNames.SYNTAX_UPDATE_BATCH_SIZE))
0218:                        .intValue();
0219:
0220:            }
0221:
0222:            public synchronized Position createPosition(int offset)
0223:                    throws BadLocationException {
0224:                boolean insertAfter = (offset == 0); // support AbstractDocument keep
0225:                // marks at position 0 behavior
0226:                if (offset == docLen + 1) { // support AbstractDocument's content
0227:                    // initial "\n" behavior
0228:                    offset = docLen;
0229:                }
0230:
0231:                return new BasePosition(this , offset,
0232:                        insertAfter ? Position.Bias.Backward
0233:                                : Position.Bias.Forward);
0234:            }
0235:
0236:            public synchronized Position createPosition(int offset,
0237:                    Position.Bias bias) throws BadLocationException {
0238:                return new BasePosition(this , offset, bias);
0239:            }
0240:
0241:            public synchronized int length() {
0242:                return docLen;
0243:            }
0244:
0245:            public String getString(int where, int len)
0246:                    throws BadLocationException {
0247:                return new String(getChars(where, len));
0248:            }
0249:
0250:            public void getChars(int where, int len, Segment txt)
0251:                    throws BadLocationException {
0252:                txt.array = getChars(where, len);
0253:                txt.offset = 0;
0254:                txt.count = len;
0255:            }
0256:
0257:            /** Retrieve the characters from the document cache. */
0258:            synchronized char[] getChars(int pos, int len)
0259:                    throws BadLocationException {
0260:                return cache.read(pos, len, null); // no cache fragment optimization
0261:                // yet
0262:            }
0263:
0264:            /**
0265:             * Get the characters into the given buffer. The buffer must contain enough
0266:             * space for the requested data.
0267:             */
0268:            synchronized void getChars(int pos, char ret[], int offset, int len)
0269:                    throws BadLocationException {
0270:                cache.read(pos, ret, offset, len, null);
0271:            }
0272:
0273:            public UndoableEdit insertString(int offset, String text)
0274:                    throws BadLocationException {
0275:                ModifyUndoEdit undoEdit = new ModifyUndoEdit(false, offset,
0276:                        text);
0277:                insertEdit(undoEdit);
0278:                return undoEdit;
0279:            }
0280:
0281:            public UndoableEdit insert(int offset, char[] chars)
0282:                    throws BadLocationException {
0283:                ModifyUndoEdit undoEdit = new ModifyUndoEdit(false, offset,
0284:                        chars);
0285:                insertEdit(undoEdit);
0286:                return undoEdit;
0287:            }
0288:
0289:            synchronized void insertEdit(ModifyUndoEdit undoEdit)
0290:                    throws BadLocationException {
0291:                int offset = undoEdit.getOffset();
0292:                checkEOLMark(offset);
0293:                if (undoEdit.isTextValid()) {
0294:                    cache.insertString(offset, undoEdit.getText(), null);
0295:                } else { // chars buffer valid
0296:                    cache.insert(offset, undoEdit.getChars(), null);
0297:                }
0298:                insertUpdate(undoEdit); // always done to update line cache
0299:            }
0300:
0301:            public UndoableEdit remove(int offset, int len)
0302:                    throws BadLocationException {
0303:                ModifyUndoEdit undoEdit = new ModifyUndoEdit(true, offset,
0304:                        getChars(offset, len));
0305:                removeEdit(undoEdit);
0306:                return undoEdit;
0307:            }
0308:
0309:            synchronized void removeEdit(ModifyUndoEdit undoEdit)
0310:                    throws BadLocationException {
0311:                checkEOLMark(undoEdit.getOffset());
0312:                cache.remove(undoEdit.getOffset(), undoEdit.getLength(), null); // no
0313:                // cache
0314:                // fragment
0315:                // optimization
0316:                // yet
0317:                removeUpdate(undoEdit);
0318:            }
0319:
0320:            synchronized int find(Finder finder, int startPos, int limitPos)
0321:                    throws BadLocationException {
0322:                return cache.find(finder, startPos, limitPos, null);
0323:            }
0324:
0325:            /**
0326:             * Insert new mark at specified position. This function finds the
0327:             * appropriate line number.
0328:             */
0329:            synchronized void insertMark(Mark mark, int offset)
0330:                    throws BadLocationException, InvalidMarkException {
0331:                if (offset < 0 || offset > docLen) {
0332:                    throw new BadLocationException(WRONG_POSITION + offset
0333:                            + DOC_LEN + docLen, offset);
0334:                }
0335:                insertMark(mark, offset, getLineImpl(offset));
0336:            }
0337:
0338:            /**
0339:             * Insert mark when knowing even the line offset. This method is used solely
0340:             * by <tt>Analyzer</tt> when document is read.
0341:             */
0342:            void insertMark(Mark mark, int offset, int line)
0343:                    throws BadLocationException, InvalidMarkException {
0344:                mark.offset = offset;
0345:                mark.line = line;
0346:                marks.insert(mark);
0347:                mark.setOp(this );
0348:            }
0349:
0350:            /**
0351:             * Write directly to the cache-support. This method is used solely by
0352:             * <tt>Analyzer</tt> when document is read.
0353:             */
0354:            void directCacheWrite(int pos, char cache[], int offset, int len)
0355:                    throws BadLocationException {
0356:                cacheSupport.write(pos, cache, offset, len);
0357:            }
0358:
0359:            /**
0360:             * Initialize the default fragment of the cache by the given data. This
0361:             * method is used solely by <tt>Analyzer</tt> when document is read.
0362:             */
0363:            void initCacheContent(char initCache[], int offset, int cacheLen) {
0364:                cache.initCacheContent(initCache, offset, cacheLen);
0365:            }
0366:
0367:            /**
0368:             * Insert new mark at specified position. The function finds appropriate
0369:             * line number.
0370:             */
0371:            Mark insertMark(int pos, boolean insertAfter)
0372:                    throws BadLocationException {
0373:                Mark mark = new Mark(insertAfter);
0374:                try {
0375:                    insertMark(mark, pos);
0376:                } catch (InvalidMarkException e) {
0377:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0378:                        e.printStackTrace();
0379:                    }
0380:                }
0381:                return mark;
0382:            }
0383:
0384:            /** Moves the mark to different position */
0385:            synchronized void moveMark(Mark mark, int newPos)
0386:                    throws BadLocationException, InvalidMarkException {
0387:                if (newPos < 0 || newPos > docLen) {
0388:                    throw new BadLocationException(WRONG_POSITION + newPos
0389:                            + DOC_LEN + docLen, newPos);
0390:                }
0391:                mark.remove();
0392:                insertMark(mark, newPos);
0393:            }
0394:
0395:            /**
0396:             * Get the first mark of the specified class that lies on the given
0397:             * position.
0398:             * 
0399:             * @param offset
0400:             *            position at which the mark is searched
0401:             * @param markClass
0402:             *            the class that the mark must be of. It can be also an instance
0403:             *            of a descendant of this class (<tt>Class.isInstance</tt> is
0404:             *            used).
0405:             * @return mark that matches the condition or null.
0406:             */
0407:            synchronized Mark getOffsetMark(int offset, Class markClass) {
0408:                return marks.getOffsetMark(offset, markClass);
0409:            }
0410:
0411:            synchronized void renderMarks(DocMarks.Renderer r) {
0412:                marks.render(r);
0413:            }
0414:
0415:            /**
0416:             * Get begin of line from position on that line
0417:             * 
0418:             * @param position
0419:             *            where the search begins
0420:             * @return position of begin of the same line
0421:             */
0422:            synchronized int getBOL(int pos) throws BadLocationException {
0423:                return getBOLImpl(pos);
0424:            }
0425:
0426:            /** Is the position at the begining of the line? */
0427:            synchronized boolean isBOL(int pos) throws BadLocationException {
0428:                return (pos == getBOLImpl(pos));
0429:            }
0430:
0431:            /** Get end of line position from position on that line. */
0432:            synchronized int getEOL(int pos) throws BadLocationException {
0433:                return getEOLImpl(pos);
0434:            }
0435:
0436:            /**
0437:             * Get end of line after the new-line position from position on that line.
0438:             * This is in fact the begining of the next line except the last line.
0439:             */
0440:            synchronized int getEOLNL(int pos) throws BadLocationException {
0441:                int eol = getEOLImpl(pos);
0442:                if (eol < docLen) {
0443:                    return eol++;
0444:                }
0445:                return eol;
0446:            }
0447:
0448:            /** Is the position at the end of the line? */
0449:            synchronized boolean isEOL(int pos) throws BadLocationException {
0450:                return (pos == getEOLImpl(pos));
0451:            }
0452:
0453:            /**
0454:             * Get the begining position of specified line
0455:             * 
0456:             * @param line
0457:             *            line offset for which the BOL should be determined
0458:             * @return position of the begining of line or -1 if line is invalid
0459:             */
0460:            synchronized int getBOLFromLine(int line) {
0461:                return getBOLFromLineImpl(line);
0462:            }
0463:
0464:            /** Get end of line position from specified line */
0465:            synchronized int getEOLFromLine(int line) {
0466:                int pos = getBOLFromLineImpl(line);
0467:                if (pos < 0) {
0468:                    return 0;
0469:                }
0470:                try {
0471:                    return getEOLImpl(pos);
0472:                } catch (BadLocationException e) {
0473:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0474:                        e.printStackTrace();
0475:                    }
0476:                    return -1;
0477:                }
0478:            }
0479:
0480:            /** Advance given position n-lines forward/backward and return BOL. */
0481:            synchronized int getBOLRelLine(int pos, int relLine)
0482:                    throws BadLocationException {
0483:                int line = getLineImpl(pos);
0484:                line += relLine;
0485:                return getBOLFromLineImpl(line);
0486:            }
0487:
0488:            /** Advance given position n-lines forward/backward and return BOL. */
0489:            synchronized int getEOLRelLine(int pos, int relLine)
0490:                    throws BadLocationException {
0491:                int line = getLineImpl(pos);
0492:                line += relLine;
0493:                pos = getBOLFromLineImpl(line);
0494:                if (pos < 0) {
0495:                    return pos;
0496:                }
0497:                try {
0498:                    return getEOLImpl(pos);
0499:                } catch (BadLocationException e) {
0500:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0501:                        e.printStackTrace();
0502:                    }
0503:                    return -1;
0504:                }
0505:            }
0506:
0507:            /**
0508:             * Get line from position. This is used for example when removal from
0509:             * document is made to find right line number for marks update.
0510:             */
0511:            synchronized int getLine(int pos) throws BadLocationException {
0512:                return getLineImpl(pos);
0513:            }
0514:
0515:            synchronized int getLineCount() {
0516:                int lineCnt;
0517:                try {
0518:                    lineCnt = endMark.getLine() + 1;
0519:                } catch (InvalidMarkException e) {
0520:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0521:                        e.printStackTrace();
0522:                    }
0523:                    return 0;
0524:                }
0525:
0526:                return lineCnt;
0527:            }
0528:
0529:            /**
0530:             * Get position on line from visual column. This method can be used only for
0531:             * superfixed font i.e. all characters of all font styles have the same
0532:             * width.
0533:             * 
0534:             * @param visCol
0535:             *            visual column
0536:             * @param startLinePos
0537:             *            position of line start
0538:             * @return position on line for particular x-coord
0539:             */
0540:            synchronized int getOffsetFromVisCol(int visCol, int startLinePos)
0541:                    throws BadLocationException {
0542:                if (visCol <= 0) {
0543:                    return startLinePos;
0544:                }
0545:                visColPosFwdFinder.setVisCol(visCol);
0546:                visColPosFwdFinder.setTabSize(doc.getTabSize());
0547:                int pos = cache
0548:                        .find(visColPosFwdFinder, startLinePos, -1, null);
0549:                return (pos != -1) ? pos : getEOLImpl(startLinePos);
0550:            }
0551:
0552:            /**
0553:             * Get visual column from position. This method can be used only for
0554:             * superfixed font i.e. all characters of all font styles have the same
0555:             * width.
0556:             * 
0557:             * @param pos
0558:             *            position for which the visual column should be returned the
0559:             *            function itself computes the begining of the line first
0560:             */
0561:            synchronized int getVisColFromPos(int pos)
0562:                    throws BadLocationException {
0563:                int startLinePos = getBOLImpl(pos);
0564:                posVisColFwdFinder.setTabSize(doc.getTabSize());
0565:                cache.find(posVisColFwdFinder, startLinePos, pos, null);
0566:                return posVisColFwdFinder.getVisCol();
0567:            }
0568:
0569:            private int getBOLImpl(int pos) throws BadLocationException {
0570:                if (pos <= 0) { // must be first line
0571:                    if (pos == 0) {
0572:                        return 0;
0573:                    }
0574:                    throw new BadLocationException(WRONG_POSITION + pos
0575:                            + DOC_LEN + length(), pos);
0576:                }
0577:
0578:                // search cache
0579:                for (int i = 0; i < CACHE_LEN; i++) {
0580:                    if (pos >= lineCache[i].bol && pos <= lineCache[i].eol) {
0581:                        // if (lineCache[i].bol != getCheckBOL(pos)) { // !!! remove
0582:                        // checkCache();
0583:                        // }
0584:                        cacheMoveFirst(i);
0585:                        statCacheHit++;
0586:                        return lineCache[0].bol;
0587:                    }
0588:                }
0589:                statCacheMiss++;
0590:
0591:                // search document when not found
0592:                return cache.find(bolBwdFinder, pos, 0, null) + 1;
0593:            }
0594:
0595:            private int getEOLImpl(int pos) throws BadLocationException {
0596:                if (pos < 0) {
0597:                    throw new BadLocationException(WRONG_POSITION + pos
0598:                            + DOC_LEN + length(), pos);
0599:                }
0600:
0601:                // search cache
0602:                for (int i = 0; i < CACHE_LEN; i++) {
0603:                    if (pos >= lineCache[i].bol && pos <= lineCache[i].eol) {
0604:                        // if (lineCache[i].eol != getCheckEOL(pos)) {
0605:                        // checkCache();
0606:                        // }
0607:                        cacheMoveFirst(i);
0608:                        statCacheHit++;
0609:                        return lineCache[0].eol;
0610:                    }
0611:                }
0612:                statCacheMiss++;
0613:
0614:                // search document
0615:                pos = cache.find(eolFwdFinder, pos, -1, null);
0616:                return (pos != -1) ? pos : docLen;
0617:            }
0618:
0619:            private int getBOLFromLineImpl(int line) {
0620:                if (line < 0) {
0621:                    return -1;
0622:                }
0623:
0624:                // check cache first
0625:                for (int i = 0; i < CACHE_LEN; i++) {
0626:                    if (line == lineCache[i].line) {
0627:                        // if (lineCache[i].bol != getCheckBOLFromLine(line)) { // !!!
0628:                        // remove
0629:                        // checkCache();
0630:                        // }
0631:                        cacheMoveFirst(i);
0632:                        statCacheHit++;
0633:                        return lineCache[0].bol;
0634:                    }
0635:                }
0636:                statCacheMiss++;
0637:
0638:                // load line into cache
0639:                cacheMoveFirst(CACHE_LEN - 1);
0640:                return cacheLoadLine(line); // returns -1 for wrong pos
0641:
0642:            }
0643:
0644:            private int getLineImpl(int pos) throws BadLocationException {
0645:                if (pos < 0 || pos > docLen) {
0646:                    throw new BadLocationException(WRONG_POSITION + pos
0647:                            + DOC_LEN + length(), pos);
0648:                }
0649:
0650:                // search cache
0651:                for (int i = 0; i < CACHE_LEN; i++) {
0652:                    if (pos >= lineCache[i].bol && pos <= lineCache[i].eol) {
0653:                        // if (lineCache[i].line != getCheckLine(pos)) {
0654:                        // checkCache();
0655:                        // }
0656:                        cacheMoveFirst(i);
0657:                        statCacheHit++;
0658:                        return lineCache[0].line;
0659:                    }
0660:                }
0661:                statCacheMiss++;
0662:
0663:                // load line into cache
0664:                cacheMoveFirst(CACHE_LEN - 1);
0665:                return cacheLoadLineByPos(pos);
0666:            }
0667:
0668:            /**
0669:             * If this position is at BOL leave it as it is if returnIfBOL is set.
0670:             * Otherwise get BOL of the next line or end of document.
0671:             * 
0672:             * @param returnIfBOL
0673:             *            return immediately if the position is already on BOL
0674:             */
0675:            private int adjustNextBOL(int pos, boolean returnIfBOL)
0676:                    throws BadLocationException {
0677:                if (returnIfBOL && pos == getBOLImpl(pos)) {
0678:                    return pos;
0679:                }
0680:                pos = getEOLImpl(pos);
0681:                if (pos < docLen) {
0682:                    pos++;
0683:                }
0684:                return pos;
0685:            }
0686:
0687:            /**
0688:             * Get the first syntax mark that is in the left direction from the desired
0689:             * position.
0690:             */
0691:            MarkFactory.SyntaxMark getLeftSyntaxMark(int pos) {
0692:                return (MarkFactory.SyntaxMark) marks.getLeftMark(pos,
0693:                        MarkFactory.SyntaxMark.class);
0694:            }
0695:
0696:            private void update(boolean remove, ModifyUndoEdit undoEdit) {
0697:                int pos = undoEdit.getOffset();
0698:                SyntaxSeg.invalidate(doc, pos);
0699:                SyntaxSeg.Slot slot = SyntaxSeg.getFreeSlot();
0700:                Syntax syntax = doc.getFreeSyntax();
0701:
0702:                try {
0703:                    // #19429
0704:                    // Removing syntax marks at pos, eolMark must be saved
0705:                    if (remove) {
0706:                        boolean eolMarkRemoved = false;
0707:                        while (true) {
0708:                            Mark mark = getOffsetMark(pos,
0709:                                    MarkFactory.SyntaxMark.class);
0710:                            if (mark == eolMark) {
0711:                                eolMarkRemoved = true;
0712:                            }
0713:                            if (mark == null) {
0714:                                break;
0715:                            }
0716:                            mark.remove();
0717:                        }
0718:                        if (eolMarkRemoved) {
0719:                            insertMark(eolMark, pos);
0720:                        }
0721:                        // Removing line marks at pos
0722:                        while (true) {
0723:                            Mark mark = getOffsetMark(pos,
0724:                                    MarkFactory.LineMark.class);
0725:                            if (mark == null) {
0726:                                break;
0727:                            }
0728:                            mark.remove();
0729:                        }
0730:                    }
0731:
0732:                    cacheUpdate(remove, undoEdit); // Update line cache
0733:                    leftUpdateMark = getLeftSyntaxMark(pos - 1); // compute left
0734:                    // syntax update
0735:                    // mark
0736:                    int leftUpdatePos = (leftUpdateMark != null) ? leftUpdateMark
0737:                            .getOffset()
0738:                            : 0;
0739:                    // Add or remove syntax marks that are too close or too far away
0740:                    updateEvenly();
0741:
0742:                    // Prepare syntax for updating the mark states of the syntax marks
0743:                    prepareSyntax(slot, syntax, leftUpdateMark, leftUpdatePos,
0744:                            0, false);
0745:
0746:                    // Update the syntax marks by mark renderer
0747:                    suRenderer.slot = slot;
0748:                    suRenderer.syntax = syntax;
0749:                    suRenderer.undoEdit = undoEdit;
0750:                    suRenderer.remove = remove;
0751:                    marks.render(suRenderer);
0752:                } catch (InvalidMarkException e) {
0753:                    e.printStackTrace();
0754:                } catch (BadLocationException e) {
0755:                    e.printStackTrace();
0756:                } finally {
0757:                    doc.releaseSyntax(syntax);
0758:                    SyntaxSeg.releaseSlot(slot);
0759:                }
0760:            }
0761:
0762:            /**
0763:             * Invalidate the state-infos in all the syntax-marks in the whole document.
0764:             */
0765:            synchronized void invalidateSyntaxMarks() {
0766:                // Render the marks by mark renderer
0767:                marks.render(new DocMarks.Renderer() {
0768:                    protected void render() {
0769:                        Mark markArray[] = getMarkArray();
0770:                        int len = getMarkArrayLength();
0771:                        for (int i = 0; i < len; i = getNextIndex(i)) {
0772:                            if (markArray[i] instanceof  MarkFactory.SyntaxMark) {
0773:                                ((MarkFactory.SyntaxMark) markArray[i])
0774:                                        .setStateInfo(null);
0775:                            }
0776:                        }
0777:                    }
0778:                });
0779:
0780:                updatedAreaEnd = 0; // force to validate when necessary
0781:            }
0782:
0783:            void initialReadUpdate() { // doesn't need to be synced
0784:                docLen = cache.getDocLength();
0785:                invalidateCache(); // invalidate the line cache
0786:                updatedAreaEnd = 0; // signal that all the syntax marks need to be
0787:                // updated
0788:            }
0789:
0790:            /**
0791:             * This function is called after document insertion to update marks. Event
0792:             * parameter contains inserted chars and also how many lines was inserted.
0793:             */
0794:            synchronized void insertUpdate(ModifyUndoEdit undoEdit) {
0795:                docLen += undoEdit.getLength();
0796:                marks.update(undoEdit.getOffset(), 0, undoEdit.getLength(),
0797:                        undoEdit.getLFCount());
0798:                update(false, undoEdit);
0799:            }
0800:
0801:            /**
0802:             * This function is called after document removal to update marks. Event
0803:             * parameter contains removed chars and also how many lines was removed.
0804:             */
0805:            synchronized void removeUpdate(ModifyUndoEdit undoEdit) {
0806:                docLen -= undoEdit.getLength();
0807:                marks.update(undoEdit.getOffset(), undoEdit.getLine(),
0808:                        -undoEdit.getLength(), -undoEdit.getLFCount());
0809:                update(true, undoEdit);
0810:            }
0811:
0812:            /**
0813:             * Update marks after insert/removal so that they are well evenly
0814:             * distributed. The method is not synchronized on mark renderer as all
0815:             * changes must be made under document being write-locked.
0816:             */
0817:            private void updateEvenly() {
0818:                // Render the marks by mark renderer
0819:                marks.render(new DocMarks.Renderer() {
0820:                    protected void render() {
0821:                        int leftMarkIndex = -1;
0822:                        int leftMarkPos = 0;
0823:                        if (leftUpdateMark != null) {
0824:                            leftMarkIndex = getMarkIndex(leftUpdateMark);
0825:                            leftMarkPos = getMarkOffset(leftUpdateMark);
0826:                        }
0827:
0828:                        Mark markArray[] = getMarkArray();
0829:                        int cnt = getMarkArrayLength(); // total mark count
0830:                        int dist = 0; // distance of mark from the current leftMarkPos
0831:                        Mark m;
0832:                        int i = getNextIndex(leftMarkIndex);
0833:                        boolean found = false;
0834:                        // First remove all the marks that are on the same position
0835:                        for (; i < cnt; i = getNextIndex(i)) {
0836:                            m = markArray[i];
0837:                            dist = getMarkOffset(m) - leftMarkPos;
0838:                            if (m.getClass() == MarkFactory.SyntaxMark.class) { // syntax
0839:                                // mark
0840:                                // found
0841:                                if (m != eolMark) { // eol mark is ignored here
0842:                                    found = true;
0843:                                    break;
0844:                                }
0845:                            }
0846:                        }
0847:                        if (!found) {
0848:                            dist = length() - leftMarkPos;
0849:                        }
0850:                        // test for too small distance
0851:                        if (dist < MIN_MARK_DISTANCE && found) {
0852:                            try {
0853:                                markArray[i].remove();
0854:                            } catch (InvalidMarkException e) {
0855:                                if (Boolean
0856:                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0857:                                    e.printStackTrace();
0858:                                }
0859:                            }
0860:                        }
0861:
0862:                        // test for too large distance
0863:                        if (dist > MAX_MARK_DISTANCE) {
0864:                            int insCnt = dist / MARK_DISTANCE;
0865:                            if (insCnt > 0) {
0866:                                int startInsPos = leftMarkPos
0867:                                        + (dist - (insCnt - 1) * MARK_DISTANCE)
0868:                                        / 2;
0869:                                try {
0870:                                    for (int j = 0; j < insCnt; j++) {
0871:                                        MarkFactory.SyntaxMark newMark = new MarkFactory.SyntaxMark();
0872:                                        insertMark(newMark, startInsPos + j
0873:                                                * MARK_DISTANCE);
0874:                                    }
0875:                                } catch (InvalidMarkException e) {
0876:                                    if (Boolean
0877:                                            .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0878:                                        e.printStackTrace();
0879:                                    }
0880:                                } catch (BadLocationException e) {
0881:                                    if (Boolean
0882:                                            .getBoolean("netbeans.debug.exceptions")) { // NOI18N
0883:                                        e.printStackTrace();
0884:                                    }
0885:                                }
0886:                            }
0887:                        }
0888:                    }
0889:                });
0890:            }
0891:
0892:            /**
0893:             * Check if the EOL syntax mark is at the right place. If not, move it to
0894:             * the end of current line and update it with the right syntax information.
0895:             * It uses instance of syntax used in document.
0896:             */
0897:            void checkEOLMark(int pos) {
0898:                try {
0899:                    int eolPos = adjustNextBOL(pos, false);
0900:                    if (eolMark.getOffset() != eolPos) { // mark at the wrong place
0901:                        SyntaxSeg.Slot slot = SyntaxSeg.getFreeSlot();
0902:                        Syntax syntax = doc.getFreeSyntax();
0903:
0904:                        if (updatedAreaEnd >= 0) { // whole doc still not fully updated
0905:                            // Force scanning till the end of document
0906:                            prepareSyntax(slot, syntax,
0907:                                    getLeftSyntaxMark(docLen), docLen, 0, false);
0908:                        }
0909:
0910:                        MarkFactory.SyntaxMark mark = getLeftSyntaxMark(eolPos - 1);
0911:
0912:                        try {
0913:                            prepareSyntax(slot, syntax, mark, eolPos, 0, false); // scan
0914:                            // up
0915:                            // to
0916:                            // eolMark
0917:                            // ignoring
0918:                            // it
0919:                            // in
0920:                            // search
0921:                            // Fix of #11130 - need to move the mark AFTER the syntax is
0922:                            // prepared
0923:                            moveMark(eolMark, eolPos);
0924:                            eolMark.updateStateInfo(syntax);
0925:                        } finally {
0926:                            doc.releaseSyntax(syntax);
0927:                            SyntaxSeg.releaseSlot(slot);
0928:                        }
0929:                    }
0930:                } catch (BadLocationException e) {
0931:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0932:                        e.printStackTrace();
0933:                    }
0934:                } catch (InvalidMarkException e) {
0935:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0936:                        e.printStackTrace();
0937:                    }
0938:                }
0939:            }
0940:
0941:            /**
0942:             * Prepare syntax scanner so that it's ready to scan from requested
0943:             * position.
0944:             * 
0945:             * @param slot
0946:             *            syntax segment slot to be used
0947:             * @param syntax
0948:             *            syntax scanner to be used
0949:             * @param leftSyntaxMark
0950:             *            first syntax mark in the left direction from the reqPos, can
0951:             *            be obtained by getLeftSyntaxMark()
0952:             * @param reqPos
0953:             *            position to which the syntax should be prepared
0954:             * @param reqLen
0955:             *            length that will be scanned by the caller after the syntax is
0956:             *            prepared. The prepareSyntax() automatically preloads this area
0957:             *            into the syntax segment slot.
0958:             * @param forceLastBuffer
0959:             *            force the syntax to think that the scanned area is the last in
0960:             *            the document. This is useful for forcing the syntax to process
0961:             *            all the characters in the given area.
0962:             * @param forceNotLastBuffer
0963:             *            force the syntax to think that the scanned area is NOT the
0964:             *            last buffer in the document. This is useful when the syntax
0965:             *            will continue scanning on another buffer.
0966:             */
0967:            void prepareSyntax(final SyntaxSeg.Slot slot, final Syntax syntax,
0968:                    MarkFactory.SyntaxMark leftSyntaxMark, final int reqPos,
0969:                    int reqLen, boolean forceLastBuffer,
0970:                    boolean forceNotLastBuffer) throws BadLocationException {
0971:
0972:                /*
0973:                 * Check whether the syntax marks in the area are already updated The
0974:                 * end of the requested area is checked although it would be enough to
0975:                 * scan till markPos. However it's better for drawing because it doesn't
0976:                 * know the end of the last token to draw and therefore it searches
0977:                 * through syntax-marks at the end of the drawn area to find the
0978:                 * syntax-mark that lays (including pre-scan) after the area end.
0979:                 */
0980:                if (updatedAreaEnd >= 0 && updatedAreaEnd < reqPos + reqLen) {
0981:                    final MarkFactory.SyntaxMark updSyntaxMark = getLeftSyntaxMark(updatedAreaEnd);
0982:                    int updMarkPos = 0;
0983:                    int updPreScan = 0;
0984:                    Syntax.StateInfo updStateInfo = null;
0985:                    if (updSyntaxMark != null) {
0986:                        try {
0987:                            updMarkPos = updSyntaxMark.getOffset();
0988:                        } catch (InvalidMarkException e) {
0989:                            if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
0990:                                e.printStackTrace();
0991:                            }
0992:                        }
0993:
0994:                        updStateInfo = updSyntaxMark.getStateInfo();
0995:                        updPreScan = updStateInfo.getPreScan();
0996:                    }
0997:
0998:                    // load the whole area so the next load below will have no work
0999:                    final int slotLoadPos = updMarkPos - updPreScan;
1000:                    // length from left mark to reqPos plus preScan
1001:                    int updLen = reqPos - slotLoadPos;
1002:                    // Compute req-len for marks updating. It is batched to update more
1003:                    // marks at once
1004:                    final int umReqLen = Math.min(reqLen
1005:                            + SYNTAX_UPDATE_BATCH_SIZE, docLen - reqPos);
1006:                    slot.load(doc, slotLoadPos, updLen + umReqLen);
1007:                    syntax.load(updStateInfo, slot.array, slot.offset
1008:                            + updPreScan, updLen - updPreScan,
1009:                            (reqPos == docLen), updMarkPos);
1010:
1011:                    final int umPos = updMarkPos; // helper final variable
1012:                    marks.render(new DocMarks.Renderer() {
1013:                        public void render() {
1014:                            int markCnt = getMarkArrayLength();
1015:                            int index = (updSyntaxMark != null) ? (getNextIndex(getMarkIndex(updSyntaxMark)))
1016:                                    : getNextIndex(-1);
1017:                            int pos = umPos;
1018:                            Mark markArray[] = getMarkArray();
1019:
1020:                            int lastPos = pos; // position of the last syntax mark
1021:                            // found
1022:                            while (index < markCnt) { // possibly till end of mark
1023:                                // array
1024:                                Mark mark = markArray[index];
1025:                                int prevIndex = index;
1026:                                index = getNextIndex(index);
1027:                                pos = getMarkOffset(mark);
1028:
1029:                                if (pos > reqPos + umReqLen) { // reached the end of
1030:                                    // area available in
1031:                                    // slot
1032:                                    index = prevIndex; // this could be a syntax mark,
1033:                                    // so go back for further test
1034:                                    break;
1035:                                }
1036:
1037:                                if (mark instanceof  MarkFactory.SyntaxMark) {
1038:                                    MarkFactory.SyntaxMark syntaxMark = (MarkFactory.SyntaxMark) mark;
1039:                                    syntax.relocate(slot.array, slot.offset
1040:                                            + lastPos - slotLoadPos, pos
1041:                                            - lastPos, (pos == docLen), pos);
1042:
1043:                                    while (syntax.nextToken() != null) {
1044:                                    } // scan till this mark
1045:
1046:                                    syntaxMark.updateStateInfo(syntax); // update
1047:                                    // state-info of
1048:                                    // the mark
1049:                                    updatedAreaEnd = pos; // this area is up-to-date
1050:                                    lastPos = pos; // move to next area between syntax
1051:                                    // marks
1052:                                }
1053:                            }
1054:
1055:                            // Try to find next syntax-mark in the array
1056:                            while (index < markCnt) {
1057:                                if (markArray[index] instanceof  MarkFactory.SyntaxMark) {
1058:                                    break;
1059:                                }
1060:                                index = getNextIndex(index);
1061:                            }
1062:                            // If there's no more SM, finally mark whole doc up-to-date
1063:                            if (index >= markCnt) { // reached the end of the mark array
1064:                                updatedAreaEnd = -1;
1065:                            }
1066:
1067:                        }
1068:                    });
1069:                }
1070:
1071:                // Get nearest previous syntax mark
1072:                int markPos = 0;
1073:                int preScan = 0;
1074:                Syntax.StateInfo stateInfo = null;
1075:                if (leftSyntaxMark != null) {
1076:                    try {
1077:                        markPos = leftSyntaxMark.getOffset(); // get position to scan
1078:                        // from
1079:                    } catch (InvalidMarkException e) {
1080:                        if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1081:                            e.printStackTrace();
1082:                        }
1083:                    }
1084:
1085:                    stateInfo = leftSyntaxMark.getStateInfo();
1086:                    preScan = stateInfo.getPreScan();
1087:                }
1088:
1089:                // load syntax segment
1090:                int loadPos = markPos - preScan;
1091:                int prepareLen = reqPos - loadPos;
1092:                slot.load(doc, loadPos, prepareLen + reqLen);
1093:
1094:                // load state into syntax scanner - will scan from mark up to reqPos
1095:                syntax.load(stateInfo, slot.array, slot.offset + preScan,
1096:                        prepareLen - preScan, forceNotLastBuffer ? false
1097:                                : (reqPos >= docLen), reqPos);
1098:
1099:                // go through all the tokens till the required position
1100:                while (syntax.nextToken() != null) {
1101:                }
1102:
1103:                syntax
1104:                        .relocate(slot.array, slot.offset + prepareLen, reqLen,
1105:                                forceNotLastBuffer ? false : forceLastBuffer
1106:                                        || (reqPos + reqLen >= docLen), reqPos
1107:                                        + reqLen);
1108:            }
1109:
1110:            void prepareSyntax(final SyntaxSeg.Slot slot, final Syntax syntax,
1111:                    MarkFactory.SyntaxMark leftSyntaxMark, final int reqPos,
1112:                    int reqLen, boolean forceLastBuffer)
1113:                    throws BadLocationException {
1114:                prepareSyntax(slot, syntax, leftSyntaxMark, reqPos, reqLen,
1115:                        forceLastBuffer, false);
1116:            }
1117:
1118:            /**
1119:             * Load the line info into lineCache[0]. The line offset must be >= 0.
1120:             * 
1121:             * @return BOL of loaded line or -1 if line offset is too high
1122:             */
1123:            private int cacheLoadLine(int line) {
1124:                if (line == 0) { // handle line 0 specially
1125:                    try {
1126:                        int eol = cache.find(eolFwdFinder, 0, -1, null);
1127:                        if (eol == -1) {
1128:                            eol = docLen;
1129:                        }
1130:                        lineCache[0].fill(0, eol, 0);
1131:                    } catch (BadLocationException e) {
1132:                        if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1133:                            e.printStackTrace();
1134:                        }
1135:                        return -1; // invalid offset
1136:                    }
1137:                    return 0;
1138:                }
1139:
1140:                int markLine;
1141:                int markPos;
1142:                try {
1143:                    Mark mark = marks.getMarkFromLine(line - 1);
1144:                    markPos = mark.getOffset();
1145:                    markLine = mark.getLine();
1146:                } catch (InvalidMarkException e) {
1147:                    return cacheLoadLine(line); // try again
1148:                }
1149:
1150:                try {
1151:                    beolLineFwdFinder.fwdLines = line - markLine;
1152:                    markPos = cache.find(beolLineFwdFinder, markPos, -1, null);
1153:                    int bolPos = beolLineFwdFinder.bolPos;
1154:                    if (bolPos == -1) { // wrong line
1155:                        return -1;
1156:                    }
1157:                    if (markPos == -1) { // correct eolPos
1158:                        markPos = docLen;
1159:                    }
1160:                    lineCache[0].fill(bolPos, markPos, line);
1161:                    return bolPos;
1162:                } catch (BadLocationException e) {
1163:                    if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1164:                        e.printStackTrace();
1165:                    }
1166:                    return -1;
1167:                }
1168:            }
1169:
1170:            /*
1171:             * Load line when position is known. @return line offset of the loaded line
1172:             */
1173:            private int cacheLoadLineByPos(int pos) throws BadLocationException {
1174:                int markPos;
1175:                int markLine;
1176:                try {
1177:                    Mark mark = marks.getLeftMark(pos, null);
1178:                    markPos = mark.getOffset();
1179:                    markLine = mark.getLine();
1180:
1181:                } catch (InvalidMarkException e) {
1182:                    return cacheLoadLineByPos(pos); // recall
1183:                }
1184:
1185:                beolPosFwdFinder.tgtPos = pos;
1186:                markPos = cache.find(beolPosFwdFinder, markPos, -1, null);
1187:                if (markPos == -1) { // correct eolPos
1188:                    markPos = docLen;
1189:                }
1190:                int bolPos = beolPosFwdFinder.bolPos;
1191:                if (bolPos == -1) { // mark was on the same line with pos
1192:                    if (pos > 0) {
1193:                        bolPos = cache.find(bolBwdFinder, pos, 0, null) + 1;
1194:                    } else {
1195:                        bolPos = 0;
1196:                    }
1197:                }
1198:                int line = markLine + beolPosFwdFinder.line;
1199:                lineCache[0].fill(bolPos, markPos, line);
1200:                return line;
1201:            }
1202:
1203:            /** Move the entry with some index to be the first in the array */
1204:            private void cacheMoveFirst(int ind) {
1205:                if (ind == 0) {
1206:                    return;
1207:                }
1208:                CacheEntry ent = lineCache[ind];
1209:                System.arraycopy(lineCache, 0, lineCache, 1, ind);
1210:                lineCache[0] = ent;
1211:            }
1212:
1213:            private void invalidateCache() {
1214:                for (int i = 0; i < CACHE_LEN; i++) {
1215:                    lineCache[i].invalidate();
1216:                }
1217:            }
1218:
1219:            /** Update cache after document change. */
1220:            private void cacheUpdate(boolean remove, ModifyUndoEdit undoEdit) {
1221:                int pos = undoEdit.getOffset();
1222:                int len = undoEdit.getLength();
1223:                int bolRemovalPos = -1;
1224:                int eolRemovalPos = -1;
1225:                for (int i = 0; i < CACHE_LEN; i++) {
1226:                    CacheEntry ent = lineCache[i];
1227:                    if (ent.line != -1) {
1228:                        if (!remove) { // insert done
1229:                            if (pos >= ent.bol) {
1230:                                if (pos <= ent.eol) { // change inside line
1231:                                    int eolOffset = undoEdit.getFirstLFOffset();
1232:                                    if (eolOffset == -1) { // no LF inside text
1233:                                        ent.eol += len;
1234:                                    } else { // at least one LF inside text
1235:                                        ent.eol = eolOffset;
1236:                                    }
1237:                                } else { // change after end -> do nothing
1238:                                }
1239:                            } else { // pos <= bol -> only move
1240:                                ent.update(len, undoEdit.getLFCount());
1241:                            }
1242:                        } else { // remove done
1243:                            if (pos + len >= ent.bol) {
1244:                                if (pos <= ent.eol) { // change before line end
1245:                                    ent.line = undoEdit.getLine();
1246:                                    if (pos + len > ent.eol) { // end of change after
1247:                                        // EOL
1248:                                        if (eolRemovalPos == -1) {
1249:                                            try {
1250:                                                eolRemovalPos = cache.find(
1251:                                                        eolFwdFinder, pos, -1,
1252:                                                        null);
1253:                                            } catch (BadLocationException e) {
1254:                                                if (Boolean
1255:                                                        .getBoolean("netbeans.debug.exceptions")) { // NOI18N
1256:                                                    e.printStackTrace();
1257:                                                }
1258:                                            }
1259:                                            if (eolRemovalPos == -1) {
1260:                                                eolRemovalPos = docLen;
1261:                                            }
1262:                                        }
1263:                                        ent.eol = eolRemovalPos;
1264:                                        if (pos < ent.bol) { // change before line
1265:                                            // begin
1266:                                            if (bolRemovalPos == -1) {
1267:                                                try {
1268:                                                    bolRemovalPos = cache.find(
1269:                                                            bolBwdFinder, pos,
1270:                                                            0, null) + 1;
1271:                                                } catch (BadLocationException e) {
1272:                                                    if (Boolean
1273:                                                            .getBoolean("netbeans.debug.exceptions")) { // NOI18N
1274:                                                        e.printStackTrace();
1275:                                                    }
1276:                                                }
1277:                                            }
1278:                                            ent.bol = bolRemovalPos;
1279:                                        }
1280:                                    } else { // end of change before EOL
1281:                                        ent.eol -= len;
1282:                                        if (pos < ent.bol) { // change before line
1283:                                            // begin
1284:                                            if (bolRemovalPos == -1) {
1285:                                                try {
1286:                                                    bolRemovalPos = cache.find(
1287:                                                            bolBwdFinder, pos,
1288:                                                            0, null) + 1;
1289:                                                } catch (BadLocationException e) {
1290:                                                    if (Boolean
1291:                                                            .getBoolean("netbeans.debug.exceptions")) { // NOI18N
1292:                                                        e.printStackTrace();
1293:                                                    }
1294:                                                }
1295:                                            }
1296:                                            ent.bol = bolRemovalPos;
1297:                                        }
1298:                                    }
1299:                                } else { // change after line end
1300:                                }
1301:                            } else { // pos + len <= bol -> only move
1302:                                ent.update(-len, -undoEdit.getLFCount());
1303:                            }
1304:                        }
1305:                    }
1306:                }
1307:            }
1308:
1309:            /**
1310:             * This mark renderer is used to cycle through syntax marks to update them.
1311:             * It also helps to compute the mark position in the fast way.
1312:             */
1313:            class SyntaxUpdateRenderer extends DocMarks.Renderer {
1314:
1315:                /** Document event for which the marks are updated */
1316:                ModifyUndoEdit undoEdit;
1317:
1318:                /** Whether removal instead of insert is being done */
1319:                boolean remove;
1320:
1321:                /** Slot for scanning the document */
1322:                SyntaxSeg.Slot slot;
1323:
1324:                /** Syntax for scanning the document */
1325:                Syntax syntax;
1326:
1327:                /** Get all syntax marks in a given range */
1328:                public void render() {
1329:                    int markCnt = getMarkArrayLength();
1330:                    int pos = 0;
1331:                    Mark markArray[] = getMarkArray();
1332:                    int syntaxUpdatePos = -1;
1333:                    int index;
1334:
1335:                    if (leftUpdateMark != null) {
1336:                        try {
1337:                            index = getNextIndex(getMarkIndex(leftUpdateMark));
1338:                            pos = leftUpdateMark.getOffset();
1339:                        } catch (InvalidMarkException e) {
1340:                            if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1341:                                e.printStackTrace();
1342:                            }
1343:                            index = getNextIndex(-1);
1344:                        }
1345:                    } else {
1346:                        index = getNextIndex(-1);
1347:                    }
1348:
1349:                    int endPos = pos; // ending position of the rescanning
1350:                    if (!remove) { // insert done
1351:                        endPos = undoEdit.getOffset() + undoEdit.getLength(); // inserted
1352:                        // area
1353:                        // that
1354:                        // can
1355:                        // contain
1356:                        // new
1357:                        // marks
1358:                    }
1359:
1360:                    try {
1361:                        // initially load the slot
1362:                        slot.load(doc, pos - syntax.getPreScan(), endPos - pos
1363:                                + syntax.getPreScan());
1364:
1365:                        int lastPos = pos; // position of the last syntax mark scanned
1366:                        while (index < markCnt) { // possibly till end of mark array
1367:                            Mark mark = markArray[index];
1368:                            index = getNextIndex(index);
1369:                            pos = getMarkOffset(mark);
1370:
1371:                            if (mark instanceof  MarkFactory.SyntaxMark) {
1372:                                MarkFactory.SyntaxMark syntaxMark = (MarkFactory.SyntaxMark) mark;
1373:                                int preScan = syntax.getPreScan();
1374:                                int loadPos = lastPos - preScan;
1375:                                int scanLen = pos - loadPos;
1376:
1377:                                if (!slot.isAreaInside(doc, loadPos, scanLen)) {
1378:                                    // load the whole area into syntax segment
1379:                                    int loadSize = Math.min(docLen - loadPos,
1380:                                            Math.max(scanLen,
1381:                                                    SYNTAX_UPDATE_BATCH_SIZE));
1382:                                    slot.load(doc, loadPos, loadSize);
1383:                                }
1384:
1385:                                // this load should transfer no data but will adjust
1386:                                // scanning offset
1387:                                slot.load(doc, loadPos, scanLen);
1388:
1389:                                // Relocate scanning for the good offsets
1390:                                syntax.relocate(slot.array, slot.offset
1391:                                        + preScan, scanLen - preScan,
1392:                                        (pos == docLen), pos);
1393:                                // System.out.println("DocOp.java:600 syntax renderer:
1394:                                // scan relocated to buffer='" +
1395:                                // EditorDebug.debugChars(slot.array, slot.offset +
1396:                                // preScan, scanLen - preScan) + "', slot.offset=" +
1397:                                // slot.offset + ", scanLen=" + scanLen + ", preScan=" +
1398:                                // preScan); // NOI18N
1399:
1400:                                while (syntax.nextToken() != null) {
1401:                                }
1402:
1403:                                if (syntax.compareState(syntaxMark
1404:                                        .getStateInfo()) == Syntax.EQUAL_STATE) {
1405:                                    if (syntaxUpdatePos < 0) {
1406:                                        syntaxUpdatePos = pos;
1407:                                    }
1408:                                    if (pos >= endPos && syntaxMark != eolMark) {
1409:                                        break;
1410:                                    }
1411:                                } else { // state stored in mark is different
1412:                                    syntaxUpdatePos = -1;
1413:                                    syntaxMark.updateStateInfo(syntax);
1414:                                }
1415:
1416:                                lastPos = pos;
1417:                            }
1418:                        }
1419:
1420:                        // Update syntax update position
1421:                        if (syntaxUpdatePos < 0) {
1422:                            syntaxUpdatePos = docLen;
1423:                        }
1424:
1425:                        undoEdit.setSyntaxUpdateOffset(adjustNextBOL(
1426:                                syntaxUpdatePos, true));
1427:
1428:                    } catch (BadLocationException e) {
1429:                        if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
1430:                            e.printStackTrace();
1431:                        }
1432:                    }
1433:                }
1434:            }
1435:
1436:            /**
1437:             * Cache entry for line and column information caching. Currently each entry
1438:             * caches begin and end of line and corresponding line number.
1439:             */
1440:            private static class CacheEntry {
1441:
1442:                /** Begin of line pos */
1443:                int bol = -1;
1444:
1445:                /** End of line pos */
1446:                int eol = -1;
1447:
1448:                /** Line offset */
1449:                int line = -1;
1450:
1451:                void fill(int bol, int eol, int line) {
1452:                    this .bol = bol;
1453:                    this .eol = eol;
1454:                    this .line = line;
1455:                }
1456:
1457:                void update(int deltaLen, int deltaLFCount) {
1458:                    this .bol += deltaLen;
1459:                    this .eol += deltaLen;
1460:                    this .line += deltaLFCount;
1461:                }
1462:
1463:                void invalidate() {
1464:                    bol = eol = line = -1;
1465:                }
1466:
1467:                public String toString() {
1468:                    return "line=" + line + ", bol=" + bol + ", eol=" + eol; // NOI18N
1469:                }
1470:
1471:            }
1472:
1473:            /** Dump the line cache */
1474:            public String cacheToString() {
1475:                StringBuffer sb = new StringBuffer();
1476:                for (int i = 0; i < CACHE_LEN; i++) {
1477:                    sb.append("\ncache[" + i + "]: " + lineCache[i].toString()); // NOI18N
1478:                }
1479:                return sb.toString();
1480:            }
1481:
1482:            public String toString() {
1483:                return "length()=" + length() + ", cache.getDocLength()="
1484:                        + cache.getDocLength()
1485:                        + "\nstatCacheHit="
1486:                        + statCacheHit // NOI18N
1487:                        + ", statCacheMiss="
1488:                        + statCacheMiss // NOI18N
1489:                        + ", Line cache hit ratio="
1490:                        + (Math.round(1000.0 * statCacheHit / (statCacheHit // NOI18N
1491:                                + statCacheMiss)) / 10d) + cacheToString();
1492:            }
1493:
1494:            public String markPlanesToString(Class markClasses[],
1495:                    char markChars[]) {
1496:                // !!! return marks.planesToString(markClasses, markChars);
1497:                return "";
1498:            }
1499:
1500:            public String infoToString() {
1501:                return "\n------------------------------ Statistics ------------------------------\n" // NOI18N
1502:                        + "cacheSupport: statCharsRead="
1503:                        + cacheSupport.statCharsRead // NOI18N
1504:                        + ", statCharsWritten=" + cacheSupport.statCharsWritten // NOI18N
1505:                        + "\nCache: " + cache // NOI18N
1506:                        + "\nMarks: " + marks // NOI18N
1507:                        + "\nDocOp: " + this ; // NOI18N
1508:            }
1509:
1510:            /**
1511:             * UnoableEdit created for inserts and removals. The <tt>remove</tt> flag
1512:             * determines whether it's insert or removal
1513:             */
1514:            class ModifyUndoEdit extends AbstractUndoableEdit {
1515:
1516:                /** Whether removal was done instead of insertion */
1517:                boolean remove;
1518:
1519:                /** Offset where the characters was inserted */
1520:                private int offset;
1521:
1522:                /**
1523:                 * The inserted characters. If the string was used for the insertion
1524:                 * this will be lazily initialized.
1525:                 */
1526:                private char[] chars;
1527:
1528:                /**
1529:                 * The inserted string. If the character buffer was used for the
1530:                 * insertion this will be lazily initialized.
1531:                 */
1532:                private String text;
1533:
1534:                /**
1535:                 * The number of the '\n' (line-feed) characters contained in the
1536:                 * inserted text. It's lazily initialized.
1537:                 */
1538:                private int lfCount = -1;
1539:
1540:                /** Line offset of the insert/removal */
1541:                private int line;
1542:
1543:                /** Offset of the end of the syntax updating */
1544:                private int syntaxUpdateOffset;
1545:
1546:                ModifyUndoEdit(boolean remove, int offset, char[] chars) {
1547:                    this .remove = remove;
1548:                    this .offset = offset;
1549:                    this .chars = chars;
1550:                    try {
1551:                        this .line = DocOp.this .getLine(offset);
1552:                    } catch (BadLocationException e) {
1553:                    }
1554:                }
1555:
1556:                ModifyUndoEdit(boolean remove, int offset, String text) {
1557:                    this .remove = remove;
1558:                    this .offset = offset;
1559:                    this .text = text;
1560:                    try {
1561:                        this .line = DocOp.this .getLine(offset);
1562:                    } catch (BadLocationException e) {
1563:                    }
1564:                }
1565:
1566:                boolean isInsert() {
1567:                    return !remove;
1568:                }
1569:
1570:                boolean isRemove() {
1571:                    return remove;
1572:                }
1573:
1574:                final int getOffset() {
1575:                    return offset;
1576:                }
1577:
1578:                /** Get the length of the inserted/removed text */
1579:                int getLength() {
1580:                    return (chars != null) ? chars.length : text.length();
1581:                }
1582:
1583:                /**
1584:                 * Get the inserted text. If the character buffer was used for the
1585:                 * insertion then the appropriate variable will be lazily initialized
1586:                 * first.
1587:                 */
1588:                String getText() {
1589:                    if (text == null) {
1590:                        text = new String(chars);
1591:                    }
1592:                    return text;
1593:                }
1594:
1595:                /**
1596:                 * The inserted characters. If the string was used for the insertion
1597:                 * then the appropriate variable will be lazily initialized first.
1598:                 */
1599:                char[] getChars() {
1600:                    if (chars == null) {
1601:                        chars = text.toCharArray();
1602:                    }
1603:                    return chars;
1604:                }
1605:
1606:                /**
1607:                 * Whether the text is valid instead of chars. This method helps to
1608:                 * avoid the possible conversion from chars to string.
1609:                 */
1610:                boolean isTextValid() {
1611:                    return (text != null);
1612:                }
1613:
1614:                /**
1615:                 * Get the number of the '\n' (line-feed) characters contained in the
1616:                 * inserted text. It's lazily initialized if necessary.
1617:                 */
1618:                int getLFCount() {
1619:                    if (lfCount == -1) {
1620:                        if (chars != null) { // chars valid valid
1621:                            lfCount = Analyzer.getLFCount(chars);
1622:                        } else { // string valid
1623:                            lfCount = Analyzer.getLFCount(text);
1624:                        }
1625:                    }
1626:                    return lfCount;
1627:                }
1628:
1629:                /**
1630:                 * Get the document offset of the first LF contained in the
1631:                 * inserted/removed text or -1 for no LFs. This value is not cached.
1632:                 */
1633:                int getFirstLFOffset() {
1634:                    if (getLFCount() <= 0) {
1635:                        return -1;
1636:                    }
1637:
1638:                    int flfOffset;
1639:                    if (chars != null) { // chars valid valid
1640:                        flfOffset = Analyzer.findFirstLFOffset(chars, 0,
1641:                                chars.length);
1642:                    } else { // string valid
1643:                        flfOffset = Analyzer.findFirstLFOffset(text);
1644:                    }
1645:
1646:                    if (flfOffset >= 0) {
1647:                        flfOffset += offset; // shift by the insert/update offset
1648:                    }
1649:
1650:                    return flfOffset;
1651:                }
1652:
1653:                int getLine() {
1654:                    return line;
1655:                }
1656:
1657:                int getSyntaxUpdateOffset() {
1658:                    return syntaxUpdateOffset;
1659:                }
1660:
1661:                void setSyntaxUpdateOffset(int syntaxUpdateOffset) {
1662:                    this .syntaxUpdateOffset = syntaxUpdateOffset;
1663:                }
1664:
1665:                public void undo() throws CannotUndoException {
1666:                    super .undo();
1667:                    try {
1668:                        if (remove) {
1669:                            insertEdit(this );
1670:                        } else { // insertion
1671:                            removeEdit(this );
1672:                        }
1673:                    } catch (BadLocationException bl) {
1674:                        throw new CannotUndoException();
1675:                    }
1676:                }
1677:
1678:                public void redo() throws CannotRedoException {
1679:                    super .redo();
1680:                    try {
1681:                        if (remove) {
1682:                            removeEdit(this );
1683:                        } else { // insertion
1684:                            insertEdit(this );
1685:                        }
1686:                    } catch (BadLocationException bl) {
1687:                        throw new CannotRedoException();
1688:                    }
1689:                }
1690:
1691:            }
1692:
1693:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.