KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > terminalemulator > Buffer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is Terminal Emulator.
16  * The Initial Developer of the Original Software is Sun Microsystems, Inc..
17  * Portions created by Sun Microsystems, Inc. are Copyright (C) 2001.
18  * All Rights Reserved.
19  *
20  * Contributor(s): Ivan Soleimanipour.
21  */

22
23 /*
24  * "Buffer.java"
25  * Buffer.java 1.8 01/07/30
26  */

27
28 package org.netbeans.lib.terminalemulator;
29
30 import java.util.Vector JavaDoc;
31
32 /**
33  * The Buffer used by Term is _not_ related to javax.swing.text.Document.
34  * <p>
35  * The Swing Document is Element based while terms is Line based.
36  * <br>
37  * The Swing Document uses offsets for coordinates, while term uses cartesian
38  * BCoords.
39  * <p>
40  */

41
42
43 class Buffer {
44
45     /*
46      * For some odd reason Vector.removeRange is protected, so
47      * we have to do this to gain access to it.
48      */

49     static class OurVector extends Vector JavaDoc {
50     public void removeRange(int fromIndex, int toIndex) {
51         super.removeRange(fromIndex, toIndex);
52     }
53     }
54
55     private OurVector lines = new OurVector(); // buffer
56

57     public int nlines; // number of lines in buffer
58
// How is this different from lines.length?
59

60     private int visible_cols; // number of columns visible in view
61
private int extra_cols; // columns needed to support lines longer
62
// than visible_cols. Only grows.
63

64     public int visibleCols() {
65     return visible_cols;
66     }
67
68     public int totalCols() {
69     return visible_cols + extra_cols;
70     }
71
72     public Buffer(int visible_cols) {
73     this.visible_cols = visible_cols;
74     }
75
76     public void setVisibleCols(int visible_cols) {
77     int delta = visible_cols - this.visible_cols;
78     this.visible_cols = visible_cols;
79     extra_cols -= delta;
80     if (extra_cols < 0)
81         extra_cols = 0;
82     }
83
84     /*
85      * Keep track of the largest column # to help set the extent of
86      * the horizontal scrollbar.
87      */

88     public void noteColumn(int col) {
89     int new_extra = col - visible_cols;
90     if (new_extra > extra_cols) {
91         extra_cols = new_extra;
92         // LATER hrange_listener.adjustHRange(extra_cols);
93
}
94     }
95
96     /* DEBUG
97     public static volatile boolean lock = false;
98     
99     private void ck_lock() {
100     if (lock) {
101         System.out.println("Buffer ck_lock fail"); // NOI18N
102         printStats();
103         Thread.dumpStack();
104     }
105     }
106     */

107
108     Line lineAt(int brow) {
109     try {
110         return (Line) lines.elementAt(brow);
111     } catch(ArrayIndexOutOfBoundsException JavaDoc x) {
112             //XXX swallowing this exception caused issue 40129.
113
//I've put in a null-check on the return value in sel.paint()
114
//as a hotfix. Should find out why bad values are being passed
115
//here. Ivan?
116

117         /* DEBUG
118         System.out.println("Buffer.lineAt(" +brow+ ") -> null\n");// NOI18N
119         Thread.dumpStack();
120         */

121         return null;
122     }
123     }
124
125     Line bottom() {
126     return lineAt(nlines);
127     }
128
129     public Line appendLine() {
130     // DEBUG ck_lock();
131
Line l = new Line();
132     lines.add(l);
133     nlines++;
134     return l;
135     }
136
137     public Line addLineAt(int row) {
138     // DEBUG ck_lock();
139
Line l = new Line();
140     lines.add(row, l);
141     nlines++;
142     return l;
143     }
144
145     /**
146      * Remove 'n' lines starting at 'row'.
147      * Return the number of characters deleted as a result.
148      */

149     public int removeLinesAt(int row, int n) {
150     // DEBUG ck_lock();
151
int nchars = 0;
152     for (int r = row; r < row+n; r++)
153         nchars += lineAt(r).length() + 1;
154         
155     lines.removeRange(row, row+n);
156     nlines -= n;
157
158     return nchars;
159     }
160
161     public void removeLineAt(int row) {
162     // DEBUG ck_lock();
163
lines.remove(row);
164     nlines--;
165     }
166
167     public Line moveLineFromTo(int from, int to) {
168     // DEBUG ck_lock();
169
Line l = (Line) lines.remove(from);
170     lines.add(to, l);
171     return l;
172     }
173
174     /**
175      * Visit the physical lines from 'begin', through 'end'.
176      * <p>
177      * If 'newlines' is set, the passed 'ecol' is set to the actual
178      * number of columns in the view to signify that the newline is included.
179      * This way of doing it helps with rendering of a whole-line selection.
180      * Also Line knows about this and will tack on a "\n" when Line.text()
181      * is asked for.
182      */

183     void visitLines(BCoord begin, BCoord end, boolean newlines,
184             LineVisitor visitor) {
185
186     // In the general case a range is made up of three
187
// rectangles. The partial line at top, the partial line
188
// at the bottom and the middle range of fully selected lines.
189

190     Line l;
191     if (begin.row == end.row) {
192         // range is on one line
193
l = lineAt(begin.row);
194         visitor.visit(l, begin.row, begin.col, end.col);
195
196     } else {
197         boolean cont = false;
198
199         // range spans multiple lines
200
l = lineAt(begin.row);
201         if (newlines && !l.isWrapped())
202         cont = visitor.visit(l, begin.row, begin.col, totalCols());
203         else
204         cont = visitor.visit(l, begin.row, begin.col, l.length()-1);
205         if (!cont)
206         return;
207
208         for (int r = begin.row+1; r < end.row; r++) {
209         l = lineAt(r);
210         if (newlines && !l.isWrapped())
211             cont = visitor.visit(l, r, 0, totalCols());
212         else
213             cont = visitor.visit(l, r, 0, l.length()-1);
214         if (!cont)
215             return;
216         }
217
218         l = lineAt(end.row);
219         cont = visitor.visit(l, end.row, 0, end.col);
220         if (!cont)
221         return;
222     }
223     }
224
225     /*
226      * Like visitLines() except in reverse.
227      * <p>
228      * Starts at 'end' and goes to 'begin'.
229      */

230     void reverseVisitLines(BCoord begin, BCoord end, boolean newlines,
231             LineVisitor visitor) {
232
233     // very similar to visitLines
234

235     Line l;
236     if (begin.row == end.row) {
237         // range is on one line
238
l = lineAt(begin.row);
239         visitor.visit(l, begin.row, begin.col, end.col);
240
241     } else {
242         boolean cont = false;
243
244         // range spans multiple lines
245
l = lineAt(end.row);
246         cont = visitor.visit(l, end.row, 0, end.col);
247         if (!cont)
248         return;
249
250         for (int r = end.row-1; r > begin.row; r--) {
251         l = lineAt(r);
252         if (newlines && !l.isWrapped())
253             cont = visitor.visit(l, r, 0, totalCols());
254         else
255             cont = visitor.visit(l, r, 0, l.length()-1);
256         if (!cont)
257             return;
258         }
259
260         l = lineAt(begin.row);
261         if (newlines && !l.isWrapped())
262         cont = visitor.visit(l, begin.row, begin.col, totalCols());
263         else
264         cont = visitor.visit(l, begin.row, begin.col, l.length()-1);
265         if (!cont)
266         return;
267     }
268     }
269
270     public BExtent find_word(WordDelineator word_delineator, BCoord coord) {
271     /*
272      * Find the boundaries of a "word" at 'coord'.
273      */

274
275     Line l = lineAt(coord.row);
276
277     if (coord.col >= l.length())
278         return new BExtent(coord, coord);
279
280     int lx = word_delineator.findLeft(l.stringBuffer(), coord.col);
281     int rx = word_delineator.findRight(l.stringBuffer(), coord.col);
282
283     return new BExtent(new BCoord(coord.row, lx),
284                new BCoord(coord.row, rx));
285     }
286
287     /**
288      * Back up the coordinate by one character and return new BCoord
289      * <p>
290      * Travels back over line boundaries
291      * <br>
292      * Returns null if 'c' is the first character of the buffer.
293      */

294
295     public BCoord backup(BCoord c) {
296     if (c.col > 0)
297         return new BCoord(c.row, c.col-1); // back one in line
298

299     // Cursor is at beginning of line.
300
// Need to find the end of previous line, but it might empty,
301
// so we go one line back etc
302
for (int prevrow = c.row-1; prevrow >= 0; prevrow--) {
303         Line l = lineAt(prevrow);
304         if (l.length() != 0)
305         return new BCoord(prevrow, l.length()-1);
306     }
307
308     // prevrow == -1, at beginning of file; nowhere to back to
309
return null;
310     }
311
312     /*
313      * Advance the coordinate by one character and return a new coord.
314      * <p>
315      * Wraps around line boundaries.
316      * <br>
317      * Returns null if 'c' is at the last character of the buffer.
318      */

319     public BCoord advance(BCoord c) {
320     int row = c.row;
321     int col = c.col;
322
323     col++;
324     Line l = lineAt(row);
325     if (col < l.length())
326         return new BCoord(row, col);
327
328     // Need to wrap, but the next line might be empty ... so we
329
// keep going til either we find a non-empty line or the end
330
// of the buffer.
331
while (++row < nlines) {
332         l = lineAt(row);
333         if (l.length() != 0)
334         return new BCoord(row, 0);
335     }
336     return null;
337     }
338
339     /*
340      * Print interesting statistics and facts about this Term
341      */

342     public void printStats() {
343     int nchars = 0;
344     int ncapacity = 0;
345     for (int lx = 0; lx < nlines; lx++) {
346         Line l = lineAt(lx);
347         ncapacity += l.capacity();
348         nchars += l.length();
349     }
350     System.out.println(
351         " nlines " + nlines + // NOI18N
352
" nchars " + nchars + // NOI18N
353
" ncapacity " + ncapacity ); // NOI18N
354
}
355 }
356
Popular Tags