/* * ContentManager.java - Manages text content * :tabSize=4:indentSize=4: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.buffer; import javax.swing.text.Segment; /** * A class internal to jEdit's document model. You should not use it * directly. To improve performance, none of the methods in this class * check for out of bounds access, nor are they thread-safe. The * <code>Buffer</code> class, through which these methods must be * called through, implements such protection. * * @author Slava Pestov * @version $Id: ContentManager.java 21885 2012-06-27 14:06:58Z k_satoda $ * @since jEdit 4.0pre1 */ class ContentManager { //{{{ getLength() method public final int getLength() { return length; } //}}} //{{{ getText() methods public String getText(int start, int len) { if(start >= gapStart) return new String(text,start + gapLength(),len); else if(start + len <= gapStart) return new String(text,start,len); else { return new String(text,start,gapStart - start) .concat(new String(text,gapEnd(),start + len - gapStart)); } } /** * Returns the specified text range in a <code>Segment</code>.<p> * * Using a <classname>Segment</classname> is generally more * efficient than using a <classname>String</classname> because it * results in less memory allocation and array copying.<p> * * * @param start The start offset * @param len The number of characters to get * @param seg The segment to copy the text to * @see JEditBuffer#getText(int, int, Segment) */ public void getText(int start, int len, Segment seg) { if(start >= gapStart) { seg.array = text; seg.offset = start + gapLength(); seg.count = len; } else if(start + len <= gapStart) { seg.array = text; seg.offset = start; seg.count = len; } else { seg.array = new char[len]; // copy text before gap System.arraycopy(text,start,seg.array,0,gapStart - start); // copy text after gap System.arraycopy(text,gapEnd(),seg.array,gapStart - start, len + start - gapStart); seg.offset = 0; seg.count = len; } } //}}} //{{{ getSegment() method /** * Returns a read-only segment of the buffer. * It doesn't copy the text * * @param start The start offset * @param len The number of characters to get * * @return a CharSequence that contains the text wanted text * @since jEdit 4.3pre15 */ public CharSequence getSegment(int start, int len) { if(start >= gapStart) return new BufferSegment(text,start + gapLength(),len); else if(start + len <= gapStart) return new BufferSegment(text,start,len); else { return new BufferSegment(text,start,gapStart - start, new BufferSegment(text,gapEnd(),start + len - gapStart)); } } //}}} //{{{ insert() methods public void insert(int start, String str) { int len = str.length(); prepareGapForInsertion(start, len); str.getChars(0,len,text,start); gapStart += len; length += len; } /** * Inserts the given data into the buffer. * * @since jEdit 4.3pre15 */ public void insert(int start, CharSequence str) { int len = str.length(); prepareGapForInsertion(start, len); for (int i = 0; i < len; i++) { text[start+i] = str.charAt(i); } gapStart += len; length += len; } public void insert(int start, Segment seg) { prepareGapForInsertion(start, seg.count); System.arraycopy(seg.array,seg.offset,text,start,seg.count); gapStart += seg.count; length += seg.count; } //}}} //{{{ _setContent() method public void _setContent(char[] text, int length) { assert text != null; assert text.length >= length; this.text = text; this.gapStart = length; this.length = length; } //}}} //{{{ remove() method public void remove(int start, int len) { moveGapStart(start); length -= len; } //}}} //{{{ Private members private static final char[] EMPTY_TEXT = new char[0]; private char[] text = EMPTY_TEXT; private int gapStart; private int length; //{{{ gapEnd() method private int gapEnd() { return gapStart + gapLength(); } //}}} //{{{ gapLength() method private int gapLength() { return text.length - length; } //}}} //{{{ moveGapStart() method private void moveGapStart(int newStart) { int gapEnd = gapEnd(); int newEnd = gapEnd + (newStart - gapStart); if(newStart == gapStart) { // nothing to do } else if(newStart > gapStart) { System.arraycopy(text,gapEnd,text,gapStart, newStart - gapStart); } else if(newStart < gapStart) { System.arraycopy(text,newStart,text,newEnd, gapStart - newStart); } gapStart = newStart; } //}}} //{{{ ensureCapacity() method private void ensureCapacity(int capacity) { if(capacity >= text.length) { int gapEndOld = gapEnd(); char[] textN = new char[capacity * 2]; System.arraycopy(text,0,textN,0,text.length); text = textN; int gapEndNew = gapEnd(); System.arraycopy(text,gapEndOld,text,gapEndNew,text.length - gapEndNew); } } //}}} //{{{ prepareGapForInsertion() method private void prepareGapForInsertion(int start, int len) { moveGapStart(start); if(gapLength() < len) ensureCapacity(length + len); } //}}} //}}} }