PageRenderTime 65ms CodeModel.GetById 46ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/textarea/RangeMap.java

#
Java | 486 lines | 350 code | 42 blank | 94 comment | 102 complexity | 4f305aa5ecd706ee7f932eb263a1dfe9 MD5 | raw file
  1/*
  2 * RangeMap.java
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001, 2005 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
 23package org.gjt.sp.jedit.textarea;
 24
 25import org.gjt.sp.jedit.Debug;
 26import org.gjt.sp.util.Log;
 27
 28/**
 29 * The fold visibility map.
 30 *
 31 * All lines from fvm[2*n] to fvm[2*n+1]-1 inclusive are visible.
 32 * All lines from position fvm[2*n+1] to fvm[2*n+2]-1 inclusive are
 33 * invisible.
 34 *
 35 * Examples:
 36 * ---------
 37 * All lines visible: { 0, buffer.getLineCount() }
 38 * Narrow from a to b: { a, b + 1 }
 39 * Collapsed fold from a to b: { 0, a + 1, b, buffer.getLineCount() }
 40 *
 41 * Note: length is always even.
 42 */
 43class RangeMap
 44{
 45	//{{{ RangeMap constructor
 46	RangeMap()
 47	{
 48		fvm = new int[2];
 49		lastfvmget = -1;
 50	} //}}}
 51
 52	//{{{ RangeMap constructor
 53	RangeMap(RangeMap copy)
 54	{
 55		this.fvm = copy.fvm.clone();
 56		this.fvmcount = copy.fvmcount;
 57	} //}}}
 58
 59	//{{{ reset() method
 60	void reset(int lines)
 61	{
 62		lastfvmget = -1;
 63		fvmcount = 2;
 64		fvm[0] = 0;
 65		fvm[1] = lines;
 66	} //}}}
 67
 68	//{{{ first() method
 69	int first()
 70	{
 71		return fvm[0];
 72	} //}}}
 73
 74	//{{{ last() method
 75	int last()
 76	{
 77		return fvm[fvmcount - 1] - 1;
 78	} //}}}
 79
 80	//{{{ lookup() method
 81	int lookup(int index)
 82	{
 83		return fvm[index];
 84	} //}}}
 85
 86	//{{{ search() method
 87	/**
 88	 * Returns the fold visibility map index for the given line.
 89	 */
 90	int search(int line)
 91	{
 92		if(line < fvm[0])
 93			return -1;
 94		if(line >= fvm[fvmcount - 1])
 95			return fvmcount - 1;
 96
 97		if(lastfvmget != -1)
 98		{
 99			if(line >= fvm[lastfvmget])
100			{
101				if(lastfvmget == fvmcount - 1
102					|| line < fvm[lastfvmget + 1])
103				{
104					return lastfvmget;
105				}
106			}
107		}
108
109		int start = 0;
110		int end = fvmcount - 1;
111
112loop:		for(;;)
113		{
114			switch(end - start)
115			{
116			case 0:
117				lastfvmget = start;
118				break loop;
119			case 1:
120				int value = fvm[end];
121				if(value <= line)
122					lastfvmget = end;
123				else
124					lastfvmget = start;
125				break loop;
126			default:
127				int pivot = (end + start) / 2;
128				value = fvm[pivot];
129				if(value == line)
130				{
131					lastfvmget = pivot;
132					break loop;
133				}
134				else if(value < line)
135					start = pivot;
136				else
137					end = pivot - 1;
138				break;
139			}
140		}
141
142		return lastfvmget;
143	} //}}}
144
145	//{{{ put() method
146	/**
147	 * Replaces from <code>start</code> to <code>end-1</code> inclusive with
148	 * <code>put</code>. Update <code>fvmcount</code>.
149	 */
150	void put(int start, int end, int[] put)
151	{
152		if(Debug.FOLD_VIS_DEBUG)
153		{
154			StringBuilder buf = new StringBuilder(50);
155			buf.append("fvmput(").append(start).append(',');
156			buf.append(end).append(',');
157			buf.append('{');
158			if(put != null)
159			{
160				for(int i = 0; i < put.length; i++)
161				{
162					if(i != 0)
163						buf.append(',');
164					buf.append(put[i]);
165				}
166			}
167			buf.append("})");
168			Log.log(Log.DEBUG,this,buf.toString());
169		}
170		int putl = put == null ? 0 : put.length;
171
172		int delta = putl - (end - start);
173		if(fvmcount + delta > fvm.length)
174		{
175			int[] newfvm = new int[(fvm.length << 1) + 1];
176			System.arraycopy(fvm,0,newfvm,0,fvmcount);
177			fvm = newfvm;
178		}
179
180		if(delta != 0)
181		{
182			System.arraycopy(fvm,end,fvm,start + putl,
183				fvmcount - end);
184		}
185
186		if(putl != 0)
187		{
188			System.arraycopy(put,0,fvm,start,put.length);
189		}
190
191		fvmcount += delta;
192
193		dump();
194
195		if(fvmcount == 0)
196			throw new InternalError();
197	} //}}}
198
199	//{{{ put2() method
200	/**
201	 * Merge previous and next entry if necessary.
202	 */
203	void put2(int starti, int endi, int start, int end)
204	{
205		if(Debug.FOLD_VIS_DEBUG)
206		{
207			Log.log(Log.DEBUG,this,"*fvmput2(" + starti + ","
208				+ endi + "," + start + "," + end + ")");
209		}
210		if(starti != -1 && fvm[starti] == start)
211		{
212			if(endi <= fvmcount - 2 && fvm[endi + 1]
213				== end + 1)
214			{
215				put(starti,endi + 2,null);
216			}
217			else
218			{
219				put(starti,endi + 1,
220					new int[] { end + 1 });
221			}
222		}
223		else
224		{
225			if(endi != fvmcount - 1 && fvm[endi + 1]
226				== end + 1)
227			{
228				put(starti + 1,endi + 2,
229					new int[] { start });
230			}
231			else
232			{
233				put(starti + 1,endi + 1,
234					new int[] { start,
235					end + 1 });
236			}
237		}
238	} //}}}
239
240	//{{{ next() method
241	int next(int line)
242	{
243		int index = search(line);
244		/* in collapsed range */
245		if(index % 2 != 0)
246		{
247			/* beyond last visible line */
248			if(fvmcount == index + 1)
249				return - 1;
250			/* start of next expanded range */
251			else
252				return fvm[index + 1];
253		}
254		/* last in expanded range */
255		else if(line == fvm[index + 1] - 1)
256		{
257			/* equal to last visible line */
258			if(fvmcount == index + 2)
259				return -1;
260			/* start of next expanded range */
261			else
262				return fvm[index + 2];
263		}
264		/* next in expanded range */
265		else
266			return line + 1;
267	} //}}}
268
269	//{{{ prev() method
270	int prev(int line)
271	{
272		int index = search(line);
273		/* before first visible line */
274		if(index == -1)
275			return -1;
276		/* in collapsed range */
277		else if(index % 2 == 1)
278		{
279			/* end of prev expanded range */
280			return fvm[index] - 1;
281		}
282		/* first in expanded range */
283		else if(line == fvm[index])
284		{
285			/* equal to first visible line */
286			if(index == 0)
287				return -1;
288			/* end of prev expanded range */
289			else
290				return fvm[index - 1] - 1;
291		}
292		/* prev in expanded range */
293		else
294			return line - 1;
295	} //}}}
296
297	//{{{ show() method
298	void show(int start, int end)
299	{
300		int starti = search(start);
301		int endi = search(end);
302
303		if(starti % 2 == 0)
304		{
305			if(endi % 2 == 0)
306				put(starti + 1,endi + 1,null);
307			else
308			{
309				if(endi != fvmcount - 1
310					&& fvm[endi + 1] == end + 1)
311					put(starti + 1,endi + 2,null);
312				else
313				{
314					put(starti + 1,endi,null);
315					fvm[starti + 1] = end + 1;
316				}
317			}
318		}
319		else
320		{
321			if(endi % 2 == 0)
322			{
323				if(starti != -1 && fvm[starti] == start)
324					put(starti,endi + 1,null);
325				else
326				{
327					put(starti + 1,endi,null);
328					fvm[starti + 1] = start;
329				}
330			}
331			else
332				put2(starti,endi,start,end);
333		}
334
335		lastfvmget = -1;
336	} //}}}
337	
338	//{{{ hide() method
339	void hide(int start, int end)
340	{
341		int starti = search(start);
342		int endi = search(end);
343
344		if(starti % 2 == 0)
345		{
346			if(endi % 2 == 0)
347				put2(starti,endi,start,end);
348			else
349			{
350				if(start == fvm[0])
351					put(starti,endi + 1,null);
352				else
353				{
354					put(starti + 1,endi,null);
355					fvm[starti + 1] = start;
356				}
357			}
358		}
359		else
360		{
361			if(endi % 2 == 0)
362			{
363				if(end + 1 == fvm[fvmcount - 1])
364					put(starti + 1,endi + 2,null);
365				else
366				{
367					put(starti + 1,endi,null);
368					fvm[starti + 1] = end + 1;
369				}
370			}
371			else
372				put(starti + 1,endi + 1,null);
373		}
374
375		lastfvmget = -1;
376	} //}}}
377
378	//{{{ count() method
379	int count()
380	{
381		return fvmcount;
382	} //}}}
383
384	//{{{ dump() method
385	void dump()
386	{
387		if(Debug.FOLD_VIS_DEBUG)
388		{
389			StringBuilder buf = new StringBuilder("{");
390			for(int i = 0; i < fvmcount; i++)
391			{
392				if(i != 0)
393					buf.append(',');
394				buf.append(fvm[i]);
395			}
396			buf.append('}');
397			Log.log(Log.DEBUG,this,"fvm = " + buf);
398		}
399	} //}}}
400
401	//{{{ contentInserted() method
402	void contentInserted(int startLine, int numLines)
403	{
404		if(numLines != 0)
405		{
406			int index = search(startLine);
407			int start = index + 1;
408
409			for(int i = start; i < fvmcount; i++)
410				fvm[i] += numLines;
411
412			lastfvmget = -1;
413			dump();
414		}
415	} //}}}
416
417	//{{{ preContentRemoved() method
418	/**
419	 * @return If the anchors should be reset.
420	 */
421	boolean preContentRemoved(int startLine, int numLines)
422	{
423		boolean returnValue = false;
424
425		int endLine = startLine + numLines;
426
427		/* update fold visibility map. */
428		int starti = search(startLine);
429		int endi = search(endLine);
430
431		/* both have same visibility; just remove
432		 * anything in between. */
433		if(Math.abs(starti % 2) == Math.abs(endi % 2))
434		{
435			if(endi - starti == fvmcount)
436			{
437				// we're removing from before
438				// the first visible to after
439				// the last visible
440				returnValue = true;
441				starti = 1;
442			}
443			else
444			{
445				put(starti + 1,endi + 1,null);
446				starti++;
447			}
448		}
449		/* collapse 2 */
450		else if(starti != -1 && fvm[starti] == startLine)
451		{
452			if(endi - starti == fvmcount - 1)
453			{
454				// we're removing from
455				// the first visible to after
456				// the last visible
457				returnValue = true;
458				starti = 1;
459			}
460			else
461				put(starti,endi + 1,null);
462		}
463		/* shift */
464		else
465		{
466			put(starti + 1,endi,null);
467			fvm[starti + 1] = startLine;
468			starti += 2;
469		}
470
471		/* update */
472		for(int i = starti; i < fvmcount; i++)
473			fvm[i] -= numLines;
474
475		lastfvmget = -1;
476		dump();
477
478		return returnValue;
479	} //}}}
480
481	//{{{ Private members
482	private int[] fvm;
483	private int fvmcount;
484	private int lastfvmget;
485	//}}}
486}