Source Code Cross Referenced for DocMarks.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) 


001:        /*
002:         *                 Sun Public License Notice
003:         * 
004:         * The contents of this file are subject to the Sun Public License
005:         * Version 1.0 (the "License"). You may not use this file except in
006:         * compliance with the License. A copy of the License is available at
007:         * http://www.sun.com/
008:         * 
009:         * The Original Code is NetBeans. The Initial Developer of the Original
010:         * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
011:         * Microsystems, Inc. All Rights Reserved.
012:         */
013:
014:        package org.netbeans.editor;
015:
016:        import java.util.Map;
017:
018:        /**
019:         * Document marks enable to store position and line information to simplify
020:         * orientation in the document. They are stored in the array with a gap similar
021:         * like in {@link javax.swing.text.GapContent}.
022:         * 
023:         * @author Miloslav Metelka
024:         * @version 1.00
025:         */
026:
027:        final class DocMarks {
028:
029:            /** Empty array of marks used initially as marks array. */
030:            private static final Mark[] EMPTY = new Mark[0];
031:
032:            /** Marks array with the gap. */
033:            private Mark[] marks;
034:
035:            /** Length of the marks array minus one. */
036:            private int marksLengthM1;
037:
038:            /** Starting index of the gap. */
039:            private int gapStart;
040:
041:            /** End of the gap (first index after the end of the gap). */
042:            private int gapEnd;
043:
044:            /** Starting offset of the fictional document's data gap. */
045:            private int dataGapStart;
046:
047:            /** Ending offset of the fictional document's data gap. */
048:            private int dataGapEnd;
049:
050:            /**
051:             * Number of line separators corresponding to the fictional document's data
052:             * gap.
053:             */
054:            private int dataGapLineCount;
055:
056:            /**
057:             * Number of marks that are still in the marks array but that have the valid
058:             * flag set to false.
059:             */
060:            int unusedMarksCount;
061:
062:            Mark startMark; // for compatibility
063:
064:            DocMarks() {
065:                marks = EMPTY;
066:                marksLengthM1 = -1;
067:                dataGapEnd = Integer.MAX_VALUE / 2;
068:                dataGapLineCount = Integer.MAX_VALUE / 2;
069:
070:                startMark = new Mark(true);
071:                insert(startMark);
072:            }
073:
074:            synchronized int getMarksCount() {
075:                return marks.length - (gapEnd - gapStart);
076:            }
077:
078:            /**
079:             * Insert mark.
080:             * 
081:             * @param mark
082:             *            mark to insert. The mark must have the valid offset and the
083:             *            line filled in.
084:             */
085:            synchronized void insert(Mark mark) {
086:                int offset = mark.offset;
087:                boolean backwardBias = mark.backwardBias;
088:
089:                int ind = findInsertIndex(offset, backwardBias);
090:
091:                if (gapStart == gapEnd) {
092:                    increaseAndMoveGap(1, ind);
093:                    ind = gapStart;
094:
095:                } else if (ind != gapStart) {
096:                    moveGap(ind);
097:                    ind = gapStart;
098:                }
099:
100:                if (offset > dataGapStart
101:                        || (offset == dataGapStart && !backwardBias)) {
102:                    mark.offset += dataGapEnd - dataGapStart;
103:                    mark.line += dataGapLineCount;
104:                }
105:
106:                marks[gapStart++] = mark;
107:                mark.valid = true;
108:            }
109:
110:            synchronized void dispose(Mark mark) {
111:                mark.valid = false;
112:                unusedMarksCount++;
113:
114:                if (unusedMarksCount > Math.max(5, marks.length
115:                        - (gapEnd - gapStart))) { // GC
116:                    // rule
117:                    removeDisposedMarks();
118:                }
119:            }
120:
121:            synchronized void remove(Mark mark) {
122:                int ind = findIndex(mark);
123:                if (ind < 0) {
124:                    throw new IllegalStateException("Invalid mark " + mark);
125:                }
126:
127:                if (ind == gapEnd) {
128:                    marks[gapEnd++] = null; // enable GC
129:
130:                } else if (ind == gapStart - 1) {
131:                    marks[--gapStart] = null; // enable GC
132:
133:                } else { // need to move the gap
134:                    moveGap(ind + 1);
135:                    marks[--gapStart] = null; // enable GC
136:                }
137:
138:                mark.valid = false;
139:            }
140:
141:            private void moveGap(int ind) {
142:                if (ind <= gapStart) { // move gap down
143:                    int moveSize = gapStart - ind;
144:                    gapEnd -= moveSize;
145:                    System.arraycopy(marks, ind, marks, gapEnd, moveSize);
146:                    gapStart = ind;
147:
148:                } else { // above gap
149:                    int moveSize = ind - gapEnd;
150:                    System.arraycopy(marks, gapEnd, marks, gapStart, moveSize);
151:                    gapStart += moveSize;
152:                    gapEnd += moveSize;
153:                }
154:            }
155:
156:            /**
157:             * Increase the size of the gap.
158:             * 
159:             * @param reqSize
160:             *            the additional size requested. Typically equals to 1.
161:             * @param ind
162:             *            index to which the gap is moved.
163:             * @return relocated index in the new marks array that corresponds to the
164:             *         original index.
165:             */
166:            private void increaseAndMoveGap(int reqSize, int ind) {
167:                int newSize = marks.length * 3 / 2 + reqSize;
168:                Mark[] newMarks = new Mark[newSize];
169:                marksLengthM1 = newSize - 1;
170:                if (ind <= gapStart) {
171:                    int moveSize = marks.length - gapEnd;
172:                    if (moveSize > 0) {
173:                        newSize -= moveSize;
174:                        System.arraycopy(marks, gapEnd, newMarks, newSize,
175:                                moveSize);
176:                    }
177:                    moveSize = gapStart - ind;
178:                    if (moveSize > 0) {
179:                        newSize -= moveSize;
180:                        System.arraycopy(marks, ind, newMarks, newSize,
181:                                moveSize);
182:                    }
183:                    if (ind > 0) {
184:                        System.arraycopy(marks, 0, newMarks, 0, ind);
185:                    }
186:                    gapStart = ind;
187:                    gapEnd = newSize;
188:
189:                } else { // ind above gap
190:                    if (gapStart > 0) {
191:                        System.arraycopy(marks, 0, newMarks, 0, gapStart);
192:                    }
193:                    int moveSize = ind - gapEnd;
194:                    if (moveSize > 0) {
195:                        System.arraycopy(marks, gapEnd, newMarks, gapStart,
196:                                moveSize);
197:                        gapStart += moveSize;
198:                    }
199:                    moveSize = marks.length - ind;
200:                    if (moveSize > 0) {
201:                        newSize -= moveSize;
202:                        System.arraycopy(marks, ind, newMarks, newSize,
203:                                moveSize);
204:                    }
205:                    gapEnd = newSize;
206:                    ind += newMarks.length - marks.length;
207:                }
208:                marks = newMarks;
209:            }
210:
211:            /**
212:             * Document was modified. This means that the ficitonal data gap must be
213:             * updated by the modifiaction. The data gap can possibly be moved and the
214:             * marks in the moved area must be updated accordingly.
215:             * 
216:             * @param offset
217:             *            offset of the modification
218:             * @param line
219:             *            line of modification. It is populated for removals only.
220:             * @param length
221:             *            length of added/removed data. If the length is positive then
222:             *            the insert occured. If the length is negative then the removal
223:             *            has occured.
224:             * @param lineCount
225:             *            number of line separators in the added/removed part. It is
226:             *            &lt;0 for removals.
227:             */
228:            synchronized void update(int offset, int line, int length,
229:                    int lineCount) {
230:
231:                if (length < 0) { // removal occured
232:                    offset -= length; // move offset after end of removal (length < 0)
233:                }
234:
235:                // First move the gap if necessary
236:                int dataGapSize = dataGapEnd - dataGapStart;
237:                int ind; // index of the first mark with offset over the data gap
238:                if (dataGapStart < offset) { // current data gap below offset
239:                    ind = findInsertIndex(dataGapStart, true);
240:
241:                    int offsetAfterGap = offset + dataGapSize;
242:                    int bound = (ind <= gapStart) ? (gapStart - 1)
243:                            : marksLengthM1;
244:                    while (true) {
245:                        while (ind <= bound) {
246:                            Mark mark = marks[ind];
247:                            if (mark.offset > offsetAfterGap
248:                                    || (mark.offset == offsetAfterGap && !mark.backwardBias)) {
249:                                bound = marksLengthM1; // break to shifting of data gap
250:                                break;
251:                            }
252:
253:                            // Move mark before future data gap
254:                            mark.offset -= dataGapSize;
255:                            mark.line -= dataGapLineCount;
256:
257:                            ind++;
258:                        }
259:
260:                        if (bound < marksLengthM1) { // shift the bound
261:                            bound = marksLengthM1;
262:                            ind = gapEnd;
263:
264:                        } else { // update gap bounds and break the infinite loop
265:                            break;
266:                        }
267:                    }
268:
269:                    dataGapEnd += (offset - dataGapStart);
270:                    dataGapStart = offset;
271:
272:                } else if (dataGapStart > offset) { // current data gap over offset
273:                    ind = findInsertIndex(dataGapStart, true);
274:
275:                    // Update marks possibly in two passes - above and below gap
276:                    int bound = (ind >= gapEnd) ? gapEnd : 0; // boundary for the
277:                    // first pass
278:                    while (true) { // possibly two passes (above and under gap)
279:                        while (ind > bound) {
280:                            Mark mark = marks[--ind];
281:                            if (mark.offset < offset
282:                                    || (mark.offset == offset && mark.backwardBias)) {
283:                                bound = 0; // break to shifting of data gap
284:                                ind++;
285:                                break;
286:                            }
287:
288:                            // Move mark after future data gap
289:                            mark.offset += dataGapSize;
290:                            mark.line += dataGapLineCount;
291:                        }
292:
293:                        if (bound > 0 && gapStart > 0) {
294:                            ind = gapStart;
295:                            bound = 0;
296:
297:                        } else { // bound == 0
298:                            break;
299:                        }
300:                    }
301:
302:                    dataGapEnd -= dataGapStart - offset;
303:                    dataGapStart = offset;
304:
305:                } else { // no move of the gap
306:                    ind = (length < 0) ? findInsertIndex(offset, true) : 0; // index no
307:                    // important
308:                    // for
309:                    // inserts
310:                }
311:
312:                dataGapStart += length; // shrink the gap
313:                // possibly decrease number of lines represented by gap
314:                dataGapLineCount -= lineCount;
315:
316:                if (length < 0) { // remove performed
317:                    /*
318:                     * Marks with backward bias within the whole removed area will be
319:                     * moved to the offset (before data gap). It is necessary that all
320:                     * the backwardBias marks within the removed area must be placed
321:                     * before all the forwardBias marks within the removed area. The
322:                     * marks with the forward bias are placed after data gap.
323:                     */
324:                    int lastBBMInd = -1; // index of last backward bias mark
325:                    int bound = (ind >= gapEnd) ? gapEnd : 0; // boundary for the
326:                    // first pass
327:                    offset += length; // offset back to original value
328:                    int offsetAfterGap = offset + (dataGapEnd - dataGapStart); // use
329:                    // current
330:                    // (updated)
331:                    // gap
332:                    // size
333:                    int lineAfterGap = line + dataGapLineCount;
334:
335:                    while (true) { // possibly two passes (above and under gap)
336:                        while (ind > bound) {
337:                            Mark mark = marks[--ind];
338:                            if (mark.offset < offset
339:                                    || (mark.offset == offset && mark.backwardBias)) {
340:                                bound = 0; // break to shifting of data gap
341:                                break;
342:                            }
343:
344:                            // service the potential move because of the biases ordering
345:                            if (mark.backwardBias) {
346:                                // Move mark before data gap
347:                                mark.offset = offset;
348:                                mark.line = line;
349:
350:                                if (lastBBMInd < 0) {
351:                                    lastBBMInd = ind;
352:                                }
353:
354:                            } else { // forward bias
355:                                // Move mark after data gap
356:                                mark.offset = offsetAfterGap;
357:                                mark.line = lineAfterGap;
358:
359:                                if (lastBBMInd >= 0) { // backward bias mark(s) exist
360:                                    // exchange this fb mark with last bb mark
361:                                    marks[ind] = marks[lastBBMInd];
362:                                    marks[lastBBMInd] = mark;
363:                                    if (lastBBMInd == gapEnd) {
364:                                        lastBBMInd = gapStart;
365:                                    }
366:                                    lastBBMInd--;
367:                                }
368:                            }
369:                        }
370:
371:                        if (bound > 0 && gapStart > 0) {
372:                            ind = gapStart;
373:                            bound = 0;
374:
375:                        } else { // bound == 0
376:                            break;
377:                        }
378:                    }
379:
380:                }
381:            }
382:
383:            private void removeDisposedMarks() {
384:                int ind = 0;
385:                int validInd = 0;
386:
387:                while (ind < gapStart) {
388:                    Mark mark = marks[ind];
389:                    if (!mark.valid) {
390:                        mark.removeDisposed();
391:
392:                    } else {
393:                        if (ind != validInd) {
394:                            marks[validInd++] = mark;
395:                        }
396:                    }
397:                    ind++;
398:                }
399:                gapStart = validInd;
400:
401:                ind = marksLengthM1;
402:                validInd = ind + 1;
403:                while (ind >= gapEnd) {
404:                    Mark mark = marks[ind];
405:                    if (!mark.valid) {
406:                        mark.removeDisposed();
407:
408:                    } else {
409:                        if (ind != --validInd) {
410:                            marks[validInd] = mark;
411:                        }
412:                    }
413:                    ind--;
414:                }
415:                gapEnd = validInd;
416:            }
417:
418:            synchronized int getOffset(Mark mark) {
419:                int offset = mark.offset;
420:                // offset == dataGapStart for backward bias marks
421:                // forward bias marks == dataGapEnd instead
422:                return (offset <= dataGapStart) ? offset
423:                        : (offset - (dataGapEnd - dataGapStart));
424:            }
425:
426:            synchronized int getLine(Mark mark) {
427:                // offset == dataGapStart for backward bias marks
428:                // forward bias marks == dataGapEnd instead
429:                return (mark.offset <= dataGapStart) ? mark.line
430:                        : (mark.line - dataGapLineCount);
431:            }
432:
433:            /**
434:             * Find the index of the given mark.
435:             * 
436:             * @param mark
437:             *            for which the index is being searched.
438:             * @return index &gt;=0 or &lt;0 if the mark was not found.
439:             */
440:            int findIndex(Mark mark) {
441:                int offset = getOffset(mark);
442:                int ind = findInsertIndex(offset, mark.backwardBias);
443:                int bound = (ind >= gapEnd) ? gapEnd : 0; // boundary for the first
444:                // pass
445:                while (true) { // possibly two passes (above and under gap)
446:                    while (ind > bound) {
447:                        if (marks[--ind] == mark) {
448:                            return ind;
449:                        }
450:                    }
451:
452:                    if (bound > 0 && gapStart > 0) {
453:                        ind = gapStart;
454:                        bound = 0;
455:
456:                    } else { // bound == 0
457:                        break;
458:                    }
459:                }
460:                return -1; // not found
461:            }
462:
463:            /**
464:             * Find the index at which it's valid to perform an insert of the new mark.
465:             * 
466:             * @param offset
467:             *            offset of the mark
468:             * @param backwardBias
469:             *            whether the mark has backward or forward bias.
470:             * @return index &gt;= 0 and &lt;=<CODE>marks.length</CODE> in the marks
471:             *         array where the insert of the mark with the given offset and bias
472:             *         can be done.<BR>
473:             *         If there is more marks with the same offset and bias as the
474:             *         requested ones then the index after these marks is returned. The
475:             *         gapStart is preferred by the method over the gapEnd
476:             *         automatically.
477:             */
478:            int findInsertIndex(int offset, boolean backwardBias) {
479:                if (!backwardBias) { // search one offset higher for forward bias
480:                    offset++;
481:                }
482:
483:                boolean belowGap = (gapStart > 0 && getOffset(marks[gapStart - 1]) >= offset);
484:
485:                // Find the index by using binary search
486:                int low;
487:                int high;
488:
489:                if (belowGap) {
490:                    low = 0;
491:                    high = gapStart - 1;
492:
493:                } else { // over gap
494:                    low = gapEnd;
495:                    high = marksLengthM1;
496:                }
497:
498:                while (low <= high) {
499:                    int ind = (low + high) / 2; // mid in the binary search
500:                    Mark mark = marks[ind];
501:                    int markOffset = getOffset(mark);
502:
503:                    if (markOffset < offset) {
504:                        low = ind + 1;
505:
506:                    } else if (markOffset > offset) {
507:                        high = ind - 1;
508:
509:                    } else { // exact offset found
510:                        if (!backwardBias) { // forward bias required
511:                            /*
512:                             * Searched for offset increased by one so go to begining of
513:                             * all marks with (offset + 1)
514:                             */
515:                            int bound = belowGap ? 0 : gapEnd;
516:                            while (true) {
517:                                while (--ind >= bound) {
518:                                    mark = marks[ind];
519:                                    if (getOffset(mark) < offset) {
520:                                        bound = 0;
521:                                        break;
522:                                    }
523:                                }
524:
525:                                if (bound > 0) {
526:                                    bound = 0;
527:                                    ind = gapStart;
528:
529:                                } else {
530:                                    break;
531:                                }
532:                            }
533:                            ind++;
534:
535:                        } else { // backward bias required
536:                            if (!mark.backwardBias) { // mark from bin-search has fwd
537:                                // bias
538:                                /*
539:                                 * Find (backward) the first mark with lower offset or
540:                                 * same offset but backward bias and go one index back.
541:                                 */
542:                                int bound = belowGap ? 0 : gapEnd;
543:                                while (true) {
544:                                    while (--ind >= bound) {
545:                                        mark = marks[ind];
546:                                        if (getOffset(mark) < offset
547:                                                || mark.backwardBias) {
548:                                            bound = 0;
549:                                            break;
550:                                        }
551:                                    }
552:
553:                                    if (bound > 0) {
554:                                        bound = 0;
555:                                        ind = gapStart;
556:
557:                                    } else {
558:                                        break;
559:                                    }
560:                                }
561:                                ind++;
562:
563:                            } else { // the mark from bin-search has bwd bias
564:                                /*
565:                                 * Goto the end of the marks with the same offset and
566:                                 * backward bias by finding the first mark with the same
567:                                 * offset but forward bias or mark with greater offset.
568:                                 */
569:                                int bound = belowGap ? (gapStart - 1)
570:                                        : marksLengthM1;
571:                                while (true) {
572:                                    while (++ind <= bound) {
573:                                        mark = marks[ind];
574:                                        if (getOffset(mark) > offset
575:                                                || !mark.backwardBias) {
576:                                            bound = Integer.MAX_VALUE;
577:                                            break;
578:                                        }
579:                                    }
580:
581:                                    if (bound < marksLengthM1) {
582:                                        bound = marksLengthM1;
583:                                        ind = gapEnd - 1;
584:
585:                                    } else {
586:                                        break;
587:                                    }
588:                                }
589:                            }
590:                        }
591:
592:                        if (ind == gapEnd) {
593:                            ind = gapStart; // prefer gapStart over gapEnd
594:                        }
595:                        return ind;
596:                    }
597:                }
598:
599:                // not exact offset found
600:                if (!belowGap && low == gapEnd) {
601:                    low = gapStart; // prefer gapStart over gapEnd
602:                }
603:
604:                return low;
605:            }
606:
607:            /**
608:             * Get the mark with offset lower than the parameter.
609:             * 
610:             * @param offset
611:             *            requested offset
612:             * @param markClass
613:             *            class of the mark to be found. It can be null to accept any
614:             *            mark.
615:             */
616:            synchronized Mark getLeftMark(int offset, Class markClass) {
617:                Mark ret = null;
618:                ;
619:                boolean done = false; // to have just one ret stmt
620:
621:                if (offset > 0) {
622:                    int ind = findInsertIndex(offset - 1, false);
623:                    if (ind > marksLengthM1) {
624:                        if (gapEnd <= marksLengthM1) {
625:                            ind--;
626:                        } else {
627:                            ind = gapStart;
628:                        }
629:                    }
630:
631:                    if (ind == gapStart) {
632:                        if (gapStart > 0) {
633:                            ind--;
634:                        } else {
635:                            ret = (markClass == null) ? startMark : null;
636:                            done = true;
637:                        }
638:
639:                    } else { // valid index
640:                        if (ind == gapEnd) {
641:                            ind = gapStart;
642:                        }
643:                        ind--; // move to startable index
644:                        if (ind < 0) {
645:                            ret = (markClass == null) ? startMark : null;
646:                            done = true;
647:                        }
648:                    }
649:
650:                    if (!done) {
651:                        int bound = (ind <= gapStart) ? 0 : gapEnd;
652:                        while (true) {
653:                            while (ind >= bound) {
654:                                Mark mark = marks[ind--];
655:                                if (markClass == null
656:                                        || markClass.isInstance(mark)) {
657:                                    ret = mark;
658:                                    done = true;
659:                                    bound = 0;
660:                                    break;
661:                                }
662:                            }
663:
664:                            if (bound > 0) {
665:                                bound = 0;
666:                                ind = gapStart - 1;
667:
668:                            } else {
669:                                break;
670:                            }
671:                        }
672:                    }
673:                }
674:
675:                if (!done) {
676:                    ret = (markClass == null) ? startMark : null;
677:                }
678:
679:                // System.err.println("getLeftMark() offset=" + offset + ", markClass="
680:                // + markClass + ", found mark=" + ret);
681:                // if (ret != null) {
682:                // System.err.println(" markOffset=" + getOffset(ret) + ", line=" +
683:                // getLine(ret));
684:                // }
685:                if (ret != null && !ret.valid) {
686:                    throw new IllegalStateException("Invalid mark");
687:                }
688:                return ret;
689:            }
690:
691:            /**
692:             * Get mark that is right at given offset or null.
693:             * 
694:             * @param offset
695:             *            offset where the mark should be found.
696:             * @param markClass
697:             *            class of the mark to be found. It can be null to accept any
698:             *            mark.
699:             */
700:            synchronized Mark getOffsetMark(int offset, Class markClass) {
701:                int ind = findInsertIndex(offset, false);
702:
703:                int bound = (ind <= gapStart) ? 0 : gapEnd;
704:                while (true) {
705:                    while (--ind >= bound) {
706:                        Mark mark = marks[ind];
707:                        if (getOffset(mark) != offset) {
708:                            return null;
709:                        }
710:                        if (markClass == null || markClass.isInstance(mark)) {
711:                            return mark;
712:                        }
713:                    }
714:
715:                    if (bound > 0) {
716:                        bound = 0;
717:                        ind = gapStart;
718:
719:                    } else {
720:                        break;
721:                    }
722:                }
723:
724:                return null;
725:            }
726:
727:            /**
728:             * Render marks by some <CODE>Renderer</CODE>. It is the most efficient
729:             * way to handle especially multiple adjacent marks. Rendering function is
730:             * called in synchronized manner, so no one will modify mark array while
731:             * executing this function.
732:             */
733:            public synchronized void render(Renderer r) {
734:                r.marks = this ;
735:                r.render();
736:                r.marks = null;
737:            }
738:
739:            /**
740:             * Gets the nearest lower position for specified line. This method can be
741:             * used when the only line information is available and the position is
742:             * needed (i.e. setting breakpoints, going to line with error etc).
743:             * 
744:             * @param line
745:             *            line offset for which we want mark
746:             * @return mark with lower or equal line. Caution! When the caller gets the
747:             *         mark and it usually tries to get position of returned mark.
748:             *         However the mark can be removed meantime and call <CODE>getOffset()</CODE>
749:             *         will throw <CODE>InvalidMarkException</CODE>. In that case
750:             *         caller should call <CODE>getMarkFromLine()</CODE> again to get
751:             *         another mark and retry.
752:             */
753:            synchronized Mark getMarkFromLine(int line) {
754:                boolean aboveGap = (gapEnd <= marksLengthM1 && getLine(marks[gapEnd]) <= line);
755:
756:                // Find the index by using binary search
757:                int low;
758:                int high;
759:
760:                if (!aboveGap) {
761:                    low = 0;
762:                    high = gapStart - 1;
763:
764:                } else { // over gap
765:                    low = gapEnd;
766:                    high = marksLengthM1;
767:                }
768:
769:                while (low <= high) {
770:                    int ind = (low + high) / 2; // mid in the binary search
771:                    Mark mark = marks[ind];
772:                    int markLine = getLine(mark);
773:
774:                    if (markLine < line) {
775:                        low = ind + 1;
776:
777:                    } else if (markLine > line) {
778:                        high = ind - 1;
779:
780:                    } else { // exact line found
781:                        return mark;
782:                    }
783:                }
784:
785:                // mark with exact line not found
786:                return (high >= 0) ? marks[high] : startMark;
787:            }
788:
789:            /**
790:             * More efficient way of handling marks especially if there is a need to
791:             * work with more than one mark at the moment.
792:             */
793:            static abstract class Renderer {
794:
795:                DocMarks marks;
796:
797:                Renderer() {
798:                }
799:
800:                DocMarks getMarks() {
801:                    return marks;
802:                }
803:
804:                /** Create array of all marks */
805:                Mark[] copyAllMarks() {
806:                    Mark[] ret = new Mark[marks.getMarksCount()];
807:                    System.arraycopy(marks.marks, 0, ret, 0, marks.gapStart);
808:                    System.arraycopy(marks.marks, marks.gapEnd, ret,
809:                            marks.gapStart, marks.marks.length - marks.gapEnd);
810:                    return ret;
811:                }
812:
813:                Mark[] getMarkArray() {
814:                    return marks.marks;
815:                }
816:
817:                int getMarkArrayLength() {
818:                    return marks.marks.length;
819:                }
820:
821:                int getMarkIndex(Mark mark) {
822:                    if (!mark.valid) {
823:                        throw new IllegalStateException();
824:                    }
825:                    return marks.findIndex(mark);
826:                }
827:
828:                int getMarkOffset(Mark mark) {
829:                    if (!mark.valid) {
830:                        throw new IllegalStateException();
831:                    }
832:                    return marks.getOffset(mark);
833:                }
834:
835:                int getNextIndex(int index) {
836:                    if (++index == marks.gapStart) {
837:                        index = marks.gapEnd;
838:                    }
839:                    return index;
840:                }
841:
842:                abstract void render();
843:
844:            }
845:
846:            /**
847:             * Check whether the marks offsets and lines are sorted correctly.
848:             */
849:            void check() {
850:                int ind = 0;
851:                int bound = gapStart - 1;
852:                int lastOffset = 0;
853:                int lastLine = 0;
854:                boolean lastBackwardBias = true;
855:
856:                while (true) {
857:                    while (ind <= bound) {
858:                        Mark mark = marks[ind++];
859:
860:                        if (mark.offset < lastOffset
861:                                || (mark.offset == lastOffset && (mark.backwardBias && !lastBackwardBias))) {
862:                            consistencyError(true, ind - 1); // offset error
863:                        }
864:
865:                        if (mark.line < lastLine) {
866:                            consistencyError(false, ind - 1);
867:                        }
868:
869:                        lastOffset = mark.offset;
870:                        lastLine = mark.line;
871:                        lastBackwardBias = mark.backwardBias;
872:
873:                    }
874:
875:                    if (bound < marksLengthM1) { // shift the bound
876:                        bound = marksLengthM1;
877:                        ind = gapEnd;
878:
879:                    } else { // update gap bounds and break the infinite loop
880:                        break;
881:                    }
882:                }
883:            }
884:
885:            private void consistencyError(boolean offsetError, int ind) {
886:                throw new IllegalStateException("DocMarks.check(): "
887:                        + (offsetError ? "Offset" : "Line")
888:                        + " inconsistency found at ind=" + ind + ", mark="
889:                        + marks[ind]);
890:            }
891:
892:            /** List all the marks into string. */
893:            public String toStringDetail() {
894:                return toStringDetail(null);
895:            }
896:
897:            String toStringDetail(Map testMarksMap) {
898:                StringBuffer sb = new StringBuffer(toString());
899:                sb.append('\n');
900:
901:                boolean beforeGap = true;
902:                while (true) {
903:                    int i = beforeGap ? 0 : gapEnd;
904:                    int bound = beforeGap ? gapStart : marks.length;
905:                    sb.append("Marks ");
906:                    sb.append(beforeGap ? "before" : "after");
907:                    sb.append(" gap:\n");
908:
909:                    while (i < bound) {
910:                        Mark mark = marks[i];
911:                        Mark testMark = null;
912:                        if (testMarksMap != null) {
913:                            testMark = (Mark) testMarksMap.get(mark);
914:                            if (testMark == null) {
915:                                throw new IllegalStateException(
916:                                        "No test mark for mark=" + mark);
917:                            }
918:                        }
919:
920:                        try {
921:                            sb.append("[");
922:                            sb.append(i);
923:                            sb.append("]: (");
924:                            sb.append(mark.offset);
925:                            sb.append(", ");
926:                            sb.append(mark.line);
927:                            sb.append(", ");
928:                            sb.append(mark.backwardBias ? 'B' : 'F');
929:                            sb.append(") -> (");
930:                            sb.append(mark.getOffset());
931:                            sb.append(", ");
932:                            sb.append(mark.getLine());
933:                            sb.append(')');
934:
935:                            if (testMark != null) {
936:                                sb.append(" testMark: (");
937:                                sb.append(testMark.offset);
938:                                sb.append(", ");
939:                                sb.append(testMark.line);
940:                                sb.append(", ");
941:                                sb.append(testMark.backwardBias ? 'B' : 'F');
942:                                sb.append(')');
943:                            }
944:
945:                            sb.append('\n');
946:
947:                        } catch (InvalidMarkException e) {
948:                            e.printStackTrace();
949:                            throw new IllegalStateException();
950:                        }
951:
952:                        i++;
953:                    }
954:
955:                    beforeGap = !beforeGap;
956:                    if (beforeGap) {
957:                        break;
958:                    }
959:                }
960:                return sb.toString();
961:            }
962:
963:            /** Get info about <CODE>DocMarks</CODE>. */
964:            public String toString() {
965:                return "marksCount=" + getMarksCount() + ", gapStart="
966:                        + gapStart + ", gapEnd=" + gapEnd + ", dataLen="
967:                        + (Integer.MAX_VALUE - (dataGapEnd - dataGapStart))
968:                        + ", dataGapStart=" + dataGapStart + ", dataGapEnd="
969:                        + dataGapEnd + ", dataGapLineCount=" + dataGapLineCount;
970:            }
971:
972:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.