KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > buffer > LineManager


1 /*
2  * LineManager.java - Manages line info, line start offsets, positions
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2001, 2004 Slava Pestov
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */

22
23 package org.gjt.sp.jedit.buffer;
24
25 //{{{ Imports
26
import org.gjt.sp.jedit.syntax.*;
27 import org.gjt.sp.jedit.Debug;
28 import org.gjt.sp.util.IntegerArray;
29 import org.gjt.sp.util.Log;
30 //}}}
31

32 /**
33  * A class internal to jEdit's document model. You should not use it
34  * directly. To improve performance, none of the methods in this class
35  * check for out of bounds access, nor are they thread-safe. The
36  * <code>Buffer</code> class, through which these methods must be
37  * called through, implements such protection.
38  *
39  * @author Slava Pestov
40  * @version $Id: LineManager.java 5484 2006-06-23 21:59:52Z kpouer $
41  * @since jEdit 4.2pre3
42  */

43 public class LineManager
44 {
45     //{{{ LineManager constructor
46
public LineManager()
47     {
48         endOffsets = new int[1];
49         endOffsets[0] = 1;
50         foldLevels = new short[1];
51         lineContext = new TokenMarker.LineContext[1];
52         lineCount = 1;
53     } //}}}
54

55     //{{{ getLineCount() method
56
public final int getLineCount()
57     {
58         return lineCount;
59     } //}}}
60

61     //{{{ getLineOfOffset() method
62
public int getLineOfOffset(int offset)
63     {
64         int start = 0;
65         int end = lineCount - 1;
66
67         for(;;)
68         {
69             switch(end - start)
70             {
71             case 0:
72                 if(getLineEndOffset(start) <= offset)
73                     return start + 1;
74                 else
75                     return start;
76             case 1:
77                 if(getLineEndOffset(start) <= offset)
78                 {
79                     if(getLineEndOffset(end) <= offset)
80                         return end + 1;
81                     else
82                         return end;
83                 }
84                 else
85                     return start;
86             default:
87                 int pivot = (end + start) / 2;
88                 int value = getLineEndOffset(pivot);
89                 if(value == offset)
90                     return pivot + 1;
91                 else if(value < offset)
92                     start = pivot + 1;
93                 else
94                     end = pivot - 1;
95                 break;
96             }
97         }
98     } //}}}
99

100     //{{{ getLineEndOffset() method
101
public final int getLineEndOffset(int line)
102     {
103         if(gapLine != -1 && line >= gapLine)
104             return endOffsets[line] + gapWidth;
105         else
106             return endOffsets[line];
107     } //}}}
108

109     //{{{ getFoldLevel() method
110
public final int getFoldLevel(int line)
111     {
112         return foldLevels[line];
113     } //}}}
114

115     //{{{ setFoldLevel() method
116
// Also sets 'fold level valid' flag
117
public final void setFoldLevel(int line, int level)
118     {
119         if(level > 0xffff)
120         {
121             // limitations...
122
level = 0xffff;
123         }
124
125         foldLevels[line] = (short)level;
126     } //}}}
127

128     //{{{ setFirstInvalidFoldLevel() method
129
public void setFirstInvalidFoldLevel(int firstInvalidFoldLevel)
130     {
131         this.firstInvalidFoldLevel = firstInvalidFoldLevel;
132     } //}}}
133

134     //{{{ getFirstInvalidFoldLevel() method
135
public int getFirstInvalidFoldLevel()
136     {
137         return firstInvalidFoldLevel;
138     } //}}}
139

140     //{{{ getLineContext() method
141
public final TokenMarker.LineContext getLineContext(int line)
142     {
143         return lineContext[line];
144     } //}}}
145

146     //{{{ setLineContext() method
147
public final void setLineContext(int line, TokenMarker.LineContext context)
148     {
149         lineContext[line] = context;
150     } //}}}
151

152     //{{{ setFirstInvalidLineContext() method
153
public void setFirstInvalidLineContext(int firstInvalidLineContext)
154     {
155         this.firstInvalidLineContext = firstInvalidLineContext;
156     } //}}}
157

158     //{{{ getFirstInvalidLineContext() method
159
public int getFirstInvalidLineContext()
160     {
161         return firstInvalidLineContext;
162     } //}}}
163

164     //{{{ _contentInserted() method
165
public void _contentInserted(IntegerArray endOffsets)
166     {
167         gapLine = -1;
168         gapWidth = 0;
169         firstInvalidLineContext = firstInvalidFoldLevel = 0;
170         lineCount = endOffsets.getSize();
171         this.endOffsets = endOffsets.getArray();
172         foldLevels = new short[lineCount];
173
174         lineContext = new TokenMarker.LineContext[lineCount];
175     } //}}}
176

177     //{{{ contentInserted() method
178
public void contentInserted(int startLine, int offset,
179         int numLines, int length, IntegerArray endOffsets)
180     {
181         int endLine = startLine + numLines;
182
183         //{{{ Update line info and line context arrays
184
if(numLines > 0)
185         {
186             //moveGap(-1,0,"contentInserted");
187

188             lineCount += numLines;
189
190             if(this.endOffsets.length <= lineCount)
191             {
192                 int[] endOffsetsN = new int[(lineCount + 1) * 2];
193                 System.arraycopy(this.endOffsets,0,endOffsetsN,0,
194                          this.endOffsets.length);
195                 this.endOffsets = endOffsetsN;
196             }
197
198             if(foldLevels.length <= lineCount)
199             {
200                 short[] foldLevelsN = new short[(lineCount + 1) * 2];
201                 System.arraycopy(foldLevels,0,foldLevelsN,0,
202                          foldLevels.length);
203                 foldLevels = foldLevelsN;
204             }
205
206             if(lineContext.length <= lineCount)
207             {
208                 TokenMarker.LineContext[] lineContextN
209                     = new TokenMarker.LineContext[(lineCount + 1) * 2];
210                 System.arraycopy(lineContext,0,lineContextN,0,
211                          lineContext.length);
212                 lineContext = lineContextN;
213             }
214
215             System.arraycopy(this.endOffsets,startLine,
216                 this.endOffsets,endLine,lineCount - endLine);
217             System.arraycopy(foldLevels,startLine,foldLevels,
218                 endLine,lineCount - endLine);
219             System.arraycopy(lineContext,startLine,lineContext,
220                 endLine,lineCount - endLine);
221
222             if(startLine <= gapLine)
223                 gapLine += numLines;
224             else if(gapLine != -1)
225                 offset -= gapWidth;
226
227             if(startLine < firstInvalidLineContext)
228                 firstInvalidLineContext += numLines;
229
230             for(int i = 0; i < numLines; i++)
231             {
232                 this.endOffsets[startLine + i] = (offset + endOffsets.get(i));
233                 foldLevels[startLine + i] = 0;
234             }
235         } //}}}
236

237         if(firstInvalidFoldLevel == -1 || firstInvalidFoldLevel > startLine)
238             firstInvalidFoldLevel = startLine;
239         moveGap(endLine,length,"contentInserted");
240     } //}}}
241

242     //{{{ contentRemoved() method
243
public void contentRemoved(int startLine, int offset,
244         int numLines, int length)
245     {
246         int endLine = startLine + numLines;
247
248         //{{{ Update line info and line context arrays
249
if(numLines > 0)
250         {
251             //moveGap(-1,0,"contentRemoved");
252

253             if(startLine + numLines < gapLine)
254                 gapLine -= numLines;
255             else if(startLine < gapLine)
256                 gapLine = startLine;
257
258             if(startLine + numLines < firstInvalidLineContext)
259                 firstInvalidLineContext -= numLines;
260             else if(startLine < firstInvalidLineContext)
261                 firstInvalidLineContext = startLine - 1;
262
263             lineCount -= numLines;
264
265             System.arraycopy(endOffsets,endLine,endOffsets,
266                 startLine,lineCount - startLine);
267             System.arraycopy(foldLevels,endLine,foldLevels,
268                 startLine,lineCount - startLine);
269             System.arraycopy(lineContext,endLine,lineContext,
270                 startLine,lineCount - startLine);
271         } //}}}
272

273         if(firstInvalidFoldLevel == -1 || firstInvalidFoldLevel > startLine)
274             firstInvalidFoldLevel = startLine;
275         moveGap(startLine,-length,"contentRemoved");
276     } //}}}
277

278     //{{{ Private members
279

280     //{{{ Instance variables
281
private int[] endOffsets;
282     private short[] foldLevels;
283     private TokenMarker.LineContext[] lineContext;
284
285     private int lineCount;
286
287     /**
288      * If -1, then there is no gap.
289      * Otherwise, all lines from this line onwards need to have gapWidth
290      * added to their end offsets.
291      */

292     private int gapLine;
293     private int gapWidth;
294
295     /**
296      * If -1, all contexts are valid. Otherwise, all lines after this have
297      * an invalid context.
298      */

299     private int firstInvalidLineContext;
300
301     /**
302      * If -1, all fold levels are valid. Otherwise, all lines after this
303      * have an invalid fold level.
304      */

305     private int firstInvalidFoldLevel;
306     //}}}
307

308     //{{{ setLineEndOffset() method
309
private final void setLineEndOffset(int line, int end)
310     {
311         endOffsets[line] = end;
312     } //}}}
313

314     //{{{ moveGap() method
315
private final void moveGap(int newGapLine, int newGapWidth, String JavaDoc method)
316     {
317         if(gapLine == -1)
318             gapWidth = newGapWidth;
319         else if(newGapLine == -1)
320         {
321             if(gapWidth != 0)
322             {
323                 if(Debug.OFFSET_DEBUG && gapLine != lineCount)
324                     Log.log(Log.DEBUG,this,method + ": update from " + gapLine + " to " + lineCount + " width " + gapWidth);
325                 for(int i = gapLine; i < lineCount; i++)
326                     setLineEndOffset(i,getLineEndOffset(i));
327             }
328
329             gapWidth = newGapWidth;
330         }
331         else if(newGapLine < gapLine)
332         {
333             if(gapWidth != 0)
334             {
335                 if(Debug.OFFSET_DEBUG && newGapLine != gapLine)
336                     Log.log(Log.DEBUG,this,method + ": update from " + newGapLine + " to " + gapLine + " width " + gapWidth);
337                 for(int i = newGapLine; i < gapLine; i++)
338                     setLineEndOffset(i,getLineEndOffset(i) - gapWidth);
339             }
340             gapWidth += newGapWidth;
341         }
342         else //if(newGapLine >= gapLine)
343
{
344             if(gapWidth != 0)
345             {
346                 if(Debug.OFFSET_DEBUG && gapLine != newGapLine)
347                     Log.log(Log.DEBUG,this,method + ": update from " + gapLine + " to " + newGapLine + " width " + gapWidth);
348                 for(int i = gapLine; i < newGapLine; i++)
349                     setLineEndOffset(i,getLineEndOffset(i));
350             }
351
352             gapWidth += newGapWidth;
353         }
354
355         if(newGapLine == lineCount)
356             gapLine = -1;
357         else
358             gapLine = newGapLine;
359     } //}}}
360

361     //}}}
362
}
363
Popular Tags