/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.custom;


import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.printing.*;
import org.eclipse.swt.widgets.*;

/**
 * A StyledText is an editable user interface object that displays lines 
 * of text.  The following style attributes can be defined for the text: 
 * <ul>
 * <li>foreground color 
 * <li>background color
 * <li>font style (bold, regular)
 * </ul>
 * <p>
 * In addition to text style attributes, the background color of a line may 
 * be specified.
 * </p>
 * <p>
 * There are two ways to use this widget when specifying text style information.  
 * You may use the API that is defined for StyledText or you may define your own 
 * LineStyleListener.  If you define your own listener, you will be responsible 
 * for maintaining the text style information for the widget.  IMPORTANT: You may 
 * not define your own listener and use the StyledText API.  The following
 * StyledText API is not supported if you have defined a LineStyleListener:
 * <ul>
 * <li>getStyleRangeAtOffset(int)
 * <li>getStyleRanges()
 * <li>replaceStyleRanges(int,int,StyleRange[])
 * <li>setStyleRange(StyleRange)
 * <li>setStyleRanges(StyleRange[])
 * </ul>
 * </p>
 * <p>
 * There are two ways to use this widget when specifying line background colors.
 * You may use the API that is defined for StyledText or you may define your own 
 * LineBackgroundListener.  If you define your own listener, you will be responsible 
 * for maintaining the line background color information for the widget.  
 * IMPORTANT: You may not define your own listener and use the StyledText API.  
 * The following StyledText API is not supported if you have defined a 
 * LineBackgroundListener:
 * <ul>
 * <li>getLineBackground(int)
 * <li>setLineBackground(int,int,Color)
 * </ul>
 * </p>
 * <p>
 * The content implementation for this widget may also be user-defined.  To do so,
 * you must implement the StyledTextContent interface and use the StyledText API
 * setContent(StyledTextContent) to initialize the widget. 
 * </p>
 * <p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 * <dl>
 * <dt><b>Styles:</b><dd>FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
 * <dt><b>Events:</b><dd>ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey
 * </dl>
 */
public class StyledText extends Canvas {
	static final char TAB = '\t';
	static final String PlatformLineDelimiter = System.getProperty("line.separator");
	static final int BIDI_CARET_WIDTH = 4;		
	static final int XINSET = BIDI_CARET_WIDTH - 1;
	static final int DEFAULT_WIDTH	= 64;
	static final int DEFAULT_HEIGHT = 64;
	
	static final int ExtendedModify = 3000;
	static final int LineGetBackground = 3001;
	static final int LineGetStyle = 3002;
	static final int TextChanging = 3003;
	static final int TextSet = 3004;
	static final int VerifyKey = 3005;
	static final int TextChanged = 3006;
	static final int LineGetSegments = 3007;
	
	Color selectionBackground;	// selection background color
	Color selectionForeground;	// selection foreground color
	StyledTextContent logicalContent;	// native content (default or user specified)
	StyledTextContent content;			// line wrapping content, same as logicalContent if word wrap is off
	DisplayRenderer renderer;
	TextChangeListener textChangeListener;	// listener for TextChanging, TextChanged and TextSet events from StyledTextContent
	DefaultLineStyler defaultLineStyler;// used for setStyles API when no LineStyleListener is registered
	LineCache lineCache;
	boolean userLineStyle = false;		// true=widget is using a user defined line style listener for line styles. false=widget is using the default line styler to store line styles
	boolean userLineBackground = false;	// true=widget is using a user defined line background listener for line backgrounds. false=widget is using the default line styler to store line backgrounds
	int verticalScrollOffset = 0;		// pixel based
	int horizontalScrollOffset = 0;		// pixel based
	int topIndex = 0;					// top visible line
	int topOffset = 0;					// offset of first character in top line
	int clientAreaHeight = 0;			// the client area height. Needed to calculate content width for new 
										// visible lines during Resize callback
	int clientAreaWidth = 0;			// the client area width. Needed during Resize callback to determine 
										// if line wrap needs to be recalculated
	int lineHeight;						// line height=font height
	int tabLength = 4;					// number of characters in a tab
	int lineEndSpaceWidth;				// space, in pixel, used to indicated a selected line break
	int leftMargin = 1;
	int topMargin = 1;
	int rightMargin = 2;
	int bottomMargin = 2;
	Cursor ibeamCursor;		
	int columnX;							// keep track of the horizontal caret position
										// when changing lines/pages. Fixes bug 5935
	int caretOffset = 0;
	Point selection = new Point(0, 0);	// x is character offset, y is length
	int selectionAnchor;				// position of selection anchor. 0 based offset from beginning of text
	Point doubleClickSelection;			// selection after last mouse double click
	boolean editable = true;
	boolean wordWrap = false;
	boolean doubleClickEnabled = true;	// see getDoubleClickEnabled 
	boolean overwrite = false;			// insert/overwrite edit mode
	int textLimit = -1;					// limits the number of characters the user can type in the widget. Unlimited by default.
	Hashtable keyActionMap = new Hashtable();
	Color background = null;			// workaround for bug 4791
	Color foreground = null;			//
	Clipboard clipboard;
	boolean mouseDoubleClick = false;	// true=a double click ocurred. Don't do mouse swipe selection.
	int autoScrollDirection = SWT.NULL;	// the direction of autoscrolling (up, down, right, left)
	int lastTextChangeStart;			// cache data of the 
	int lastTextChangeNewLineCount;		// last text changing 
	int lastTextChangeNewCharCount;		// event for use in the 
	int lastTextChangeReplaceLineCount;	// text changed handler
	int lastTextChangeReplaceCharCount;	
	boolean isBidi;
	boolean bidiColoring = false;		// apply the BIDI algorithm on text segments of the same color
	Image leftCaretBitmap = null;
	Image rightCaretBitmap = null;
	int caretDirection = SWT.NULL;
	PaletteData caretPalette = null;	
	int lastCaretDirection = SWT.NULL;
	boolean isCarbon;					// flag set to true on Mac OSX
	
	/**
	 * The Printing class implements printing of a range of text.
	 * An instance of <class>Printing </class> is returned in the 
	 * StyledText#print(Printer) API. The run() method may be 
	 * invoked from any thread.
	 */
	class Printing implements Runnable {
		final static int LEFT = 0;						// left aligned header/footer segment
		final static int CENTER = 1;					// centered header/footer segment
		final static int RIGHT = 2;						// right aligned header/footer segment

		Printer printer;
		PrintRenderer renderer;
		StyledTextPrintOptions printOptions;
		StyledTextContent printerContent;				// copy of the widget content
		Rectangle clientArea;							// client area to print on
		Font printerFont;
		FontData displayFontData;
		Hashtable printerColors;						// printer color cache for line backgrounds and style
		Hashtable lineBackgrounds = new Hashtable();	// cached line backgrounds
		Hashtable lineStyles = new Hashtable();			// cached line styles
		Hashtable bidiSegments = new Hashtable();		// cached bidi segments when running on a bidi platform
		GC gc;											// printer GC
		int pageWidth;									// width of a printer page in pixels
		int startPage;									// first page to print
		int endPage;									// last page to print
		int pageSize;									// number of lines on a page
		int startLine;									// first (wrapped) line to print
		int endLine;									// last (wrapped) line to print
		boolean singleLine;								// widget single line mode
		Point selection = null;					// selected text

	/**
	 * Creates an instance of <class>Printing</class>.
	 * Copies the widget content and rendering data that needs 
	 * to be requested from listeners.
	 * </p>
	 * @param parent StyledText widget to print.
	 * @param printer printer device to print on.
	 * @param printOptions print options
	 */		
	Printing(StyledText parent, Printer printer, StyledTextPrintOptions printOptions) {
		PrinterData data = printer.getPrinterData();
		
		this.printer = printer;
		this.printOptions = printOptions;
		singleLine = parent.isSingleLine();
		startPage = 1;
		endPage = Integer.MAX_VALUE;
		if (data.scope == PrinterData.PAGE_RANGE) {
			startPage = data.startPage;
			endPage = data.endPage;
			if (endPage < startPage) {
				int temp = endPage;
				endPage = startPage;
				startPage = temp;
			}			
		} 
		else 
		if (data.scope == PrinterData.SELECTION) {
			selection = parent.getSelectionRange();
		}

		displayFontData = getFont().getFontData()[0];
		copyContent(parent.getContent());
		cacheLineData(printerContent);
	}
	/**
	 * Caches the bidi segments of the given line.
	 * </p>
	 * @param lineOffset offset of the line to cache bidi segments for. 
	 * 	Relative to the start of the document.
	 * @param line line to cache bidi segments for. 
	 */
	void cacheBidiSegments(int lineOffset, String line) {
		int[] segments = getBidiSegments(lineOffset, line);
		
		if (segments != null) {
			bidiSegments.put(new Integer(lineOffset), segments);
		}
	}
	/**
	 * Caches the line background color of the given line.
	 * </p>
	 * @param lineOffset offset of the line to cache the background 
	 * 	color for. Relative to the start of the document.
	 * @param line line to cache the background color for
	 */
	void cacheLineBackground(int lineOffset, String line) {
		StyledTextEvent event = getLineBackgroundData(lineOffset, line);
		
		if (event != null) {
			lineBackgrounds.put(new Integer(lineOffset), event);
		}
	}
	/**
	 * Caches all line data that needs to be requested from a listener.
	 * </p>
	 * @param printerContent <class>StyledTextContent</class> to request 
	 * 	line data for.
	 */
	void cacheLineData(StyledTextContent printerContent) {	
		for (int i = 0; i < printerContent.getLineCount(); i++) {
			int lineOffset = printerContent.getOffsetAtLine(i);
			String line = printerContent.getLine(i);
	
			if (printOptions.printLineBackground) {
				cacheLineBackground(lineOffset, line);
			}
			if (printOptions.printTextBackground ||
				printOptions.printTextForeground ||
				printOptions.printTextFontStyle) {
				cacheLineStyle(lineOffset, line);
			}
			if (isBidi()) {
				cacheBidiSegments(lineOffset, line);
			}
		}
	}
	/**
	 * Caches all line styles of the given line.
	 * </p>
	 * @param lineOffset offset of the line to cache the styles for.
	 * 	Relative to the start of the document.
	 * @param line line to cache the styles for.
	 */
	void cacheLineStyle(int lineOffset, String line) {
		StyledTextEvent event = getLineStyleData(lineOffset, line);
		
		if (event != null) {
			StyleRange[] styles = event.styles;
			for (int i = 0; i < styles.length; i++) {
				StyleRange styleCopy = null;
				if (printOptions.printTextBackground == false && styles[i].background != null) {
					styleCopy = (StyleRange) styles[i].clone();
					styleCopy.background = null;
				}
				if (printOptions.printTextForeground == false && styles[i].foreground != null) {
					if (styleCopy == null) {
						styleCopy = (StyleRange) styles[i].clone();
					}
					styleCopy.foreground = null;
				}
				if (printOptions.printTextFontStyle == false && styles[i].fontStyle != SWT.NORMAL) {
					if (styleCopy == null) {
						styleCopy = (StyleRange) styles[i].clone();
					}
					styleCopy.fontStyle = SWT.NORMAL;
				}
				if (styleCopy != null) {
					styles[i] = styleCopy;
				}
			}	
			lineStyles.put(new Integer(lineOffset), event);
		}
	}
	/**
	 * Copies the text of the specified <class>StyledTextContent</class>.
	 * </p>
	 * @param original the <class>StyledTextContent</class> to copy.
	 */
	void copyContent(StyledTextContent original) {
		int insertOffset = 0;
		
		printerContent = new DefaultContent();
		for (int i = 0; i < original.getLineCount(); i++) {
			int insertEndOffset;
			if (i < original.getLineCount() - 1) {
				insertEndOffset = original.getOffsetAtLine(i + 1);
			}
			else {
				insertEndOffset = original.getCharCount();
			}
			printerContent.replaceTextRange(insertOffset, 0, original.getTextRange(insertOffset, insertEndOffset - insertOffset));
			insertOffset = insertEndOffset;
		}
	}
	/**
	 * Replaces all display colors in the cached line backgrounds and 
	 * line styles with printer colors.
	 */
	void createPrinterColors() {
		Enumeration values = lineBackgrounds.elements();
		printerColors = new Hashtable();
		while (values.hasMoreElements()) {
			StyledTextEvent event = (StyledTextEvent) values.nextElement();
			event.lineBackground = getPrinterColor(event.lineBackground);
		}
		
		values = lineStyles.elements();
		while (values.hasMoreElements()) {
			StyledTextEvent event = (StyledTextEvent) values.nextElement();
			for (int i = 0; i < event.styles.length; i++) {
				StyleRange style = event.styles[i];
				Color printerBackground = getPrinterColor(style.background);
				Color printerForeground = getPrinterColor(style.foreground);
				
				if (printerBackground != style.background || 
					printerForeground != style.foreground) {
					style = (StyleRange) style.clone();
					style.background = printerBackground;
					style.foreground = printerForeground;
					event.styles[i] = style;
				}
			}
		}		
	}
	/**
	 * Disposes of the resources and the <class>PrintRenderer</class>.
	 */
	void dispose() {
		if (printerColors != null) {
			Enumeration colors = printerColors.elements();
			
			while (colors.hasMoreElements()) {
				Color color = (Color) colors.nextElement();
				color.dispose();
			}
			printerColors = null;
		}
		if (gc != null) {
			gc.dispose();
			gc = null;
		}
		if (printerFont != null) {
			printerFont.dispose();
			printerFont = null;
		}
		if (renderer != null) {
			renderer.dispose();
			renderer = null;
		}
	}
	/**
	 * Finish printing the indicated page.
	 * 
	 * @param page page that was printed
	 */
	void endPage(int page) {
		printDecoration(page, false);
		printer.endPage();
	}
	/**
	 * Creates a <class>PrintRenderer</class> and calculate the line range
	 * to print.
	 */
	void initializeRenderer() {
		Rectangle trim = printer.computeTrim(0, 0, 0, 0);
		Point dpi = printer.getDPI();
		
		printerFont = new Font(printer, displayFontData.getName(), displayFontData.getHeight(), SWT.NORMAL);
		clientArea = printer.getClientArea();
		pageWidth = clientArea.width;
		// one inch margin around text
		clientArea.x = dpi.x + trim.x; 				
		clientArea.y = dpi.y + trim.y;
		clientArea.width -= (clientArea.x + trim.width);
		clientArea.height -= (clientArea.y + trim.height); 
		
		gc = new GC(printer);
		gc.setFont(printerFont);				
		renderer = new PrintRenderer(
			printer, printerFont, isBidi(), gc, printerContent,
			lineBackgrounds, lineStyles, bidiSegments, 
			tabLength, clientArea);
		if (printOptions.header != null) {
			int lineHeight = renderer.getLineHeight();
			clientArea.y += lineHeight * 2;
			clientArea.height -= lineHeight * 2;
		}
		if (printOptions.footer != null) {
			clientArea.height -= renderer.getLineHeight() * 2;
		}
		pageSize = clientArea.height / renderer.getLineHeight();
		StyledTextContent content = renderer.getContent();
		startLine = 0;
		if (singleLine) {
			endLine = 0;
		}
		else {
			endLine = content.getLineCount() - 1;
		}
		PrinterData data = printer.getPrinterData();
		if (data.scope == PrinterData.PAGE_RANGE) {
			startLine = (startPage - 1) * pageSize;
		} 
		else
		if (data.scope == PrinterData.SELECTION) {
			startLine = content.getLineAtOffset(selection.x);
			if (selection.y > 0) {
				endLine = content.getLineAtOffset(selection.x + selection.y - 1);
			} 
			else {
				endLine = startLine - 1;
			}
		}
	}
	/**
	 * Returns the printer color for the given display color.
	 * </p>
	 * @param color display color
	 * @return color create on the printer with the same RGB values 
	 * 	as the display color.
 	 */
	Color getPrinterColor(Color color) {
		Color printerColor = null;
		
		if (color != null) {
			printerColor = (Color) printerColors.get(color);		
			if (printerColor == null) {
				printerColor = new Color(printer, color.getRGB());
				printerColors.put(color, printerColor);
			}
		}
		return printerColor;
	}
	/**
	 * Prints the lines in the specified page range.
	 */
	void print() {
		StyledTextContent content = renderer.getContent();
		Color background = gc.getBackground();
		Color foreground = gc.getForeground();
		int lineHeight = renderer.getLineHeight();
		int paintY = clientArea.y;
		int page = startPage;
		
		for (int i = startLine; i <= endLine && page <= endPage; i++, paintY += lineHeight) {
			String line = content.getLine(i);
			
			if (paintY == clientArea.y) {
				startPage(page);
			}
			renderer.drawLine(
				line, i, paintY, gc, background, foreground, true);
			if (paintY + lineHeight * 2 > clientArea.y + clientArea.height) {
				// close full page
				endPage(page);
				paintY = clientArea.y - lineHeight;
				page++;
			}
		}
		if (paintY > clientArea.y) {
			// close partial page
			endPage(page);
		}
	}
	/**
	 * Print header or footer decorations.
	 * 
	 * @param page page number to print, if specified in the StyledTextPrintOptions header or footer.
	 * @param header true = print the header, false = print the footer
	 */
	void printDecoration(int page, boolean header) {
		int lastSegmentIndex = 0;
		final int SegmentCount = 3;
		String text;
		
		if (header) {
			text = printOptions.header;
		}
		else {
			text = printOptions.footer;
		}
		if (text == null) {
			return;
		}
		for (int i = 0; i < SegmentCount; i++) {
			int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
			String segment;
			
			if (segmentIndex == -1) {
				segment = text.substring(lastSegmentIndex);
				printDecorationSegment(segment, i, page, header);
				break;
			}
			else {
				segment = text.substring(lastSegmentIndex, segmentIndex);
				printDecorationSegment(segment, i, page, header);
				lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length();
			}
		}
	}
	/**
	 * Print one segment of a header or footer decoration.
	 * Headers and footers have three different segments.
	 * One each for left aligned, centered, and right aligned text.
	 * 
	 * @param segment decoration segment to print
	 * @param alignment alignment of the segment. 0=left, 1=center, 2=right 
	 * @param page page number to print, if specified in the decoration segment.
	 * @param header true = print the header, false = print the footer
	 */
	void printDecorationSegment(String segment, int alignment, int page, boolean header) {		
		int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
		
		if (pageIndex != -1) {
			final int PageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
			StringBuffer buffer = new StringBuffer(segment);
			buffer.replace(pageIndex, pageIndex + PageTagLength, new Integer(page).toString());
			segment = buffer.toString();
		}
		if (segment.length() > 0) {
			int segmentWidth;
			int drawX = 0;
			int drawY;
			StyledTextBidi bidi = null;
			
			if (isBidi()) {
				bidi = new StyledTextBidi(gc, tabLength, segment, null, null, new int[] {0, segment.length()});
				segmentWidth = bidi.getTextWidth();
			}			
			else {
				segmentWidth = gc.textExtent(segment).x;
			}
			if (header) {
				drawY = clientArea.y - renderer.getLineHeight() * 2;
			}
			else {
				drawY = clientArea.y + clientArea.height + renderer.getLineHeight();
			}			
			if (alignment == LEFT) {
				drawX = clientArea.x;
			}
			else				
			if (alignment == CENTER) {
				drawX = (pageWidth - segmentWidth) / 2;
			}
			else 
			if (alignment == RIGHT) {
				drawX = clientArea.x + clientArea.width - segmentWidth;
			}
			if (bidi != null) {
				bidi.drawBidiText(0, segment.length(), drawX, drawY);
			}
			else {
				gc.drawString(segment, drawX, drawY, true);
			}
		}
	}
	/**
	 * Starts a print job and prints the pages specified in the constructor.
	 */
	public void run() {
		String jobName = printOptions.jobName;
		
		if (jobName == null) {
			jobName = "Printing";
		}		
		if (printer.startJob(jobName)) {
			createPrinterColors();
			initializeRenderer();
			print();
			dispose();
			printer.endJob();			
		}
	}
	/**
	 * Start printing a new page.
	 * 
	 * @param page page number to be started
	 */
	void startPage(int page) {
		printer.startPage();
		printDecoration(page, true);
	}	
	}
	/**
	 * The <code>RTFWriter</code> class is used to write widget content as
	 * rich text. The implementation complies with the RTF specification 
	 * version 1.5.
	 * <p>
	 * toString() is guaranteed to return a valid RTF string only after 
	 * close() has been called. 
	 * </p>
	 * <p>
	 * Whole and partial lines and line breaks can be written. Lines will be
	 * formatted using the styles queried from the LineStyleListener, if 
	 * set, or those set directly in the widget. All styles are applied to
	 * the RTF stream like they are rendered by the widget. In addition, the 
	 * widget font name and size is used for the whole text.
	 * </p>
	 */
	class RTFWriter extends TextWriter {
		final int DEFAULT_FOREGROUND = 0;
		final int DEFAULT_BACKGROUND = 1;
		Vector colorTable = new Vector();
		boolean WriteUnicode;
		
	/**
	 * Creates a RTF writer that writes content starting at offset "start"
	 * in the document.  <code>start</code> and <code>length</code>can be set to specify partial 
	 * lines.
	 * <p>
	 *
	 * @param start start offset of content to write, 0 based from 
	 * 	beginning of document
	 * @param length length of content to write
	 */
	public RTFWriter(int start, int length) {
		super(start, length);
		colorTable.addElement(getForeground());
		colorTable.addElement(getBackground());		
		setUnicode();
	}
	/**
	 * Closes the RTF writer. Once closed no more content can be written.
	 * <b>NOTE:</b>  <code>toString()</code> does not return a valid RTF string until 
	 * <code>close()</code> has been called.
	 */
	public void close() {
		if (isClosed() == false) {
			writeHeader();
			write("\n}}\0");
			super.close();
		}
	}	
	/**
	 * Returns the index of the specified color in the RTF color table.
	 * <p>
	 *
	 * @param color the color
	 * @param defaultIndex return value if color is null
	 * @return the index of the specified color in the RTF color table
	 * 	or "defaultIndex" if "color" is null.
	 */
	int getColorIndex(Color color, int defaultIndex) {
		int index;
		
		if (color == null) {
			index = defaultIndex;
		}
		else {		
			index = colorTable.indexOf(color);
			if (index == -1) {
				index = colorTable.size();
				colorTable.addElement(color);
			}
		}
		return index;
	}
	/**
	 * Determines if Unicode RTF should be written.
	 * Don't write Unicode RTF on Windows 95/98/ME or NT.
	 */
	void setUnicode() {
		final String Win95 = "windows 95";
		final String Win98 = "windows 98";
		final String WinME = "windows me";		
		final String WinNT = "windows nt";
		String osName = System.getProperty("os.name").toLowerCase();
		String osVersion = System.getProperty("os.version");
		int majorVersion = 0;
		
		if (osName.startsWith(WinNT) && osVersion != null) {
			int majorIndex = osVersion.indexOf('.');
			if (majorIndex != -1) {
				osVersion = osVersion.substring(0, majorIndex);
				try {
					majorVersion = Integer.parseInt(osVersion);
				}
				catch (NumberFormatException exception) {
					// ignore exception. version number remains unknown.
					// will write without Unicode
				}
			}
		}
		if (osName != null &&
			osName.startsWith(Win95) == false &&
			osName.startsWith(Win98) == false &&
			osName.startsWith(WinME) == false &&
			(osName.startsWith(WinNT) == false || majorVersion > 4)) {
			WriteUnicode = true;
		}
		else {
			WriteUnicode = false;
		}
	}
	/**
	 * Appends the specified segment of "string" to the RTF data.
	 * Copy from <code>start</code> up to, but excluding, <code>end</code>.
	 * <p>
	 *
	 * @param string string to copy a segment from. Must not contain
	 * 	line breaks. Line breaks should be written using writeLineDelimiter()
	 * @param start start offset of segment. 0 based.
	 * @param end end offset of segment
	 */
	void write(String string, int start, int end) {
		for (int index = start; index < end; index++) {
			char ch = string.charAt(index);
			if (ch > 0xFF && WriteUnicode) {
				// write the sub string from the last escaped character 
				// to the current one. Fixes bug 21698.
				if (index > start) {
					write(string.substring(start, index));
				}
				write("\\u");
				write(Integer.toString((short) ch));
				write(' ');						// control word delimiter
				start = index + 1;
			}
			else
			if (ch == '}' || ch == '{' || ch == '\\') {
				// write the sub string from the last escaped character 
				// to the current one. Fixes bug 21698.
				if (index > start) {
					write(string.substring(start, index));
				}
				write('\\');
				write(ch);
				start = index + 1;
			}
		}
		// write from the last escaped character to the end.
		// Fixes bug 21698.
		if (start < end) {
			write(string.substring(start, end));
		}
	}	
	/**
	 * Writes the RTF header including font table and color table.
	 */
	void writeHeader() {
		StringBuffer header = new StringBuffer();
		FontData fontData = getFont().getFontData()[0];
		header.append("{\\rtf1\\ansi");
		// specify code page, necessary for copy to work in bidi 
		// systems that don't support Unicode RTF.
		String cpg = System.getProperty("file.encoding").toLowerCase();
		if (cpg.startsWith("cp") || cpg.startsWith("ms")) {
			cpg = cpg.substring(2, cpg.length());
			header.append("\\ansicpg");
			header.append(cpg);
		}
		header.append("\\uc0\\deff0{\\fonttbl{\\f0\\fnil ");
		header.append(fontData.getName());
		header.append(";}}\n{\\colortbl");
		for (int i = 0; i < colorTable.size(); i++) {
			Color color = (Color) colorTable.elementAt(i);
			header.append("\\red");
			header.append(color.getRed());
			header.append("\\green");
			header.append(color.getGreen());
			header.append("\\blue");
			header.append(color.getBlue());
			header.append(";");
		} 
		// some RTF readers ignore the deff0 font tag. Explicitly 
		// set the font for the whole document to work around this.
		header.append("}\n{\\f0\\fs");
		// font size is specified in half points
		header.append(fontData.getHeight() * 2);
		header.append(" ");
		write(header.toString(), 0);
	}
	/**
	 * Appends the specified line text to the RTF data.  Lines will be formatted 
	 * using the styles queried from the LineStyleListener, if set, or those set 
	 * directly in the widget.
	 * <p>
	 *
	 * @param line line text to write as RTF. Must not contain line breaks
	 * 	Line breaks should be written using writeLineDelimiter()
	 * @param lineOffset offset of the line. 0 based from the start of the 
	 * 	widget document. Any text occurring before the start offset or after the 
	 * 	end offset specified during object creation is ignored.
	 * @exception SWTException <ul>
	 *   <li>ERROR_IO when the writer is closed.</li>
	 * </ul>
	 */
	public void writeLine(String line, int lineOffset) {
		StyleRange[] styles = new StyleRange[0];
		Color lineBackground = null;
		StyledTextEvent event;
		
		if (isClosed()) {
			SWT.error(SWT.ERROR_IO);
		}
		event = renderer.getLineStyleData(lineOffset, line);
		if (event != null) {
			styles = event.styles;
		}
		event = renderer.getLineBackgroundData(lineOffset, line);
		if (event != null) {
			lineBackground = event.lineBackground;
		}
		if (lineBackground == null) {
			lineBackground = getBackground();
		}
		writeStyledLine(line, lineOffset, styles, lineBackground);
	}
	/**
	 * Appends the specified line delmimiter to the RTF data.
	 * <p>
	 *
	 * @param lineDelimiter line delimiter to write as RTF.
	 * @exception SWTException <ul>
	 *   <li>ERROR_IO when the writer is closed.</li>
	 * </ul>
	 */
	public void writeLineDelimiter(String lineDelimiter) {
		if (isClosed()) {
			SWT.error(SWT.ERROR_IO);
		}
		write(lineDelimiter, 0, lineDelimiter.length());
		write("\\par ");
	}
	/**
	 * Appends the specified line text to the RTF data.
	 * Use the colors and font styles specified in "styles" and "lineBackground".
	 * Formatting is written to reflect the text rendering by the text widget.
	 * Style background colors take precedence over the line background color.
	 * Background colors are written using the \highlight tag (vs. the \cb tag).
	 * <p>
	 *
	 * @param line line text to write as RTF. Must not contain line breaks
	 * 	Line breaks should be written using writeLineDelimiter()
	 * @param lineOffset offset of the line. 0 based from the start of the 
	 * 	widget document. Any text occurring before the start offset or after the 
	 * 	end offset specified during object creation is ignored.
	 * @param styles styles to use for formatting. Must not be null.
	 * @param linebackground line background color to use for formatting. 
	 * 	May be null.
	 */
	void writeStyledLine(String line, int lineOffset, StyleRange[] styles, Color lineBackground) {
		int lineLength = line.length();
		int lineIndex;
		int copyEnd;
		int startOffset = getStart();		
		int endOffset = startOffset + super.getCharCount();
		int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
		int writeOffset = startOffset - lineOffset;
		
		if (writeOffset >= line.length()) {
			return;					// whole line is outside write range
		}
		else
		if (writeOffset > 0) {
			lineIndex = writeOffset;		// line starts before RTF write start
		}
		else {
			lineIndex = 0;
		}
		if (lineBackground != null) {
			write("{\\highlight");
			write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
			write(" "); 
		}
		for (int i = 0; i < styles.length; i++) {		
			StyleRange style = styles[i];
			int start = style.start - lineOffset;
			int end = start + style.length;
			int colorIndex;
			// skip over partial first line
			if (end < writeOffset) {
				continue;
			}
			// style starts beyond line end or RTF write end
			if (start >= lineEndOffset) {
				break;
			}
			// write any unstyled text
			if (lineIndex < start) { 
				// copy to start of style
				// style starting betond end of write range or end of line 
				// is guarded against above.
				write(line, lineIndex, start);
				lineIndex = start;
			}
			// write styled text
			colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
			write("{\\cf");
			write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
			if (colorIndex != DEFAULT_BACKGROUND) {
				write("\\highlight");
				write(colorIndex);
			}
			if (style.fontStyle == SWT.BOLD) {
				write("\\b"); 
			}
			write(" "); 
			// copy to end of style or end of write range or end of line
			copyEnd = Math.min(end, lineEndOffset);
			// guard against invalid styles and let style processing continue
			copyEnd = Math.max(copyEnd, lineIndex);
			write(line, lineIndex, copyEnd);
			if (style.fontStyle == SWT.BOLD) {
				write("\\b0"); 
			}
			write("}");
			lineIndex = copyEnd;
		}
		// write unstyled text at the end of the line
		if (lineIndex < lineEndOffset) {
			write(line, lineIndex, lineEndOffset);
		}
		if (lineBackground != null) {
			write("}");
		}
	}
	}
	/**
	 * The <code>TextWriter</code> class is used to write widget content to
	 * a string.  Whole and partial lines and line breaks can be written. To write 
	 * partial lines, specify the start and length of the desired segment 
	 * during object creation.
	 * <p>
	 * </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close() 
	 * has been called. 
	 */
	class TextWriter {
		private StringBuffer buffer;
		private int startOffset;	// offset of first character that will be written
		private int endOffset;		// offset of last character that will be written. 
									// 0 based from the beginning of the widget text. 
		private boolean isClosed = false;
	
	/**
	 * Creates a writer that writes content starting at offset "start"
	 * in the document.  <code>start</code> and <code>length</code> can be set to specify partial lines.
	 * <p>
	 *
	 * @param start start offset of content to write, 0 based from beginning of document
	 * @param length length of content to write
	 */
	public TextWriter(int start, int length) {
		buffer = new StringBuffer(length);
		startOffset = start;
		endOffset = start + length;
	}
	/**
	 * Closes the writer. Once closed no more content can be written.
	 * <b>NOTE:</b>  <code>toString()</code> is not guaranteed to return a valid string unless
	 * the writer is closed.
	 */
	public void close() {
		if (isClosed == false) {
			isClosed = true;
		}
	}
	/** 
	 * Returns the number of characters to write.
	 */
	public int getCharCount() {
		return endOffset - startOffset;
	}	
	/** 
	 * Returns the offset where writing starts. 0 based from the start of 
	 * the widget text. Used to write partial lines.
	 */
	public int getStart() {
		return startOffset;
	}
	/**
	 * Returns whether the writer is closed.
	 */
	public boolean isClosed() {
		return isClosed;
	}
	/**
	 * Returns the string.  <code>close()</code> must be called before <code>toString()</code> 
	 * is guaranteed to return a valid string.
	 * <p>
	 *
	 * @return the string
	 */
	public String toString() {
		return buffer.toString();
	}
	/**
	 * Appends the given string to the data.
	 */
	void write(String string) {
		buffer.append(string);
	}	
	/**
	 * Inserts the given string to the data at the specified offset.
	 * Do nothing if "offset" is < 0 or > getCharCount()
	 * <p>
	 *
	 * @param string text to insert
	 * @param offset offset in the existing data to insert "string" at.
	 */
	void write(String string, int offset) {
		if (offset < 0 || offset > buffer.length()) {
			return;
		}
		buffer.insert(offset, string);
	}	
	/**
	 * Appends the given int to the data.
	 */
	void write(int i) {
		buffer.append(i);
	}
	/**
	 * Appends the given character to the data.
	 */
	void write(char i) {
		buffer.append(i);
	}			
	/**
	 * Appends the specified line text to the data.
	 * <p>
	 *
	 * @param line line text to write. Must not contain line breaks
	 * 	Line breaks should be written using writeLineDelimiter()
	 * @param lineOffset offset of the line. 0 based from the start of the 
	 * 	widget document. Any text occurring before the start offset or after the 
	 *	end offset specified during object creation is ignored.
	 * @exception SWTException <ul>
	 *   <li>ERROR_IO when the writer is closed.</li>
	 * </ul>
	 */
	public void writeLine(String line, int lineOffset) {
		int lineLength = line.length();
		int lineIndex;
		int copyEnd;
		int writeOffset = startOffset - lineOffset;
		
		if (isClosed) {
			SWT.error(SWT.ERROR_IO);
		}		
		if (writeOffset >= lineLength) {
			return;							// whole line is outside write range
		}
		else
		if (writeOffset > 0) {
			lineIndex = writeOffset;		// line starts before write start
		}
		else {
			lineIndex = 0;
		}
		copyEnd = Math.min(lineLength, endOffset - lineOffset);
		if (lineIndex < copyEnd) {
			write(line.substring(lineIndex, copyEnd));
		}		
	}
	/**
	 * Appends the specified line delmimiter to the data.
	 * <p>
	 *
	 * @param lineDelimiter line delimiter to write
	 * @exception SWTException <ul>
	 *   <li>ERROR_IO when the writer is closed.</li>
	 * </ul>
	 */
	public void writeLineDelimiter(String lineDelimiter) {
		if (isClosed) {
			SWT.error(SWT.ERROR_IO);
		}
		write(lineDelimiter);
	}
	}
	/**
	 * LineCache provides an interface to calculate and invalidate 
	 * line based data.
	 * Implementors need to return a line width in <code>getWidth</code>.
	 */
	interface LineCache {
	/**
	 * Calculates the lines in the specified range.
	 * <p>
	 * 
	 * @param startLine first line to calculate
	 * @param lineCount number of lines to calculate
	 */
	public void calculate(int startLine, int lineCount);
	/**
	 * Returns a width that will be used by the <code>StyledText</code> 
	 * widget to size a horizontal scroll bar.
	 * <p>
	 *
	 * @return the line width
	 */
	public int getWidth();
	/**
	 * Resets the lines in the specified range.
	 * This method is called in <code>StyledText.redraw()</code>
	 * and allows implementors to call redraw themselves during reset.
	 * <p>
	 *
	 * @param startLine the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=implementors should retain a 
	 * 	valid width even if it is affected by the reset operation.
	 * 	false=the width may be set to 0
	 */
	public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth);
	/**
	 * Resets the lines in the specified range.
	 * <p>
	 *
	 * @param startLine the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=implementors should retain a 
	 * 	valid width even if it is affected by the reset operation.
	 * 	false=the width may be set to 0
	 */
	public void reset(int startLine, int lineCount, boolean calculateMaxWidth);
	/** 
	 * Called when a text change occurred.
	 * <p>
	 *
	 * @param startOffset	the start offset of the text change
	 * @param newLineCount the number of inserted lines
	 * @param replaceLineCount the number of deleted lines
	 * @param newCharCount the number of new characters
	 * @param replaceCharCount the number of deleted characters
	 */  
	public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount);
	}
	/**
	 * Keeps track of line widths and the longest line in the 
	 * StyledText document.
	 * Line widths are calculated when requested by a call to 
	 * <code>calculate</code> and cached until reset by a call 
	 * to <code>redrawReset</code> or <code>reset</code>.
	 */
	class ContentWidthCache implements LineCache {
		StyledText parent;				// parent widget, used to create a GC for line measuring
		int[] lineWidth;				// width in pixel of each line in the document, -1 for unknown width
		StyledTextContent content;		// content to use for line width calculation
		int lineCount;					// number of lines in lineWidth array
		int maxWidth;					// maximum line width of all measured lines
		int maxWidthLineIndex;			// index of the widest line
				
	/** 
	 * Creates a new <code>ContentWidthCache</code> and allocates space 
	 * for the given number of lines.
	 * <p>
	 *
	 * @param parent the StyledText widget used to create a GC for 
	 * 	line measuring
	 * @param lineCount initial number of lines to allocate space for
	 */
	public ContentWidthCache(StyledText parent, StyledTextContent content) {
		this.parent = parent;
		this.content = content;
		this.lineCount = content.getLineCount();
		lineWidth = new int[lineCount];
		reset(0, lineCount, false);
	}
	/**
	 * Calculates the width of each line in the given range if it has
	 * not been calculated yet.
	 * If any line in the given range is wider than the currently widest
	 * line, the maximum line width is updated,
	 * <p>
	 * 
	 * @param startLine first line to calculate the line width of
	 * @param lineCount number of lines to calculate the line width for
	 */
	public void calculate(int startLine, int lineCount) {
		GC gc = null;
		int caretWidth = 0;
		int endLine = startLine + lineCount;
			
		if (startLine < 0 || endLine > lineWidth.length) {
			return;
		}
		for (int i = startLine; i < endLine; i++) {
			if (lineWidth[i] == -1) {
				String line = content.getLine(i);
				int lineOffset = content.getOffsetAtLine(i);
		
				if (gc == null) {
					gc = parent.getGC();
					caretWidth = getCaretWidth();
				}		
				lineWidth[i] = contentWidth(line, lineOffset, gc) + caretWidth;
			}
			if (lineWidth[i] > maxWidth) {
				maxWidth = lineWidth[i];
				maxWidthLineIndex = i;
			}
		}
		if (gc != null) {
			gc.dispose();	
		}
	}
	/** 
	 * Calculates the width of the visible lines in the specified 
	 * range.
	 * <p>
	 *
	 * @param startLine	the first changed line
	 * @param newLineCount the number of inserted lines
	 */  
	void calculateVisible(int startLine, int newLineCount) {
		int topIndex = parent.getTopIndex();
		int bottomLine = Math.min(getPartialBottomIndex(), startLine + newLineCount);
		
		startLine = Math.max(startLine, topIndex);
		calculate(startLine, bottomLine - startLine + 1);
	}
	/**
	 * Measures the width of the given line.
	 * <p>
	 * 
	 * @param line the line to measure
	 * @param lineOffset start offset of the line to measure, relative 
	 * 	to the start of the document
	 * @param gc the GC to use for measuring the line
	 * @param currentFont the font currently set in gc. Cached for better 
	 * 	performance. Null when running in a bidi locale.
	 * @return the width of the given line
	 */
	int contentWidth(String line, int lineOffset, GC gc) {
		int width;
		
		if (isBidi()) {
			StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc);
			width = bidi.getTextWidth();
		}
		else {
			StyledTextEvent event = renderer.getLineStyleData(lineOffset, line);
			StyleRange[] styles = null;
			if (event != null) {
				styles = renderer.filterLineStyles(event.styles);
			}
			width = renderer.getTextWidth(line, lineOffset, 0, line.length(), styles, 0, gc);
		}
		return width + leftMargin;
	}
	/**
	 * Grows the <code>lineWidth</code> array to accomodate new line width
	 * information.
	 * <p>
	 *
	 * @param numLines the number of elements to increase the array by
	 */
	void expandLines(int numLines) {
		int size = lineWidth.length;
		if (size - lineCount >= numLines) {
			return;
		}
		int[] newLines = new int[Math.max(size * 2, size + numLines)];
		System.arraycopy(lineWidth, 0, newLines, 0, size);
		lineWidth = newLines;
		reset(size, lineWidth.length - size, false);
	}
	/**
	 * Returns the width of the longest measured line.
	 * <p>
	 *
	 * @return the width of the longest measured line.
	 */
	public int getWidth() {
		return maxWidth;
	}
	/**
	 * Updates the line width array to reflect inserted or deleted lines.
	 * <p>
	 *
	 * @param start	the starting line of the change that took place
	 * @param delta	the number of lines in the change, > 0 indicates lines inserted,
	 * 	< 0 indicates lines deleted
	 */
	void linesChanged(int startLine, int delta) {
		boolean inserting = delta > 0;
		
		if (delta == 0) {
			return;
		}
		if (inserting) {
			// shift the lines down to make room for new lines
			expandLines(delta);
			for (int i = lineCount - 1; i >= startLine; i--) {
				lineWidth[i + delta] = lineWidth[i];
			}
			// reset the new lines
			for (int i = startLine + 1; i <= startLine + delta && i < lineWidth.length; i++) {
				lineWidth[i] = -1;
			}
			// have new lines been inserted above the longest line?
			if (maxWidthLineIndex >= startLine) {
				maxWidthLineIndex += delta;
			}
		} 
		else {
			// shift up the lines
			for (int i = startLine - delta; i < lineCount; i++) {
				lineWidth[i+delta] = lineWidth[i];
			}
			// has the longest line been removed?
			if (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine - delta) {
				maxWidth = 0;
				maxWidthLineIndex = -1;
			}
			else
			if (maxWidthLineIndex >= startLine - delta) {
				maxWidthLineIndex += delta;
			}
		}
		lineCount += delta;
	}
	/**
	 * Resets the line width of the lines in the specified range.
	 * <p>
	 *
	 * @param startLine	the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=if the widest line is being 
	 * 	reset the maximum width of all remaining cached lines is 
	 * 	calculated. false=the maximum width is set to 0 if the 
	 * 	widest line is being reset.
	 */
	public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) {
		reset(startLine, lineCount, calculateMaxWidth);
	}
	/**
	 * Resets the line width of the lines in the specified range.
	 * <p>
	 *
	 * @param startLine	the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=if the widest line is being 
	 * 	reset the maximum width of all remaining cached lines is 
	 * 	calculated. false=the maximum width is set to 0 if the 
	 * 	widest line is being reset.
	 */
	public void reset(int startLine, int lineCount, boolean calculateMaxWidth) {
		int endLine = startLine + lineCount;
		
		if (startLine < 0 || endLine > lineWidth.length) {
			return;
		}
		for (int i = startLine; i < endLine; i++) {
			lineWidth[i] = -1;
		}		
		// if the longest line is one of the reset lines, the maximum line 
		// width is no longer valid
		if (maxWidthLineIndex >= startLine && maxWidthLineIndex < endLine) {
			maxWidth = 0;
			maxWidthLineIndex = -1;
			if (calculateMaxWidth) {
				for (int i = 0; i < lineCount; i++) {
					if (lineWidth[i] > maxWidth) {
						maxWidth = lineWidth[i];
						maxWidthLineIndex = i;
					}
				}			
			}
		}
	}
	/** 
	 * Updates the line width array to reflect a text change.
	 * Lines affected by the text change will be reset.
	 * <p>
	 *
	 * @param startOffset	the start offset of the text change
	 * @param newLineCount the number of inserted lines
	 * @param replaceLineCount the number of deleted lines
	 * @param newCharCount the number of new characters
	 * @param replaceCharCount the number of deleted characters
	 */  
	public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) {
		int startLine = parent.getLineAtOffset(startOffset);
		boolean removedMaxLine = (maxWidthLineIndex > startLine && maxWidthLineIndex <= startLine + replaceLineCount);
		// entire text deleted?
		if (startLine == 0 && replaceLineCount == lineCount) {
			lineCount = newLineCount;
			lineWidth = new int[lineCount];
			reset(0, lineCount, false);
			maxWidth = 0;
		}
		else {
			linesChanged(startLine, -replaceLineCount);
			linesChanged(startLine, newLineCount);
			lineWidth[startLine] = -1;
		}
		// only calculate the visible lines. otherwise measurements of changed lines 
		// outside the visible area may subsequently change again without the 
		// lines ever being visible.
		calculateVisible(startLine, newLineCount);
		// maxWidthLineIndex will be -1 (i.e., unknown line width) if the widget has 
		// not been visible yet and the changed lines have therefore not been
		// calculated above.
		if (removedMaxLine || 
			(maxWidthLineIndex != -1 && lineWidth[maxWidthLineIndex] < maxWidth)) {
			// longest line has been removed or changed and is now shorter.
			// need to recalculate maximum content width for all lines
			maxWidth = 0;
			for (int i = 0; i < lineCount; i++) {
				if (lineWidth[i] > maxWidth) {
					maxWidth = lineWidth[i];
					maxWidthLineIndex = i;
				}
			}			
		}
	}
	}
	/**
	 * Updates the line wrapping of the content.
	 * The line wrapping must always be in a consistent state. 
	 * Therefore, when <code>reset</code> or <code>redrawReset</code>
	 * is called, the line wrapping is recalculated immediately 
	 * instead of in <code>calculate</code>.
	 */
	class WordWrapCache implements LineCache {
		StyledText parent;
		WrappedContent visualContent;
				
	/** 
	 * Creates a new <code>WordWrapCache</code> and calculates an initial
	 * line wrapping.
	 * <p>
	 *
	 * @param parent the StyledText widget to wrap content in.
	 * @param content the content provider that does the actual line wrapping.
	 */
	public WordWrapCache(StyledText parent, WrappedContent content) {
		this.parent = parent;
		visualContent = content;
		visualContent.wrapLines();
	}
	/**
	 * Do nothing. Lines are wrapped immediately after reset.
	 * <p>
	 * 
	 * @param startLine first line to calculate
	 * @param lineCount number of lines to calculate
	 */
	public void calculate(int startLine, int lineCount) {
	}
	/**
	 * Returns the client area width. Lines are wrapped so there
	 * is no horizontal scroll bar.
	 * <p>
	 *
	 * @return the line width
	 */
	public int getWidth() {
		return parent.getClientArea().width;
	}
	/**
	 * Wraps the lines in the specified range.
	 * This method is called in <code>StyledText.redraw()</code>.
	 * A redraw is therefore not necessary.
	 * <p>
	 *
	 * @param startLine the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=implementors should retain a 
	 * 	valid width even if it is affected by the reset operation.
	 * 	false=the width may be set to 0
	 */
	public void redrawReset(int startLine, int lineCount, boolean calculateMaxWidth) {
	    if (lineCount == visualContent.getLineCount()) {
			// do a full rewrap if all lines are reset
			visualContent.wrapLines();
	    }
	    else {
		    visualContent.reset(startLine, lineCount);
	    }
	}
	/**
	 * Rewraps the lines in the specified range and redraws
	 * the widget if the line wrapping has changed.
	 * <p>
	 *
	 * @param startLine the first line to reset
	 * @param lineCount the number of lines to reset
	 * @param calculateMaxWidth true=implementors should retain a 
	 * 	valid width even if it is affected by the reset operation.
	 * 	false=the width may be set to 0
	 */
	public void reset(int startLine, int lineCount, boolean calculateMaxWidth) {
		int itemCount = getPartialBottomIndex() - topIndex + 1;
	    int[] oldLineOffsets = new int[itemCount];
	    
	    for (int i = 0; i < itemCount; i++) {
	    	oldLineOffsets[i] = visualContent.getOffsetAtLine(i + topIndex);
	    }
	    redrawReset(startLine, lineCount, calculateMaxWidth);
		// check for cases which will require a full redraw
	    if (getPartialBottomIndex() - topIndex + 1 != itemCount) {
	    	// number of visible lines has changed
	    	parent.internalRedraw();
	    }
	    else {
		    for (int i = 0; i < itemCount; i++) {
		    	if (visualContent.getOffsetAtLine(i + topIndex) != oldLineOffsets[i]) {
		    		// wrapping of one of the visible lines has changed
		    		parent.internalRedraw();
		    		break;
		    	}
	    	}	    	
	    }
	}
	/** 
	 * Passes the text change notification to the line wrap content.
	 * <p>
	 *
	 * @param startOffset	the start offset of the text change
	 * @param newLineCount the number of inserted lines
	 * @param replaceLineCount the number of deleted lines
	 * @param newCharCount the number of new characters
	 * @param replaceCharCount the number of deleted characters
	 */  
	public void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) {
		int startLine = visualContent.getLineAtOffset(startOffset);
		
		visualContent.textChanged(startOffset, newLineCount, replaceLineCount, newCharCount, replaceCharCount);
		if (startLine <= getPartialBottomIndex()) {
			// only redraw if the text change is inside or above the 
			// visible lines. if it is below the visible lines it will
			// not affect the word wrapping. fixes bug 14047.
			parent.internalRedraw();
		}
	}
	}

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together 
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 * </ul>
 *
 * @see SWT#FULL_SELECTION
 * @see SWT#MULTI
 * @see SWT#READ_ONLY
 * @see SWT#SINGLE
 * @see SWT#WRAP
 * @see #getStyle
 */
public StyledText(Composite parent, int style) {
	super(parent, checkStyle(style | SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND));
	// set the bg/fg in the OS to ensure that these are the same as StyledText, necessary
	// for ensuring that the bg/fg the IME box uses is the same as what StyledText uses
	super.setForeground(getForeground());
	super.setBackground(getBackground());
	Display display = getDisplay();
	boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0;
	isBidi = StyledTextBidi.isBidiPlatform() || isRightOriented;
	if ((style & SWT.READ_ONLY) != 0) {
		setEditable(false);
	}
	if ((style & SWT.BORDER) == 0 || (style & SWT.SINGLE) == 0) {
		leftMargin = topMargin = rightMargin = bottomMargin = 0;
	}
	clipboard = new Clipboard(display);
	installDefaultContent();
	initializeRenderer();
	if ((style & SWT.WRAP) != 0) {
		setWordWrap(true);
	}
	else {
	    lineCache = new ContentWidthCache(this, content);
	}	
	if (isBidi() == false) {
		Caret caret = new Caret(this, SWT.NULL);
		caret.setSize(1, caret.getSize().y);
	} 
	else {
		createCaretBitmaps();
		if (isRightOriented) {
			BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
		}
		new Caret(this, SWT.NULL);			
		setBidiCaretDirection();
		Runnable runnable = new Runnable() {
			public void run() {
				// setBidiCaretLocation calculates caret location like during 
				// cursor movement and takes keyboard language into account. 
				// Fixes 1GKPYMK
				setBidiCaretLocation(null);
			}
		};
		StyledTextBidi.addLanguageListener(this, runnable);
	}
	
	String platform= SWT.getPlatform();
	isCarbon = "carbon".equals(platform);	
	
	// set the caret width, the height of the caret will default to the line height
	calculateScrollBars();
	createKeyBindings();
	ibeamCursor = new Cursor(display, SWT.CURSOR_IBEAM);
	setCursor(ibeamCursor);
	installListeners();
	installDefaultLineStyler();
}
/**	 
 * Adds an extended modify listener. An ExtendedModify event is sent by the 
 * widget when the widget text has changed.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
	checkWidget();
	if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	StyledTextListener typedListener = new StyledTextListener(extendedModifyListener);
	addListener(ExtendedModify, typedListener);
}
/** 
 * Maps a key to an action.
 * One action can be associated with N keys. However, each key can only 
 * have one action (key:action is N:1 relation).
 * <p>
 *
 * @param key a key code defined in SWT.java or a character. 
 * 	Optionally ORd with a state mask.  Preferred state masks are one or more of
 *  SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform 
 *  differences.  However, there may be cases where using the specific state masks
 *  (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
 * @param action one of the predefined actions defined in ST.java. 
 * 	Use SWT.NULL to remove a key binding.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setKeyBinding(int key, int action) {
	checkWidget(); 
	
	int keyValue = key & SWT.KEY_MASK;
	int modifierValue = key & SWT.MODIFIER_MASK;
	char keyChar = (char)keyValue;

	if (Character.isLetter(keyChar)) {
		// make the keybinding case insensitive by adding it
		// in its upper and lower case form
		char ch = Character.toUpperCase(keyChar);
		int newKey = ch | modifierValue;
		if (action == SWT.NULL) {
			keyActionMap.remove(new Integer(newKey));
		}
		else {
		 	keyActionMap.put(new Integer(newKey), new Integer(action));
		}
		ch = Character.toLowerCase(keyChar);
		newKey = ch | modifierValue;
		if (action == SWT.NULL) {
			keyActionMap.remove(new Integer(newKey));
		}
		else {
		 	keyActionMap.put(new Integer(newKey), new Integer(action));
		}
	} else {
		if (action == SWT.NULL) {
			keyActionMap.remove(new Integer(key));
		}
		else {
		 	keyActionMap.put(new Integer(key), new Integer(action));
		}
	}
		
}
/**
 * Adds a bidirectional segment listener. A BidiSegmentEvent is sent 
 * whenever a line of text is measured or rendered. The user can 
 * specify text ranges in the line that should be treated as if they 
 * had a different direction than the surrounding text.
 * This may be used when adjacent segments of right-to-left text should
 * not be reordered relative to each other. 
 * E.g., Multiple Java string literals in a right-to-left language
 * should generally remain in logical order to each other, that is, the
 * way they are stored. 
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 * @see BidiSegmentEvent
 * @since 2.0
 */
public void addBidiSegmentListener(BidiSegmentListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	StyledTextListener typedListener = new StyledTextListener(listener);
	addListener(LineGetSegments, typedListener);	
}
/**
 * Adds a line background listener. A LineGetBackground event is sent by the 
 * widget to determine the background color for a line.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addLineBackgroundListener(LineBackgroundListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (userLineBackground == false) {
		removeLineBackgroundListener(defaultLineStyler);
		defaultLineStyler.setLineBackground(0, logicalContent.getLineCount(), null);
		userLineBackground = true;
	}	
	StyledTextListener typedListener = new StyledTextListener(listener);
	addListener(LineGetBackground, typedListener);	
}
/**
 * Adds a line style listener. A LineGetStyle event is sent by the widget to 
 * determine the styles for a line.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addLineStyleListener(LineStyleListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	if (userLineStyle == false) {
		removeLineStyleListener(defaultLineStyler);
		defaultLineStyler.setStyleRange(null);
		userLineStyle = true;
	}
	StyledTextListener typedListener = new StyledTextListener(listener);
	addListener(LineGetStyle, typedListener);	
}
/**	 
 * Adds a modify listener. A Modify event is sent by the widget when the widget text 
 * has changed.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addModifyListener(ModifyListener modifyListener) {
	checkWidget();
	if (modifyListener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	TypedListener typedListener = new TypedListener(modifyListener);
	addListener(SWT.Modify, typedListener);
}
/**	 
 * Adds a selection listener. A Selection event is sent by the widget when the 
 * selection has changed.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	TypedListener typedListener = new TypedListener(listener);
	addListener(SWT.Selection, typedListener);	
}
/**	 
 * Adds a verify key listener. A VerifyKey event is sent by the widget when a key 
 * is pressed. The widget ignores the key press if the listener sets the doit field 
 * of the event to false. 
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addVerifyKeyListener(VerifyKeyListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	StyledTextListener typedListener = new StyledTextListener(listener);
	addListener(VerifyKey, typedListener);	
}
/**	 
 * Adds a verify listener. A Verify event is sent by the widget when the widget text 
 * is about to change. The listener can set the event text and the doit field to 
 * change the text that is set in the widget or to force the widget to ignore the 
 * text change.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void addVerifyListener(VerifyListener verifyListener) {
	checkWidget();
	if (verifyListener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	TypedListener typedListener = new TypedListener(verifyListener);
	addListener(SWT.Verify, typedListener);
}
/** 
 * Appends a string to the text at the end of the widget.
 * <p>
 *
 * @param string the string to be appended
 * @see #replaceTextRange(int,int,String)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void append(String string) {
	checkWidget();
	if (string == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	int lastChar = Math.max(getCharCount(), 0);
	replaceTextRange(lastChar, 0, string);
}
/**
 * Calculates the width of the widest visible line.
 */
void calculateContentWidth() {
    lineCache = getLineCache(content);
	lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1);
}
/**
 * Calculates the scroll bars
 */
void calculateScrollBars() {
	ScrollBar horizontalBar = getHorizontalBar();
	ScrollBar verticalBar = getVerticalBar();
	
	setScrollBars();
	if (verticalBar != null) {
		verticalBar.setIncrement(getVerticalIncrement());
	}	
	if (horizontalBar != null) {
		horizontalBar.setIncrement(getHorizontalIncrement());
	}
}
/**
 * Calculates the top index based on the current vertical scroll offset.
 * The top index is the index of the topmost fully visible line or the
 * topmost partially visible line if no line is fully visible.
 * The top index starts at 0.
 */
void calculateTopIndex() {
	int oldTopIndex = topIndex;
	int verticalIncrement = getVerticalIncrement();
	int clientAreaHeight = getClientArea().height;
	
	if (verticalIncrement == 0) {
		return;
	}
	topIndex = Compatibility.ceil(verticalScrollOffset, verticalIncrement);
	// Set top index to partially visible top line if no line is fully 
	// visible but at least some of the widget client area is visible.
	// Fixes bug 15088.
	if (topIndex > 0) {
		if (clientAreaHeight > 0) {
			int bottomPixel = verticalScrollOffset + clientAreaHeight;
			int fullLineTopPixel = topIndex * verticalIncrement;
			int fullLineVisibleHeight = bottomPixel - fullLineTopPixel;
			// set top index to partially visible line if no line fully fits in 
			// client area or if space is available but not used (the latter should
			// never happen because we use claimBottomFreeSpace)
			if (fullLineVisibleHeight < verticalIncrement) {
				topIndex--;
			}
		}
		else 
		if (topIndex >= content.getLineCount()) {
			topIndex = content.getLineCount() - 1;
		}
	}
	if (topIndex != oldTopIndex) {
		topOffset = content.getOffsetAtLine(topIndex);
		lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1);
		setHorizontalScrollBar();
	}
}
/**
 * Hides the scroll bars if widget is created in single line mode.
 */
static int checkStyle(int style) {
	if ((style & SWT.SINGLE) != 0) {
		style &= ~(SWT.H_SCROLL | SWT.V_SCROLL);
	} else {
		style |= SWT.MULTI;
	}
	return style;
}
/**
 * Scrolls down the text to use new space made available by a resize or by 
 * deleted lines.
 */
void claimBottomFreeSpace() {
	int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - getClientArea().height);
	
	if (newVerticalOffset < verticalScrollOffset) {
		// Scroll up so that empty lines below last text line are used.
		// Fixes 1GEYJM0
		setVerticalScrollOffset(newVerticalOffset, true);
	}
}
/**
 * Scrolls text to the right to use new space made available by a resize.
 */
void claimRightFreeSpace() {
	int newHorizontalOffset = Math.max(0, lineCache.getWidth() - (getClientArea().width - leftMargin - rightMargin));
	
	if (newHorizontalOffset < horizontalScrollOffset) {			
		// item is no longer drawn past the right border of the client area
		// align the right end of the item with the right border of the 
		// client area (window is scrolled right).
		scrollHorizontalBar(newHorizontalOffset - horizontalScrollOffset);					
	}
}
/**
 * Clears the widget margin.
 * 
 * @param gc GC to render on
 * @param background background color to use for clearing the margin
 * @param clientArea widget client area dimensions
 * @param renderHeight height in pixel of the rendered lines
 */
void clearMargin(GC gc, Color background, Rectangle clientArea, int renderHeight) {
	if (renderHeight + topMargin <= 0) {
		return;
	}
	// clear the margin background
	gc.setBackground(background);
	gc.fillRectangle(0, 0, clientArea.width, topMargin);
	gc.fillRectangle(0, 0, leftMargin, renderHeight + topMargin);	
	gc.fillRectangle(
		0, clientArea.height - bottomMargin, 
		clientArea.width, bottomMargin);
	gc.fillRectangle(
		clientArea.width - rightMargin, 0, 
		rightMargin, renderHeight + topMargin);
}
/**
 * Removes the widget selection.
 * <p>
 *
 * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset.
 */
void clearSelection(boolean sendEvent) {
	int selectionStart = selection.x;
	int selectionEnd = selection.y;
	int length = content.getCharCount();
	
	resetSelection();
	// redraw old selection, if any
	if (selectionEnd - selectionStart > 0) {
		// called internally to remove selection after text is removed
		// therefore make sure redraw range is valid.
		int redrawStart = Math.min(selectionStart, length);
		int redrawEnd = Math.min(selectionEnd, length);
		if (redrawEnd - redrawStart > 0) {
			internalRedrawRange(redrawStart, redrawEnd - redrawStart, true);
		}
		if (sendEvent == true) {
			sendSelectionEvent();
		}
	}
}
/**
 * Computes the preferred size.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	int count, width, height;
	boolean singleLine = (getStyle() & SWT.SINGLE) != 0;
	
	if (singleLine) {
		count = 1;
	} else {
		count = content.getLineCount();
	}
	if (wHint != SWT.DEFAULT) {
		width = wHint;
	} 
	else {
		width = DEFAULT_WIDTH;
	}
	if (wHint == SWT.DEFAULT) {
		LineCache computeLineCache = lineCache;
		if (wordWrap) {
			// set non-wrapping content width calculator. Ensures ideal line width 
			// that does not required wrapping. Fixes bug 31195.
			computeLineCache = new ContentWidthCache(this, logicalContent);
			if (singleLine == false) {
				count = logicalContent.getLineCount();
			}
		}
		// Only calculate what can actually be displayed.
		// Do this because measuring each text line is a 
		// time-consuming process.
		int visibleCount = Math.min (count, getDisplay().getBounds().height / lineHeight);
		computeLineCache.calculate(0, visibleCount);
		width = computeLineCache.getWidth() + leftMargin + rightMargin;
	}
	else
	if (wordWrap && singleLine == false) {
		// calculate to wrap to width hint. Fixes bug 20377. 
		// don't wrap live content. Fixes bug 38344.
		WrappedContent wrappedContent = new WrappedContent(renderer, logicalContent);
		wrappedContent.wrapLines(width);
		count = wrappedContent.getLineCount();
	}
	if (hHint != SWT.DEFAULT) {
		height = hHint;
	} 
	else {
		height = count * lineHeight + topMargin + bottomMargin;
	}
	// Use default values if no text is defined.
	if (width == 0) {
		width = DEFAULT_WIDTH;
	}
	if (height == 0) {
		if (singleLine) {
			height = lineHeight;
		}
		else {
			height = DEFAULT_HEIGHT;
		}
	}
	Rectangle rect = computeTrim(0, 0, width, height);
	return new Point (rect.width, rect.height);
}
/**
 * Copies the selected text to the clipboard.  The text will be put in the 
 * clipboard in plain text format and RTF format.
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void copy() {
	checkWidget();
	int length = selection.y - selection.x;
	if (length > 0) {
		try {
			setClipboardContent(selection.x, length);
		}
		catch (SWTError error) {
			// Copy to clipboard failed. This happens when another application 
			// is accessing the clipboard while we copy. Ignore the error.
			// Fixes 1GDQAVN
			// Rethrow all other errors. Fixes bug 17578.
			if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
				throw error;
			}
		}
	}
}
/**
 * Returns a string that uses only the line delimiter specified by the 
 * StyledTextContent implementation.
 * Returns only the first line if the widget has the SWT.SINGLE style.
 * <p>
 *
 * @param text the text that may have line delimiters that don't 
 * 	match the model line delimiter. Possible line delimiters 
 * 	are CR ('\r'), LF ('\n'), CR/LF ("\r\n")
 * @return the converted text that only uses the line delimiter 
 * 	specified by the model. Returns only the first line if the widget 
 * 	has the SWT.SINGLE style.
 */
String getModelDelimitedText(String text) {
	StringBuffer convertedText;
	String delimiter = getLineDelimiter();
	int length = text.length();	
	int crIndex = 0;
	int lfIndex = 0;
	int i = 0;
	
	if (length == 0) {
		return text;
	}
	convertedText = new StringBuffer(length);
	while (i < length) {
		if (crIndex != -1) {
			crIndex = text.indexOf(SWT.CR, i);
		}
		if (lfIndex != -1) {
			lfIndex = text.indexOf(SWT.LF, i);
		}
		if (lfIndex == -1 && crIndex == -1) {	// no more line breaks?
			break;
		}
		else									// CR occurs before LF or no LF present?
		if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) {	
			convertedText.append(text.substring(i, crIndex));
			if (lfIndex == crIndex + 1) {		// CR/LF combination?
				i = lfIndex + 1;
			}
			else {
				i = crIndex + 1;
			}
		}
		else {									// LF occurs before CR!
			convertedText.append(text.substring(i, lfIndex));
			i = lfIndex + 1;
		}
		if (isSingleLine()) {
			break;
		}
		convertedText.append(delimiter);
	}
	// copy remaining text if any and if not in single line mode or no 
	// text copied thus far (because there only is one line)
	if (i < length && (isSingleLine() == false || convertedText.length() == 0)) {
		convertedText.append(text.substring(i));
	}
	return convertedText.toString();
}
/**
 * Creates default key bindings.
 */
void createKeyBindings() {
	// Navigation
	setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);	
	setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
	setKeyBinding(SWT.HOME, ST.LINE_START);
	setKeyBinding(SWT.END, ST.LINE_END);
	setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
	setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
	setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);	
	setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
	setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
	if ((getStyle() & SWT.MIRRORED) == 0) {
		setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS);
		setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT);
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT);
	} 
	else {
		setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_NEXT);
		setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_PREVIOUS);
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_NEXT);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_PREVIOUS);
	}
	
	// Selection
	setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);	
	setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
	setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
	setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
	setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
	setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);	
	setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
	setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
	if ((getStyle() & SWT.MIRRORED) == 0) {
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);	    	    
	}
	else {
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);	  
		setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
		setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
	}
           	  	
	// Modification
	// Cut, Copy, Paste
	setKeyBinding('X' | SWT.MOD1, ST.CUT);
	setKeyBinding('C' | SWT.MOD1, ST.COPY);
	setKeyBinding('V' | SWT.MOD1, ST.PASTE);
	// Cut, Copy, Paste Wordstar style
	setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT);
	setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY);
	setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE);
	setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS);
	
	setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS);
	setKeyBinding(SWT.DEL, ST.DELETE_NEXT);
	setKeyBinding(SWT.BS | SWT.MOD1, ST.DELETE_WORD_PREVIOUS);
	setKeyBinding(SWT.DEL | SWT.MOD1, ST.DELETE_WORD_NEXT);
	
	// Miscellaneous
	setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE);
}
/**
 * Create the bitmaps to use for the caret in bidi mode.  This
 * method only needs to be called upon widget creation and when the
 * font changes (the caret bitmap height needs to match font height).
 */
void createCaretBitmaps() {
	int caretWidth = BIDI_CARET_WIDTH;
	int gcStyle = getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
	
	Display display = getDisplay();	
	if (caretPalette == null) {
		caretPalette = new PaletteData(new RGB[] {new RGB (0,0,0), new RGB (255,255,255)});
	}	
	if (leftCaretBitmap != null) {
		leftCaretBitmap.dispose();
	}
	ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette);
	leftCaretBitmap = new Image(display, imageData);
	// mirror the caret gc because when the bitmap is rendered on the screen it will be 
	// mirrored since the GC for the canvas is mirrored
	GC gc = new GC (leftCaretBitmap, gcStyle); 
	gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
	gc.drawLine(0,0,0,lineHeight);
	gc.drawLine(0,0,caretWidth-1,0);
	gc.drawLine(0,1,1,1);
	gc.dispose();	
	
	if (rightCaretBitmap != null) {
		rightCaretBitmap.dispose();
	}
	rightCaretBitmap = new Image(display, imageData);
	// mirror the caret gc because when the bitmap is rendered on the screen it will be 
	// mirrored since the GC for the canvas is mirrored
	gc = new GC (rightCaretBitmap, gcStyle); 
	gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
	gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
	gc.drawLine(0,0,caretWidth-1,0);
	gc.drawLine(caretWidth-1,1,1,1);
	gc.dispose();	
}
/**
 * Moves the selected text to the clipboard.  The text will be put in the 
 * clipboard in plain text format and RTF format.
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void cut(){
	checkWidget();
	int length = selection.y - selection.x;
	
	if (length > 0) {
		try {
			setClipboardContent(selection.x, length);
		}
		catch (SWTError error) {
			// Copy to clipboard failed. This happens when another application 
			// is accessing the clipboard while we copy. Ignore the error.
			// Fixes 1GDQAVN
			// Rethrow all other errors. Fixes bug 17578.
			if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
				throw error;
			}
			// Abort cut operation if copy to clipboard fails.
			// Fixes bug 21030.
			return;
		}
		doDelete();
	}
}
/** 
 * A mouse move event has occurred.  See if we should start autoscrolling.  If
 * the move position is outside of the client area, initiate autoscrolling.  
 * Otherwise, we've moved back into the widget so end autoscrolling.
 */
void doAutoScroll(Event event) {
	Rectangle area = getClientArea();		
	
	if (event.y > area.height) {
		doAutoScroll(SWT.DOWN);
	}
	else 
	if (event.y < 0) {
		doAutoScroll(SWT.UP);
	}
	else 
	if (event.x < leftMargin && wordWrap == false) {
		doAutoScroll(ST.COLUMN_PREVIOUS);
	}
	else 
	if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) {
		doAutoScroll(ST.COLUMN_NEXT);
	}
	else {
		endAutoScroll();
	}
}
/** 
 * Initiates autoscrolling.
 * <p>
 *
 * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
 */
void doAutoScroll(int direction) {
	Runnable timer = null;
	final int TIMER_INTERVAL = 5;
	
	// If we're already autoscrolling in the given direction do nothing
	if (autoScrollDirection == direction) {
		return;
	}
	
	final Display display = getDisplay();
	// Set a timer that will simulate the user pressing and holding
	// down a cursor key (i.e., arrowUp, arrowDown).
	if (direction == SWT.UP) {
		timer = new Runnable() {
			public void run() {
				if (autoScrollDirection == SWT.UP) {
					doSelectionLineUp();
					display.timerExec(TIMER_INTERVAL, this);
				}
			}
		};
	} else if (direction == SWT.DOWN) {
		timer = new Runnable() {
			public void run() {
				if (autoScrollDirection == SWT.DOWN) {
					doSelectionLineDown();
					display.timerExec(TIMER_INTERVAL, this);
				}
			}
		};
	} else if (direction == ST.COLUMN_NEXT) {
		timer = new Runnable() {
			public void run() {
				if (autoScrollDirection == ST.COLUMN_NEXT) {
					doVisualNext();
					setMouseWordSelectionAnchor();
					doMouseSelection();
					display.timerExec(TIMER_INTERVAL, this);
				}
			}
		};
	} else if (direction == ST.COLUMN_PREVIOUS) {
		timer = new Runnable() {
			public void run() {
				if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
					doVisualPrevious();
					setMouseWordSelectionAnchor();
					doMouseSelection();
					display.timerExec(TIMER_INTERVAL, this);
				}
			}
		};
	} 	
	if (timer != null) {
		autoScrollDirection = direction;
		display.timerExec(TIMER_INTERVAL, timer);
	}
}
/**
 * Deletes the previous character. Delete the selected text if any.
 * Move the caret in front of the deleted text.
 */
void doBackspace() {
	Event event = new Event();
	event.text = "";
	if (selection.x != selection.y) {
		event.start = selection.x;
		event.end = selection.y;
		sendKeyEvent(event);
	}
	else
	if (caretOffset > 0) {
		int line = content.getLineAtOffset(caretOffset);
		int lineOffset = content.getOffsetAtLine(line);			
	
		if (caretOffset == lineOffset) {
			lineOffset = content.getOffsetAtLine(line - 1);
			event.start = lineOffset + content.getLine(line - 1).length();
			event.end = caretOffset;
		}
		else {
			event.start = caretOffset - 1;
			event.end = caretOffset;
		}
		sendKeyEvent(event);
	}
}
/**
 * Replaces the selection with the character or insert the character at the 
 * current caret position if no selection exists.
 * If a carriage return was typed replace it with the line break character 
 * used by the widget on this platform.
 * <p>
 *
 * @param key the character typed by the user
 */
void doContent(char key) {
	Event event;
	
	if (textLimit > 0 && 
		content.getCharCount() - (selection.y - selection.x) >= textLimit) {
		return;
	}	
	event = new Event();
	event.start = selection.x;
	event.end = selection.y;
	// replace a CR line break with the widget line break
	// CR does not make sense on Windows since most (all?) applications
	// don't recognize CR as a line break.
	if (key == SWT.CR || key == SWT.LF) {
		if (isSingleLine() == false) {
			event.text = getLineDelimiter();
		}
	}
	// no selection and overwrite mode is on and the typed key is not a
	// tab character (tabs are always inserted without overwriting)?
	else
	if (selection.x == selection.y && overwrite == true && key != TAB) {
		int lineIndex = content.getLineAtOffset(event.end);
		int lineOffset = content.getOffsetAtLine(lineIndex);
		String line = content.getLine(lineIndex);
		// replace character at caret offset if the caret is not at the 
		// end of the line
		if (event.end < lineOffset + line.length()) {
			event.end++;
		}
		event.text = new String(new char[] {key});
	}
	else {
		event.text = new String(new char[] {key});
	}
	if (event.text != null) {
		sendKeyEvent(event);
	}
}
/**
 * Moves the caret after the last character of the widget content.
 */
void doContentEnd() {
	// place caret at end of first line if receiver is in single 
	// line mode. fixes 4820.
	if (isSingleLine()) {
		doLineEnd();
	}
	else {
		int length = content.getCharCount();		
		if (caretOffset < length) {
			caretOffset = length;
			showCaret();
		}
	}
}
/**
 * Moves the caret in front of the first character of the widget content.
 */
void doContentStart() {
	if (caretOffset > 0) {
		caretOffset = 0;
		showCaret();
	}
}
/**
 * Moves the caret to the start of the selection if a selection exists.
 * Otherwise, if no selection exists move the cursor according to the 
 * cursor selection rules.
 * <p>
 *
 * @see #doSelectionCursorPrevious
 */
void doCursorPrevious() {
	if (selection.y - selection.x > 0) {
		int caretLine;
		
		caretOffset = selection.x;
		caretLine = getCaretLine();
		showCaret(caretLine);
	}
	else {
		doSelectionCursorPrevious();
	}
}
/**
 * Moves the caret to the end of the selection if a selection exists.
 * Otherwise, if no selection exists move the cursor according to the 
 * cursor selection rules.
 * <p>
 *
 * @see #doSelectionCursorNext
 */
void doCursorNext() {
	if (selection.y - selection.x > 0) {
		int caretLine;

		caretOffset = selection.y;
		caretLine = getCaretLine();
		showCaret(caretLine);
	}
	else {
		doSelectionCursorNext();
	}
}
/**
 * Deletes the next character. Delete the selected text if any.
 */
void doDelete() {
	Event event = new Event();
	
	event.text = "";
	if (selection.x != selection.y) {
		event.start = selection.x;
		event.end = selection.y;
		sendKeyEvent(event);
	}
	else
	if (caretOffset < content.getCharCount()) {
		int line = content.getLineAtOffset(caretOffset);
		int lineOffset = content.getOffsetAtLine(line);
		int lineLength = content.getLine(line).length();
				
		if (caretOffset == lineOffset + lineLength) {
			event.start = caretOffset;
			event.end = content.getOffsetAtLine(line + 1);
		}
		else {
			event.start = caretOffset;
			event.end = caretOffset + 1;
		}
		sendKeyEvent(event);
	}
}
/**
 * Deletes the next word.
 */
void doDeleteWordNext() {
	if (selection.x != selection.y) {
		// if a selection exists, treat the as if 
		// only the delete key was pressed
		doDelete();
	} else {
		Event event = new Event();
		event.text = "";
		event.start = caretOffset;
		event.end = getWordEnd(caretOffset);
		sendKeyEvent(event);
	}
}
/**
 * Deletes the previous word.
 */
void doDeleteWordPrevious() {
	if (selection.x != selection.y) {
		// if a selection exists, treat as if 
		// only the backspace key was pressed
		doBackspace();
	} else {
		Event event = new Event();
		event.text = "";
		event.start = getWordStart(caretOffset);
		event.end = caretOffset;
		sendKeyEvent(event);
	}
}
/**
 * Moves the caret one line down and to the same character offset relative 
 * to the beginning of the line. Move the caret to the end of the new line 
 * if the new line is shorter than the character offset.
 * 
 * @return index of the new line relative to the first line in the document
 */
int doLineDown() {
	if (isSingleLine()) {
		return 0;
	}
	// allow line down action only if receiver is not in single line mode.
	// fixes 4820.
	int caretLine = getCaretLine(); 
	if (caretLine < content.getLineCount() - 1) {
		caretLine++;
		if (isBidi()) {
			int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine); 
			caretOffset = offsetDirection[0];
			lastCaretDirection = offsetDirection[1];
		}
		else {
			caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
		}		
	}
	return caretLine;
}
/**
 * Moves the caret to the end of the line.
 */
void doLineEnd() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);	
	int lineLength = content.getLine(caretLine).length();
	int lineEndOffset = lineOffset + lineLength;
	
	if (caretOffset < lineEndOffset) {
		caretOffset = lineEndOffset;
		showCaret();
	}
}
/**
 * Moves the caret to the beginning of the line.
 */
void doLineStart() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);
		
	if (caretOffset > lineOffset) {
		caretOffset = lineOffset;
		showCaret(caretLine);
	}
}
/**
 * Moves the caret one line up and to the same character offset relative 
 * to the beginning of the line. Move the caret to the end of the new line 
 * if the new line is shorter than the character offset.
 * 
 * @return index of the new line relative to the first line in the document
 */
int doLineUp() {
	int caretLine = getCaretLine();

	if (caretLine > 0) {
		caretLine--;
		if (isBidi()) {
			int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine); 
			caretOffset = offsetDirection[0];
			lastCaretDirection = offsetDirection[1];
		}
		else {
			caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
		}		
	}
	return caretLine;
}
/**
 * Moves the caret to the specified location.
 * <p>
 *
 * @param x x location of the new caret position
 * @param y y location of the new caret position
 * @param select the location change is a selection operation.
 * 	include the line delimiter in the selection
 */
void doMouseLocationChange(int x, int y, boolean select) {
	int line = (y + verticalScrollOffset) / lineHeight;
	int lineCount = content.getLineCount();
	int newCaretOffset;
	int newCaretLine;
	int newCaretDirection = lastCaretDirection;
	
	if (line > lineCount - 1) {
		line = lineCount - 1;
	}	
	// allow caret to be placed below first line only if receiver is 
	// not in single line mode. fixes 4820.
	if (line < 0 || (isSingleLine() && line > 0)) {
		return;
	}
	if (isBidi()) {
		int offsetDirection[] = getBidiOffsetAtMouseLocation(x, line);
		newCaretOffset = offsetDirection[0];
		newCaretDirection = offsetDirection[1];
	}
	else {
		newCaretOffset = getOffsetAtMouseLocation(x, line);
	}
	if (mouseDoubleClick) {
		// double click word select the previous/next word. fixes bug 15610
		newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
	}
	newCaretLine = content.getLineAtOffset(newCaretOffset);
	// Is the mouse within the left client area border or on 
	// a different line? If not the autoscroll selection 
	// could be incorrectly reset. Fixes 1GKM3XS
	if (y >= 0 && y < getClientArea().height && 
		(x >= 0 && x < getClientArea().width || newCaretLine != content.getLineAtOffset(caretOffset))) {
		if (newCaretOffset != caretOffset) {
			lastCaretDirection = newCaretDirection;
			caretOffset = newCaretOffset;
			if (select) {
				doMouseSelection();
			}
			showCaret();
		}
	}
	if (select == false) {
		lastCaretDirection = newCaretDirection;
		clearSelection(true);
	}
}
/**
 * Updates the selection based on the caret position
 */
void doMouseSelection() {
	if (caretOffset <= selection.x || 
		(caretOffset > selection.x && 
		 caretOffset < selection.y && selectionAnchor == selection.x)) {
		doSelection(ST.COLUMN_PREVIOUS);
	}
	else {
		doSelection(ST.COLUMN_NEXT);
	}
}
/**
 * Returns the offset of the word at the specified offset. 
 * If the current selection extends from high index to low index 
 * (i.e., right to left, or caret is at left border of selecton on 
 * non-bidi platforms) the start offset of the word preceeding the
 * selection is returned. If the current selection extends from 
 * low index to high index the end offset of the word following 
 * the selection is returned.
 * 
 * @param x mouse x location
 * @param newCaretOffset caret offset of the mouse cursor location
 * @param line line index of the mouse cursor location
 */
int doMouseWordSelect(int x, int newCaretOffset, int line) {
	int wordOffset;

	// flip selection anchor based on word selection direction from 
	// base double click. Always do this here (and don't rely on doAutoScroll)
	// because auto scroll only does not cover all possible mouse selections
	// (e.g., mouse x < 0 && mouse y > caret line y)
 	if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) {
		selectionAnchor = doubleClickSelection.y;
	}
	else
	if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) {
		selectionAnchor = doubleClickSelection.x;
	}
	if (x >= 0 && x < getClientArea().width) {
		// find the previous/next word
		if (caretOffset == selection.x) {
			wordOffset = getWordStart(newCaretOffset);
		}
		else {
			wordOffset = getWordEndNoSpaces(newCaretOffset);
		}
		// mouse word select only on same line mouse cursor is on
		if (content.getLineAtOffset(wordOffset) == line) {
			newCaretOffset = wordOffset;
		}
	}
	return newCaretOffset;
}
/**
 * Scrolls one page down so that the last line (truncated or whole)
 * of the current page becomes the fully visible top line.
 * The caret is scrolled the same number of lines so that its location 
 * relative to the top line remains the same. The exception is the end 
 * of the text where a full page scroll is not possible. In this case 
 * the caret is moved after the last character.
 * <p>
 *
 * @param select whether or not to select the page
 */
void doPageDown(boolean select) {
	int lineCount = content.getLineCount();
	int oldColumnX = columnX;
	int caretLine;
	
	// do nothing if in single line mode. fixes 5673
	if (isSingleLine()) {
		return;
	}
	caretLine = getCaretLine();
	if (caretLine < lineCount - 1) {
		int verticalMaximum = lineCount * getVerticalIncrement();
		int pageSize = getClientArea().height;
		int scrollLines = Math.min(lineCount - caretLine - 1, getLineCountWhole());
		int scrollOffset;
		
		// ensure that scrollLines never gets negative and at leat one 
		// line is scrolled. fixes bug 5602.
		scrollLines = Math.max(1, scrollLines);
		caretLine += scrollLines;		
		if (isBidi()) {
			int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine); 
			caretOffset = offsetDirection[0];
			lastCaretDirection = offsetDirection[1];
		}
		else {
			caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
		}	
		if (select) {
			doSelection(ST.COLUMN_NEXT);
		}
		// scroll one page down or to the bottom
		scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
		if (scrollOffset + pageSize > verticalMaximum) {
			scrollOffset = verticalMaximum - pageSize;
		}
		if (scrollOffset > verticalScrollOffset) {		
			setVerticalScrollOffset(scrollOffset, true);
		}
	}
	// explicitly go to the calculated caret line. may be different 
	// from content.getLineAtOffset(caretOffset) when in word wrap mode
	showCaret(caretLine);
	// save the original horizontal caret position	
	columnX = oldColumnX;
}
/**
 * Moves the cursor to the end of the last fully visible line.
 */
void doPageEnd() {
	// go to end of line if in single line mode. fixes 5673
	if (isSingleLine()) {
		doLineEnd();
	}
	else {
		int line = getBottomIndex();
		int bottomCaretOffset = content.getOffsetAtLine(line) + content.getLine(line).length();	

		if (caretOffset < bottomCaretOffset) {
			caretOffset = bottomCaretOffset;
			showCaret();
		}
	}
}
/**
 * Moves the cursor to the beginning of the first fully visible line.
 */
void doPageStart() {
	int topCaretOffset = content.getOffsetAtLine(topIndex);
	
	if (caretOffset > topCaretOffset) {
		caretOffset = topCaretOffset;
		// explicitly go to the calculated caret line. may be different 
		// from content.getLineAtOffset(caretOffset) when in word wrap mode
		showCaret(topIndex);
	}
}
/**
 * Scrolls one page up so that the first line (truncated or whole)
 * of the current page becomes the fully visible last line.
 * The caret is scrolled the same number of lines so that its location 
 * relative to the top line remains the same. The exception is the beginning 
 * of the text where a full page scroll is not possible. In this case the
 * caret is moved in front of the first character.
 */
void doPageUp() {
	int oldColumnX = columnX;
	int caretLine = getCaretLine();
	
	if (caretLine > 0) {	
		int scrollLines = Math.max(1, Math.min(caretLine, getLineCountWhole()));
		int scrollOffset;
		
		caretLine -= scrollLines;		
		if (isBidi()) {
			int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine); 
			caretOffset = offsetDirection[0];
			lastCaretDirection = offsetDirection[1];
		}
		else {
			caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
		}	
		// scroll one page up or to the top
		scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
		if (scrollOffset < verticalScrollOffset) {				
			setVerticalScrollOffset(scrollOffset, true);
		}
	}
	// explicitly go to the calculated caret line. may be different 
	// from content.getLineAtOffset(caretOffset) when in word wrap mode
	showCaret(caretLine);
	// save the original horizontal caret position	
	columnX = oldColumnX;
}
/**
 * Updates the selection to extend to the current caret position.
 */
void doSelection(int direction) {
	int redrawStart = -1;
	int redrawEnd = -1;
	
	if (selectionAnchor == -1) {
		selectionAnchor = selection.x;
	}
	if (direction == ST.COLUMN_PREVIOUS) {
		if (caretOffset < selection.x) {
			// grow selection
			redrawEnd = selection.x; 
			redrawStart = selection.x = caretOffset;		
			// check if selection has reversed direction
			if (selection.y != selectionAnchor) {
				redrawEnd = selection.y;
				selection.y = selectionAnchor;
			}
		}
		else	// test whether selection actually changed. Fixes 1G71EO1
		if (selectionAnchor == selection.x && caretOffset < selection.y) {
			// caret moved towards selection anchor (left side of selection). 
			// shrink selection			
			redrawEnd = selection.y;
			redrawStart = selection.y = caretOffset;		
		}
	}
	else {
		if (caretOffset > selection.y) {
			// grow selection
			redrawStart = selection.y;
			redrawEnd = selection.y = caretOffset;
			// check if selection has reversed direction
			if (selection.x != selectionAnchor) {
				redrawStart = selection.x;				
				selection.x = selectionAnchor;
			}
		}
		else	// test whether selection actually changed. Fixes 1G71EO1
		if (selectionAnchor == selection.y && caretOffset > selection.x) {
			// caret moved towards selection anchor (right side of selection). 
			// shrink selection			
			redrawStart = selection.x;
			redrawEnd = selection.x = caretOffset;		
		}
	}
	if (redrawStart != -1 && redrawEnd != -1) {
		internalRedrawRange(redrawStart, redrawEnd - redrawStart, true);
		sendSelectionEvent();
	}
}
/**
 * Moves the caret to the next character or to the beginning of the 
 * next line if the cursor is at the end of a line.
 */
void doSelectionCursorNext() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);
	int offsetInLine = caretOffset - lineOffset;
		
	if (offsetInLine < content.getLine(caretLine).length()) {
		// Remember the last direction. Always update lastCaretDirection,
		// even though it's not used in non-bidi mode in order to avoid 
		// extra methods.		
		lastCaretDirection = ST.COLUMN_NEXT;
		caretOffset++;
		showCaret();
	}
	else
	if (caretLine < content.getLineCount() - 1 && isSingleLine() == false) {
		// only go to next line if not in single line mode. fixes 5673
		caretLine++;		
		caretOffset = content.getOffsetAtLine(caretLine);
		// explicitly go to the calculated caret line. may be different 
		// from content.getLineAtOffset(caretOffset) when in word wrap mode
		showCaret(caretLine);
	}
}
/**
 * Moves the caret to the previous character or to the end of the previous 
 * line if the cursor is at the beginning of a line.
 */
void doSelectionCursorPrevious() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);
	int offsetInLine = caretOffset - lineOffset;
	
	if (offsetInLine > 0) {
		// Remember the last direction. Always update lastCaretDirection,
		// even though it's not used in non-bidi mode in order to avoid 
		// extra methods.			
		lastCaretDirection = ST.COLUMN_PREVIOUS;		
		caretOffset--;
		// explicitly go to the calculated caret line. may be different 
		// from content.getLineAtOffset(caretOffset) when in word wrap mode
		showCaret(caretLine);
	}
	else
	if (caretLine > 0) {
		caretLine--;
		lineOffset = content.getOffsetAtLine(caretLine);
		caretOffset = lineOffset + content.getLine(caretLine).length();
		showCaret();
	}
}
/**
 * Moves the caret one line down and to the same character offset relative 
 * to the beginning of the line. Moves the caret to the end of the new line 
 * if the new line is shorter than the character offset.
 * Moves the caret to the end of the text if the caret already is on the 
 * last line.
 * Adjusts the selection according to the caret change. This can either add
 * to or subtract from the old selection, depending on the previous selection
 * direction.
 */
void doSelectionLineDown() {
	int oldColumnX;
	int caretLine;
	int lineStartOffset;
	
	if (isSingleLine()) {
		return;
	}
	caretLine = getCaretLine();	
	lineStartOffset = content.getOffsetAtLine(caretLine);
	// reset columnX on selection
	oldColumnX = columnX = getXAtOffset(
		content.getLine(caretLine), caretLine, caretOffset - lineStartOffset);
	if (caretLine == content.getLineCount() - 1) {
		caretOffset = content.getCharCount();
	}
	else {
		caretLine = doLineDown();
	}
	setMouseWordSelectionAnchor();	
	// select first and then scroll to reduce flash when key 
	// repeat scrolls lots of lines
	doSelection(ST.COLUMN_NEXT);
	// explicitly go to the calculated caret line. may be different 
	// from content.getLineAtOffset(caretOffset) when in word wrap mode
	showCaret(caretLine);
	// save the original horizontal caret position
	columnX = oldColumnX;
}
/**
 * Moves the caret one line up and to the same character offset relative 
 * to the beginning of the line. Moves the caret to the end of the new line 
 * if the new line is shorter than the character offset.
 * Moves the caret to the beginning of the document if it is already on the
 * first line.
 * Adjusts the selection according to the caret change. This can either add
 * to or subtract from the old selection, depending on the previous selection
 * direction.
 */
void doSelectionLineUp() {
	int oldColumnX;
	int caretLine = getCaretLine();	
	int lineStartOffset = content.getOffsetAtLine(caretLine);
	
	// reset columnX on selection
	oldColumnX = columnX = getXAtOffset(
		content.getLine(caretLine), caretLine, caretOffset - lineStartOffset);	
	if (caretLine == 0) {
		caretOffset = 0;
	}
	else {
		caretLine = doLineUp();
	}
	setMouseWordSelectionAnchor();
	// explicitly go to the calculated caret line. may be different 
	// from content.getLineAtOffset(caretOffset) when in word wrap mode
	showCaret(caretLine);
	doSelection(ST.COLUMN_PREVIOUS);
	// save the original horizontal caret position	
	columnX = oldColumnX;
}
/**
 * Scrolls one page down so that the last line (truncated or whole)
 * of the current page becomes the fully visible top line.
 * The caret is scrolled the same number of lines so that its location 
 * relative to the top line remains the same. The exception is the end 
 * of the text where a full page scroll is not possible. In this case 
 * the caret is moved after the last character.
 * <p>
 * Adjusts the selection according to the caret change. This can either add
 * to or subtract from the old selection, depending on the previous selection
 * direction.
 * </p>
 */
void doSelectionPageDown() {
	int oldColumnX;
	int caretLine = getCaretLine();
	int lineStartOffset = content.getOffsetAtLine(caretLine);
	
	// reset columnX on selection
	oldColumnX = columnX = getXAtOffset(
		content.getLine(caretLine), caretLine, caretOffset - lineStartOffset);
	doPageDown(true);
	columnX = oldColumnX;
}
/**
 * Scrolls one page up so that the first line (truncated or whole)
 * of the current page becomes the fully visible last line.
 * The caret is scrolled the same number of lines so that its location 
 * relative to the top line remains the same. The exception is the beginning 
 * of the text where a full page scroll is not possible. In this case the
 * caret is moved in front of the first character.
 * <p>
 * Adjusts the selection according to the caret change. This can either add
 * to or subtract from the old selection, depending on the previous selection
 * direction.
 * </p>
 */
void doSelectionPageUp() {
	int oldColumnX;
	int caretLine = getCaretLine();
	int lineStartOffset = content.getOffsetAtLine(caretLine);
	
	// reset columnX on selection
	oldColumnX = columnX = getXAtOffset(
		content.getLine(caretLine), caretLine, caretOffset - lineStartOffset);
	doPageUp();
	columnX = oldColumnX;
}
/**
 * Moves the caret to the end of the next word .
 */
void doSelectionWordNext() {
	int newCaretOffset = getWordEnd(caretOffset);
	
	// don't change caret position if in single line mode and the cursor 
	// would be on a different line. fixes 5673
	if (isSingleLine() == false || 
		content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) {
		lastCaretDirection = ST.COLUMN_NEXT;
		caretOffset = newCaretOffset;
		showCaret();
	}
}
/**
 * Moves the caret to the start of the previous word.
 */
void doSelectionWordPrevious() {
	int caretLine;
	
	lastCaretDirection = ST.COLUMN_PREVIOUS;
	caretOffset = getWordStart(caretOffset);
	caretLine = content.getLineAtOffset(caretOffset);
	// word previous always comes from bottom line. when
	// wrapping lines, stay on bottom line when on line boundary
	if (wordWrap && caretLine < content.getLineCount() - 1 &&
		caretOffset == content.getOffsetAtLine(caretLine + 1)) {
		caretLine++;
	}
	showCaret(caretLine);
}
/**
 * Moves the caret one character to the left.  Do not go to the previous line.
 * When in a bidi locale and at a R2L character the caret is moved to the 
 * beginning of the R2L segment (visually right) and then one character to the 
 * left (visually left because it's now in a L2R segment).
 */
void doVisualPrevious() {
	int line = content.getLineAtOffset(caretOffset);
	int lineOffset = content.getOffsetAtLine(line);	
	int offsetInLine = caretOffset - lineOffset;
	
	if (isBidi()) {
		// check if caret location is at the visual beginning of the line
		if (columnX <= XINSET && horizontalScrollOffset == 0) { 
			return;
		}		
		String lineText = content.getLine(line);
		int lineLength = lineText.length();
		GC gc = getGC();
		StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc);
		int visualOffset = -1;
		
		if (offsetInLine == lineLength) {
			//logical end of line may not be visual end, setup visualOffset to process as usual
			visualOffset = bidi.getVisualOffset(offsetInLine - 1);
		}
		else
		if (offsetInLine < lineLength) {
			visualOffset = bidi.getVisualOffset(offsetInLine);
		}
		if (visualOffset != -1) {
			if (visualOffset > 0) {
				visualOffset--;
				offsetInLine = bidi.getLogicalOffset(visualOffset);
			}
			else
			if (visualOffset == 0) {
				boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0;

				//move to visual line end (i.e., behind L2R character/in front of R2L character at visual 0)
				if ((isRightOriented && bidi.isRightToLeft(offsetInLine) == false) ||
					(isRightOriented == false && bidi.isRightToLeft(offsetInLine))) {
					offsetInLine++;
				}
				
				if (offsetInLine > 0 && offsetInLine < lineLength) {
					if (isRightOriented) {
						boolean rightToLeftStart = bidi.isRightToLeft(offsetInLine) && bidi.isRightToLeft(offsetInLine - 1) == false;
						if (rightToLeftStart) {
							//moving from LtoR segment to RtoL segment
							lastCaretDirection = ST.COLUMN_NEXT;
						}						
					}
					else {
						boolean leftToRightStart = bidi.isRightToLeft(offsetInLine) == false && bidi.isRightToLeft(offsetInLine - 1);
						if (bidi.isLatinNumber(offsetInLine) && bidi.isRightToLeftInput(offsetInLine - 1)) {
							//moving from LtoR segment to latin number 
							lastCaretDirection = ST.COLUMN_PREVIOUS;
						}
						else
						if (leftToRightStart) {
							//moving from RtoL segment to LtoR segment
							lastCaretDirection = ST.COLUMN_NEXT;
						}						
					}
				}
			}
			caretOffset = lineOffset + offsetInLine;
			showCaret();
		}
		if (bidi.getTextPosition(offsetInLine, ST.COLUMN_NEXT) == XINSET) {
			//scroll to origin if caret is at origin
			scrollHorizontalBar(-horizontalScrollOffset);
		}
		gc.dispose();
	}
	else
	if (offsetInLine > 0) {
		caretOffset--;
		showCaret();
	}
}
/**
 * Moves the caret one character to the right.  Do not go to the next line.
 * When in a bidi locale and at a R2L character the caret is moved to the 
 * end of the R2L segment (visually left) and then one character to the 
 * right (visually right because it's now in a L2R segment).
 */
void doVisualNext() {
	int line = content.getLineAtOffset(caretOffset);
	int lineOffset = content.getOffsetAtLine(line);	
	int offsetInLine = caretOffset - lineOffset;
	String lineText = content.getLine(line);
	int lineLength = lineText.length();
	
	if (isBidi()) {
		GC gc = getGC();
		StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc);
		int lineEndPixel = bidi.getTextWidth() + leftMargin; 

		// check if caret location is at the visual end of the line (can't use 
		// caret location here since it's location is dependent on current keyboard
		// language direction)
		if (bidi.getTextPosition(offsetInLine, lastCaretDirection) == lineEndPixel) {
			gc.dispose(); 
			return;
		}
		int visualOffset = -1;
		if (offsetInLine == lineLength) {
			//logical end of line may not be visual end, setup visualOffset to process as usual
			visualOffset = bidi.getVisualOffset(offsetInLine - 1);
		}
		else
		if (offsetInLine < lineLength) {
			visualOffset = bidi.getVisualOffset(offsetInLine);
		}
		if (visualOffset != -1) {
			visualOffset++;
			offsetInLine = bidi.getLogicalOffset(visualOffset);
			if (offsetInLine > 0 && offsetInLine < lineLength) {
				boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0;
				if (isRightOriented) {
					boolean leftToRightStart = bidi.isRightToLeft(offsetInLine) == false && bidi.isRightToLeft(offsetInLine - 1);
					if (leftToRightStart) {
						//moving from RtoL segment to LtoR segment
						lastCaretDirection = ST.COLUMN_PREVIOUS;
					}						
				}
				else {
					boolean rightToLeftStart = bidi.isRightToLeft(offsetInLine) && bidi.isRightToLeft(offsetInLine - 1) == false;
					if (bidi.isRightToLeftInput(offsetInLine) && bidi.isLatinNumber(offsetInLine - 1)) {
						//moving from latin number to RtoL segment
						lastCaretDirection = ST.COLUMN_NEXT;
					}
					else
					if (rightToLeftStart) {
						//moving from LtoR segment to RtoL segment
						lastCaretDirection = ST.COLUMN_PREVIOUS;
					}						
				}
			}
			caretOffset = lineOffset + offsetInLine;
			showCaret();
		}
		gc.dispose();
	}
	else
	if (offsetInLine < lineLength) {
		caretOffset++;
		showCaret();
	}
}
/**
 * Moves the caret to the end of the next word.
 * If a selection exists, move the caret to the end of the selection
 * and remove the selection.
 */
void doWordNext() {
	if (selection.y - selection.x > 0) {
		int caretLine;
		
		caretOffset = selection.y;
		caretLine = getCaretLine();
		showCaret(caretLine);
	}
	else {
		doSelectionWordNext();
	}
}
/**
 * Moves the caret to the start of the previous word.
 * If a selection exists, move the caret to the start of the selection
 * and remove the selection.
 */
void doWordPrevious() {
	if (selection.y - selection.x > 0) {
		int caretLine;
		
		caretOffset = selection.x;
		caretLine = getCaretLine();
		showCaret(caretLine);
	}
	else {
		doSelectionWordPrevious();
	}
}
/**
 * Draws the specified rectangle.
 * Draw directly without invalidating the affected area when clearBackground is 
 * false.
 * <p>
 *
 * @param x the x position
 * @param y the y position
 * @param width the width
 * @param height the height
 * @param clearBackground true=clear the background by invalidating the requested 
 * 	redraw area, false=draw the foreground directly without invalidating the 
 * 	redraw area.
 */
void draw(int x, int y, int width, int height, boolean clearBackground) {
	if (clearBackground) {
		redraw(x + leftMargin, y + topMargin, width, height, true);
	}
	else {
		int startLine = (y + verticalScrollOffset) / lineHeight;
		int endY = y + height;
		int paintYFromTopLine = (startLine - topIndex) * lineHeight;
		int topLineOffset = (topIndex * lineHeight - verticalScrollOffset);
		int paintY = paintYFromTopLine + topLineOffset + topMargin;	// adjust y position for pixel based scrolling
		int lineCount = content.getLineCount();
		Color background = getBackground();
		Color foreground = getForeground();
		GC gc = getGC();
	
		if (isSingleLine()) {
			lineCount = 1;
			if (startLine > 1) {
				startLine = 1;
			}
		}
		for (int i = startLine; paintY < endY && i < lineCount; i++, paintY += lineHeight) {
			String line = content.getLine(i);
			renderer.drawLine(line, i, paintY, gc, background, foreground, clearBackground);
		}
		gc.dispose();	
	}
}
/** 
 * Ends the autoscroll process.
 */
void endAutoScroll() {
	autoScrollDirection = SWT.NULL;
}
/**
 * @see org.eclipse.swt.widgets.Control#getBackground
 */
public Color getBackground() {
	checkWidget();
	if (background == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
	}
	return background;
}
/**
 * Gets the BIDI coloring mode.  When true the BIDI text display
 * algorithm is applied to segments of text that are the same
 * color.
 *
 * @return the current coloring mode
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * <p>
 * @deprecated use BidiSegmentListener instead.
 * </p>
 */
public boolean getBidiColoring() {
	checkWidget();
	return bidiColoring;
}
/**
 * Returns the offset and caret direction at the specified x location 
 * in the specified line.
 * The returned caret direction needs to be set in order to place the 
 * caret correctly based on whether the mouse location is in a R2L 
 * or L2R segment.
 * <p>
 *
 * @param x	x location of the mouse location
 * @param line	line the mouse location is in
 * @return int array, first element is the offset at the specified x 
 * 	location in the specified line, relative to the beginning of the 
 * 	document. second element is the caret direction.
 */
int[] getBidiOffsetAtMouseLocation(int x, int line) {
	String lineText = content.getLine(line);
	int lineOffset = content.getOffsetAtLine(line);
	GC gc = getGC();
	StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc);
	int[] values = bidi.getCaretOffsetAndDirectionAtX(x + horizontalScrollOffset - leftMargin);
	
	gc.dispose();	
	return new int[] {lineOffset + values[0], values[1]};
}
/**
 * Returns the x position of the character at the specified offset 
 * relative to the first character in the line.
 * </p>
 *
 * @param text text to be measured.
 * @param endOffset offset of the character
 * @param bidi the bidi object to use for measuring text in bidi
 *	locales. 
 * @return x position of the character at the specified offset. 
 * 	0 if the length is outside the specified text.
 */
int getBidiTextPosition(String text, int endOffset, StyledTextBidi bidi) {
	if (endOffset > text.length()) {
		return 0;
	}
	// Use lastCaretDirection in order to get same results as during
	// caret positioning (setBidiCaretLocation). Fixes 1GKU4C5.
	return bidi.getTextPosition(endOffset, lastCaretDirection);
}
/** 
 * Returns the index of the last fully visible line.
 * <p>
 *
 * @return index of the last fully visible line.
 */
int getBottomIndex() {
	int lineCount = 1;
	
	if (lineHeight != 0) {
		// calculate the number of lines that are fully visible
		int partialTopLineHeight = topIndex * lineHeight - verticalScrollOffset;
		lineCount = (getClientArea().height - partialTopLineHeight) / lineHeight;
	}
	return Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
}
/**
 * Returns the caret position relative to the start of the text.
 * <p>
 *
 * @return the caret position relative to the start of the text.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getCaretOffset() {
	checkWidget();
	
	return caretOffset;
}
/**
 * Returns the caret offset at the given x location in the line.
 * The caret offset is the offset of the character where the caret will be
 * placed when a mouse click occurs. The caret offset will be the offset of 
 * the character after the clicked one if the mouse click occurs at the second 
 * half of a character.
 * Doesn't properly handle ligatures and other context dependent characters 
 * unless the current locale is a bidi locale. 
 * Ligatures are handled properly as long as they don't occur at lineXOffset.
 * <p>
 *
 * @param line text of the line to calculate the offset in
 * @param lineOffset offset of the first character in the line. 
 * 	0 based from the beginning of the document.
 * @param lineXOffset x location in the line
 * @return caret offset at the x location relative to the start of the line.
 */
int getCaretOffsetAtX(String line, int lineOffset, int lineXOffset) {
	int offset = 0;
	GC gc = getGC();
	StyleRange[] styles = null;
	StyledTextEvent event = renderer.getLineStyleData(lineOffset, line);
	
	lineXOffset += horizontalScrollOffset;
	if (event != null) {
		styles = renderer.filterLineStyles(event.styles);
	}
	int low = -1;
	int high = line.length();
	while (high - low > 1) {
		offset = (high + low) / 2;
		int x = renderer.getTextPosition(line, lineOffset, offset, styles, gc) + leftMargin;
		int charWidth = renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc) + leftMargin - x;
		if (lineXOffset <= x + charWidth / 2) {
			high = offset;			
		}
		else {
			low = offset;
		}
	}
	offset = high;
	gc.dispose();
	return offset;	
}
/**
 * Returns the caret width.
 * <p>
 *
 * @return the caret width, 0 if caret is null.
 */
int getCaretWidth() {
	Caret caret = getCaret();
	if (caret == null) return 0;
	return caret.getSize().x;
}
/**
 * Returns the content implementation that is used for text storage
 * or null if no user defined content implementation has been set.
 * <p>
 *
 * @return content implementation that is used for text storage or null 
 * if no user defined content implementation has been set.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public StyledTextContent getContent() {
	checkWidget();
	
	return logicalContent;
}
/** 
 * Returns whether the widget implements double click mouse behavior.
 * <p>
 *
 * @return true if double clicking a word selects the word, false if double clicks
 * have the same effect as regular mouse clicks
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean getDoubleClickEnabled() {
	checkWidget();
	return doubleClickEnabled;
}
/**
 * Returns whether the widget content can be edited.
 * <p>
 *
 * @return true if content can be edited, false otherwise
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean getEditable() {
	checkWidget();
	return editable;
}
/**
 * @see org.eclipse.swt.widgets.Control#getForeground
 */
public Color getForeground() {
	checkWidget();
	if (foreground == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
	}
	return foreground;
}
/** 
 * Return a GC to use for rendering and update the cached font style to
 * represent the current style.
 * <p>
 *
 * @return GC.
 */
GC getGC() {
	renderer.setCurrentFontStyle(SWT.NORMAL);
	return new GC(this);
}
/** 
 * Returns the horizontal scroll increment.
 * <p>
 *
 * @return horizontal scroll increment.
 */
int getHorizontalIncrement() {
	GC gc = getGC();
	int increment = gc.getFontMetrics().getAverageCharWidth();
	
	gc.dispose();
	return increment;
}
/** 
 * Returns the horizontal scroll offset relative to the start of the line.
 * <p>
 *
 * @return horizontal scroll offset relative to the start of the line,
 * measured in character increments starting at 0, if > 0 the content is scrolled
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getHorizontalIndex() {	
	checkWidget();
	return horizontalScrollOffset / getHorizontalIncrement();
}
/** 
 * Returns the horizontal scroll offset relative to the start of the line.
 * <p>
 *
 * @return the horizontal scroll offset relative to the start of the line,
 * measured in pixel starting at 0, if > 0 the content is scrolled.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getHorizontalPixel() {	
	checkWidget();
	return horizontalScrollOffset;
}
/** 
 * Returns the action assigned to the key.
 * Returns SWT.NULL if there is no action associated with the key.
 * <p>
 *
 * @param key a key code defined in SWT.java or a character. 
 * 	Optionally ORd with a state mask.  Preferred state masks are one or more of
 *  SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform 
 *  differences.  However, there may be cases where using the specific state masks
 *  (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense.
 * @return one of the predefined actions defined in ST.java or SWT.NULL 
 * 	if there is no action associated with the key.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getKeyBinding(int key) {
	checkWidget();
	Integer action = (Integer) keyActionMap.get(new Integer(key));
	int intAction;
	
	if (action == null) {
		intAction = SWT.NULL;
	}
	else {
		intAction = action.intValue();
	}
	return intAction;
}
/**
 * Gets the number of characters.
 * <p>
 *
 * @return number of characters in the widget
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getCharCount() {
	checkWidget();
	return content.getCharCount();
}
/**
 * Returns the background color of the line at the given index.
 * Returns null if a LineBackgroundListener has been set or if no background 
 * color has been specified for the line. Should not be called if a
 * LineBackgroundListener has been set since the listener maintains the
 * line background colors.
 * <p>
 *
 * @return the background color of the line at the given index.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT when the index is invalid</li>
 * </ul>
 */
public Color getLineBackground(int index) {
	checkWidget();
	Color lineBackground = null;
	
	if (index < 0 || index > logicalContent.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (userLineBackground == false) {
		lineBackground = defaultLineStyler.getLineBackground(index);
	}
	return lineBackground;
}
/**
 * Returns the line background data for the given line or null if 
 * there is none.
 * <p>
 * @param lineOffset offset of the line start relative to the start
 * 	of the content.
 * @param line line to get line background data for
 * @return line background data for the given line.
 */
StyledTextEvent getLineBackgroundData(int lineOffset, String line) {
	return sendLineEvent(LineGetBackground, lineOffset, line);
}
/** 
 * Gets the number of text lines.
 * <p>
 *
 * @return the number of lines in the widget
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getLineCount() {
	checkWidget();
	return getLineAtOffset(getCharCount()) + 1;
}
/**
 * Returns the number of lines that can be completely displayed in the 
 * widget client area.
 * <p>
 *
 * @return number of lines that can be completely displayed in the widget 
 * 	client area.
 */
int getLineCountWhole() {
	int lineCount;
	
	if (lineHeight != 0) {
		lineCount = getClientArea().height / lineHeight;
	}
	else {
		lineCount = 1;
	}
	return lineCount;
}
/**
 * Returns the line at the specified offset in the text
 * where 0 &lt= offset &lt= getCharCount() so that getLineAtOffset(getCharCount())
 * returns the line of the insert location.
 *
 * @param offset offset relative to the start of the content. 
 * 	0 <= offset <= getCharCount()
 * @return line at the specified offset in the text
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> 
 * </ul>
 */
public int getLineAtOffset(int offset) {
	checkWidget();
	
	if (offset < 0 || offset > getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_RANGE);		
	}
	return logicalContent.getLineAtOffset(offset);
}
/**
 * Returns the line delimiter used for entering new lines by key down
 * or paste operation.
 * <p>
 *
 * @return line delimiter used for entering new lines by key down
 * or paste operation.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public String getLineDelimiter() {
	checkWidget();
	return content.getLineDelimiter();
}
/**
 * Returns a StyledTextEvent that can be used to request data such 
 * as styles and background color for a line.
 * The specified line may be a visual (wrapped) line if in word 
 * wrap mode. The returned object will always be for a logical 
 * (unwrapped) line.
 * <p>
 *
 * @param lineOffset offset of the line. This may be the offset of
 * 	a visual line if the widget is in word wrap mode.
 * @param line line text. This may be the text of a visualline if 
 * 	the widget is in word wrap mode.
 * @return StyledTextEvent that can be used to request line data 
 * 	for the given line.
 */
StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) {
	StyledTextEvent event = null;
	
	if (isListening(eventType)) {
		event = new StyledTextEvent(logicalContent);		
		if (wordWrap) {
		    // if word wrap is on, the line offset and text may be visual (wrapped)
		    int lineIndex = logicalContent.getLineAtOffset(lineOffset);
		    
		    event.detail = logicalContent.getOffsetAtLine(lineIndex);
			event.text = logicalContent.getLine(lineIndex);
		}
		else {
			event.detail = lineOffset;
			event.text = line;
		}
		notifyListeners(eventType, event);
	}
	return event;	
}
/**
 * Returns the line height.
 * <p>
 *
 * @return line height in pixel.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getLineHeight() {
	checkWidget();
	return lineHeight;
}
/**
 * Returns a LineCache implementation. Depending on whether or not
 * word wrap is on this may be a line wrapping or line width 
 * calculating implementaiton.
 * <p>
 * 
 * @param content StyledTextContent to create the LineCache on.
 * @return a LineCache implementation
 */
LineCache getLineCache(StyledTextContent content) {
    LineCache lineCache;
    
	if (wordWrap) {
	    lineCache = new WordWrapCache(this, (WrappedContent) content);
	}
	else {
	    lineCache = new ContentWidthCache(this, content);
	}
	return lineCache;
}
/**
 * Returns the line style data for the given line or null if there is 
 * none. If there is a LineStyleListener but it does not set any styles, 
 * the StyledTextEvent.styles field will be initialized to an empty 
 * array.
 * <p>
 * 
 * @param lineOffset offset of the line start relative to the start of 
 * 	the content.
 * @param line line to get line styles for
 * @return line style data for the given line. Styles may start before 
 * 	line start and end after line end
 */
StyledTextEvent getLineStyleData(int lineOffset, String line) {
	return sendLineEvent(LineGetStyle, lineOffset, line);
}
/**
 * Returns the x, y location of the upper left corner of the character 
 * bounding box at the specified offset in the text. The point is 
 * relative to the upper left corner of the widget client area.
 * <p>
 *
 * @param offset offset relative to the start of the content. 
 * 	0 <= offset <= getCharCount()
 * @return x, y location of the upper left corner of the character 
 * 	bounding box at the specified offset in the text.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> 
 * </ul>
 */
public Point getLocationAtOffset(int offset) {
	checkWidget();
	if (offset < 0 || offset > getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_RANGE);		
	}
	int line = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(line);
	String lineContent = content.getLine(line);
	int x = getXAtOffset(lineContent, line, offset - lineOffset);
	int y = line * lineHeight - verticalScrollOffset;
	
	return new Point(x, y);
}
/**
 * Returns the character offset of the first character of the given line.
 * <p>
 *
 * @param lineIndex index of the line, 0 based relative to the first 
 * 	line in the content. 0 <= lineIndex < getLineCount(), except
 * 	lineIndex may always be 0
 * @return offset offset of the first character of the line, relative to
 * 	the beginning of the document. The first character of the document is
 *	at offset 0.  
 *  When there are not any lines, getOffsetAtLine(0) is a valid call that 
 * 	answers 0.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> 
 * </ul>
 * @since 2.0
 */
public int getOffsetAtLine(int lineIndex) {
	checkWidget();
	
	if (lineIndex < 0 || 
		(lineIndex > 0 && lineIndex >= logicalContent.getLineCount())) {
		SWT.error(SWT.ERROR_INVALID_RANGE);		
	}
	return logicalContent.getOffsetAtLine(lineIndex);
}
/**
 * Returns the offset of the character at the given location relative 
 * to the first character in the document.
 * The return value reflects the character offset that the caret will
 * be placed at if a mouse click occurred at the specified location.
 * If the x coordinate of the location is beyond the center of a character
 * the returned offset will be behind the character.
 * <p>
 *
 * @param point the origin of character bounding box relative to 
 * 	the origin of the widget client area.
 * @return offset of the character at the given location relative 
 * 	to the first character in the document.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT when point is null</li>
 *   <li>ERROR_INVALID_ARGUMENT when there is no character at the specified location</li>
 * </ul>
 */
public int getOffsetAtLocation(Point point) {
	checkWidget();
	int line;
	int lineOffset;
	int offsetInLine;
	String lineText;
	
	if (point == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	// is y above first line or is x before first column?
	if (point.y + verticalScrollOffset < 0 || point.x + horizontalScrollOffset < 0) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}	
	line = (getTopPixel() + point.y) / lineHeight;	
	// does the referenced line exist?
	if (line >= content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}	
	lineText = content.getLine(line);
	lineOffset = content.getOffsetAtLine(line);	
	offsetInLine = getOffsetAtX(lineText, lineOffset, point.x);
	// is the x position within the line?
	if (offsetInLine == -1) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return lineOffset + offsetInLine;
}
/**
 * Returns the offset at the specified x location in the specified line.
 * <p>
 *
 * @param x	x location of the mouse location
 * @param line	line the mouse location is in
 * @return the offset at the specified x location in the specified line,
 * 	relative to the beginning of the document
 */
int getOffsetAtMouseLocation(int x, int line) {
	String lineText = content.getLine(line);
	int lineOffset = content.getOffsetAtLine(line);
	int offsetInLine = getCaretOffsetAtX(lineText, lineOffset, x);
	return lineOffset + offsetInLine;
}
/**
 * Returns the offset of the character at the given x location in the line.
 * <p>
 *
 * @param line text of the line to calculate the offset in
 * @param lineOffset offset of the first character in the line. 
 * 	0 based from the beginning of the document.
 * @param lineXOffset x location in the line
 * @return offset of the character at the x location relative to the start 
 * 	of the line. -1 if the x location is past the end if the line.
 */
int getOffsetAtX(String line, int lineOffset, int lineXOffset) {
	GC gc = getGC();
	int offset;	
	
	lineXOffset += (horizontalScrollOffset - leftMargin);
	if (isBidi()) {
		StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc);
		offset = bidi.getOffsetAtX(lineXOffset);
	}		
	else {
		StyleRange[] styles = null;
		StyledTextEvent event = renderer.getLineStyleData(lineOffset, line);
					
		if (event != null) {
			styles = renderer.filterLineStyles(event.styles);
		}
		int low = -1;
		int high = line.length();
		while (high - low > 1) {
			offset = (high + low) / 2;
			// Restrict right/high search boundary only if x is within searched text segment.
			// Fixes 1GL4ZVE.			
			if (lineXOffset < renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc)) {
				high = offset;			
			}
			else 
			if (high == line.length() && high - offset == 1) {
				// requested x location is past end of line
				high = -1;
			}
			else {
				low = offset;
			}
		}
		offset = high;
	}
	gc.dispose();	
	return offset;	
}
/** 
 * Returns the index of the last partially visible line.
 *
 * @return index of the last partially visible line.
 */
int getPartialBottomIndex() {
	int partialLineCount = Compatibility.ceil(getClientArea().height, lineHeight);
	return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1;
}
/**
 * Returns the content in the specified range using the platform line 
 * delimiter to separate lines.
 * <p>
 *
 * @param writer the TextWriter to write line text into
 * @return the content in the specified range using the platform line 
 * 	delimiter to separate lines as written by the specified TextWriter.
 */
String getPlatformDelimitedText(TextWriter writer) {
	int end = writer.getStart() + writer.getCharCount();
	int startLine = logicalContent.getLineAtOffset(writer.getStart());
	int endLine = logicalContent.getLineAtOffset(end);
	String endLineText = logicalContent.getLine(endLine);
	int endLineOffset = logicalContent.getOffsetAtLine(endLine);
	
	for (int i = startLine; i <= endLine; i++) {
		writer.writeLine(logicalContent.getLine(i), logicalContent.getOffsetAtLine(i));
		if (i < endLine) {
			writer.writeLineDelimiter(PlatformLineDelimiter);
		}
	}
	if (end > endLineOffset + endLineText.length()) {
		writer.writeLineDelimiter(PlatformLineDelimiter);
	}
	writer.close();
	return writer.toString();
}
/**
 * Returns the selection.
 * <p>
 * Text selections are specified in terms of caret positions.  In a text
 * widget that contains N characters, there are N+1 caret positions, 
 * ranging from 0..N
 * <p>
 *
 * @return start and end of the selection, x is the offset of the first 
 * 	selected character, y is the offset after the last selected character.
 *  The selection values returned are visual (i.e., x will always always be   
 *  <= y).  To determine if a selection is right-to-left (RtoL) vs. left-to-right 
 *  (LtoR), compare the caretOffset to the start and end of the selection 
 *  (e.g., caretOffset == start of selection implies that the selection is RtoL).
 * @see #getSelectionRange
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point getSelection() {
	checkWidget();
	return new Point(selection.x, selection.y);
}
/**
 * Returns the selection.
 * <p>
 *
 * @return start and length of the selection, x is the offset of the 
 * 	first selected character, relative to the first character of the 
 * 	widget content. y is the length of the selection. 
 *  The selection values returned are visual (i.e., length will always always be   
 *  positive).  To determine if a selection is right-to-left (RtoL) vs. left-to-right 
 *  (LtoR), compare the caretOffset to the start and end of the selection 
 *  (e.g., caretOffset == start of selection implies that the selection is RtoL).
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point getSelectionRange() {
	checkWidget();
	return new Point(selection.x, selection.y - selection.x);
}
/**
 * Returns the receiver's selection background color.
 *
 * @return the selection background color
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.1
 */
public Color getSelectionBackground() {
	checkWidget();
	if (selectionBackground == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
	}
	return selectionBackground;
}
/**
 * Gets the number of selected characters.
 * <p>
 *
 * @return the number of selected characters.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getSelectionCount() {
	checkWidget();
	return getSelectionRange().y;
}
/**
 * Returns the receiver's selection foreground color.
 *
 * @return the selection foreground color
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.1
 */
public Color getSelectionForeground() {
	checkWidget();
	if (selectionForeground == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
	}
	return selectionForeground;
}
/**
 * Returns the selected text.
 * <p>
 *
 * @return selected text, or an empty String if there is no selection.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public String getSelectionText() {
	checkWidget();
	return content.getTextRange(selection.x, selection.y - selection.x);
}
/**
 * Returns the text segments that should be treated as if they 
 * had a different direction than the surrounding text.
 * <p>
 *
 * @param lineOffset offset of the first character in the line. 
 * 	0 based from the beginning of the document.
 * @param line text of the line to specify bidi segments for
 * @return text segments that should be treated as if they had a
 * 	different direction than the surrounding text. Only the start 
 * 	index of a segment is specified, relative to the start of the 
 * 	line. Always starts with 0 and ends with the line length. 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the segment indices returned 
 * 		by the listener do not start with 0, are not in ascending order,
 * 		exceed the line length or have duplicates</li>
 * </ul>
 */
int [] getBidiSegments(int lineOffset, String line) {
	if (isListening(LineGetSegments) == false) {
		return getBidiSegmentsCompatibility(line, lineOffset);
	}
	StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line);
	int lineLength = line.length();
	int[] segments;
	if (event == null || event.segments == null || event.segments.length == 0) {
		segments = new int[] {0, lineLength};
	}
	else {
		int segmentCount = event.segments.length;
		
		// test segment index consistency
		if (event.segments[0] != 0) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		} 	
		for (int i = 1; i < segmentCount; i++) {
			if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) {
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			} 	
		}
		// ensure that last segment index is line end offset
		if (event.segments[segmentCount - 1] != lineLength) {
			segments = new int[segmentCount + 1];
			System.arraycopy(event.segments, 0, segments, 0, segmentCount);
			segments[segmentCount] = lineLength;
		}
		else {
			segments = event.segments;
		}
	}
	return segments;
}
/**
 * @see getBidiSegments
 * Supports deprecated setBidiColoring API. Remove when API is removed.
 */
int [] getBidiSegmentsCompatibility(String line, int lineOffset) {
	StyledTextEvent event;
	StyleRange [] styles = new StyleRange [0];
	int lineLength = line.length();
	if (bidiColoring == false) {
		return new int[] {0, lineLength};
	}
	event = renderer.getLineStyleData(lineOffset, line);
	if (event != null) {
		styles = event.styles;
	}
	if (styles.length == 0) {
		return new int[] {0, lineLength};
	}
	int k=0, count = 1;
	while (k < styles.length && styles[k].start == 0 && styles[k].length == lineLength) {
		k++;
	}
	int[] offsets = new int[(styles.length - k) * 2 + 2];
	for (int i = k; i < styles.length; i++) {
		StyleRange style = styles[i];
		int styleLineStart = Math.max(style.start - lineOffset, 0);
		int styleLineEnd = Math.max(style.start + style.length - lineOffset, styleLineStart);
		styleLineEnd = Math.min (styleLineEnd, line.length ());
		if (i > 0 && count > 1 &&
			((styleLineStart >= offsets[count-2] && styleLineStart <= offsets[count-1]) ||
			 (styleLineEnd >= offsets[count-2] && styleLineEnd <= offsets[count-1])) &&
			 style.similarTo(styles[i-1])) {
			offsets[count-2] = Math.min(offsets[count-2], styleLineStart);
			offsets[count-1] = Math.max(offsets[count-1], styleLineEnd);
		} else {
			if (styleLineStart > offsets[count - 1]) {
				offsets[count] = styleLineStart;
				count++;
			}
			offsets[count] = styleLineEnd;
			count++;
		}
	}
	// add offset for last non-colored segment in line, if any
	if (lineLength > offsets[count-1]) {
		offsets [count] = lineLength;
		count++;
	}		
	if (count == offsets.length) {
		return offsets;
	}
	int [] result = new int [count];
	System.arraycopy (offsets, 0, result, 0, count);
	return result;
}
/**
 * Returns the style range at the given offset.
 * Returns null if a LineStyleListener has been set or if a style is not set
 * for the offset. 
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * <p>
 *
 * @param offset the offset to return the style for. 
 * 	0 <= offset < getCharCount() must be true.
 * @return a StyleRange with start == offset and length == 1, indicating
 * 	the style at the given offset. null if a LineStyleListener has been set 
 * 	or if a style is not set for the given offset.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_ARGUMENT when the offset is invalid</li>
 * </ul>
 */
public StyleRange getStyleRangeAtOffset(int offset) {
	checkWidget();
	if (offset < 0 || offset >= getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	} 	
	if (userLineStyle == false) {
		return defaultLineStyler.getStyleRangeAtOffset(offset);
	} 
	return null;
}
/**
 * Returns the styles.
 * Returns an empty array if a LineStyleListener has been set. 
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * <p>
 *
 * @return the styles or null if a LineStyleListener has been set.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public StyleRange [] getStyleRanges() {
	checkWidget();
	StyleRange styles[];
	
	if (userLineStyle == false) {
		styles = defaultLineStyler.getStyleRanges();
	}
	else {
		styles = new StyleRange[0];
	}
	return styles;
}
/**
 * Returns a StyledTextBidi object for the specified line.
 * <p>
 * 
 * @param lineText the line that the StyledTextBidi object should 
 * 	work on.
 * @param lineOffset offset of the beginning of the line, relative 
 * 	to the beginning of the document
 * @param gc GC to use when creating a new StyledTextBidi object.
 * @return a StyledTextBidi object for the specified line.
 */
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc) {
	return getStyledTextBidi(lineText, lineOffset, gc, null);
}
/**
 * Returns a StyledTextBidi object for the specified line.
 * <p>
 * 
 * @param lineText the line that the StyledTextBidi object should 
 * 	work on.
 * @param lineOffset offset of the beginning of the line, relative 
 * 	to the beginning of the document
 * @param gc GC to use when creating a new StyledTextBidi object.
 * @param styles StyleRanges to use when creating a new StyledTextBidi 
 * 	object.
 * @return a StyledTextBidi object for the specified line.
 */
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc, StyleRange[] styles) {
	return renderer.getStyledTextBidi(lineText, lineOffset, gc, styles);
}		
/**
 * Returns the tab width measured in characters.
 *
 * @return tab width measured in characters
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getTabs() {
	checkWidget();
	return tabLength;
}
/**
 * Returns a copy of the widget content.
 * <p>
 *
 * @return copy of the widget content
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public String getText() {
	checkWidget();
	return content.getTextRange(0, getCharCount());
}	
/**
 * Returns the widget content between the two offsets.
 * <p>
 *
 * @param start offset of the first character in the returned String
 * @param end offset of the last character in the returned String 
 * @return widget content starting at start and ending at end
 * @see #getTextRange(int,int)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> 
 * </ul>
 */
public String getText(int start, int end) {
	checkWidget();
	int contentLength = getCharCount();
	
	if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}	
	return content.getTextRange(start, end - start + 1);
}
/**
 * Returns the widget content starting at start for length characters.
 * <p>
 *
 * @param start offset of the first character in the returned String
 * @param length number of characters to return 
 * @return widget content starting at start and extending length characters.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> 
 * </ul>
 */
public String getTextRange(int start, int length) {
	checkWidget();
	int contentLength = getCharCount();
	int end = start + length;
	
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}	
	return content.getTextRange(start, length);
}
/**
 * Gets the text limit.  The text limit specifies the amount of text that the user 
 * can type into the widget.
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getTextLimit() {
	checkWidget();
	
	return textLimit;
}
/**
 * Returns the x position of the character at the specified offset 
 * relative to the first character in the line.
 * Expands tabs to tab stops using the widget tab width.
 * <p>
 *
 * @param line line to be measured.
 * @param lineIndex index of the line relative to the first kine of the 
 * 	document
 * @param length number of characters to measure. Tabs are counted 
 * 	as one character in this parameter.
 * @param gc GC to use for measuring text
 * @return x position of the character at the specified offset 
 * 	with tabs expanded to tab stops. 0 if the length is outside the 
 * 	specified text.
 */
int getTextPosition(String line, int lineIndex, int length, GC gc) {
	int lineOffset = content.getOffsetAtLine(lineIndex);
	int lineLength = line.length();
	int width;
	if (lineLength == 0 || length > lineLength) {
		return 0;
	}	
	if (isBidi()) {
		StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc, null);
		width = getBidiTextPosition(line, length, bidi);
	}
	else {
		StyledTextEvent event = renderer.getLineStyleData(lineOffset, line);
		StyleRange[] styles = null;
		if (event != null) {
			styles = renderer.filterLineStyles(event.styles);
		}
		width = renderer.getTextPosition(line, lineOffset, length, styles, gc);
	}
	return width;
}
/**
 * Gets the top index.  The top index is the index of the fully visible line that
 * is currently at the top of the widget or the topmost partially visible line if 
 * no line is fully visible. 
 * The top index changes when the widget is scrolled. Indexing is zero based.
 * <p>
 *
 * @return the index of the top line
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getTopIndex() {
	checkWidget();
	int logicalTopIndex = topIndex;
	
	if (wordWrap) {
		int visualLineOffset = content.getOffsetAtLine(topIndex);
		logicalTopIndex = logicalContent.getLineAtOffset(visualLineOffset);
	}
	return logicalTopIndex;
}
/**
 * Gets the top pixel.  The top pixel is the pixel position of the line that is 
 * currently at the top of the widget.The text widget can be scrolled by pixels 
 * by dragging the scroll thumb so that a partial line may be displayed at the top 
 * the widget.  The top pixel changes when the widget is scrolled.  The top pixel 
 * does not include the widget trimming.
 * <p>
 *
 * @return pixel position of the top line
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getTopPixel() {
	checkWidget();
	return verticalScrollOffset;
}
/** 
 * Returns the vertical scroll increment.
 * <p>
 *
 * @return vertical scroll increment.
 */
int getVerticalIncrement() {
	return lineHeight;
}
/**
 * Returns the index of the line the caret is on.
 * When in word wrap mode and at the end of one wrapped line/ 
 * beginning of the continuing wrapped line the caret offset
 * is not sufficient to determine the caret line.
 * 
 * @return the index of the line the caret is on.
 */
int getCaretLine() {
	int caretLine = content.getLineAtOffset(caretOffset);
	int leftColumnX = 0;
	
	if (isBidi()) {
		leftColumnX = XINSET;
	}	
	if (wordWrap && columnX <= leftColumnX &&
		caretLine < content.getLineCount() - 1 &&
		caretOffset == content.getOffsetAtLine(caretLine + 1)) {
		caretLine++;
	}
	return caretLine;
}
/**
 * Returns the offset of the character after the word at the specified
 * offset.
 * <p>
 * There are two classes of words formed by a sequence of characters:
 * <ul>
 * <li>from 0-9 and A-z (ASCII 48-57 and 65-122)
 * <li>every other character except line breaks
 * </ul>
 * </p>
 * <p>
 * Space characters ' ' (ASCII 20) are special as they are treated as
 * part of the word leading up to the space character.  Line breaks are 
 * treated as one word.
 * </p>
 */
int getWordEnd(int offset) {
	int line = logicalContent.getLineAtOffset(offset);
	int lineOffset = logicalContent.getOffsetAtLine(line);
	String lineText = logicalContent.getLine(line);
	int lineLength = lineText.length();
	
	if (offset >= getCharCount()) {
		return offset;
	}
	if (offset == lineOffset + lineLength) {
		line++;
		offset = logicalContent.getOffsetAtLine(line);
	}
	else {
		offset -= lineOffset;
		char ch = lineText.charAt(offset);
		boolean letterOrDigit = Compatibility.isLetterOrDigit(ch);
		while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit) {
			offset++;
			ch = lineText.charAt(offset);
		}
		// skip over trailing whitespace
		while (offset < lineLength - 1 && Compatibility.isSpaceChar(ch)) {
			offset++;
			ch = lineText.charAt(offset);		
		}
		if (offset == lineLength - 1 && (Compatibility.isLetterOrDigit(ch) == letterOrDigit || Compatibility.isSpaceChar(ch))) {
			offset++;
		}
		offset += lineOffset;
	}
	return offset;
}
/**
 * Returns the offset of the character after the word at the specified
 * offset.
 * <p>
 * There are two classes of words formed by a sequence of characters:
 * <ul>
 * <li>from 0-9 and A-z (ASCII 48-57 and 65-122)
 * <li>every other character except line breaks
 * </ul>
 * </p>
 * <p>
 * Spaces are ignored and do not represent a word.  Line breaks are treated 
 * as one word.
 * </p>
 */
int getWordEndNoSpaces(int offset) {
	int line = logicalContent.getLineAtOffset(offset);
	int lineOffset = logicalContent.getOffsetAtLine(line);
	String lineText = logicalContent.getLine(line);
	int lineLength = lineText.length();
	
	if (offset >= getCharCount()) {
		return offset;
	}
	if (offset == lineOffset + lineLength) {
		line++;
		offset = logicalContent.getOffsetAtLine(line);
	}
	else {
		offset -= lineOffset;
		char ch = lineText.charAt(offset);
		boolean letterOrDigit = Compatibility.isLetterOrDigit(ch);
		
		while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) {
			offset++;
			ch = lineText.charAt(offset);
		}
		if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) {
			offset++;
		}
		offset += lineOffset;
	}
	return offset;
}
/**
 * Returns the start offset of the word at the specified offset.
 * There are two classes of words formed by a sequence of characters:
 * <p>
 * <ul>
 * <li>from 0-9 and A-z (ASCII 48-57 and 65-122)
 * <li>every other character except line breaks
 * </ul>
 * </p>
 * <p>
 * Space characters ' ' (ASCII 20) are special as they are treated as
 * part of the word leading up to the space character.  Line breaks are treated 
 * as one word.
 * </p>
 */
int getWordStart(int offset) {
	int line = logicalContent.getLineAtOffset(offset);
	int lineOffset = logicalContent.getOffsetAtLine(line);
	String lineText = logicalContent.getLine(line);
	
	if (offset <= 0) {
		return offset;
	}
	if (offset == lineOffset) {
		line--;
		lineText = logicalContent.getLine(line);
		offset = logicalContent.getOffsetAtLine(line) + lineText.length();
	}
	else {
		char ch;
		boolean letterOrDigit;
		
		offset -= lineOffset;
		// skip over trailing whitespace
		do {		
			offset--;
			ch = lineText.charAt(offset);
		} while (offset > 0 && Compatibility.isSpaceChar(ch));
		letterOrDigit = Compatibility.isLetterOrDigit(ch);
		while (offset > 0 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) {
			offset--;
			ch = lineText.charAt(offset);
		}
		if (offset > 0 || Compatibility.isLetterOrDigit(ch) != letterOrDigit) {
			offset++;
		}
		offset += lineOffset;
	}
	return offset;
}
/**
 * Returns whether the widget wraps lines.
 * <p>
 *
 * @return true if widget wraps lines, false otherwise
 * @since 2.0
 */
public boolean getWordWrap() {
	checkWidget();
	return wordWrap;
}
/** 
 * Returns the x location of the character at the give offset in the line.
 * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts).
 * <p>
 *
 * @return x location of the character at the given offset in the line.
 */
int getXAtOffset(String line, int lineIndex, int lineOffset) {
	int x;
	if (lineOffset == 0 && isBidi() == false) {
		x = leftMargin;
	}
	else {
		GC gc = getGC();		
		x = getTextPosition(line, lineIndex, Math.min(line.length(), lineOffset), gc) + leftMargin;
		gc.dispose();
		if (lineOffset > line.length()) {
			// offset is not on the line. return an x location one character 
			// after the line to indicate the line delimiter.
			x += lineEndSpaceWidth;
		}
	}
	return x - horizontalScrollOffset;
}
/** 
 * Inserts a string.  The old selection is replaced with the new text.  
 * <p>
 *
 * @param string the string
 * @see #replaceTextRange(int,int,String)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when string is null</li>
 * </ul>
 */
public void insert(String string) {
	checkWidget();
	if (string == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	Point sel = getSelectionRange();
	replaceTextRange(sel.x, sel.y, string);
}
/**
 * Creates content change listeners and set the default content model.
 */
void installDefaultContent() {
	textChangeListener = new TextChangeListener() {
		public void textChanging(TextChangingEvent event) {
			handleTextChanging(event);
		}
		public void textChanged(TextChangedEvent event) {
			handleTextChanged(event);
		}
		public void textSet(TextChangedEvent event) {
			handleTextSet(event);
		}
	};
	logicalContent = content = new DefaultContent();
	content.addTextChangeListener(textChangeListener);
}
/**
 * Creates a default line style listener.
 * Used to store line background colors and styles.
 * Removed when the user sets a LineStyleListener.
 * <p>
 *
 * @see #addLineStyleListener
 */
void installDefaultLineStyler() {
	defaultLineStyler = new DefaultLineStyler(logicalContent);
	StyledTextListener typedListener = new StyledTextListener(defaultLineStyler);
	if (userLineStyle == false) {
		addListener(LineGetStyle, typedListener);
	}
	if (userLineBackground == false) {
		addListener(LineGetBackground, typedListener);
	}
}
/** 
 * Adds event listeners
 */
void installListeners() {
	ScrollBar verticalBar = getVerticalBar();
	ScrollBar horizontalBar = getHorizontalBar();
	
	addListener(SWT.Dispose, new Listener() {
		public void handleEvent(Event event) {
			handleDispose();
		}
	});
	addListener(SWT.KeyDown, new Listener() {
		public void handleEvent(Event event) {
			handleKeyDown(event);
		}
	});
	addListener(SWT.MouseDown, new Listener() {
		public void handleEvent(Event event) {
			handleMouseDown(event);
		}
	});
	addListener(SWT.MouseUp, new Listener() {
		public void handleEvent(Event event) {
			handleMouseUp(event);
		}
	});
	addListener(SWT.MouseDoubleClick, new Listener() {
		public void handleEvent(Event event) {
			handleMouseDoubleClick(event);
		}
	});
	addListener(SWT.MouseMove, new Listener() {
		public void handleEvent(Event event) {
			handleMouseMove(event);
		}
	});
	addListener(SWT.Paint, new Listener() {
		public void handleEvent(Event event) {
			handlePaint(event);
		}
	});
	addListener(SWT.Resize, new Listener() {
		public void handleEvent(Event event) {
			handleResize(event);
		}
	});
	addListener(SWT.Traverse, new Listener() {
		public void handleEvent(Event event) {
			handleTraverse(event);
		}
	});
	if (verticalBar != null) {
		verticalBar.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				handleVerticalScroll(event);
			}
		});
	}
	if (horizontalBar != null) {
		horizontalBar.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				handleHorizontalScroll(event);
			}
		});
	}
}
StyledTextContent internalGetContent() {
	return content;
}
int internalGetHorizontalPixel() {
	return horizontalScrollOffset;
}
LineCache internalGetLineCache() {
	return lineCache;
}
Point internalGetSelection() {
	return selection;
}
boolean internalGetWordWrap() {
	return wordWrap;
}
/**
 * Used by WordWrapCache to bypass StyledText.redraw which does
 * an unwanted cache reset.
 */
void internalRedraw() {
	super.redraw();
}
/** 
 * Redraws the specified text range.
 * <p>
 *
 * @param start offset of the first character to redraw
 * @param length number of characters to redraw
 * @param clearBackground true if the background should be cleared as 
 * 	part of the redraw operation.  If true, the entire redraw range will
 *  be cleared before anything is redrawn.  If the redraw range includes
 *	the last character of a line (i.e., the entire line is redrawn) the 
 * 	line is cleared all the way to the right border of the widget.
 *  The redraw operation will be faster and smoother if clearBackground is 
 * 	set to false.  Whether or not the flag can be set to false depends on 
 * 	the type of change that has taken place.  If font styles or background 
 * 	colors for the redraw range have changed, clearBackground should be 
 * 	set to true.  If only foreground colors have changed for the redraw 
 * 	range, clearBackground can be set to false. 
 */
void internalRedrawRange(int start, int length, boolean clearBackground) {
	int end = start + length;
	int firstLine = content.getLineAtOffset(start);
	int lastLine = content.getLineAtOffset(end);
	int offsetInFirstLine;
	int partialBottomIndex = getPartialBottomIndex();
	int partialTopIndex = verticalScrollOffset / lineHeight;
	// do nothing if redraw range is completely invisible	
	if (firstLine > partialBottomIndex || lastLine < partialTopIndex) {
		return;
	}
	// only redraw visible lines
	if (partialTopIndex > firstLine) {
		firstLine = partialTopIndex;
		offsetInFirstLine = 0;
	}
	else {
		offsetInFirstLine = start - content.getOffsetAtLine(firstLine);
	}
	if (partialBottomIndex + 1 < lastLine) {
		lastLine = partialBottomIndex + 1;	// + 1 to redraw whole bottom line, including line break
		end = content.getOffsetAtLine(lastLine);
	}
	// redraw first and last lines
	if (isBidi()) {
		redrawBidiLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground);
	}	
	else {
		redrawLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground);
	}
	// redraw entire center lines if redraw range includes more than two lines
	if (lastLine - firstLine > 1) {
		Rectangle clientArea = getClientArea();
		int redrawStopY = lastLine * lineHeight - verticalScrollOffset;		
		int redrawY = (firstLine + 1) * lineHeight - verticalScrollOffset;				
		draw(0, redrawY, clientArea.width, redrawStopY - redrawY, clearBackground);
	}
}
/**
 * Returns the widget text with style information encoded using RTF format
 * specification version 1.5.
 *
 * @return the widget text with style information encoded using RTF format
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
String getRtf(){
	checkWidget();
	RTFWriter rtfWriter = new RTFWriter(0, getCharCount());
	return getPlatformDelimitedText(rtfWriter);
}
/** 
 * Frees resources.
 */
void handleDispose() {
	clipboard.dispose();
	ibeamCursor.dispose();
	if (renderer != null) {
		renderer.dispose();
		renderer = null;
	}
	if (content != null) {
		content.removeTextChangeListener(textChangeListener);
	}	
	if (leftCaretBitmap != null) {
		leftCaretBitmap.dispose();
		leftCaretBitmap = null;
	}
	if (rightCaretBitmap != null) {
		rightCaretBitmap.dispose();
		rightCaretBitmap = null;
	}
	if (isBidi()) {
		StyledTextBidi.removeLanguageListener(this);
	}
}
/** 
 * Scrolls the widget horizontally.
 */
void handleHorizontalScroll(Event event) {
	int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
	scrollHorizontal(scrollPixel);
}
/**
 * If an action has been registered for the key stroke execute the action.
 * Otherwise, if a character has been entered treat it as new content.
 * <p>
 *
 * @param event keyboard event
 */
void handleKey(Event event) {
	int action;
	
	if (event.keyCode != 0) {
		// special key pressed (e.g., F1)
		action = getKeyBinding(event.keyCode | event.stateMask);
	}
	else {
		// character key pressed
		action = getKeyBinding(event.character | event.stateMask);
		if (action == SWT.NULL) { 
			// see if we have a control character
			if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) {
				// get the character from the CTRL+char sequence, the control
				// key subtracts 64 from the value of the key that it modifies
				int c = event.character + 64;
				action = getKeyBinding(c | event.stateMask);
			}
		}
	}
	if (action == SWT.NULL) {
		boolean ignore = false;
		
		if (isCarbon) {
			// Ignore acclerator key combinations (we do not want to 
			// insert a character in the text in this instance). Do not  
			// ignore COMMAND+ALT combinations since that key sequence
			// produces characters on the mac.
			ignore = (event.stateMask ^ SWT.COMMAND) == 0 ||
					(event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0;
		} else {
			// Ignore acclerator key combinations (we do not want to 
			// insert a character in the text in this instance). Don't  
			// ignore CTRL+ALT combinations since that is the Alt Gr 
			// key on some keyboards.  See bug 20953. 
			ignore = (event.stateMask ^ SWT.ALT) == 0 || 
					(event.stateMask ^ SWT.CTRL) == 0 ||
					(event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 ||
					(event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0;
		}
		// -ignore anything below SPACE except for line delimiter keys and tab.
		// -ignore DEL 
		if (!ignore && event.character > 31 && event.character != SWT.DEL || 
		    event.character == SWT.CR || event.character == SWT.LF || 
		    event.character == TAB) {
			doContent(event.character);
		}
	}
	else {
		invokeAction(action);		
	}
}
/**
 * If a VerifyKey listener exists, verify that the key that was entered
 * should be processed.
 * <p>
 *
 * @param event keyboard event
 */
void handleKeyDown(Event event) {
	Event verifyEvent = new Event();
	
	verifyEvent.character = event.character;
	verifyEvent.keyCode = event.keyCode;
	verifyEvent.stateMask = event.stateMask;
	verifyEvent.doit = true;
	notifyListeners(VerifyKey, verifyEvent);
	if (verifyEvent.doit == true) {
		handleKey(event);
	}
}
/**
 * Updates the caret location and selection if mouse button 1 has been 
 * pressed.
 */
void handleMouseDoubleClick(Event event) {
	if (event.button != 1 || doubleClickEnabled == false) {
		return;
	}
	event.y -= topMargin;
	mouseDoubleClick = true;
	caretOffset = getWordStart(caretOffset);
	resetSelection();
	caretOffset = getWordEndNoSpaces(caretOffset);
	showCaret();
	doMouseSelection();
	doubleClickSelection = new Point(selection.x, selection.y);
}
/** 
 * Updates the caret location and selection if mouse button 1 has been 
 * pressed.
 */
void handleMouseDown(Event event) {
	if ((event.button != 1) || (isCarbon && (event.stateMask & SWT.MOD4) != 0)) {
		return;	
	}
	boolean select = (event.stateMask & SWT.MOD2) != 0;	
	mouseDoubleClick = false;
	event.y -= topMargin;
	doMouseLocationChange(event.x, event.y, select);
}
/** 
 * Updates the caret location and selection if mouse button 1 is pressed 
 * during the mouse move.
 */
void handleMouseMove(Event event) {
	if ((event.stateMask & SWT.BUTTON1) == 0) {
		return;
	}
	event.y -= topMargin;
	doMouseLocationChange(event.x, event.y, true);
	doAutoScroll(event);
}
/** 
 * Autoscrolling ends when the mouse button is released.
 */
void handleMouseUp(Event event) {
	event.y -= topMargin;
	endAutoScroll();
}
/**
 * Renders the invalidated area specified in the paint event.
 * <p>
 *
 * @param event paint event
 */
void handlePaint(Event event) {
	int startLine = Math.max(0, (event.y - topMargin + verticalScrollOffset) / lineHeight);
	int paintYFromTopLine = (startLine - topIndex) * lineHeight;
	int topLineOffset = topIndex * lineHeight - verticalScrollOffset;
	int startY = paintYFromTopLine + topLineOffset + topMargin;	// adjust y position for pixel based scrolling and top margin
	int renderHeight = event.y + event.height - startY;
	Rectangle clientArea = getClientArea();
	
	// Check if there is work to do. clientArea.width should never be 0
	// if we receive a paint event but we never want to try and create 
	// an Image with 0 width.
	if (clientArea.width == 0 || event.height == 0) {		
		return;
	}
	performPaint(event.gc, startLine, startY, renderHeight);
}	
/**
 * Recalculates the scroll bars. Rewraps all lines when in word 
 * wrap mode.
 * <p>
 *
 * @param event resize event
 */
void handleResize(Event event) {
	int oldHeight = clientAreaHeight;
	int oldWidth = clientAreaWidth;
	
	clientAreaHeight = getClientArea().height;
	clientAreaWidth = getClientArea().width;
	if (wordWrap) {
	    if (oldWidth != clientAreaWidth) {	
	    	wordWrapResize(oldWidth);
	    }
	}
	else
	if (clientAreaHeight > oldHeight) {
		int lineCount = content.getLineCount();
		int oldBottomIndex = topIndex + oldHeight / lineHeight;
		int newItemCount = Compatibility.ceil(clientAreaHeight - oldHeight, lineHeight);
		
		oldBottomIndex = Math.min(oldBottomIndex, lineCount);
		newItemCount = Math.min(newItemCount, lineCount - oldBottomIndex);
		lineCache.calculate(oldBottomIndex, newItemCount);
	}	
	setScrollBars();
	claimBottomFreeSpace();
	claimRightFreeSpace();	
	if (oldHeight != clientAreaHeight) {
		calculateTopIndex();
	}
}
/**
 * Updates the caret position and selection and the scroll bars to reflect 
 * the content change.
 * <p>
 */
void handleTextChanged(TextChangedEvent event) {
	lineCache.textChanged(lastTextChangeStart, 
		lastTextChangeNewLineCount, 
		lastTextChangeReplaceLineCount,
		lastTextChangeNewCharCount,
		lastTextChangeReplaceCharCount);
	setScrollBars();
	// update selection/caret location after styles have been changed.
	// otherwise any text measuring could be incorrect
	// 
	// also, this needs to be done after all scrolling. Otherwise, 
	// selection redraw would be flushed during scroll which is wrong.
	// in some cases new text would be drawn in scroll source area even 
	// though the intent is to scroll it.
	// fixes 1GB93QT
	updateSelection(
		lastTextChangeStart, 
		lastTextChangeReplaceCharCount, 
		lastTextChangeNewCharCount);
		
	if (lastTextChangeReplaceLineCount > 0) {
		// Only check for unused space when lines are deleted.
		// Fixes 1GFL4LY
		// Scroll up so that empty lines below last text line are used.
		// Fixes 1GEYJM0
		claimBottomFreeSpace();
	}
	if (lastTextChangeReplaceCharCount > 0) {
		// fixes bug 8273
		claimRightFreeSpace();
	}
	// do direct drawing if the text change is confined to a single line.
	// optimization and fixes bug 13999. see also handleTextChanging.
	if (lastTextChangeNewLineCount == 0 && lastTextChangeReplaceLineCount == 0) {
		int startLine = content.getLineAtOffset(lastTextChangeStart);
		int startY = startLine * lineHeight - verticalScrollOffset + topMargin;

		GC gc = getGC();
		Caret caret = getCaret();
		boolean caretVisible = false;
		
		if (caret != null) {
			caretVisible = caret.getVisible();
			caret.setVisible(false);
		}
		performPaint(gc, startLine, startY, lineHeight);
		if (caret != null) {		
			caret.setVisible(caretVisible);
		}
		gc.dispose();
	}
}
/**
 * Updates the screen to reflect a pending content change.
 * <p>
 *
 * @param event.start the start offset of the change
 * @param event.newText text that is going to be inserted or empty String 
 *	if no text will be inserted
 * @param event.replaceCharCount length of text that is going to be replaced
 * @param event.newCharCount length of text that is going to be inserted
 * @param event.replaceLineCount number of lines that are going to be replaced
 * @param event.newLineCount number of new lines that are going to be inserted
 */
void handleTextChanging(TextChangingEvent event) {
	int firstLine;	
	int textChangeY;
	boolean isMultiLineChange = event.replaceLineCount > 0 || event.newLineCount > 0;
			
	if (event.replaceCharCount < 0) {
		event.start += event.replaceCharCount;
		event.replaceCharCount *= -1;
	}
	lastTextChangeStart = event.start;
	lastTextChangeNewLineCount = event.newLineCount;
	lastTextChangeNewCharCount = event.newCharCount;
	lastTextChangeReplaceLineCount = event.replaceLineCount;
	lastTextChangeReplaceCharCount = event.replaceCharCount;
	firstLine = content.getLineAtOffset(event.start);
	textChangeY = firstLine * lineHeight - verticalScrollOffset + topMargin;
	if (isMultiLineChange) {
		redrawMultiLineChange(textChangeY, event.newLineCount, event.replaceLineCount);
	}
	// notify default line styler about text change
	if (defaultLineStyler != null) {
		defaultLineStyler.textChanging(event);
	}
	
	// Update the caret offset if it is greater than the length of the content.
	// This is necessary since style range API may be called between the
	// handleTextChanging and handleTextChanged events and this API sets the
	// caretOffset.
	int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount;
	if (caretOffset > newEndOfText) caretOffset = newEndOfText;
}
/**
 * Called when the widget content is set programatically, overwriting 
 * the old content. Resets the caret position, selection and scroll offsets. 
 * Recalculates the content width and scroll bars. Redraws the widget.
 * <p>
 *
 * @param event text change event. 
 */
void handleTextSet(TextChangedEvent event) {
	reset();
}
/**
 * Called when a traversal key is pressed.
 * Allow tab next traversal to occur when the widget is in single 
 * line mode or in multi line and non-editable mode . 
 * When in editable multi line mode we want to prevent the tab 
 * traversal and receive the tab key event instead.
 * <p>
 *
 * @param event the event
 */
void handleTraverse(Event event) {
	int style = getStyle();
	boolean ignoreTab = (style & SWT.MULTI) != 0 && !editable || isSingleLine();
	
	if ((event.detail == SWT.TRAVERSE_TAB_NEXT || 
		 event.detail == SWT.TRAVERSE_RETURN) && ignoreTab) {
		event.doit = true;
	}
}
/** 
 * Scrolls the widget vertically.
 */
void handleVerticalScroll(Event event) {
	setVerticalScrollOffset(getVerticalBar().getSelection(), false);
}
/** 
 * Initializes the fonts used to render font styles.
 * Presently only regular and bold fonts are supported.
 */
void initializeRenderer() {
	if (renderer != null) {
		renderer.dispose();
	}
	renderer = new DisplayRenderer(
		getDisplay(), getFont(), isBidi(), leftMargin, this, tabLength);
	lineHeight = renderer.getLineHeight();
	lineEndSpaceWidth = renderer.getLineEndSpaceWidth();
}
/**
 * Executes the action.
 * <p>
 *
 * @param action one of the actions defined in ST.java
 */
public void invokeAction(int action) {
	int oldColumnX;
	int caretLine;
	
	checkWidget();	
	switch (action) {
		// Navigation
		case ST.LINE_UP:
			caretLine = doLineUp();
			oldColumnX = columnX;
			// explicitly go to the calculated caret line. may be different 
			// from content.getLineAtOffset(caretOffset) when in word wrap mode
			showCaret(caretLine);
			// save the original horizontal caret position
			columnX = oldColumnX;
			clearSelection(true);
			break;
		case ST.LINE_DOWN:
			caretLine = doLineDown();
			oldColumnX = columnX;
			// explicitly go to the calculated caret line. may be different 
			// from content.getLineAtOffset(caretOffset) when in word wrap mode
			showCaret(caretLine);
			// save the original horizontal caret position
			columnX = oldColumnX;
			clearSelection(true);
			break;
		case ST.LINE_START:
			doLineStart();
			clearSelection(true);
			break;
		case ST.LINE_END:
			doLineEnd();
			clearSelection(true);
			break;
		case ST.COLUMN_PREVIOUS:
			doCursorPrevious();
			clearSelection(true);
			break;
		case ST.COLUMN_NEXT:
			doCursorNext();
			clearSelection(true);
			break;
		case ST.PAGE_UP:
			doPageUp();
			clearSelection(true);
			break;
		case ST.PAGE_DOWN:
			doPageDown(false);
			clearSelection(true);
			break;
		case ST.WORD_PREVIOUS:
			doWordPrevious();
			clearSelection(true);
			break;
		case ST.WORD_NEXT:
			doWordNext();
			clearSelection(true);
			break;
		case ST.TEXT_START:
			doContentStart();
			clearSelection(true);
			break;
		case ST.TEXT_END:
			doContentEnd();
			clearSelection(true);
			break;
		case ST.WINDOW_START:
			doPageStart();
			clearSelection(true);
			break;
		case ST.WINDOW_END:
			doPageEnd();
			clearSelection(true);
			break;
		// Selection	
		case ST.SELECT_LINE_UP:
			doSelectionLineUp();
			break;
		case ST.SELECT_LINE_DOWN:
			doSelectionLineDown();
			break;
		case ST.SELECT_LINE_START:
			doLineStart();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_LINE_END:
			doLineEnd();
			doSelection(ST.COLUMN_NEXT);
			break;
		case ST.SELECT_COLUMN_PREVIOUS:
			doSelectionCursorPrevious();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_COLUMN_NEXT:
			doSelectionCursorNext();
			doSelection(ST.COLUMN_NEXT);
			break;
		case ST.SELECT_PAGE_UP:
			doSelectionPageUp();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_PAGE_DOWN:
			doSelectionPageDown();
			break;
		case ST.SELECT_WORD_PREVIOUS:
			doSelectionWordPrevious();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_WORD_NEXT:
			doSelectionWordNext();
			doSelection(ST.COLUMN_NEXT);
			break;
		case ST.SELECT_TEXT_START:
			doContentStart();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_TEXT_END:
			doContentEnd();
			doSelection(ST.COLUMN_NEXT);
			break;
		case ST.SELECT_WINDOW_START:
			doPageStart();
			doSelection(ST.COLUMN_PREVIOUS);
			break;
		case ST.SELECT_WINDOW_END:
			doPageEnd();
			doSelection(ST.COLUMN_NEXT);
			break;
		// Modification			
		case ST.CUT:
			cut();
			break;
		case ST.COPY:
			copy();
			break;
		case ST.PASTE:
			paste();
			break;
		case ST.DELETE_PREVIOUS:
			doBackspace();
			break;
		case ST.DELETE_NEXT:
			doDelete();
			break;
		case ST.DELETE_WORD_PREVIOUS:
			doDeleteWordPrevious();
			break;
		case ST.DELETE_WORD_NEXT:
			doDeleteWordNext();
			break;
		// Miscellaneous
		case ST.TOGGLE_OVERWRITE:
			overwrite = !overwrite;		// toggle insert/overwrite mode
			break;
	}
}
/**
 * Temporary until SWT provides this
 */
boolean isBidi() {
	return isBidi;
}
/**
 * Returns whether the given offset is inside a multi byte line delimiter.
 * Example: 
 * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true
 * 
 * @return true if the given offset is inside a multi byte line delimiter.
 * false if the given offset is before or after a line delimiter.
 */
boolean isLineDelimiter(int offset) {
	int line = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(line);	
	int offsetInLine = offset - lineOffset;
	// offsetInLine will be greater than line length if the line 
	// delimiter is longer than one character and the offset is set
	// in between parts of the line delimiter.
	return offsetInLine > content.getLine(line).length();
}
/**
 * Returns whether or not the given lines are visible.
 * <p>
 *
 * @return true if any of the lines is visible
 * false if none of the lines is visible
 */
boolean isAreaVisible(int firstLine, int lastLine) {
	int partialBottomIndex = getPartialBottomIndex();
	int partialTopIndex = verticalScrollOffset / lineHeight;
	boolean notVisible = firstLine > partialBottomIndex || lastLine < partialTopIndex;
	return !notVisible;
}
/**
 * Returns whether or not the given styles will necessitate a redraw for the given start line.  
 * A redraw is necessary when font style changes after the start of a style will take place.  
 * This method assumes ranges is in order and non-overlapping.
 * <p>
 *
 * @return true if a redraw of the given line is necessary, false otherwise
 */
boolean isRedrawFirstLine(StyleRange[] ranges, int firstLine, int firstLineOffset) {
	int lineEnd = firstLineOffset + content.getLine(firstLine).length();
	for (int i=0; i<ranges.length; i++) {
		StyleRange range = ranges[i];
		// does the style start on the first line?
		if (range.start < lineEnd) {
			int rangeEnd = range.start + range.length;
			if (isStyleChanging(range, range.start, Math.min(rangeEnd, lineEnd))) return true;
		} else {
			return false;
		}
	}
	return false;
}
/**
 * Returns whether or not the given styles will necessitate a redraw for the given end line.  
 * A redraw is necessary when font style changes after the start of a style will take place.  
 * This method assumes ranges is in order and non-overlapping.
 * <p>
 *
 * @return true if a redraw of the last line is necessary, false otherwise
 */
boolean isRedrawLastLine(StyleRange[] ranges, int lastLine, int lastLineOffset) {
	for (int i = ranges.length - 1; i >= 0; i--) {
		StyleRange range = ranges[i];
		int rangeEnd = range.start + range.length;
		// does style range end on the last line?
		if (rangeEnd >= lastLineOffset) {
			if (isStyleChanging(range, Math.max(range.start, lastLineOffset), rangeEnd)) return true;
		} else {
			break;
		}
	}
	return false;
}
/**
 * Returns whether the widget can have only one line.
 * <p>
 *
 * @return true if widget can have only one line, false if widget can have 
 * 	multiple lines
 */
boolean isSingleLine() {
	return (getStyle() & SWT.SINGLE) != 0;
}
/** 
 * Returns whether the font style in the given style range is changing 
 * from SWT.NORMAL to SWT.BOLD or vice versa.
 * <p>
 *
 * @param range StyleRange to compare current font style with.
 * @param start offset of the first font style to compare 
 * @param end offset behind the last font style to compare
 * @return true if the font style is changing in the given style range,
 * 	false if the font style is not changing in the given style range.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
boolean isStyleChanging(StyleRange range, int start, int end) {
	checkWidget();
	StyleRange[] styles = defaultLineStyler.getStyleRangesFor(start, end - start);
	
	if (styles == null) {
		return (range.fontStyle != SWT.NORMAL);
	}
	for (int i = 0; i < styles.length; i++) {
		StyleRange newStyle = styles[i];
		if (newStyle.fontStyle != range.fontStyle) {
			return true;
		}
	}
	return false;
}
/**
 * Sends the specified verify event, replace/insert text as defined by 
 * the event and send a modify event.
 * <p>
 *
 * @param event	the text change event. 
 *	<ul>
 *	<li>event.start - the replace start offset</li>
 * 	<li>event.end - the replace end offset</li>
 * 	<li>event.text - the new text</li>
 *	</ul>
 * @param updateCaret whether or not he caret should be set behind
 *	the new text
 */
void modifyContent(Event event, boolean updateCaret) {
	event.doit = true;
	notifyListeners(SWT.Verify, event);
	if (event.doit) {
		StyledTextEvent styledTextEvent = null;
		int replacedLength = event.end - event.start;
		boolean isCharacterRemove = replacedLength == 1 && event.text.length() == 0;
		boolean isBackspace = event.start < caretOffset;
		boolean isDirectionBoundary = false;
				
		if (updateCaret && isBidi() && isCharacterRemove) {
			// set the keyboard language to the language of the deleted character.
			// determine direction boundary so that caret location can be updated 
			// properly.
			int line = content.getLineAtOffset(caretOffset);
			int lineStartOffset = content.getOffsetAtLine(line);		
			int offsetInLine = caretOffset - lineStartOffset;
			String lineText = content.getLine(line);
			GC gc = getGC();
			StyledTextBidi bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText));			
			if (isBackspace) {
				if (offsetInLine > 0) {
					// the line start/end does not represent a direction boundary 
					// even if the previous/next line has a different direction.
					isDirectionBoundary = 
						offsetInLine < lineText.length() && 
						(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || 
						 bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1));
					bidi.setKeyboardLanguage(offsetInLine - 1);
				}
			}
			else {
				if (offsetInLine < lineText.length()) {
					// the line start/end does not represent a direction boundary 
					// even if the previous/next line has a different direction.
					isDirectionBoundary = 
						offsetInLine > 0 && 
						(bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || 
						 bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1));
					bidi.setKeyboardLanguage(offsetInLine);
				}
			}
			gc.dispose();
		}						
		if (isListening(ExtendedModify)) {
			styledTextEvent = new StyledTextEvent(logicalContent);
			styledTextEvent.start = event.start;
			styledTextEvent.end = event.start + event.text.length();
			styledTextEvent.text = content.getTextRange(event.start, replacedLength);
		}
		content.replaceTextRange(event.start, replacedLength, event.text);
		// set the caret position prior to sending the modify event.
		// fixes 1GBB8NJ
		if (updateCaret) {		
			// always update the caret location. fixes 1G8FODP
			internalSetSelection(event.start + event.text.length(), 0, true);
			if (isBidi()) {
				// Update the caret direction so that the caret moves to the 
				// typed/deleted character. Fixes 1GJLQ16.
				if (isCharacterRemove) {
					updateBidiDirection(isBackspace, isDirectionBoundary);
				}
				else {
					lastCaretDirection = ST.COLUMN_NEXT;
				}
				showBidiCaret();
			}
			else {
				showCaret();
			}
		}	
		notifyListeners(SWT.Modify, event);		
		if (isListening(ExtendedModify)) {
			notifyListeners(ExtendedModify, styledTextEvent);
		}
	}
}
/** 
 * Replaces the selection with the clipboard text or insert the text at 
 * the current caret offset if there is no selection. 
 * If the widget has the SWT.SINGLE style and the clipboard text contains
 * more than one line, only the first line without line delimiters is 
 * inserted in the widget.
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void paste(){
	checkWidget();	
	TextTransfer transfer = TextTransfer.getInstance();
	String text;
	text = (String) clipboard.getContents(transfer);
	if (text != null && text.length() > 0) {
		Event event = new Event();
		event.start = selection.x;
		event.end = selection.y;
		event.text = getModelDelimitedText(text);
		sendKeyEvent(event);
	}
}
/**
 * Render the specified area.  Broken out as its own method to support
 * direct drawing.
 * <p>
 *
 * @param gc GC to render on 
 * @param startLine first line to render
 * @param startY y pixel location to start rendering at
 * @param renderHeight renderHeight widget area that needs to be filled with lines
 */
void performPaint(GC gc,int startLine,int startY, int renderHeight)	{
	Rectangle clientArea = getClientArea();
	Color background = getBackground();
	
	// Check if there is work to do. We never want to try and create 
	// an Image with 0 width or 0 height.
	if (clientArea.width == 0) {
		return;
	}
	if (renderHeight > 0) {
		// renderHeight will be negative when only top margin needs redrawing
		Color foreground = getForeground();
		int lineCount = content.getLineCount();
		int paintY = 0;
		int gcStyle = getStyle() & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
		
		if (isSingleLine()) {
			lineCount = 1;
			if (startLine > 1) {
				startLine = 1;
			}
		}
		Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight);
		GC lineGC = new GC(lineBuffer, gcStyle);	
	
		lineGC.setFont(getFont());
		renderer.setCurrentFontStyle(SWT.NORMAL);
		lineGC.setForeground(foreground);
		lineGC.setBackground(background);
		
		for (int i = startLine; paintY < renderHeight && i < lineCount; i++, paintY += lineHeight) {
			String line = content.getLine(i);
			renderer.drawLine(line, i, paintY, lineGC, background, foreground, true);
		}
		if (paintY < renderHeight) {
			lineGC.setBackground(background);
			lineGC.setForeground(background);
			lineGC.fillRectangle(0, paintY, clientArea.width, renderHeight - paintY);
		}
		gc.drawImage(lineBuffer, 0, startY);
		lineGC.dispose();
		lineBuffer.dispose();
	}
	clearMargin(gc, background, clientArea, renderHeight);
}
/** 
 * Prints the widget's text to the default printer.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void print() {
	checkWidget();
	Printer printer = new Printer();
	StyledTextPrintOptions options = new StyledTextPrintOptions();
	
	options.printTextForeground = true;
	options.printTextBackground = true;
	options.printTextFontStyle = true;
	options.printLineBackground = true;	
	new Printing(this, printer, options).run();
	printer.dispose();
}
/** 
 * Returns a runnable that will print the widget's text
 * to the specified printer.
 * <p>
 * The runnable may be run in a non-UI thread.
 * </p>
 * 
 * @param printer the printer to print to
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when printer is null</li>
 * </ul>
 */
public Runnable print(Printer printer) {
	StyledTextPrintOptions options = new StyledTextPrintOptions();

	checkWidget();	
	options.printTextForeground = true;
	options.printTextBackground = true;
	options.printTextFontStyle = true;
	options.printLineBackground = true;
	if (printer == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	return print(printer, options);
}
/** 
 * Returns a runnable that will print the widget's text
 * to the specified printer.
 * <p>
 * The runnable may be run in a non-UI thread.
 * </p>
 * 
 * @param printer the printer to print to
 * @param options print options to use during printing
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when printer or options is null</li>
 * </ul>
 * @since 2.1
 */
public Runnable print(Printer printer, StyledTextPrintOptions options) {
	checkWidget();
	if (printer == null || options == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	return new Printing(this, printer, options);
}
/**
 * Causes the entire bounds of the receiver to be marked
 * as needing to be redrawn. The next time a paint request
 * is processed, the control will be completely painted.
 * <p>
 * Recalculates the content width for all lines in the bounds.
 * When a <code>LineStyleListener</code> is used a redraw call 
 * is the only notification to the widget that styles have changed 
 * and that the content width may have changed.
 * </p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Control#update
 */
public void redraw() {
	int itemCount;
	
	super.redraw();
	itemCount = getPartialBottomIndex() - topIndex + 1;
	lineCache.redrawReset(topIndex, itemCount, true);
	lineCache.calculate(topIndex, itemCount);
	setHorizontalScrollBar();
}
/**
 * Causes the rectangular area of the receiver specified by
 * the arguments to be marked as needing to be redrawn. 
 * The next time a paint request is processed, that area of
 * the receiver will be painted. If the <code>all</code> flag
 * is <code>true</code>, any children of the receiver which
 * intersect with the specified area will also paint their
 * intersecting areas. If the <code>all</code> flag is 
 * <code>false</code>, the children will not be painted.
 * <p>
 * Marks the content width of all lines in the specified rectangle
 * as unknown. Recalculates the content width of all visible lines.
 * When a <code>LineStyleListener</code> is used a redraw call 
 * is the only notification to the widget that styles have changed 
 * and that the content width may have changed.
 * </p>
 *
 * @param x the x coordinate of the area to draw
 * @param y the y coordinate of the area to draw
 * @param width the width of the area to draw
 * @param height the height of the area to draw
 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Control#update
 */
public void redraw(int x, int y, int width, int height, boolean all) {
	if (isBidi()) {	
		// workaround for bug 4776
		super.redraw(x, y, width + 1, height, all);
	} else {
		super.redraw(x, y, width, height, all);
	}	
	if (height > 0) {
		int lineCount = content.getLineCount();
		int startLine = (getTopPixel() + y) / lineHeight;
		int endLine = startLine + Compatibility.ceil(height, lineHeight);
		int itemCount;
		
		// reset all lines in the redraw rectangle
		startLine = Math.min(startLine, lineCount);
		itemCount = Math.min(endLine, lineCount) - startLine;
		lineCache.reset(startLine, itemCount, true);
		// only calculate the visible lines
		itemCount = getPartialBottomIndex() - topIndex + 1;
		lineCache.calculate(topIndex, itemCount);
		setHorizontalScrollBar();
	}
}
/** 
 * Redraws a text range in the specified lines
 * <p>
 *
 * @param firstLine first line to redraw at the specified offset
 * @param offsetInFirstLine offset in firstLine to start redrawing
 * @param lastLine last line to redraw
 * @param endOffset offset in the last where redrawing should stop
 * @param clearBackground true=clear the background by invalidating
 *  the requested redraw range, false=draw the foreground directly
 *  without invalidating the redraw range.
 */
void redrawBidiLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) {
	int lineCount = lastLine - firstLine + 1;
	int redrawY = firstLine * lineHeight - verticalScrollOffset;
	int firstLineOffset = content.getOffsetAtLine(firstLine);
	String line = content.getLine(firstLine);
	GC gc = getGC();
	StyledTextBidi bidi = getStyledTextBidi(line, firstLineOffset, gc);
			
	bidi.redrawRange(
		this, offsetInFirstLine, 	
		Math.min(line.length(), endOffset) - offsetInFirstLine, 
		leftMargin - horizontalScrollOffset, redrawY + topMargin, lineHeight);
	// redraw line break marker (either space or full client area width)
	// if redraw range extends over more than one line and background should be redrawn
	if (lastLine > firstLine && clearBackground) {
		int lineBreakWidth;		
		int lineBreakStartX = bidi.getTextWidth();
		// handle empty line case
		if (lineBreakStartX == leftMargin) {
			lineBreakStartX += XINSET;
		}
		lineBreakStartX = lineBreakStartX - horizontalScrollOffset;
		if ((getStyle() & SWT.FULL_SELECTION) != 0) {
			lineBreakWidth = getClientArea().width - lineBreakStartX;
		}
		else {
			lineBreakWidth = lineEndSpaceWidth;
		}
		draw(lineBreakStartX, redrawY, lineBreakWidth, lineHeight, clearBackground);
	}
	// redraw last line if more than one line needs redrawing 
	if (lineCount > 1) {
		int lastLineOffset = content.getOffsetAtLine(lastLine);
		int offsetInLastLine = endOffset - lastLineOffset;	
		// no redraw necessary if redraw offset is 0
		if (offsetInLastLine > 0) {				
			line = content.getLine(lastLine);
			redrawY = lastLine * lineHeight - verticalScrollOffset;		
			bidi = getStyledTextBidi(line, lastLineOffset, gc);
			bidi.redrawRange(
				this, 0, offsetInLastLine, 
				leftMargin - horizontalScrollOffset, 
				redrawY + topMargin, lineHeight);
		}
	}
	gc.dispose();
}
/** 
 * Redraw the given line.
 * <p>
 *
 * @param line index of the line to redraw
 * @param offset offset in line to start redrawing
 */
void redrawLine(int line, int offset) {
	int redrawX = 0;
	if (offset > 0) {
		String lineText = content.getLine(line);
		redrawX = getXAtOffset(lineText, line, offset);
	}
	int redrawY = line * lineHeight - verticalScrollOffset;
	super.redraw(
		redrawX + leftMargin, redrawY + topMargin, 
		getClientArea().width, lineHeight, true);
}
/** 
 * Redraws a text range in the specified lines
 * <p>
 *
 * @param firstLine first line to redraw at the specified offset
 * @param offsetInFirstLine offset in firstLine to start redrawing
 * @param lastLine last line to redraw
 * @param endOffset offset in the last where redrawing should stop
 * @param clearBackground true=clear the background by invalidating
 *  the requested redraw range. If the redraw range includes the 
 * 	last character of a line (i.e., the entire line is redrawn) the 
 * 	line is cleared all the way to the right border of the widget.
 *  false=draw the foreground directly without invalidating the 
 * 	redraw range.
 */
void redrawLines(int firstLine, int offsetInFirstLine, int lastLine, int endOffset, boolean clearBackground) {
	String line = content.getLine(firstLine);
	int lineCount = lastLine - firstLine + 1;
	int redrawX = getXAtOffset(line, firstLine, offsetInFirstLine) - leftMargin;
	int redrawStopX;
	int redrawY = firstLine * lineHeight - verticalScrollOffset;
	int firstLineOffset = content.getOffsetAtLine(firstLine);
	boolean fullLineRedraw = ((getStyle() & SWT.FULL_SELECTION) != 0 && lastLine > firstLine);

	// if redraw range includes last character on the first line, 
	// clear background to right widget border. fixes bug 19595.
	if (clearBackground && endOffset - firstLineOffset >= line.length()) {
		fullLineRedraw = true;
	}
	// calculate redraw stop location
	if (fullLineRedraw) {
		redrawStopX = getClientArea().width - leftMargin;
	}
	else {
		redrawStopX = getXAtOffset(line, firstLine, endOffset - firstLineOffset) - leftMargin;
	}
	draw(redrawX, redrawY, redrawStopX - redrawX, lineHeight, clearBackground);
	// redraw last line if more than one line needs redrawing 
	if (lineCount > 1) {
		int offsetInLastLine = endOffset - content.getOffsetAtLine(lastLine);	
		// no redraw necessary if redraw offset is 0
		if (offsetInLastLine > 0) {
			line = content.getLine(lastLine);
			// if redraw range includes last character on the last line, 
			// clear background to right widget border. fixes bug 19595.
			if (clearBackground && offsetInLastLine >= line.length()) {
				fullLineRedraw = true;
			}
			if (fullLineRedraw) {
				redrawStopX = getClientArea().width - leftMargin;
			}
			else {
				redrawStopX = getXAtOffset(line, lastLine, offsetInLastLine) - leftMargin;
			}
			redrawY = lastLine * lineHeight - verticalScrollOffset;
			draw(0, redrawY, redrawStopX, lineHeight, clearBackground);
		}
	}
}
/**
 * Fixes the widget to display a text change.
 * Bit blitting and redrawing is done as necessary.
 * <p>
 *
 * @param y y location of the text change
 * @param newLineCount number of new lines.
 * @param replacedLineCount number of replaced lines.
 */
void redrawMultiLineChange(int y, int newLineCount, int replacedLineCount) {
	Rectangle clientArea = getClientArea();
	int lineCount = newLineCount - replacedLineCount;
	int sourceY;
	int destinationY;
		
	if (lineCount > 0) {
		sourceY = Math.max(0, y + lineHeight);
		destinationY = sourceY + lineCount * lineHeight;
	} 
	else {
		destinationY = Math.max(0, y + lineHeight);
		sourceY = destinationY - lineCount * lineHeight;
	}	
	scroll(
		0, destinationY,			// destination x, y
		0, sourceY,					// source x, y
		clientArea.width, clientArea.height, true);
	// Always redrawing causes the bottom line to flash when a line is
	// deleted. This is because SWT merges the paint area of the scroll
	// with the paint area of the redraw call below.
	// To prevent this we could call update after the scroll. However,
	// adding update can cause even more flash if the client does other 
	// redraw/update calls (ie. for syntax highlighting).
	// We could also redraw only when a line has been added or when 
	// contents has been added to a line. This would require getting 
	// line index info from the content and is not worth the trouble
	// (the flash is only on the bottom line and minor).
	// Specifying the NO_MERGE_PAINTS style bit prevents the merged 
	// redraw but could cause flash/slowness elsewhere.
	if (y + lineHeight > 0 && y <= clientArea.height) {
		// redraw first changed line in case a line was split/joined
		super.redraw(0, y, clientArea.width, lineHeight, true);
	}
	if (newLineCount > 0) {
		int redrawStartY = y + lineHeight;
		int redrawHeight = newLineCount * lineHeight;
		
		if (redrawStartY + redrawHeight > 0 && redrawStartY <= clientArea.height) {
			// display new text
			super.redraw(0, redrawStartY, clientArea.width, redrawHeight, true);
		}
	}
}
/** 
 * Redraws the specified text range.
 * <p>
 *
 * @param start offset of the first character to redraw
 * @param length number of characters to redraw
 * @param clearBackground true if the background should be cleared as
 *  part of the redraw operation.  If true, the entire redraw range will
 *  be cleared before anything is redrawn.  If the redraw range includes
 *	the last character of a line (i.e., the entire line is redrawn) the 
 * 	line is cleared all the way to the right border of the widget.
 * 	The redraw operation will be faster and smoother if clearBackground 
 * 	is set to false.  Whether or not the flag can be set to false depends 
 * 	on the type of change that has taken place.  If font styles or 
 * 	background colors for the redraw range have changed, clearBackground 
 * 	should be set to true.  If only foreground colors have changed for 
 * 	the redraw range, clearBackground can be set to false. 
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> 
 * </ul>
 */
public void redrawRange(int start, int length, boolean clearBackground) {
	checkWidget();
	int end = start + length;
	int contentLength = content.getCharCount();
	int firstLine;
	int lastLine;
	
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}	
	firstLine = content.getLineAtOffset(start);
	lastLine = content.getLineAtOffset(end);
	// reset all affected lines but let the redraw recalculate only 
	// those that are visible.
	lineCache.reset(firstLine, lastLine - firstLine + 1, true);
	internalRedrawRange(start, length, clearBackground);
}
/**
 * Removes the specified bidirectional segment listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 * @since 2.0
 */
public void removeBidiSegmentListener(BidiSegmentListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(LineGetSegments, listener);	
}
/**
 * Removes the specified extended modify listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) {
	checkWidget();
	if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(ExtendedModify, extendedModifyListener);	
}
/**
 * Removes the specified line background listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeLineBackgroundListener(LineBackgroundListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(LineGetBackground, listener);	
	// use default line styler if last user line styler was removed.
	if (isListening(LineGetBackground) == false && userLineBackground) {
		StyledTextListener typedListener = new StyledTextListener(defaultLineStyler);
		addListener(LineGetBackground, typedListener);	
		userLineBackground = false;
	}
}
/**
 * Removes the specified line style listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeLineStyleListener(LineStyleListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(LineGetStyle, listener);	
	// use default line styler if last user line styler was removed. Fixes 1G7B1X2
	if (isListening(LineGetStyle) == false && userLineStyle) {
		StyledTextListener typedListener = new StyledTextListener(defaultLineStyler);
		addListener(LineGetStyle, typedListener);	
		userLineStyle = false;
	}
}
/**
 * Removes the specified modify listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeModifyListener(ModifyListener modifyListener) {
	checkWidget();
	if (modifyListener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(SWT.Modify, modifyListener);	
}
/**
 * Removes the specified selection listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(SWT.Selection, listener);	
}
/**
 * Removes the specified verify listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeVerifyListener(VerifyListener verifyListener) {
	checkWidget();
	if (verifyListener == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	removeListener(SWT.Verify, verifyListener);	
}
/**
 * Removes the specified key verify listener.
 * <p>
 *
 * @param listener the listener
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void removeVerifyKeyListener(VerifyKeyListener listener) {
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(VerifyKey, listener);	
}
/** 
 * Replaces the styles in the given range with new styles.  This method
 * effectively deletes the styles in the given range and then adds the
 * the new styles. 
 * <p>
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * </p>
 *
 * @param start offset of first character where styles will be deleted
 * @param length length of the range to delete styles in
 * @param ranges StyleRange objects containing the new style information.
 * The ranges should not overlap and should be within the specified start 
 * and length. The style rendering is undefined if the ranges do overlap
 * or are ill-defined. Must not be null.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> 
 *   <li>ERROR_NULL_ARGUMENT when string is null</li>
 * </ul>
 * @since 2.0
 */
public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
	checkWidget();
	if (userLineStyle) {
		return;
	}
 	if (ranges == null) {
 		SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	}
 	if (ranges.length == 0) {
 		setStyleRange(new StyleRange(start, length, null, null));
 		return;
 	}
	int end = start + length;
	if (start > end || start < 0 || end > getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}	
	
	int firstLine = content.getLineAtOffset(start);
	int lastLine = content.getLineAtOffset(end);

	// if the area is not visible, there is no need to redraw
	boolean redrawLines = isAreaVisible(firstLine, lastLine);

	if (!redrawLines) {
		defaultLineStyler.replaceStyleRanges(start, length, ranges);
		lineCache.reset(firstLine, lastLine - firstLine + 1, true);
	} else {
		boolean redrawFirstLine = false;
		boolean redrawLastLine = false;	
		// the first and last line needs to be redrawn completely if the 
		// font style is changing from SWT.NORMAL to something else or 
		// vice versa. fixes 1G7M5WE.
		int firstLineOffset = content.getOffsetAtLine(firstLine);
		if (isBidi()) {
			redrawFirstLine = true;
			redrawLastLine = true;
		} else {
			int firstLineEnd = firstLineOffset + content.getLine(firstLine).length();
			redrawFirstLine = isRedrawFirstLine(ranges, firstLine, firstLineOffset);
			// check if any bold styles will be cleared
			StyleRange clearRange = new StyleRange(firstLineOffset, firstLineEnd - firstLineOffset, null, null);
			redrawFirstLine = redrawFirstLine || isRedrawFirstLine(new StyleRange[] {clearRange}, firstLine, firstLineOffset);
			if (lastLine != firstLine) {
				int lastLineOffset = content.getOffsetAtLine(lastLine);
				int lastLineEnd = lastLineOffset + content.getLine(lastLine).length();
				redrawLastLine = isRedrawLastLine(ranges, lastLine, lastLineOffset);
				// check if any bold styles will be cleared
				clearRange = new StyleRange(lastLineOffset, lastLineEnd - lastLineOffset, null, null);
				redrawLastLine = redrawLastLine || isRedrawLastLine(new StyleRange[] {clearRange}, lastLine, lastLineOffset);
			}
		}
		defaultLineStyler.replaceStyleRanges(start, length, ranges);
		// reset all lines affected by the style change but let the redraw
		// recalculate only those that are visible.
		lineCache.reset(firstLine, lastLine - firstLine + 1, true);
		internalRedrawRange(start, length, true);
		if (redrawFirstLine) {
			redrawLine(firstLine, start - firstLineOffset);
		}
		if (redrawLastLine) {
			redrawLine(lastLine, 0);
		}
	}

	// make sure that the caret is positioned correctly.
	// caret location may change if font style changes.
	// fixes 1G8FODP
	setCaretLocation();
}
/**
 * Replaces the given text range with new text.
 * If the widget has the SWT.SINGLE style and "text" contains more than 
 * one line, only the first line is rendered but the text is stored 
 * unchanged. A subsequent call to getText will return the same text 
 * that was set. Note that only a single line of text should be set when 
 * the SWT.SINGLE style is used.
 * <p>
 * <b>NOTE:</b> During the replace operation the current selection is
 * changed as follows:
 * <ul>	
 * <li>selection before replaced text: selection unchanged
 * <li>selection after replaced text: adjust the selection so that same text 
 * remains selected
 * <li>selection intersects replaced text: selection is cleared and caret
 * is placed after inserted text
 * </ul>
 * </p>
 *
 * @param start offset of first character to replace
 * @param length number of characters to replace. Use 0 to insert text
 * @param text new text. May be empty to delete text.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> 
 *   <li>ERROR_INVALID_ARGUMENT when either start or end is inside a multi byte line delimiter. 
 * 		Splitting a line delimiter for example by inserting text in between the CR and LF and deleting part of a line delimiter is not supported</li>  
 *   <li>ERROR_NULL_ARGUMENT when string is null</li>
 * </ul>
 */
public void replaceTextRange(int start, int length, String text) {
	checkWidget();
	int contentLength = getCharCount();
	int end = start + length;
	Event event = new Event();
	
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}	
	if (text == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	event.start = start;
	event.end = end;
	event.text = text;
	modifyContent(event, false);
}
/**
 * Resets the caret position, selection and scroll offsets. Recalculate
 * the content width and scroll bars. Redraw the widget.
 */
void reset() {
	ScrollBar verticalBar = getVerticalBar();
	ScrollBar horizontalBar = getHorizontalBar();
	caretOffset = 0;
	topIndex = 0;
	topOffset = 0;
	verticalScrollOffset = 0;
	horizontalScrollOffset = 0;	
	resetSelection();
	// discard any styles that may have been set by creating a 
	// new default line styler
	if (defaultLineStyler != null) {
		removeLineBackgroundListener(defaultLineStyler);
		removeLineStyleListener(defaultLineStyler);
		installDefaultLineStyler();
	}	
	calculateContentWidth();
	if (verticalBar != null) {
		verticalBar.setSelection(0);
	}
	if (horizontalBar != null) {
		horizontalBar.setSelection(0);	
	}
	setScrollBars();
	setCaretLocation();
	super.redraw();
}
/**
 * Resets the selection.
 */
void resetSelection() {
	selection.x = selection.y = caretOffset;
	selectionAnchor = -1;
}
/**
 * Scrolls the widget horizontally.
 * <p>
 *
 * @param pixels number of pixels to scroll, > 0 = scroll left,
 * 	< 0 scroll right
 */
void scrollHorizontal(int pixels) {
	Rectangle clientArea;
	
	if (pixels == 0) {
		return;
	}
	clientArea = getClientArea();
	if (pixels > 0) {
		int sourceX = leftMargin + pixels;
		int scrollWidth = clientArea.width - sourceX - rightMargin;
		int scrollHeight = clientArea.height - topMargin - bottomMargin;
		scroll(
			leftMargin, topMargin, 						// destination x, y
			sourceX, topMargin,							// source x, y
			scrollWidth, scrollHeight, true);
		if (sourceX > scrollWidth) {
			// redraw from end of scrolled area to beginning of scroll 
			// invalidated area
			super.redraw(
				leftMargin + scrollWidth, topMargin, 
				pixels - scrollWidth, scrollHeight, true);
		}
	}
	else {
		int destinationX = leftMargin - pixels;
		int scrollWidth = clientArea.width - destinationX - rightMargin;
		int scrollHeight = clientArea.height - topMargin - bottomMargin;
		scroll(
			destinationX, topMargin,					// destination x, y
			leftMargin, topMargin,						// source x, y
			scrollWidth, scrollHeight, true);
		if (destinationX > scrollWidth) {
			// redraw from end of scroll invalidated area to scroll 
			// destination
			super.redraw(
				leftMargin + scrollWidth, topMargin, 
				-pixels - scrollWidth, scrollHeight, true);	
		}
	}
	horizontalScrollOffset += pixels;
	setCaretLocation();
}
/**
 * Scrolls the widget horizontally and adjust the horizontal scroll
 * bar to reflect the new horizontal offset..
 * <p>
 *
 * @param pixels number of pixels to scroll, > 0 = scroll left,
 * 	< 0 scroll right
 * @return
 *	true=the widget was scrolled 
 *	false=the widget was not scrolled, the given offset is not valid.
 */
boolean scrollHorizontalBar(int pixels) {
	if (pixels == 0) {
		return false;
	}
	ScrollBar horizontalBar = getHorizontalBar();
	if (horizontalBar != null) {
		horizontalBar.setSelection(horizontalScrollOffset + pixels);
	}
	scrollHorizontal(pixels);
	return true;
}
/** 
 * Selects all the text.
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void selectAll() {
	checkWidget();
	setSelection(new Point(0, Math.max(getCharCount(),0)));
}
/**
 * Replaces/inserts text as defined by the event.
 * <p>
 *
 * @param event the text change event. 
 *	<ul>
 *	<li>event.start - the replace start offset</li>
 * 	<li>event.end - the replace end offset</li>
 * 	<li>event.text - the new text</li>
 *	</ul>
 */
void sendKeyEvent(Event event) {
	if (editable == false) {
		return;
	}
	modifyContent(event, true);
}
/**
 * Sends the specified selection event.
 */
void sendSelectionEvent() {
	Event event = new Event();
	event.x = selection.x;
	event.y = selection.y;
	notifyListeners(SWT.Selection, event);
}
/**
 * Sets whether the widget wraps lines.
 * This overrides the creation style bit SWT.WRAP.
 * <p>
 *
 * @param wrap true=widget wraps lines, false=widget does not wrap lines
 * @since 2.0
 */
public void setWordWrap(boolean wrap) {
	checkWidget();
	
	if (wrap != wordWrap) {
		ScrollBar horizontalBar = getHorizontalBar();
		
		wordWrap = wrap;
		if (wordWrap) {
		    logicalContent = content;
		    content = new WrappedContent(renderer, logicalContent);
		}
		else {
		    content = logicalContent;
		}
		calculateContentWidth();
	    horizontalScrollOffset = 0;
	    if (horizontalBar != null) {
			horizontalBar.setVisible(!wordWrap);		
	    }
		setScrollBars();
		setCaretLocation();
		super.redraw();		
	}
}
/**
 * Sets the caret location and scrolls the caret offset into view.
 */
void showBidiCaret() {
	int line = content.getLineAtOffset(caretOffset);
	int lineOffset = content.getOffsetAtLine(line);
	int offsetInLine = caretOffset - lineOffset;
	String lineText = content.getLine(line);
	int xAtOffset = 0;
	boolean scrolled = false;		
	GC gc = getGC();
	StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc);
	// getXAtOffset, inlined for better performance
	xAtOffset = getBidiTextPosition(lineText, offsetInLine, bidi) + leftMargin;
	if (offsetInLine > lineText.length()) {
		// offset is not on the line. return an x location one character 
		// after the line to indicate the line delimiter.
		xAtOffset += lineEndSpaceWidth;
	}
	xAtOffset -= horizontalScrollOffset;
	//
	scrolled = showLocation(xAtOffset, line);
	if (scrolled == false) {
		setBidiCaretLocation(bidi);
	}
	gc.dispose();
}
/**
 * Sets the receiver's caret.  Set the caret's height and location.
 * 
 * </p>
 * @param caret the new caret for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setCaret(Caret caret) {
	checkWidget ();
	super.setCaret(caret);
	if (caret != null) {
		if (isBidi() == false) {
			caret.setSize(caret.getSize().x, lineHeight);
		}
		setCaretLocation();
		if (isBidi()) {
			setBidiKeyboardLanguage();	
		}
	}		
}
/**
 * @see org.eclipse.swt.widgets.Control#setBackground
 */
public void setBackground(Color color) {
	checkWidget();
	super.setBackground(color);
	background = color;
	redraw();
}
/**
 * Set the caret to indicate the current typing direction.
 */
void setBidiCaretDirection() {
	Caret caret = getCaret();
	int direction = StyledTextBidi.getKeyboardLanguageDirection();
	
	if (caret == null || direction == caretDirection) {
		return;
	}
	caretDirection = direction;
	if (direction == SWT.DEFAULT) {
		caret.setImage(null);
		caret.setSize(caret.getSize().x, lineHeight);
	} 
	else 
	if (caretDirection == SWT.LEFT) {
		caret.setImage(leftCaretBitmap);			
	} 
	else 
	if (caretDirection == SWT.RIGHT) {
		caret.setImage(rightCaretBitmap);			
	}
}
/**
 * Moves the Caret to the current caret offset.
 * <p>
 * 
 * @param bidi StyledTextBidi object to use for measuring.
 * 	May be left null in which case a new object will be created.
 */
void setBidiCaretLocation(StyledTextBidi bidi) {
	int caretLine = getCaretLine();
	
	setBidiCaretLocation(bidi, caretLine);
}
/**
 * Moves the Caret to the current caret offset.
 * <p>
 * 
 * @param bidi StyledTextBidi object to use for measuring.
 * 	May be left null in which case a new object will be created.
 * @param caretLine line the caret should be placed on. Relative to
 * 	first line in document
 */
void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) {
	Caret caret = getCaret();
	String lineText = content.getLine(caretLine);
	int lineStartOffset = content.getOffsetAtLine(caretLine);
	int offsetInLine = caretOffset - lineStartOffset;
	GC gc = null;
	boolean isRightOriented = (getStyle() & SWT.MIRRORED) != 0;
	
	if (bidi == null) {
		gc = getGC();
		bidi = getStyledTextBidi(lineText, lineStartOffset, gc);
	}		
	if (lastCaretDirection == SWT.NULL) {
		columnX = bidi.getTextPosition(offsetInLine) + leftMargin - horizontalScrollOffset;
	} else {
		columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset;
	}
	// take the width of the caret into account
	int keyboardDirection = StyledTextBidi.getKeyboardLanguageDirection();
	if ((keyboardDirection == SWT.RIGHT && isRightOriented == false) || 
		(keyboardDirection == SWT.LEFT && isRightOriented)){  
		columnX -= (getCaretWidth() - 1);
	}
	if (caret != null) {
		setBidiCaretDirection();		
		caret.setLocation(
			columnX, 
			caretLine * lineHeight - verticalScrollOffset + topMargin);
	}
	if (gc != null) {
		gc.dispose();
	}
}
/**
 * Sets the BIDI coloring mode.  When true the BIDI text display
 * algorithm is applied to segments of text that are the same
 * color.
 *
 * @param mode the new coloring mode
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * <p>
 * @deprecated use BidiSegmentListener instead.
 * </p>
 */
public void setBidiColoring(boolean mode) {
	checkWidget();
	bidiColoring = mode;
}
/**
 * Switches the keyboard language according to the current editing 
 * position and cursor direction.
 */
void setBidiKeyboardLanguage() {
	int caretLine = getCaretLine();	
	int lineStartOffset = content.getOffsetAtLine(caretLine);
	int offsetInLine = caretOffset - lineStartOffset;
	String lineText = content.getLine(caretLine);
	GC gc = getGC();
	StyledTextBidi bidi;
	int lineLength = lineText.length();
	
	// Don't supply the bold styles/font since we don't want to measure anything
	bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText));
	if (offsetInLine == 0) {
		bidi.setKeyboardLanguage(offsetInLine);
	}
	else
	if (offsetInLine >= lineLength) {
		offsetInLine = Math.min(offsetInLine, lineLength - 1);
		bidi.setKeyboardLanguage(offsetInLine);
	}
	else
	if (lastCaretDirection == ST.COLUMN_NEXT) {
		// continue with previous character type
		bidi.setKeyboardLanguage(offsetInLine - 1);
	} 
	else {
		bidi.setKeyboardLanguage(offsetInLine);
	}	
	gc.dispose();
}
/**
 * Moves the Caret to the current caret offset.
 * <p>
 * 
 * @param newCaretX the new x location of the caret.
 * 	passed in for better performance when it has already been 
 * 	calculated outside this method.
 * @param line index of the line the caret is on. Relative to 
 *	the first line in the document.
 */
void setCaretLocation(int newCaretX, int line) {
	if (isBidi()) {
		setBidiCaretLocation(null, line);
	}
	else {	
		Caret caret = getCaret();
		
		columnX = newCaretX;
		if (caret != null) {
			caret.setLocation(
				newCaretX, 
				line * lineHeight - verticalScrollOffset + topMargin);
		}
	}
}
/**
 * Moves the Caret to the current caret offset.
 */
void setCaretLocation() {
	if (isBidi()) {
		setBidiCaretLocation(null);
	}
	else {	
		Caret caret = getCaret();
		int caretLine = getCaretLine();	
		int lineStartOffset = content.getOffsetAtLine(caretLine);
									
		columnX = getXAtOffset(
			content.getLine(caretLine), caretLine, caretOffset - lineStartOffset);
		if (caret != null) {
			caret.setLocation(
				columnX, 
				caretLine * lineHeight - verticalScrollOffset + topMargin);
		}
	}
}
/**
 * Sets the caret offset.
 *
 * @param offset caret offset, relative to the first character in the text.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a 
 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
 * </ul>
 */
public void setCaretOffset(int offset) {
	checkWidget();
	int length = getCharCount();
				
	if (length > 0 && offset != caretOffset) {
		if (offset < 0) {
			caretOffset = 0;
		}
		else
		if (offset > length) {
			caretOffset = length;
		}
		else {
			if (isLineDelimiter(offset)) {
				// offset is inside a multi byte line delimiter. This is an 
				// illegal operation and an exception is thrown. Fixes 1GDKK3R
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			}
			caretOffset = offset;
		}
		// clear the selection if the caret is moved.
		// don't notify listeners about the selection change.
		clearSelection(false);
	}
	// always update the caret location. fixes 1G8FODP
	setCaretLocation();
	if (isBidi()) {
		setBidiKeyboardLanguage();	
	}
}	
/**
 * Copies the specified text range to the clipboard.  The text will be placed
 * in the clipboard in plain text format and RTF format.
 * <p>
 *
 * @param start start index of the text
 * @param length length of text to place in clipboard
 * 
 * @exception SWTError, see Clipboard.setContents
 * @see org.eclipse.swt.dnd.Clipboard.setContents
 */
void setClipboardContent(int start, int length) throws SWTError {
	RTFTransfer rtfTransfer = RTFTransfer.getInstance();
	TextTransfer plainTextTransfer = TextTransfer.getInstance();
	RTFWriter rtfWriter = new RTFWriter(start, length);
	TextWriter plainTextWriter = new TextWriter(start, length);
	String rtfText = getPlatformDelimitedText(rtfWriter);
	String plainText = getPlatformDelimitedText(plainTextWriter);

	clipboard.setContents(
		new String[]{rtfText, plainText}, 
		new Transfer[]{rtfTransfer, plainTextTransfer});
}
/**
 * Sets the content implementation to use for text storage.
 * <p>
 *
 * @param content StyledTextContent implementation to use for text storage.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 * </ul>
 */
public void setContent(StyledTextContent newContent) {
	checkWidget();	
	if (newContent == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	if (content != null) {
		content.removeTextChangeListener(textChangeListener);
	}	
	logicalContent = newContent;
	if (wordWrap) {
	    content = new WrappedContent(renderer, logicalContent);
	}
	else {
	    content = logicalContent;
	}
	content.addTextChangeListener(textChangeListener);
	reset();
}
/**
 * Sets the receiver's cursor to the cursor specified by the
 * argument.  Overridden to handle the null case since the 
 * StyledText widget uses an ibeam as its default cursor.
 *
 * @see org.eclipse.swt.widgets.Control#setCursor
 */
public void setCursor (Cursor cursor) {
	if (cursor == null) {
		super.setCursor(ibeamCursor);
	} else {
		super.setCursor(cursor);
	}
}
/** 
 * Sets whether the widget implements double click mouse behavior.
 * </p>
 *
 * @param enable if true double clicking a word selects the word, if false
 * 	double clicks have the same effect as regular mouse clicks.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setDoubleClickEnabled(boolean enable) {
	checkWidget();
	doubleClickEnabled = enable;
}
/**
 * Sets whether the widget content can be edited.
 * </p>
 *
 * @param editable if true content can be edited, if false content can not be 
 * 	edited
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setEditable(boolean editable) {
	checkWidget();
	this.editable = editable;
}
/**
 * Sets a new font to render text with.
 * <p>
 * <b>NOTE:</b> Italic fonts are not supported unless they have no overhang
 * and the same baseline as regular fonts.
 * </p>
 *
 * @param font new font
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setFont(Font font) {
	checkWidget();
	int oldLineHeight = lineHeight;
	
	super.setFont(font);	
	initializeRenderer();
	// keep the same top line visible. fixes 5815
	if (lineHeight != oldLineHeight) {
		setVerticalScrollOffset(verticalScrollOffset * lineHeight / oldLineHeight, true);
		claimBottomFreeSpace();
	}
	calculateContentWidth();
	calculateScrollBars();
	if (isBidi()) {
		caretDirection = SWT.NULL;
		createCaretBitmaps();
		setBidiCaretDirection();
	} 
	else {
		Caret caret = getCaret();
		if (caret != null) {
			caret.setSize(caret.getSize().x, lineHeight);
		}
	}
	// always set the caret location. Fixes 6685
	setCaretLocation();
	super.redraw();
}
/**
 * @see org.eclipse.swt.widgets.Control#setForeground
 */
public void setForeground(Color color) {
	checkWidget();
	super.setForeground(color);
	foreground = color;
	redraw();
}
/** 
 * Sets the horizontal scroll offset relative to the start of the line.
 * Do nothing if there is no text set.
 * <p>
 * <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the 
 * widget.
 * </p>
 *
 * @param offset horizontal scroll offset relative to the start 
 * 	of the line, measured in character increments starting at 0, if 
 * 	equal to 0 the content is not scrolled, if > 0 = the content is scrolled.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setHorizontalIndex(int offset) {
	checkWidget();
	int clientAreaWidth = getClientArea().width;
	if (getCharCount() == 0) {
		return;
	}	
	if (offset < 0) {
		offset = 0;
	}
	offset *= getHorizontalIncrement();
	// allow any value if client area width is unknown or 0. 
	// offset will be checked in resize handler.
	// don't use isVisible since width is known even if widget 
	// is temporarily invisible
	if (clientAreaWidth > 0) {
		int width = lineCache.getWidth();
		// prevent scrolling if the content fits in the client area.
		// align end of longest line with right border of client area
		// if offset is out of range.
		if (offset > width - clientAreaWidth) {
			offset = Math.max(0, width - clientAreaWidth);
		}
	}
	scrollHorizontalBar(offset - horizontalScrollOffset);
}
/** 
 * Sets the horizontal pixel offset relative to the start of the line.
 * Do nothing if there is no text set.
 * <p>
 * <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text 
 * is set in the widget.
 * </p>
 *
 * @param pixel horizontal pixel offset relative to the start 
 * 	of the line.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.0
 */
public void setHorizontalPixel(int pixel) {
	checkWidget();
	int clientAreaWidth = getClientArea().width;
	if (getCharCount() == 0) {
		return;
	}	
	if (pixel < 0) {
		pixel = 0;
	}
	// allow any value if client area width is unknown or 0. 
	// offset will be checked in resize handler.
	// don't use isVisible since width is known even if widget 
	// is temporarily invisible
	if (clientAreaWidth > 0) {
		int width = lineCache.getWidth();
		// prevent scrolling if the content fits in the client area.
		// align end of longest line with right border of client area
		// if offset is out of range.
		if (pixel > width - clientAreaWidth) {
			pixel = Math.max(0, width - clientAreaWidth);
		}
	}
	scrollHorizontalBar(pixel - horizontalScrollOffset);
}
/**
 * Adjusts the maximum and the page size of the horizontal scroll bar 
 * to reflect content width changes.
 */
void setHorizontalScrollBar() {
	ScrollBar horizontalBar = getHorizontalBar();
	
	if (horizontalBar != null && horizontalBar.getVisible()) {
		final int INACTIVE = 1;
		Rectangle clientArea = getClientArea();
		// only set the real values if the scroll bar can be used 
		// (ie. because the thumb size is less than the scroll maximum)
		// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
		if (clientArea.width < lineCache.getWidth()) {
			horizontalBar.setValues(
				horizontalBar.getSelection(),
				horizontalBar.getMinimum(),
				lineCache.getWidth(),							// maximum
				clientArea.width - leftMargin - rightMargin,	// thumb size
				horizontalBar.getIncrement(),
				clientArea.width - leftMargin - rightMargin);	// page size
		}
		else 
		if (horizontalBar.getThumb() != INACTIVE || horizontalBar.getMaximum() != INACTIVE) {
			horizontalBar.setValues(
				horizontalBar.getSelection(),
				horizontalBar.getMinimum(),
				INACTIVE,
				INACTIVE,
				horizontalBar.getIncrement(),
				INACTIVE);
		}
	}
}
/** 
 * Sets the background color of the specified lines.
 * The background color is drawn for the width of the widget. All
 * line background colors are discarded when setText is called.
 * The text background color if defined in a StyleRange overlays the 
 * line background color. Should not be called if a LineBackgroundListener 
 * has been set since the listener maintains the line backgrounds.
 * <p>
 * Line background colors are maintained relative to the line text, not the 
 * line index that is specified in this method call.
 * During text changes, when entire lines are inserted or removed, the line 
 * background colors that are associated with the lines after the change 
 * will "move" with their respective text. An entire line is defined as 
 * extending from the first character on a line to the last and including the 
 * line delimiter. 
 * </p>
 * <p>
 * When two lines are joined by deleting a line delimiter, the top line 
 * background takes precedence and the color of the bottom line is deleted. 
 * For all other text changes line background colors will remain unchanged. 
 * </p>
 * 
 * @param startLine first line the color is applied to, 0 based
 * @param lineCount number of lines the color applies to.
 * @param background line background color
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_ARGUMENT when the specified line range is invalid</li>
 * </ul>
 */
public void setLineBackground(int startLine, int lineCount, Color background) {
	checkWidget();
	int partialBottomIndex = getPartialBottomIndex();
	
	// this API can not be used if the client is providing the line background
	if (userLineBackground) {
		return;
	}
	if (startLine < 0 || startLine + lineCount > logicalContent.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	} 
	defaultLineStyler.setLineBackground(startLine, lineCount, background);
	// do nothing if redraw range is completely invisible	
	if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) {
		return;
	}
	// only redraw visible lines
	if (startLine < topIndex) {
		lineCount -= topIndex - startLine;
		startLine = topIndex;
	}
	if (startLine + lineCount - 1 > partialBottomIndex) {
		lineCount = partialBottomIndex - startLine + 1;
	}
	startLine -= topIndex;
	super.redraw(
		leftMargin, startLine * lineHeight + topMargin, 
		getClientArea().width - leftMargin - rightMargin, lineCount * lineHeight, true);
}
/**
 * Flips selection anchor based on word selection direction.
 */
void setMouseWordSelectionAnchor() {
	if (mouseDoubleClick == false) {
		return;
	}
 	if (caretOffset < doubleClickSelection.x) {
		selectionAnchor = doubleClickSelection.y;
	}
	else
	if (caretOffset > doubleClickSelection.y) {
		selectionAnchor = doubleClickSelection.x;
	}
}
/**
 * Adjusts the maximum and the page size of the scroll bars to 
 * reflect content width/length changes.
 */
void setScrollBars() {
	ScrollBar verticalBar = getVerticalBar();
	
	if (verticalBar != null) {
		Rectangle clientArea = getClientArea();
		final int INACTIVE = 1;
		int maximum = content.getLineCount() * getVerticalIncrement();
		
		// only set the real values if the scroll bar can be used 
		// (ie. because the thumb size is less than the scroll maximum)
		// avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92
		if (clientArea.height < maximum) {
			verticalBar.setValues(
				verticalBar.getSelection(),
				verticalBar.getMinimum(),
				maximum,
				clientArea.height,				// thumb size
				verticalBar.getIncrement(),
				clientArea.height);				// page size
		}
		else
		if (verticalBar.getThumb() != INACTIVE || verticalBar.getMaximum() != INACTIVE) {
			verticalBar.setValues(
				verticalBar.getSelection(),
				verticalBar.getMinimum(),
				INACTIVE,
				INACTIVE,
				verticalBar.getIncrement(),
				INACTIVE);
		}		
	}
	setHorizontalScrollBar();
}
/** 
 * Sets the selection to the given position and scrolls it into view.  Equivalent to setSelection(start,start).
 * <p>
 *
 * @param start new caret position
 * @see #setSelection(int,int)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when start is outside the widget content
 *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a 
 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
 * </ul> 
 */
public void setSelection(int start) {
	// checkWidget test done in setSelectionRange	
	setSelection(start, start);
}
/** 
 * Sets the selection and scrolls it into view.
 * <p>
 * Indexing is zero based.  Text selections are specified in terms of
 * caret positions.  In a text widget that contains N characters, there are 
 * N+1 caret positions, ranging from 0..N
 * </p>
 *
 * @param point x=selection start offset, y=selection end offset
 * 	The caret will be placed at the selection start when x > y.
 * @see #setSelection(int,int)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT when point is null</li>
 *   <li>ERROR_INVALID_RANGE when start or end is outside the widget content
 *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a 
 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
 * </ul> 
 */
public void setSelection(Point point) {
	checkWidget();
	if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);	
	setSelection(point.x, point.y);
}
/**
 * Sets the receiver's selection background color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 *
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.1
 */
public void setSelectionBackground (Color color) {
	checkWidget ();
	if (color != null) {
		if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	selectionBackground = color;
	redraw();
}	
/**
 * Sets the receiver's selection foreground color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 *
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.1
 */
public void setSelectionForeground (Color color) {
	checkWidget ();
	if (color != null) {
		if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	selectionForeground = color;
	redraw();
}	
/** 
 * Sets the selection and scrolls it into view.
 * <p>
 * Indexing is zero based.  Text selections are specified in terms of
 * caret positions.  In a text widget that contains N characters, there are 
 * N+1 caret positions, ranging from 0..N
 * </p>
 *
 * @param start selection start offset. The caret will be placed at the 
 * 	selection start when start > end.
 * @param end selection end offset
 * @see #setSelectionRange(int,int)
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when start or end is outside the widget content
 *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a 
 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
 * </ul>
 */
public void setSelection(int start, int end) {
	// checkWidget test done in setSelectionRange
	setSelectionRange(start, end - start);
	showSelection();
}
/** 
 * Sets the selection. The new selection may not be visible. Call showSelection to scroll 
 * the selection into view.
 * <p>
 *
 * @param start offset of the first selected character, start >= 0 must be true.
 * @param length number of characters to select, 0 <= start + length <= getCharCount() 
 * 	must be true.
 * 	A negative length places the caret at the visual start of the selection.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when the range specified by start and length is outside the widget content
 *   <li>ERROR_INVALID_ARGUMENT when either the start or the end of the selection range is inside a 
 * multi byte line delimiter (and thus neither clearly in front of or after the line delimiter)
 * </ul>
 */
public void setSelectionRange(int start, int length) {
	checkWidget();
	int contentLength = getCharCount();
	int end = start + length;
	
	if (start < 0 || end < 0 || start > contentLength || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	if (isLineDelimiter(start) || isLineDelimiter(end)) {
		// the start offset or end offset of the selection range is inside a 
		// multi byte line delimiter. This is an illegal operation and an exception 
		// is thrown. Fixes 1GDKK3R
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}					
	internalSetSelection(start, length, false);
	// always update the caret location. fixes 1G8FODP
	setCaretLocation();
	if (isBidi()) {
		setBidiKeyboardLanguage();	
	}
}
/** 
 * Sets the selection. 
 * The new selection may not be visible. Call showSelection to scroll 
 * the selection into view.
 * <p>
 *
 * @param start offset of the first selected character, start >= 0 must be true.
 * @param length number of characters to select, 0 <= start + length 
 * 	<= getCharCount() must be true. 
 * 	A negative length places the caret at the selection start.
 * @param sendEvent a Selection event is sent when set to true and when 
 * 	the selection is reset.
 */
void internalSetSelection(int start, int length, boolean sendEvent) {
	int end = start + length;
	
	if (start > end) {
		int temp = end;
		end = start;
		start = temp;
	}
	// is the selection range different or is the selection direction 
	// different?
	if (selection.x != start || selection.y != end || 
		(length > 0 && selectionAnchor != selection.x) || 
		(length < 0 && selectionAnchor != selection.y)) {
		clearSelection(sendEvent);
		if (length < 0) {
			selectionAnchor = selection.y = end;
			caretOffset = selection.x = start;
		}
		else {
			selectionAnchor = selection.x = start;
			caretOffset = selection.y = end;
		}
		internalRedrawRange(selection.x, selection.y - selection.x, true);
	}
}
/** 
 * Adds the specified style. The new style overwrites existing styles for the
 * specified range.  Existing style ranges are adjusted if they partially 
 * overlap with the new style, To clear an individual style, call setStyleRange 
 * with a StyleRange that has null attributes. 
 * <p>
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * </p>
 *
 * @param range StyleRange object containing the style information.
 * Overwrites the old style in the given range. May be null to delete
 * all styles.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> 
 * </ul>
 */
public void setStyleRange(StyleRange range) {
	checkWidget();
	
	// this API can not be used if the client is providing the line styles
	if (userLineStyle) {
		return;
	}
 	// check the range, make sure it falls within the range of the
 	// text 
	if (range != null && range.start + range.length > content.getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	} 	
	if (range != null) {
		boolean redrawFirstLine = false;
		boolean redrawLastLine = false;
		int firstLine = content.getLineAtOffset(range.start);
		int lastLine = content.getLineAtOffset(range.start + range.length);

		// if the style is not visible, there is no need to redraw
		boolean redrawLines = isAreaVisible(firstLine, lastLine);

		if (!redrawLines) {
			defaultLineStyler.setStyleRange(range);
			lineCache.reset(firstLine, lastLine - firstLine + 1, true);
		} else {
			// the first and last line needs to be redrawn completely if the 
			// font style is changing from SWT.NORMAL to something else or 
			// vice versa. fixes 1G7M5WE.
			int firstLineOffset = content.getOffsetAtLine(firstLine);
			int lastLineOffset = content.getOffsetAtLine(lastLine);
			if (isBidi()) {
				if (firstLine != lastLine) {
					redrawFirstLine = true;
				}
				redrawLastLine = true;
			} else {
				redrawFirstLine = isRedrawFirstLine(new StyleRange[] {range}, firstLine, firstLineOffset);
				if (lastLine != firstLine) {
					redrawLastLine = isRedrawLastLine(new StyleRange[] {range}, lastLine, lastLineOffset);
				}
			}
			defaultLineStyler.setStyleRange(range);
			// reset all lines affected by the style change but let the redraw
			// recalculate only those that are visible.
			lineCache.reset(firstLine, lastLine - firstLine + 1, true);
			internalRedrawRange(range.start, range.length, true);
			if (redrawFirstLine) {
				redrawLine(firstLine, range.start - firstLineOffset);
			}
			if (redrawLastLine) {
				redrawLine(lastLine, 0);
			}
		}
	} else {
		// clearing all styles
		defaultLineStyler.setStyleRange(range);
		lineCache.reset(0, content.getLineCount(), false);
		redraw();
	}
	
	// make sure that the caret is positioned correctly.
	// caret location may change if font style changes.
	// fixes 1G8FODP
	setCaretLocation();
}
/** 
 * Sets styles to be used for rendering the widget content. All styles 
 * in the widget will be replaced with the given set of styles.
 * <p>
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * </p>
 *
 * @param ranges StyleRange objects containing the style information.
 * The ranges should not overlap. The style rendering is undefined if 
 * the ranges do overlap. Must not be null.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when listener is null</li>
 *    <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> 
 * </ul>
 */
public void setStyleRanges(StyleRange[] ranges) {
	checkWidget();
	// this API can not be used if the client is providing the line styles
	if (userLineStyle) {
		return;
	}
 	if (ranges == null) {
 		SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	}
 	// check the last range, make sure it falls within the range of the
 	// current text 
 	if (ranges.length != 0) {
 		StyleRange last = ranges[ranges.length-1];
 		int lastEnd = last.start + last.length;
		int firstLine = content.getLineAtOffset(ranges[0].start);
		int lastLine;
		if (lastEnd > content.getCharCount()) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		} 	
		lastLine = content.getLineAtOffset(lastEnd);
		// reset all lines affected by the style change
		lineCache.reset(firstLine, lastLine - firstLine + 1, true);
 	}
 	else {
		// reset all lines
		lineCache.reset(0, content.getLineCount(), false);
 	}
	defaultLineStyler.setStyleRanges(ranges);
	redraw(); // should only redraw affected area to avoid flashing
	// make sure that the caret is positioned correctly.
	// caret location may change if font style changes.
	// fixes 1G8FODP
	setCaretLocation();
}
/** 
 * Sets the tab width. 
 * <p>
 *
 * @param tabs tab width measured in characters.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setTabs(int tabs) {
	checkWidget();	
	tabLength = tabs;
	renderer.setTabLength(tabLength);
	if (caretOffset > 0) {
		caretOffset = 0;
		if (isBidi()) {
			showBidiCaret();
		}
		else {
			showCaret();
		}
		clearSelection(false);
	}
	// reset all line widths when the tab width changes
	lineCache.reset(0, content.getLineCount(), false);
	redraw();
}
/** 
 * Sets the widget content. 
 * If the widget has the SWT.SINGLE style and "text" contains more than 
 * one line, only the first line is rendered but the text is stored 
 * unchanged. A subsequent call to getText will return the same text 
 * that was set.
 * <p>
 * <b>Note:</b> Only a single line of text should be set when the SWT.SINGLE 
 * style is used.
 * </p>
 *
 * @param text new widget content. Replaces existing content. Line styles 
 * 	that were set using StyledText API are discarded.  The
 * 	current selection is also discarded.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT when string is null</li>
 * </ul>
 */
public void setText(String text) {
	checkWidget();
	Event event = new Event();
	
	if (text == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	event.start = 0;
	event.end = getCharCount();
	event.text = text;
	event.doit = true;	
	notifyListeners(SWT.Verify, event);
	if (event.doit) {
		StyledTextEvent styledTextEvent = null;
		
		if (isListening(ExtendedModify)) {		
			styledTextEvent = new StyledTextEvent(logicalContent);
			styledTextEvent.start = event.start;
			styledTextEvent.end = event.start + event.text.length();
			styledTextEvent.text = content.getTextRange(event.start, event.end - event.start);
		}
		content.setText(event.text);
		notifyListeners(SWT.Modify, event);	
		if (styledTextEvent != null) {
			notifyListeners(ExtendedModify, styledTextEvent);
		}
	}
}
/**
 * Sets the text limit.
 * <p>
 * The text limit specifies the amount of text that
 * the user can type into the widget.
 * </p>
 *
 * @param limit the new text limit.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_CANNOT_BE_ZERO when limit is 0</li>
 * </ul>
 */
public void setTextLimit(int limit) {
	checkWidget();
	if (limit == 0) {
		SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
	}
	textLimit = limit;
}
/**
 * Sets the top index. Do nothing if there is no text set.
 * <p>
 * The top index is the index of the line that is currently at the top 
 * of the widget. The top index changes when the widget is scrolled.
 * Indexing starts from zero.
 * Note: The top index is reset to 0 when new text is set in the widget.
 * </p>
 *
 * @param index new top index. Must be between 0 and 
 * 	getLineCount() - fully visible lines per page. If no lines are fully 
 * 	visible the maximum value is getLineCount() - 1. An out of range 
 * 	index will be adjusted accordingly.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setTopIndex(int topIndex) {
	checkWidget();
	int lineCount = logicalContent.getLineCount();
	int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole()));
	
	if (getCharCount() == 0) {
		return;
	}	
	if (topIndex < 0) {
		topIndex = 0;
	}
	else 
	if (topIndex > lineCount - pageSize) {
		topIndex = lineCount - pageSize;
	}
	if (wordWrap) {
		int logicalLineOffset = logicalContent.getOffsetAtLine(topIndex);
		topIndex = content.getLineAtOffset(logicalLineOffset);
	}
	setVerticalScrollOffset(topIndex * getVerticalIncrement(), true);
}
/**
 * Sets the top pixel offset. Do nothing if there is no text set.
 * <p>
 * The top pixel offset is the vertical pixel offset of the widget. The
 * widget is scrolled so that the given pixel position is at the top.
 * The top index is adjusted to the corresponding top line.
 * Note: The top pixel is reset to 0 when new text is set in the widget.
 * </p>
 *
 * @param pixel new top pixel offset. Must be between 0 and 
 * 	(getLineCount() - visible lines per page) / getLineHeight()). An out
 * 	of range offset will be adjusted accordingly.
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * @since 2.0
 */
public void setTopPixel(int pixel) {
	checkWidget();
	int lineCount =content.getLineCount();
	int height = getClientArea().height;
	int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height);
	
	if (getCharCount() == 0) {
		return;
	}	
	if (pixel < 0) {
		pixel = 0;
	}
	else 
	if (pixel > maxTopPixel) {
		pixel = maxTopPixel;
	}
	setVerticalScrollOffset(pixel, true);
}
/**
 * Scrolls the widget vertically.
 * <p>
 *
 * @param pixelOffset the new vertical scroll offset
 * @param adjustScrollBar 
 * 	true= the scroll thumb will be moved to reflect the new scroll offset.
 * 	false = the scroll thumb will not be moved
 * @return 
 *	true=the widget was scrolled 
 *	false=the widget was not scrolled, the given offset is not valid.
 */
boolean setVerticalScrollOffset(int pixelOffset, boolean adjustScrollBar) {
	Rectangle clientArea;
	ScrollBar verticalBar = getVerticalBar();
	
	if (pixelOffset == verticalScrollOffset) {
		return false;
	}
	if (verticalBar != null && adjustScrollBar) {
		verticalBar.setSelection(pixelOffset);
	}
	clientArea = getClientArea();
	scroll(
		0, 0, 									// destination x, y
		0, pixelOffset - verticalScrollOffset,	// source x, y
		clientArea.width, clientArea.height, true);

	verticalScrollOffset = pixelOffset;
	calculateTopIndex();
	setCaretLocation();
	return true;
}
/**
 * Scrolls the specified location into view.
 * <p>
 * 
 * @param x the x coordinate that should be made visible.
 * @param line the line that should be made visible. Relative to the
 *	first line in the document.
 * @return 
 *	true=the widget was scrolled to make the specified location visible. 
 *	false=the specified location is already visible, the widget was 
 *	not scrolled. 	
 */
boolean showLocation(int x, int line) {
	int clientAreaWidth = getClientArea().width - leftMargin - rightMargin;
	int verticalIncrement = getVerticalIncrement();
	int horizontalIncrement = clientAreaWidth / 4;
	boolean scrolled = false;		
	
	if (x < leftMargin) {
		// always make 1/4 of a page visible
		x = Math.max(horizontalScrollOffset * -1, x - horizontalIncrement);	
		scrolled = scrollHorizontalBar(x);
	}
	else 
	if (x >= clientAreaWidth) {
		// always make 1/4 of a page visible
		x = Math.min(lineCache.getWidth() - horizontalScrollOffset, x + horizontalIncrement);
		scrolled = scrollHorizontalBar(x - clientAreaWidth);
	}
	if (line < topIndex) {
		scrolled = setVerticalScrollOffset(line * verticalIncrement, true);
	}
	else
	if (line > getBottomIndex()) {
		scrolled = setVerticalScrollOffset((line + 1) * verticalIncrement - getClientArea().height, true);
	}
	return scrolled;
}
/**
 * Sets the caret location and scrolls the caret offset into view.
 */
void showCaret() {
	int caretLine = content.getLineAtOffset(caretOffset);
	
	showCaret(caretLine);
}
/**
 * Sets the caret location and scrolls the caret offset into view.
 */
void showCaret(int caretLine) {
	int lineOffset = content.getOffsetAtLine(caretLine);
	String lineText = content.getLine(caretLine);
	int offsetInLine = caretOffset - lineOffset;
	int xAtOffset = getXAtOffset(lineText, caretLine, offsetInLine);	
	boolean scrolled = showLocation(xAtOffset, caretLine);
	boolean setWrapCaretLocation = false;
	Caret caret = getCaret();

	if (wordWrap && caret != null) {
		int caretY = caret.getLocation().y;
		if ((caretY + verticalScrollOffset) / getVerticalIncrement() - 1 != caretLine) {
			setWrapCaretLocation = true;
		}
	}
	if (scrolled == false || setWrapCaretLocation) {
		// set the caret location if a scroll operation did not set it (as a 
		// sideeffect of scrolling) or when in word wrap mode and the caret 
		// line was explicitly specified (i.e., because getWrapCaretLine does 
		// not return the desired line causing scrolling to not set it correctly)
		setCaretLocation(xAtOffset, caretLine);
	}
	if (isBidi()) {
		setBidiKeyboardLanguage();
	}
}
/**
 * Scrolls the specified offset into view.
 * <p>
 *
 * @param offset offset that should be scolled into view
 */
void showOffset(int offset) {
	int line = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(line);
	int offsetInLine = offset - lineOffset;
	String lineText = content.getLine(line);
	int xAtOffset = getXAtOffset(lineText, line, offsetInLine);
	
	showLocation(xAtOffset, line);	
}
/**
/**
 * Scrolls the selection into view.  The end of the selection will be scrolled into
 * view.  Note that if a right-to-left selection exists, the end of the selection is the
 * visual beginning of the selection (i.e., where the caret is located).
 * <p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void showSelection() {
	checkWidget();
	boolean selectionFits;
	int startOffset, startLine, startX, endOffset, endLine, endX, offsetInLine;

	// is selection from right-to-left?
	boolean rightToLeft = caretOffset == selection.x;

	if (rightToLeft) {
		startOffset = selection.y;
		endOffset = selection.x;
	} else {
		startOffset = selection.x;
		endOffset = selection.y;
	}
	
	// calculate the logical start and end values for the selection
	startLine = content.getLineAtOffset(startOffset);
	offsetInLine = startOffset - content.getOffsetAtLine(startLine);
	startX = getXAtOffset(content.getLine(startLine), startLine, offsetInLine);	
	endLine  = content.getLineAtOffset(endOffset);
	offsetInLine = endOffset - content.getOffsetAtLine(endLine);
	endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine);	

	// can the selection be fully displayed within the widget's visible width?
	int w = getClientArea().width;
	if (rightToLeft) {
		selectionFits = startX - endX <= w;
	} else {
		selectionFits = endX - startX <= w;
	}
	
	if (selectionFits) {
		// show as much of the selection as possible by first showing
		// the start of the selection
		showLocation(startX, startLine);
		// endX value could change if showing startX caused a scroll to occur
		endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine);	
		showLocation(endX, endLine);
	} else {
		// just show the end of the selection since the selection start 
		// will not be visible
		showLocation(endX, endLine);
	}	 
}
/**
 * Updates the caret direction when a delete operation occured based on 
 * the type of the delete operation (next/previous character) and the 
 * caret location (at a direction boundary or inside a direction segment).
 * The intent is to place the caret at the visual location where a
 * character was deleted.
 * <p>
 * 
 * @param isBackspace true=the previous character was deleted, false=the 
 * 	character next to the caret location was deleted
 * @param isDirectionBoundary true=the caret is between a R2L and L2R segment,
 * 	false=the caret is within a direction segment
 */
void updateBidiDirection(boolean isBackspace, boolean isDirectionBoundary) {
	if (isDirectionBoundary) {
		if (isBackspace) {
			// Deleted previous character (backspace) at a direction boundary
			// Go to direction segment of deleted character
			lastCaretDirection = ST.COLUMN_NEXT;
		}
		else {
			// Deleted next character. Go to direction segment of deleted character
			lastCaretDirection = ST.COLUMN_PREVIOUS;
		}
	}
	else {
		if (isBackspace) {
			// Delete previous character inside direction segment (i.e., not at a direction boundary)
			lastCaretDirection = ST.COLUMN_PREVIOUS;
		}
		else {
			// Deleted next character.
			lastCaretDirection = ST.COLUMN_NEXT;
		}
	}
}
/**
 * Updates the selection and caret position depending on the text change.
 * If the selection intersects with the replaced text, the selection is 
 * reset and the caret moved to the end of the new text.
 * If the selection is behind the replaced text it is moved so that the
 * same text remains selected.  If the selection is before the replaced text 
 * it is left unchanged.
 * <p>
 *
 * @param startOffset offset of the text change
 * @param replacedLength length of text being replaced
 * @param newLength length of new text
 */
void updateSelection(int startOffset, int replacedLength, int newLength) {
	if (selection.y <= startOffset) {
		// selection ends before text change
		return;
	}
	if (selection.x < startOffset) {
		// clear selection fragment before text change
		internalRedrawRange(selection.x, startOffset - selection.x, true);
	}
	if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) {
		// clear selection fragment after text change.
		// do this only when the selection is actually affected by the 
		// change. Selection is only affected if it intersects the change (1GDY217).
		int netNewLength = newLength - replacedLength;
		int redrawStart = startOffset + newLength;
		internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart, true);
	}
	if (selection.y > startOffset && selection.x < startOffset + replacedLength) {
		// selection intersects replaced text. set caret behind text change
		internalSetSelection(startOffset + newLength, 0, true);
		// always update the caret location. fixes 1G8FODP
		setCaretLocation();
	}
	else {
		// move selection to keep same text selected
		internalSetSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true);
		// always update the caret location. fixes 1G8FODP
		setCaretLocation();
	}	
}
/**
 * Rewraps all lines
 * <p>
 * 
 * @param oldClientAreaWidth client area width before resize 
 * 	occurred
 */
void wordWrapResize(int oldClientAreaWidth) {
	WrappedContent wrappedContent = (WrappedContent) content;
	int newTopIndex;

	// all lines are wrapped and no rewrap required if widget has already 
	// been visible, client area is now wider and visual (wrapped) line 
	// count equals logical line count.
	if (oldClientAreaWidth != 0 && clientAreaWidth > oldClientAreaWidth &&
		wrappedContent.getLineCount() == logicalContent.getLineCount()) {
		return;
	}
    wrappedContent.wrapLines();
    
    // adjust the top index so that top line remains the same
	newTopIndex = content.getLineAtOffset(topOffset);
	// topOffset is the beginning of the top line. therefore it 
	// needs to be adjusted because in a wrapped line this is also 
	// the end of the preceeding line.  
	if (newTopIndex < content.getLineCount() - 1 &&
		topOffset == content.getOffsetAtLine(newTopIndex + 1)) {
		newTopIndex++;
	}
    if (newTopIndex != topIndex) {
    	ScrollBar verticalBar = getVerticalBar();
    	// adjust index and pixel offset manually instead of calling
    	// setVerticalScrollOffset because the widget does not actually need
    	// to be scrolled. causes flash otherwise.
    	verticalScrollOffset += (newTopIndex - topIndex) * getVerticalIncrement();
    	// verticalScrollOffset may become negative if first line was 
    	// partially visible and second line was top line. prevent this from 
    	// happening to fix 8503.
    	if (verticalScrollOffset < 0) {
    		verticalScrollOffset = 0;
    	}
    	topIndex = newTopIndex;
    	topOffset = content.getOffsetAtLine(topIndex);
    	if (verticalBar != null) {
			verticalBar.setSelection(verticalScrollOffset);
    	}
    }
  	// caret may be on a different line after a rewrap.
  	// call setCaretLocation after fixing vertical scroll offset.
	setCaretLocation();    
	// word wrap may have changed on one of the visible lines
    super.redraw();
}
}
