alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Selection.java - Selected text
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 2001, 2002 Slava Pestov
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package org.gjt.sp.jedit.textarea;

//{{{ Imports
import java.util.ArrayList;
import org.gjt.sp.jedit.Buffer;
import org.gjt.sp.jedit.MiscUtilities;
//}}}

/**
 * An abstract class that holds data on a region of selected text.
 * As an abstract class, it cannot be used
 * directly, but instead serves as a parent class for two specific types
 * of selection structures:
 * 
    *
  • {@link Selection.Range} - represents an ordinary range of selected text.
  • *
  • {@link Selection.Rect} - represents a rectangular selection.
  • *
* * @author Slava Pestov * @author John Gellene (API documentation) * @version $Id: Selection.java,v 1.22 2004/04/06 19:05:31 spestov Exp $ * @since jEdit 3.2pre1 */ public abstract class Selection implements Cloneable { //{{{ getStart() method /** * Returns the start offset of this selection. */ public int getStart() { return start; } //}}} //{{{ getEnd() method /** * Returns the end offset of this selection. */ public int getEnd() { return end; } //}}} //{{{ getStart() method /** * Returns the beginning of the portion of the selection * falling on the specified line. Used to manipulate * selection text on a line-by-line basis. * @param buffer The buffer * @param line The line number * @since jEdit 4.1pre1 */ public abstract int getStart(Buffer buffer, int line); //}}} //{{{ getEnd() method /** * Returns the end of the portion of the selection * falling on the specified line. Used to manipulate * selection text on a line-by-line basis. * @param buffer The buffer * @param line The line number * @since jEdit 4.1pre1 */ public abstract int getEnd(Buffer buffer, int line); //}}} //{{{ getStartLine() method /** * Returns the starting line number of this selection. */ public int getStartLine() { return startLine; } //}}} //{{{ getEndLine() method /** * Returns the ending line number of this selection. */ public int getEndLine() { return endLine; } //}}} //{{{ overlaps() method /** * Returns if this selection and the specified selection overlap. * @param s The other selection * @since jEdit 4.1pre1 */ public boolean overlaps(Selection s) { if((start >= s.start && start <= s.end) || (end >= s.start && end <= s.end)) return true; else return false; } //}}} //{{{ toString() method public String toString() { return getClass().getName() + "[start=" + start + ",end=" + end + ",startLine=" + startLine + ",endLine=" + endLine + "]"; } //}}} //{{{ clone() method public Object clone() { try { return super.clone(); } catch(CloneNotSupportedException e) { throw new InternalError("I just drank a whole " + "bottle of cough syrup and I feel " + "funny!"); } } //}}} //{{{ Package-private members int start, end; int startLine, endLine; //{{{ Selection constructor Selection() { } //}}} //{{{ Selection constructor Selection(Selection sel) { this.start = sel.start; this.end = sel.end; } //}}} //{{{ Selection constructor Selection(int start, int end) { this.start = start; this.end = end; } //}}} // should the next two be public, maybe? abstract void getText(Buffer buffer, StringBuffer buf); abstract int setText(Buffer buffer, String text); abstract boolean contentInserted(Buffer buffer, int startLine, int start, int numLines, int length); abstract boolean contentRemoved(Buffer buffer, int startLine, int start, int numLines, int length); //}}} //{{{ Range class /** * An ordinary range selection. * @since jEdit 3.2pre1 */ public static class Range extends Selection { //{{{ Range constructor public Range() { } //}}} //{{{ Range constructor public Range(Selection sel) { super(sel); } //}}} //{{{ Range constructor public Range(int start, int end) { super(start,end); } //}}} //{{{ getStart() method public int getStart(Buffer buffer, int line) { if(line == startLine) return start; else return buffer.getLineStartOffset(line); } //}}} //{{{ getEnd() method public int getEnd(Buffer buffer, int line) { if(line == endLine) return end; else return buffer.getLineEndOffset(line) - 1; } //}}} //{{{ Package-private members //{{{ getText() method void getText(Buffer buffer, StringBuffer buf) { buf.append(buffer.getText(start,end - start)); } //}}} //{{{ setText() method int setText(Buffer buffer, String text) { buffer.remove(start,end - start); if(text != null && text.length() != 0) { buffer.insert(start,text); return start + text.length(); } else return start; } //}}} //{{{ contentInserted() method boolean contentInserted(Buffer buffer, int startLine, int start, int numLines, int length) { boolean changed = false; if(this.start >= start) { this.start += length; if(numLines != 0) this.startLine = buffer.getLineOfOffset(this.start); changed = true; } if(this.end >= start) { this.end += length; if(numLines != 0) this.endLine = buffer.getLineOfOffset(this.end); changed = true; } return changed; } //}}} //{{{ contentRemoved() method boolean contentRemoved(Buffer buffer, int startLine, int start, int numLines, int length) { int end = start + length; boolean changed = false; if(this.start > start && this.start <= end) { this.start = start; changed = true; } else if(this.start > end) { this.start -= length; changed = true; } if(this.end > start && this.end <= end) { this.end = start; changed = true; } else if(this.end > end) { this.end -= length; changed = true; } if(changed && numLines != 0) { this.startLine = buffer.getLineOfOffset(this.start); this.endLine = buffer.getLineOfOffset(this.end); } return changed; } //}}} //}}} } //}}} //{{{ Rect class /** * A rectangular selection. * @since jEdit 3.2pre1 */ // this class is not very fast... public static class Rect extends Selection { //{{{ Rect constructor public Rect() { super(); } //}}} //{{{ Rect constructor public Rect(Selection sel) { super(sel); } //}}} //{{{ Rect constructor public Rect(int start, int end) { super(start,end); } //}}} //{{{ Rect constructor public Rect(int startLine, int start, int endLine, int end) { this.startLine = startLine; this.start = start; this.endLine = endLine; this.end = end; } //}}} //{{{ Rect constructor public Rect(Buffer buffer, int startLine, int startColumn, int endLine, int endColumn) { this.startLine = startLine; this.endLine = endLine; int[] width = new int[1]; int startOffset = buffer.getOffsetOfVirtualColumn(startLine, startColumn,width); if(startOffset == -1) { extraStartVirt = startColumn - width[0]; startOffset = buffer.getLineEndOffset(startLine) - 1; } else startOffset += buffer.getLineStartOffset(startLine); int endOffset = buffer.getOffsetOfVirtualColumn(endLine, endColumn,width); if(endOffset == -1) { extraEndVirt = endColumn - width[0]; endOffset = buffer.getLineEndOffset(endLine) - 1; } else endOffset += buffer.getLineStartOffset(endLine); } //}}} //{{{ getStartColumn() method public int getStartColumn(Buffer buffer) { int virtColStart = buffer.getVirtualWidth(startLine, start - buffer.getLineStartOffset(startLine)) + extraStartVirt; int virtColEnd = buffer.getVirtualWidth(endLine, end - buffer.getLineStartOffset(endLine)) + extraEndVirt; return Math.min(virtColStart,virtColEnd); } //}}} //{{{ getEndColumn() method public int getEndColumn(Buffer buffer) { int virtColStart = buffer.getVirtualWidth(startLine, start - buffer.getLineStartOffset(startLine)) + extraStartVirt; int virtColEnd = buffer.getVirtualWidth(endLine, end - buffer.getLineStartOffset(endLine)) + extraEndVirt; return Math.max(virtColStart,virtColEnd); } //}}} //{{{ getStart() method public int getStart(Buffer buffer, int line) { return getColumnOnOtherLine(buffer,line, getStartColumn(buffer)); } //}}} //{{{ getEnd() method public int getEnd(Buffer buffer, int line) { return getColumnOnOtherLine(buffer,line, getEndColumn(buffer)); } //}}} //{{{ Package-private members int extraStartVirt; int extraEndVirt; //{{{ getText() method void getText(Buffer buffer, StringBuffer buf) { int start = getStartColumn(buffer); int end = getEndColumn(buffer); for(int i = startLine; i <= endLine; i++) { int lineStart = buffer.getLineStartOffset(i); int lineLen = buffer.getLineLength(i); int rectStart = buffer.getOffsetOfVirtualColumn( i,start,null); if(rectStart == -1) rectStart = lineLen; int rectEnd = buffer.getOffsetOfVirtualColumn( i,end,null); if(rectEnd == -1) rectEnd = lineLen; if(rectEnd < rectStart) System.err.println(i + ":::" + start + ":" + end + " ==> " + rectStart + ":" + rectEnd); buf.append(buffer.getText(lineStart + rectStart, rectEnd - rectStart)); if(i != endLine) buf.append('\n'); } } //}}} //{{{ setText() method int setText(Buffer buffer, String text) { int startColumn = getStartColumn(buffer); int endColumn = getEndColumn(buffer); int[] total = new int[1]; int tabSize = buffer.getTabSize(); int maxWidth = 0; int totalLines = 0; ArrayList lines = new ArrayList(); //{{{ Split the text into lines if(text != null) { int lastNewline = 0; int currentWidth = startColumn; for(int i = 0; i < text.length(); i++) { char ch = text.charAt(i); if(ch == '\n') { totalLines++; lines.add(text.substring( lastNewline,i)); lastNewline = i + 1; maxWidth = Math.max(maxWidth,currentWidth); lines.add(new Integer(currentWidth)); currentWidth = startColumn; } else if(ch == '\t') currentWidth += tabSize - (currentWidth % tabSize); else currentWidth++; } if(lastNewline != text.length()) { totalLines++; lines.add(text.substring(lastNewline)); lines.add(new Integer(currentWidth)); maxWidth = Math.max(maxWidth,currentWidth); } } //}}} //{{{ Insert the lines into the buffer int endOffset = 0; int lastLine = Math.max(startLine + totalLines - 1,endLine); for(int i = startLine; i <= lastLine; i++) { if(i == buffer.getLineCount()) buffer.insert(buffer.getLength(),"\n"); int lineStart = buffer.getLineStartOffset(i); int lineLen = buffer.getLineLength(i); int rectStart = buffer.getOffsetOfVirtualColumn( i,startColumn,total); int startWhitespace; if(rectStart == -1) { startWhitespace = (startColumn - total[0]); rectStart = lineLen; } else startWhitespace = 0; int rectEnd = buffer.getOffsetOfVirtualColumn( i,endColumn,null); if(rectEnd == -1) rectEnd = lineLen; buffer.remove(rectStart + lineStart,rectEnd - rectStart); if(startWhitespace != 0) { buffer.insert(rectStart + lineStart, MiscUtilities.createWhiteSpace(startWhitespace,0)); } int endWhitespace; if(totalLines == 0) { if(rectEnd == lineLen) endWhitespace = 0; else endWhitespace = maxWidth - startColumn; } else { int index = 2 * ((i - startLine) % totalLines); String str = (String)lines.get(index); buffer.insert(rectStart + lineStart + startWhitespace,str); if(rectEnd == lineLen) endWhitespace = 0; else { endWhitespace = maxWidth - ((Integer)lines.get(index+1)) .intValue(); } startWhitespace += str.length(); } if(endWhitespace != 0) { buffer.insert(rectStart + lineStart + startWhitespace, MiscUtilities.createWhiteSpace(endWhitespace,0)); } endOffset = rectStart + lineStart + startWhitespace + endWhitespace; } //}}} //{{{ Move the caret down a line if(text == null || text.length() == 0) return end; else return endOffset; //}}} } //}}} //{{{ contentInserted() method boolean contentInserted(Buffer buffer, int startLine, int start, int numLines, int length) { if(this.end < start) return false; this.end += length; if(this.startLine > startLine) { this.start += length; if(numLines != 0) { this.startLine = buffer.getLineOfOffset( this.start); this.endLine = buffer.getLineOfOffset( this.end); } return true; } int endVirtualColumn = buffer.getVirtualWidth( this.endLine,end - buffer.getLineStartOffset(this.endLine)); if(this.start == start) { int startVirtualColumn = buffer.getVirtualWidth( this.startLine,start - buffer.getLineStartOffset( this.startLine)); this.start += length; int newStartVirtualColumn = buffer.getVirtualWidth( startLine,start - buffer.getLineStartOffset( this.startLine)); int[] totalVirtualWidth = new int[1]; int newEnd = buffer.getOffsetOfVirtualColumn( this.endLine,endVirtualColumn + newStartVirtualColumn - startVirtualColumn, totalVirtualWidth); if(newEnd != -1) { end = buffer.getLineStartOffset( this.endLine) + newEnd; } else { end = buffer.getLineEndOffset( this.endLine) - 1; extraEndVirt = totalVirtualWidth[0] - endVirtualColumn; } } else if(this.start > start) { this.start += length; if(numLines != 0) { this.startLine = buffer.getLineOfOffset( this.start); } } if(numLines != 0) this.endLine = buffer.getLineOfOffset(this.end); int newEndVirtualColumn = buffer.getVirtualWidth( endLine, end - buffer.getLineStartOffset(this.endLine)); if(startLine == this.endLine && extraEndVirt != 0) { extraEndVirt += (endVirtualColumn - newEndVirtualColumn); } else if(startLine == this.startLine && extraStartVirt != 0) { extraStartVirt += (endVirtualColumn - newEndVirtualColumn); } return true; } //}}} //{{{ contentRemoved() method boolean contentRemoved(Buffer buffer, int startLine, int start, int numLines, int length) { int end = start + length; boolean changed = false; if(this.start > start && this.start <= end) { this.start = start; changed = true; } else if(this.start > end) { this.start -= length; changed = true; } if(this.end > start && this.end <= end) { this.end = start; changed = true; } else if(this.end > end) { this.end -= length; changed = true; } if(changed && numLines != 0) { this.startLine = buffer.getLineOfOffset(this.start); this.endLine = buffer.getLineOfOffset(this.end); } return changed; } //}}} //}}} //{{{ Private members //{{{ getColumnOnOtherLine() method private int getColumnOnOtherLine(Buffer buffer, int line, int col) { int returnValue = buffer.getOffsetOfVirtualColumn( line,col,null); if(returnValue == -1) return buffer.getLineEndOffset(line) - 1; else return buffer.getLineStartOffset(line) + returnValue; } //}}} //}}} } //}}} }
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.