Milán Major

netscape-revival

1 branch
Code

sun-java/classsrc/sun/awt/tiny/TinyTextAreaPeer.java

/*
 * @(#)TinyTextAreaPeer.java
 *
 * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */
package sun.awt.tiny;

import java.awt.*;
import java.awt.peer.*;

class TinyTextAreaPeer extends TinyComponentPeer implements TextAreaPeer, TinyScrollbarClient {
    
    public static final int MARGIN = 4;
    public static final int BORDER = 2;
    public static final int SCROLLBAR = 17;
    public static final int HORSCROLLBAR = 0;
    public static final int VERSCROLLBAR = 1;
    public static final int TEXTAREA = 2;
    
    TinyVerticalScrollbar 	vsb;
    TinyHorizontalScrollbar 	hsb;
    
    boolean 	hasFocus;
    char 	text[];
    int 	lines[];
    int 	nrOfLines;
    int 	textLength;
    int 	mpos;
    int 	selStart;
    int 	selEnd;
    long 	mtm;
    int 	topLine;
    int 	movedRight;
    int 	active;
    int 	fontAscent;
    int 	fontLeading;
    int 	fontHeight;
    
    /**
     * Create a Text area.
     */
    TinyTextAreaPeer(TextArea target) {
	winCreate((TinyComponentPeer)target.getParent().getPeer());
	init(target);
	target.isEditable();
        
 	FontMetrics fm = getFontMetrics(target.getFont());
	fontAscent = fm.getAscent();
	fontLeading = fm.getLeading();
	fontHeight = fm.getHeight();
	
	// initialize Horizontal Scrollbar
	hsb = new TinyHorizontalScrollbar();
	hsb.sb = this;
	hsb.line = 10;

        // initialize Vertical Scrollbar
	vsb = new TinyVerticalScrollbar();
	vsb.sb = this;
	vsb.line = 1;

	// set the text of this object to the text of it's target
	setText(target.getText());
    }

    /**
     * Compute minimum size.
     */
    public Dimension minimumSize() {
	return minimumSize(10, 60);
    }
    public Dimension preferredSize(int rows, int cols) {
	return minimumSize(rows, cols);
    }
    public Dimension minimumSize(int rows, int cols) {
	FontMetrics fm = getFontMetrics(target.getFont());	
	return new Dimension(fm.charWidth('0') * cols + 20, fm.getHeight() * rows + 20);
    }

    
    /**
     * Update the index Array from the specified lineNumber
     */
    protected void updateIndex(int nr) {
    	nrOfLines = nr + 1;
	int offset = 0;
	lines[0] = 0;
	for (int i = lines[nr]; i < textLength; i++) {
	    if (lines.length == nrOfLines) {
	        int tmp[] = new int[nrOfLines + 10];
		System.arraycopy(lines, 0, tmp, 0, nrOfLines);
		lines = tmp;        	
	    }	    
	    if(text[i] == '\n') {
		offset = i + 1;
		lines[nrOfLines++] = offset;
	    }
	    else if(text[i] == '\r') {
		offset = i + 1;
		if((i+1) < textLength) {
		    if(text[i+1] == '\n') {
			offset++;
		    }		    
		}
		lines[nrOfLines++] = offset;
	    }
	}
    }

    /** 
     * return the position on the line "ln" given the old xPosition
     */
    int xPos(int xo, int ln) {
	FontMetrics fm = getFontMetrics(target.getFont());	
	int pose = (ln + 1 < nrOfLines) ? lines[ln + 1] - 1 : textLength;	
	int x = MARGIN, widths[] = fm.getWidths();
	int posn = lines[ln];
	while((x < xo) && (posn < pose)) {
	    x += widths[text[posn]];
	    posn++;	
	}
	return posn;
    }	

    /**
     * number of lines that can fit in the window
     */
    int linesInWindow() {
	int htotal = height - ((2 * MARGIN) + SCROLLBAR);
	return htotal / fontHeight;
    }

    /** 
     * return the position in the array "lines" from the values x and y.
     */
    public int xy2pos(int x, int y) {
    	int ln = 0;
	int endl = lineNumber(selEnd);
	if (y < 0) {
	    if (topLine - 1 >= 0) { 
	    	ln = topLine - 1;
	    } else {
		return 0;
	    }	
	} else if (y > height) {
	    if (endl < nrOfLines - 1) {
		ln = endl + 1;
	    } else {
		return textLength;
	    }
	} else {
	    ln = topLine;
	    int ys = MARGIN + fontHeight;
	    while ((y > ys) && (ln < nrOfLines - 1)) {
		ys += fontHeight;
	    	ln++;
	    }
        }
	FontMetrics fm = getFontMetrics(target.getFont());	
	int widths[] = fm.getWidths();
	int begin = lines[ln];
	int end = (ln + 1 < nrOfLines) ? lines[ln + 1] - 1 : textLength;
	x -= MARGIN;
	for (int i = begin; i < end ; i++) {
	    int w = widths[text[i]];
	    if (x < (w / 2)) {
		return i;
	    }
	    x -= w;
	}
	return end;
    }
    
    /**
     * return the x position of the position pos 	
     */
     int pos2x(int pos) {
	FontMetrics fm = getFontMetrics(target.getFont());	
	int widths[] = fm.getWidths();
	int ln = lineNumber(pos);
	int begin = lines[ln];
	int x = MARGIN;
	for (int i = begin ; i < pos ; i++) {
	    x += widths[text[i]];
	}
	return x;
    }
    
    /**
     * return the y position of the lineNumber
     */
    int ln2y(int ln) {
	return MARGIN + fontLeading + ((ln - topLine) * fontHeight);
    }

    /**
     * return the lineNumber
     * use binairy search
     */
    int lineNumber(int pos) {	
	int i = 0, j = nrOfLines - 1;
	while (i < j) {
	    int m = i + ((j - i) >> 1);
	    int s = lines[m];
	    int e = lines[m + 1];
	    if (pos < s) {
		j = m - 1;
	    } else if (pos >= e) {
		i = m + 1;
	    } else {
		return m;
	    }
	}
	return i;
    }

    /**
     * return the length of the largest line
     */
    int maxLength() {
	FontMetrics fm = getFontMetrics(target.getFont());	
	int max = hsb.val;
	for(int i = 0 ; i < nrOfLines ; i++) {
	    int b = lines[i];
	    int e = (i + 1 == nrOfLines) ? textLength - 1 : lines[i + 1];
	    int l = fm.charsWidth(text, b, e - b);
	    max = Math.max(max, l);
	}
    	return max;
    }

    /**
     * Paint the vertical scrollbar to the screen
     */
    void paintVerScrollbar(Graphics g) {
	
	// initialize scrollbar
	int l = linesInWindow();
	vsb.vis = l;
	vsb.page = l;
	vsb.max = Math.max(0, nrOfLines - l);
	vsb.val = Math.min(topLine, vsb.max);
	
	// paint scrollbar
	Graphics ng = g.create();
	g.setColor(target.getBackground());
	g.fillRect(width - 14, 1, 13, height - (SCROLLBAR - 2));
	
	try {
	    ng.translate(width - (SCROLLBAR - 2), 0);
	    vsb.paint(ng, target.getBackground(), SCROLLBAR - 2, height - (SCROLLBAR - 2));
	} finally {
	    ng.dispose();
	}
    }    
    
    /**
     * paint the horizontal scrollbar to the screen
     */
    void paintHorScrollbar(Graphics g) {
	int w = width - ((2 * BORDER) + SCROLLBAR);
	
	// initialize
	hsb.vis = w;
	hsb.page = hsb.vis;
	hsb.max = Math.max(0, (MARGIN + maxLength()) - w);
	hsb.val = Math.min(hsb.max, movedRight);
	
	// paint scrollbar
	Graphics ng = g.create();
	g.setColor(target.getBackground());
	g.fillRect(1, height - 14, width - (SCROLLBAR + 2), 13);
	
	try {
	    ng.translate(0, height - (SCROLLBAR - 2));
	    hsb.paint(ng, target.getBackground(), width - (SCROLLBAR - 2), SCROLLBAR - 2);
	} finally {
	    ng.dispose();
	}
    }       
	    
   /**
    * Paint the component
    * this method is called when the repaint instruction has been used
    */
    public void paintComponent(Graphics g) {
	TextArea area = (TextArea)target;
	
	int w = width - ((2 * BORDER) + SCROLLBAR);
	int h = height - ((2 * BORDER) + SCROLLBAR);
	
	g.setFont(area.getFont());
	g.setColor(area.isEditable() ? target.getBackground().brighter() : target.getBackground());
	g.fillRect(BORDER, BORDER, w, h);
	paintVerScrollbar(g);
	paintHorScrollbar(g);
	
	if (hasFocus) {
	    g.setColor(Color.black);
	    g.drawRect(0, 0, width - (SCROLLBAR + 1), height - (SCROLLBAR + 1));
	    g.drawRect(1, 1, width - (SCROLLBAR + 3), height - (SCROLLBAR + 3));	    
	} else {
	    g.setColor(target.getBackground());
	    g.drawRect(0, 0, width - (SCROLLBAR + 1), height - (SCROLLBAR + 1));
	    g.draw3DRect(1, 1, width - (SCROLLBAR + 3), height - (SCROLLBAR + 3), false);
	} 
	
	if (text != null) {
	    int l = linesInWindow();
	    h = height - ((2 * MARGIN) + SCROLLBAR);
	    int e = Math.min(nrOfLines - 1, (topLine + l) - 1);
	    paintLines(g, topLine, e);
	}
    }
    
    /**
     * fill the position on the screen with the desired color
     * the color is given by "s". 
     * true = selectColor
     * false = backGroundColor
     */
    void paintRange(Graphics g, int start, int end) {
	int lnrStart = lineNumber(start);
	int lnrEnd = lineNumber(end);
	Graphics ng = g.create();
	
	if (lnrStart == lnrEnd) {
	    int xmax = width - (BORDER + SCROLLBAR);
	    int xs = Math.max(BORDER, pos2x(start) - movedRight);
	    int xe = Math.min(xmax, pos2x(end) - movedRight);
	    int w = (start == end) ? 1 : xe - xs;
	    int y = ln2y(lnrStart) - fontLeading;
	    ng.clipRect(xs, y, w, fontHeight);
	    paintLine(ng, lnrStart);
	} else {
	    int diff = lnrEnd - lnrStart;
	    int w = width - ((2 * BORDER) + SCROLLBAR);
	    int h = height - ((2 * MARGIN) + SCROLLBAR);
	    ng.clipRect(BORDER, MARGIN, w, h);
	    paintLine(ng, lnrStart);
	    lnrStart++;
	    
	    while (diff > 1) {
		paintLine(ng, lnrStart);
		lnrStart++;
		diff--;
	    }
	    paintLine(ng, lnrEnd);
	}
   	ng.dispose();
    }
    	    
    /**
     * draw the lines to the screen
     */
    void paintLines(Graphics g, int s, int e) {
	int w = width - ((2 * BORDER) + SCROLLBAR);
	int h = height - ((2 * MARGIN) + SCROLLBAR);
	int lm = linesInWindow() + topLine;
	s = Math.max(topLine, s);
	e = Math.min(e, lm - 1);
	Graphics ng = g.create();
	ng.clipRect(BORDER, MARGIN, w, h);
	
	for (int i = s ; i <= e; i++) {
	    paintLine(ng, i);
	}     
    	ng.dispose();
    }

    /**
     * paint the background color of the line "lnr" to the screen and then paint draw the 
     * line to the screen
     * if the line number is greater than nrOfLines - 1 than do a fillrect to the
     * position of the line, use the background color
     */
    void paintLine(Graphics g, int lnr) {
	int l = linesInWindow();

	if((lnr < topLine) || (lnr >= l + topLine)) { 
	    return;
	}
	int w = width - ((2 * BORDER) + SCROLLBAR); 
	int y = ln2y(lnr);
	
	if (lnr > nrOfLines - 1) {
	    g.setColor(backGroundColor());
	    g.fillRect(BORDER, y - fontLeading, w, fontHeight);
	    return;
	}
	int s = lines[lnr];
	int e = (lnr < nrOfLines - 1) ? lines[lnr + 1] - 1 : textLength;
	int xs = pos2x(selStart) - movedRight;
	int xe = pos2x(selEnd) - movedRight;

	if ((selStart < s) && (selEnd > e)) {
	    g.setColor(selectColor());
	    g.fillRect(BORDER, y - fontLeading, w, fontHeight);
	} else {
	    g.setColor(backGroundColor());
	    g.fillRect(BORDER, y - fontLeading, w, fontHeight);
		
	    if ((selStart >= s) && (selStart <= e)) {
		g.setColor(selectColor());
		    
		if (selEnd > e) {
		    g.fillRect(xs, y - fontLeading, (w + BORDER) - xs, fontHeight);
		} else if (selStart == selEnd) { 
		    g.fillRect(xs, y - fontLeading, 1, fontHeight);
		} else { 
			g.fillRect(xs, y - fontLeading, xe - xs, fontHeight);
		}		
	    } else if ((selEnd >= s) && (selEnd <= e)) {
		g.setColor(selectColor());
		g.fillRect(BORDER, y - fontLeading, xe - BORDER, fontHeight);
	    }	    
	}
	g.setColor(target.getForeground());
	g.drawChars(text, s, e - s, MARGIN - movedRight, y + fontAscent);	
    }    

    /**
     * return the background color
     */
    Color backGroundColor() {
	TextArea area = (TextArea)target;
	return (area.isEditable() ? target.getBackground().brighter() : target.getBackground()); 
    }

    /**
     * return the selection color
     */
    Color selectColor() {
	TextArea area = (TextArea)target;
	return (area.isEditable() ? target.getBackground() : target.getBackground().darker());
    }
    
    /**
     * get the value back from the scrollbar
     */
    public void notifyValue(Object obj, int c, int b) {
    	int w = width - ((2 * BORDER) + SCROLLBAR);
	int h = height - ((2 * BORDER) + SCROLLBAR);
	Graphics g = getGraphics();
	
	if ((TinyVerticalScrollbar)obj == vsb) {
	    scrollVertical(g, b - topLine);
	    paintVerScrollbar(g);
	} else if ((TinyHorizontalScrollbar)obj == hsb) {
	    scrollHorizontal(g, b - movedRight); 
	    paintHorScrollbar(g);
	}
    	g.dispose();
    }

    /**
     * is (x, y) in the horizontal scrollbar
     */
    boolean inHorScrollbar(int x, int y) {
	return (y >= height - SCROLLBAR) && (y <= height) && (x <= width - SCROLLBAR);
    }
    
    /**
     * is (x, y) in the vertical scrollbar
     */
     boolean inVerScrollbar(int x, int y) {
	return (x >= width - SCROLLBAR) && (x <= width) && (y <= height - SCROLLBAR);
    }
    
    /**
     * is (x, y) in the Textfield
     */ 
    boolean inTextField(int x, int y) {
	return (x < width - SCROLLBAR) && (y < height - SCROLLBAR); 
    }

    /**
     * Handle events.
     */
    public boolean handleWindowEvent(Event evt) {
	TextArea area = (TextArea)target;
	switch (evt.id) {
			
	case Event.MOUSE_DOWN:
	    if (inVerScrollbar(evt.x, evt.y)) {
		evt.x -= width - SCROLLBAR;
		active = VERSCROLLBAR;
		return vsb.handleWindowEvent(evt, SCROLLBAR, height - SCROLLBAR);
	    } else if (inHorScrollbar(evt.x, evt.y)) {	
		evt.y -= height - SCROLLBAR;
		active = HORSCROLLBAR;
		return hsb.handleWindowEvent(evt, width - SCROLLBAR, SCROLLBAR);
	    } else if (inTextField(evt.x, evt.y)) {
		if (!hasFocus()) {
		    requestFocus();
		}
	    	active = TEXTAREA;
		mpos = xy2pos(evt.x + movedRight, evt.y);
	    	select(mpos, mpos);
		return true;
	    }
	    break;
	
	case Event.MOUSE_UP:
	    if ((evt.when - mtm < 200) && (inTextField(evt.x, evt.y))) {
		select(0, textLength);
	    }
	    mtm = evt.when;
	    return true;

	case Event.MOUSE_DRAG:
	    
	    if (active == VERSCROLLBAR) {
		evt.x -= width - SCROLLBAR;
		return vsb.handleWindowEvent(evt, SCROLLBAR, height - SCROLLBAR);
	    } else if (active == HORSCROLLBAR) {	
		evt.y -= height - SCROLLBAR;
		return hsb.handleWindowEvent(evt, width - SCROLLBAR, SCROLLBAR);
	    } else if (active == TEXTAREA) {
		int mpos2 = xy2pos(evt.x + movedRight, evt.y);
	    	if (mpos < mpos2) {
		    select(mpos, mpos2);	
		    scrollTo(selEnd);
		} else {
		    select(mpos2, mpos);
		    scrollTo(selStart); 
		}
		return true;
	    }
	 
	case Event.GOT_FOCUS:
	    hasFocus = true;
	    repaint();
	    return true;
	
	case Event.LOST_FOCUS:
	    hasFocus = false;
	    repaint();
	    return true;
	
	case Event.KEY_ACTION:
	    switch(evt.key) {
	        case Event.UP:
		     int ln = lineNumber(selStart);
		     if(ln > 0) {
			 int xo = pos2x(selStart);
			 int posn = xPos(xo, ln - 1);
		    	 select(posn, posn);
		     	 scrollTo(selStart);
			 return true;
		     }	
		     return false;
	 
	    	case Event.LEFT:
		    if(selStart > 0) {
			select(selStart - 1, selStart - 1);
		        scrollTo(selStart);
		        return true;
		    }
		    return false;
		    
	    	case Event.RIGHT:
		    if(selStart < textLength) {
			select(selStart + 1, selStart + 1);
		        scrollTo(selStart);
			return true;
		    }
		    return false;
		    	
		case Event.DOWN:
		    int lnr = lineNumber(selStart);
		    if(lnr + 1 < nrOfLines) { 
			int xo = pos2x(selStart);
			int posn = xPos(xo, lnr + 1);
		    	select(posn, posn);
		    	scrollTo(selStart);
			return true;
		    }
		    return false;
	    	}
         case Event.KEY_PRESS:
	     if(area.isEditable()) {
	    	switch (evt.key) {
	    		
		case '\r':
		    if(selStart != selEnd) {
			delete(selStart, selEnd);
		    }
		    insertText("\r", selStart);
		    return true;
	   	
		case '\n':
	    	    if(selStart != selEnd) {
		       delete(selStart, selEnd);
		    }
		    insertText("\n", selStart);
		    return true;
	   		
	        case 8:
	        case 127:
		    if(selStart != selEnd) {
		        delete(selStart, selEnd);
		    }		    
		    else if(selStart > 0) {
		        delete(selStart-1, selStart);
		    }
		    return true;

	        default:
		    char data[] = {(char)evt.key};
		    if(selStart != selEnd) {
		        replaceText(new String(data), selStart, selEnd);
		    }
		    else {
		        insertText(new String(data), selStart);
		    }
		    return true;
	        }
            }
	}	    
	return false;
    }
    
    /**
     * scroll the text to the position "pos". Pos is the position in the text.
     * if the pos is already on the screen then do nothing
     */
    void scrollTo(int pos) {
	
	int lnr = lineNumber(pos);
	int l = linesInWindow();
	Graphics g = getGraphics();
	
	// scroll vertical
	if (lnr >= l + topLine) {
	    if (selStart < selEnd) {
		scrollVertical(g, 1);
	    } else if (lnr == topLine + l) {
		scrollVertical(g, (l + 1) / 2);
	    } else {
		int i = (topLine + l) - 1;
		int j = (lnr - i) + (l / 2);
		scrollVertical(g, j);
	    }
	} else if (lnr < topLine) {
	    if(selStart < selEnd) {
		scrollVertical(g, -1);
	    } else if(lnr + 1 == topLine) {
		scrollVertical(g, (-l - 1) / 2);
	    } else {
		scrollVertical(g, lnr - (topLine + 1));
	    }
	}
 	
	int x = pos2x(pos);
	int w = width - (MARGIN + SCROLLBAR);
	int xMax = w + movedRight;
	int xMin = movedRight + MARGIN;

	// scroll horizontal
	if (x > xMax) {
	    int diff = x - xMax;
	    scrollHorizontal(g, diff);
	} else if (x < xMin) {
	    int diff = x - xMin;
	    scrollHorizontal(g, diff);
	}
	paintHorScrollbar(g);
	paintVerScrollbar(g);
	g.dispose();
    }

    /**
     * Scroll "mp" horizontal 
     */
    void scrollHorizontal(Graphics g, int mp) {
	int l = linesInWindow();
	int le = Math.min((topLine + l) - 1, nrOfLines - 1);
	movedRight += mp;
	paintLines(g, topLine, le);
    } 

    /**
     * scroll the text "ml"  times vertical.
     */
    void scrollVertical(Graphics g, int ml) {
			
	if (topLine < -ml) {
	    ml = -topLine;
	}
	
	if (ml < 0) {
	    int l = linesInWindow();
	    topLine += ml;
            
	    if(ml + l > 0) {
		int hg = ((ml + l) * fontHeight);
		int w = width - ((2 * BORDER) + SCROLLBAR);
		g.copyArea(BORDER, MARGIN, w, hg, 0, -ml * fontHeight);  
	    } 	
	    int le = Math.min(nrOfLines - 1, topLine + -ml); 
	    paintLines(g, topLine, le);
	} else if (ml > 0) {
	    int l = linesInWindow();
	    topLine += ml;
	    	    
	    if (ml < l) {
		int y = MARGIN + (ml * fontHeight); 
		int hg = ((l - ml) * fontHeight);
		int w = width - ((2 * BORDER) + SCROLLBAR);
		g.copyArea(BORDER, y, w, hg, 0, -ml * fontHeight);  
	    }
	    paintLines(g, topLine + (l - ml), (topLine + l) - 1);
	}
    }
    
    /**
     * setEditable
     */
    public void setEditable(boolean editable) {
	repaint();
    }
    
    /**
     * get the selection start
     */
    public int getSelectionStart() {
	return selStart;
    }
    
    /**
     * get the selection end
     */
    public int getSelectionEnd() {
	return selEnd;
    }
    
    /**
     * get the text
     */
    public String getText() {
	return String.valueOf(text, 0, textLength);
    }
    
    /**
     * select the text between selStart and selEnd
     */
    public void select(int s, int e) {
    	
	if ((s > textLength) || (s < 0) || (e > textLength) || (e < 0)) {
	    return;
	}
	
	if ((this.selStart == s) && (this.selEnd == e)) {
	    return;
	}
	
	int startOld = this.selStart;
	int endOld = this.selEnd;
	selEnd = e;
	selStart = s;
 	Graphics g = getGraphics();
		
	if ((selStart >= endOld) || (selEnd <= startOld)) {
	    paintRange(g, startOld, endOld);
	    paintRange(g, selStart, selEnd);	
	} else {
	    int start = Math.min(selStart, startOld);
	    int end = Math.max(selStart, startOld);
	    
	    if (start != end) {
		paintRange(g, start, end);
	    }	
	    start = Math.min(selEnd, endOld);
	    end = Math.max(selEnd, endOld);
				  
	    if (start != end) {
		paintRange(g, start, end);
	    }
   	}   
	g.dispose();
    }

    /**
     * Set the text.
     */
    public void setText(String t) {
	textLength = t.length();
	this.text = new char[textLength+100]; 
	int nr = Math.max(textLength / 20, 1);
	lines = new int[nr];
	t.getChars(0, textLength, this.text, 0); 
	updateIndex(0);
	selStart = 0;
	selEnd = selStart;
	topLine = 0;
	movedRight = 0;
	target.repaint(); 
    }
    
    /** 
     * insert the text "txt on position "pos" in the array lines
     */
    public void insertText(String txt, int p) {
	TextArea area = (TextArea)target;
	
	if((p >= 0) && (p <= textLength)) {
	    int l = txt.length();
	    int lnr = lineNumber(p);
	    char ln[] = new char[l];
	    txt.getChars(0, l, ln, 0);
	    
	    if (text.length < textLength + l) {
		char tmp[] = new char[textLength + l + 20];
		System.arraycopy(text, 0, tmp, 0, textLength);
		text = tmp;
	    }
	    System.arraycopy(text, p, text, p + l, textLength - p);
	    System.arraycopy(ln, 0, text, p, l);
	    textLength += l;
	    int oldStart = selStart;
	    selStart += l;
	    selEnd = selStart;
	    int nr = nrOfLines;
	    updateIndex(lnr);    
	    int li = linesInWindow();
	    int le = (nrOfLines != nr) ? (topLine + li) - 1 : lnr;
	    Graphics g = getGraphics();
	    paintLines(g, lnr, le);
	    g.dispose();
	    scrollTo(selStart);
	}
    }
    
    /**
     * replace the text between the position "start" and "end" with "txt"
     */
    public void replaceText(String txt, int s, int e) {
    		
	if ((e > textLength) || (s > e) || (s < 0)) {
	    return;
	}
	TextArea area = (TextArea)target;
	delete(s, e);
	insertText(txt, s);    
    }
    
    /**
     * remove the text from the position start to the position end in the aray lines
     */
    protected void delete(int s, int e) {
    	int lnr = lineNumber(s);
	int length = e - s;	
	System.arraycopy(text, e, text, s, textLength - e); 
	textLength -= length;
	selStart = s;
	selEnd = s;
	int nr = nrOfLines;
	updateIndex(lnr);    
	Graphics g = getGraphics();
	int li = linesInWindow();
	int le = (nrOfLines != nr) ? (topLine + li) - 1 : lnr;
	paintLines(g, lnr, le);
    	g.dispose();
	scrollTo(selStart);
    }
}