PageRenderTime 76ms CodeModel.GetById 40ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 1ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/textarea/Selection.java

#
Java | 508 lines | 330 code | 63 blank | 115 comment | 58 complexity | 0d1f8688193c9316243538ce6564abd6 MD5 | raw file
  1/*
  2 * Selection.java - Selected text
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001, 2002 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
 25//{{{ Imports
 26import javax.swing.text.Segment;
 27import java.util.ArrayList;
 28import org.gjt.sp.jedit.Buffer;
 29import org.gjt.sp.jedit.MiscUtilities;
 30//}}}
 31
 32/**
 33 * An interface representing a portion of the current selection.
 34 * @author Slava Pestov
 35 * @version $Id: Selection.java 4249 2002-06-14 06:07:18Z spestov $
 36 * @since jEdit 3.2pre1
 37 */
 38public abstract class Selection implements Cloneable
 39{
 40	//{{{ getStart() method
 41	/**
 42	 * Returns the start offset of this selection.
 43	 */
 44	public int getStart()
 45	{
 46		return start;
 47	} //}}}
 48
 49	//{{{ getEnd() method
 50	/**
 51	 * Returns the end offset of this selection.
 52	 */
 53	public int getEnd()
 54	{
 55		return end;
 56	} //}}}
 57
 58	//{{{ getStart() method
 59	/**
 60	 * Returns the start offset of this selection on the specified
 61	 * line.
 62	 * @param buffer The buffer
 63	 * @param line The line number
 64	 * @since jEdit 4.1pre1
 65	 */
 66	public abstract int getStart(Buffer buffer, int line);
 67	//}}}
 68
 69	//{{{ getEnd() method
 70	/**
 71	 * Returns the end offset of this selection on the specified
 72	 * line.
 73	 * @param buffer The buffer
 74	 * @param line The line number
 75	 * @since jEdit 4.1pre1
 76	 */
 77	public abstract int getEnd(Buffer buffer, int line);
 78	//}}}
 79
 80	//{{{ getStartLine() method
 81	/**
 82	 * Returns the starting line number of this selection.
 83	 */
 84	public int getStartLine()
 85	{
 86		return startLine;
 87	} //}}}
 88
 89	//{{{ getEndLine() method
 90	/**
 91	 * Returns the ending line number of this selection.
 92	 */
 93	public int getEndLine()
 94	{
 95		return endLine;
 96	} //}}}
 97
 98	//{{{ overlaps() method
 99	/**
100	 * Returns if this selection and the specified selection overlap.
101	 * @param s The other selection
102	 * @since jEdit 4.1pre1
103	 */
104	public boolean overlaps(Selection s)
105	{
106		if((start >= s.start && start <= s.end)
107			|| (end >= s.start && end <= s.end))
108			return true;
109		else
110			return false;
111	} //}}}
112
113	//{{{ toString() method
114	public String toString()
115	{
116		return getClass().getName() + "[start=" + start
117			+ ",end=" + end + ",startLine=" + startLine
118			+ ",endLine=" + endLine + "]";
119	} //}}}
120
121	//{{{ clone() method
122	public Object clone()
123	{
124		try
125		{
126			return super.clone();
127		}
128		catch(CloneNotSupportedException e)
129		{
130			throw new InternalError("I just drank a whole "
131				+ "bottle of cough syrup and I feel "
132				+ "funny!");
133		}
134	} //}}}
135
136	//{{{ Package-private members
137	int start, end;
138	int startLine, endLine;
139
140	//{{{ Selection constructor
141	Selection()
142	{
143	} //}}}
144
145	//{{{ Range constructor
146	Selection(Selection sel)
147	{
148		this.start = sel.start;
149		this.end = sel.end;
150	} //}}}
151
152	//{{{ Selection constructor
153	Selection(int start, int end)
154	{
155		this.start = start;
156		this.end = end;
157	} //}}}
158
159	// should the next two be public, maybe?
160	abstract void getText(Buffer buffer, StringBuffer buf);
161	abstract int setText(Buffer buffer, String text);
162	//}}}
163
164	//{{{ Range class
165	/**
166	 * An ordinary range selection.
167	 * @since jEdit 3.2pre1
168	 */
169	public static class Range extends Selection
170	{
171		//{{{ Range constructor
172		public Range()
173		{
174		} //}}}
175
176		//{{{ Range constructor
177		public Range(Selection sel)
178		{
179			super(sel);
180		} //}}}
181
182		//{{{ Range constructor
183		public Range(int start, int end)
184		{
185			super(start,end);
186		} //}}}
187
188		//{{{ getStart() method
189		public int getStart(Buffer buffer, int line)
190		{
191			if(line == startLine)
192				return start;
193			else
194				return buffer.getLineStartOffset(line);
195		} //}}}
196
197		//{{{ getEnd() method
198		public int getEnd(Buffer buffer, int line)
199		{
200			if(line == endLine)
201				return end;
202			else
203				return buffer.getLineEndOffset(line) - 1;
204		} //}}}
205
206		//{{{ getText() method
207		void getText(Buffer buffer, StringBuffer buf)
208		{
209			buf.append(buffer.getText(start,end - start));
210		} //}}}
211
212		//{{{ setText() method
213		int setText(Buffer buffer, String text)
214		{
215			buffer.remove(start,end - start);
216			if(text != null && text.length() != 0)
217			{
218				buffer.insert(start,text);
219				return start + text.length();
220			}
221			else
222				return start;
223		} //}}}
224	} //}}}
225
226	//{{{ Rect class
227	/**
228	 * A rectangular selection.
229	 * @since jEdit 3.2pre1
230	 */
231	// this class is not very fast...
232	public static class Rect extends Selection
233	{
234		//{{{ Rect constructor
235		public Rect()
236		{
237			super();
238		} //}}}
239
240		//{{{ Rect constructor
241		public Rect(Selection sel)
242		{
243			super(sel);
244		} //}}}
245
246		//{{{ Rect constructor
247		public Rect(int start, int end)
248		{
249			super(start,end);
250		} //}}}
251
252		//{{{ Rect constructor
253		public Rect(int startLine, int start, int endLine, int end)
254		{
255			this.startLine = startLine;
256			this.start = start;
257			this.endLine = endLine;
258			this.end = end;
259		} //}}}
260
261		//{{{ Rect constructor
262		public Rect(Buffer buffer, int startLine, int startColumn,
263			int endLine, int endColumn)
264		{
265			this.startLine = startLine;
266			this.endLine = endLine;
267
268			int[] width = new int[1];
269			int startOffset = buffer.getOffsetOfVirtualColumn(startLine,
270				startColumn,width);
271			if(startOffset == -1)
272			{
273				extraStartVirt = startColumn - width[0];
274				startOffset = buffer.getLineEndOffset(startLine) - 1;
275			}
276			else
277				startOffset += buffer.getLineStartOffset(startLine);
278
279			int endOffset = buffer.getOffsetOfVirtualColumn(endLine,
280				endColumn,width);
281			if(endOffset == -1)
282			{
283				extraEndVirt = endColumn - width[0];
284				endOffset = buffer.getLineEndOffset(endLine) - 1;
285			}
286			else
287				endOffset += buffer.getLineStartOffset(endLine);
288		} //}}}
289
290		//{{{ getStartColumn() method
291		public int getStartColumn(Buffer buffer)
292		{
293			int virtColStart = buffer.getVirtualWidth(startLine,
294				start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
295			int virtColEnd = buffer.getVirtualWidth(endLine,
296				end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
297			return Math.min(virtColStart,virtColEnd);
298		} //}}}
299
300		//{{{ getEndColumn() method
301		public int getEndColumn(Buffer buffer)
302		{
303			int virtColStart = buffer.getVirtualWidth(startLine,
304				start - buffer.getLineStartOffset(startLine)) + extraStartVirt;
305			int virtColEnd = buffer.getVirtualWidth(endLine,
306				end - buffer.getLineStartOffset(endLine)) + extraEndVirt;
307			return Math.max(virtColStart,virtColEnd);
308		} //}}}
309
310		//{{{ getStart() method
311		public int getStart(Buffer buffer, int line)
312		{
313			return getColumnOnOtherLine(buffer,startLine,line,
314				getStartColumn(buffer));
315		} //}}}
316
317		//{{{ getEnd() method
318		public int getEnd(Buffer buffer, int line)
319		{
320			return getColumnOnOtherLine(buffer,startLine,line,
321				getEndColumn(buffer));
322		} //}}}
323
324		//{{{ Package-private members
325		int extraStartVirt;
326		int extraEndVirt;
327
328		//{{{ getText() method
329		void getText(Buffer buffer, StringBuffer buf)
330		{
331			int start = getStartColumn(buffer);
332			int end = getEndColumn(buffer);
333
334			for(int i = startLine; i <= endLine; i++)
335			{
336				int lineStart = buffer.getLineStartOffset(i);
337				int lineLen = buffer.getLineLength(i);
338
339				int rectStart = buffer.getOffsetOfVirtualColumn(
340					i,start,null);
341				if(rectStart == -1)
342					rectStart = lineLen;
343
344				int rectEnd = buffer.getOffsetOfVirtualColumn(
345					i,end,null);
346				if(rectEnd == -1)
347					rectEnd = lineLen;
348
349				buf.append(buffer.getText(lineStart + rectStart,
350					rectEnd - rectStart));
351
352				if(i != endLine)
353					buf.append('\n');
354			}
355		} //}}}
356
357		//{{{ setText() method
358		int setText(Buffer buffer, String text)
359		{
360			int startColumn = getStartColumn(buffer);
361			int endColumn = getEndColumn(buffer);
362
363			int[] total = new int[1];
364
365			int tabSize = buffer.getTabSize();
366
367			int maxWidth = 0;
368			int totalLines = 0;
369			ArrayList lines = new ArrayList();
370
371			//{{{ Split the text into lines
372			if(text != null)
373			{
374				int lastNewline = 0;
375				int currentWidth = startColumn;
376				for(int i = 0; i < text.length(); i++)
377				{
378					char ch = text.charAt(i);
379					if(ch == '\n')
380					{
381						totalLines++;
382						lines.add(text.substring(
383							lastNewline,i));
384						lastNewline = i + 1;
385						maxWidth = Math.max(maxWidth,currentWidth);
386						lines.add(new Integer(currentWidth));
387						currentWidth = startColumn;
388					}
389					else if(ch == '\t')
390						currentWidth += tabSize - (currentWidth % tabSize);
391					else
392						currentWidth++;
393				}
394
395				if(lastNewline != text.length())
396				{
397					totalLines++;
398					lines.add(text.substring(lastNewline));
399					lines.add(new Integer(currentWidth));
400					maxWidth = Math.max(maxWidth,currentWidth);
401				}
402			} //}}}
403
404			//{{{ Insert the lines into the buffer
405			int endOffset = 0;
406			int lastLine = Math.max(startLine + totalLines - 1,endLine);
407			for(int i = startLine; i <= lastLine; i++)
408			{
409				if(i == buffer.getLineCount())
410					buffer.insert(buffer.getLength(),"\n");
411
412				int lineStart = buffer.getLineStartOffset(i);
413				int lineLen = buffer.getLineLength(i);
414
415				int rectStart = buffer.getOffsetOfVirtualColumn(
416					i,startColumn,total);
417				int startWhitespace;
418				if(rectStart == -1)
419				{
420					startWhitespace = (startColumn - total[0]);
421					rectStart = lineLen;
422				}
423				else
424					startWhitespace = 0;
425
426				int rectEnd = buffer.getOffsetOfVirtualColumn(
427					i,endColumn,null);
428				if(rectEnd == -1)
429					rectEnd = lineLen;
430
431				buffer.remove(rectStart + lineStart,rectEnd - rectStart);
432
433				int index = 2 * (i - startLine);
434
435				int endWhitespace;
436				if(rectEnd == lineLen)
437					endWhitespace = 0;
438				else if(i - startLine >= totalLines)
439					endWhitespace = maxWidth - startColumn;
440				else
441				{
442					endWhitespace = maxWidth
443						- ((Integer)lines.get(index+1))
444						.intValue();
445				}
446
447				String str = (i - startLine >= totalLines
448					? "" : (String)lines.get(index));
449				if(startWhitespace != 0)
450				{
451					buffer.insert(rectStart + lineStart,
452						MiscUtilities.createWhiteSpace(startWhitespace,0));
453				}
454
455				buffer.insert(rectStart + lineStart + startWhitespace,str);
456
457				if(endWhitespace != 0)
458				{
459					buffer.insert(rectStart + lineStart
460						+ startWhitespace + str.length(),
461						MiscUtilities.createWhiteSpace(endWhitespace,0));
462				}
463
464				endOffset = rectStart + lineStart
465					+ startWhitespace
466					+ endWhitespace
467					+ str.length();
468			} //}}}
469
470			//{{{ Move the caret down a line
471			if(text == null || text.length() == 0)
472				return end;
473			if(lastLine != buffer.getLineCount() - 1)
474			{
475				int offset = buffer.getOffsetOfVirtualColumn(
476					lastLine + 1,startColumn,null);
477				if(offset == -1)
478				{
479					buffer.insertAtColumn(lastLine + 1,startColumn,"");
480					return buffer.getLineEndOffset(lastLine + 1) - 1;
481				}
482				else
483					return buffer.getLineStartOffset(lastLine + 1) + offset;
484			}
485			else
486				return endOffset;
487			//}}}
488		} //}}}
489
490		//}}}
491
492		//{{{ Private members
493
494		//{{{ getColumnOnOtherLine() method
495		private int getColumnOnOtherLine(Buffer buffer, int line1,
496			int line2, int col)
497		{
498			int returnValue = buffer.getOffsetOfVirtualColumn(
499				line2,col,null);
500			if(returnValue == -1)
501				return buffer.getLineEndOffset(line2) - 1;
502			else
503				return buffer.getLineStartOffset(line2) + returnValue;
504		} //}}}
505
506		//}}}
507	} //}}}
508}