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


import java.util.*;
import java.util.List;

import org.eclipse.swt.*;
import org.eclipse.swt.accessibility.*;
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, italic, bold-italic, regular)
 * <li>underline
 * <li>strikeout
 * </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>
 * <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, OrientationChange
 * </dl>
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#styledtext">StyledText snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Examples: CustomControlExample, TextEditor</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class StyledText extends Canvas {
	static final char TAB = '\t';
	static final String PlatformLineDelimiter = System.getProperty("line.separator");
	static final int BIDI_CARET_WIDTH = 3;
	static final int DEFAULT_WIDTH	= 64;
	static final int DEFAULT_HEIGHT = 64;
	static final int V_SCROLL_RATE = 50;
	static final int H_SCROLL_RATE = 10;
	static final int PREVIOUS_OFFSET_TRAILING = 0;
	static final int OFFSET_LEADING = 1;
	
	Color selectionBackground;	// selection background color
	Color selectionForeground;	// selection foreground color
	StyledTextContent content;			// native content (default or user specified)
	StyledTextRenderer renderer;
	Listener listener;
	TextChangeListener textChangeListener;	// listener for TextChanging, TextChanged and TextSet events from StyledTextContent
	int verticalScrollOffset = 0;		// pixel based
	int horizontalScrollOffset = 0;		// pixel based
	boolean alwaysShowScroll = true;
	int ignoreResize = 0;
	int topIndex = 0;					// top visible line
	int topIndexY;
	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 tabLength = 4;					// number of characters in a tab
	int [] tabs;
	int leftMargin;
	int topMargin;
	int rightMargin;
	int bottomMargin;
	Color marginColor;
	int columnX;						// keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935
	int caretOffset;
	int caretAlignment;
	Point selection = new Point(0, 0);	// x and y are start and end caret offsets of selection
	Point clipboardSelection;           // x and y are start and end caret offsets of previous selection
	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;			// text is wrapped automatically
	boolean visualWrap = false;		// process line breaks inside logical lines (inserted by BidiSegmentEvent)
	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<Integer, Integer> keyActionMap = new Hashtable<Integer, Integer>();
	Color background = null;			// workaround for bug 4791
	Color foreground = null;			//
	Clipboard clipboard;
	int clickCount;
	int autoScrollDirection = SWT.NULL;	// the direction of autoscrolling (up, down, right, left)
	int autoScrollDistance = 0;
	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;
	int lastCharCount = 0;
	int lastLineBottom;					// the bottom pixel of the last line been replaced
	boolean bidiColoring = false;		// apply the BIDI algorithm on text segments of the same color
	Image leftCaretBitmap = null;
	Image rightCaretBitmap = null;
	int caretDirection = SWT.NULL;
	int caretWidth = 0;
	Caret defaultCaret = null;
	boolean updateCaretDirection = true;
	boolean fixedLineHeight;
	boolean dragDetect = true;
	IME ime;
	Cursor cursor;
	int alignment;
	boolean justify;
	int indent, wrapIndent;
	int lineSpacing;
	int alignmentMargin;
	int newOrientation = SWT.NONE;
	int accCaretOffset;
	Accessible acc;
	AccessibleControlAdapter accControlAdapter;
	AccessibleAttributeAdapter accAttributeAdapter;
	AccessibleEditableTextListener accEditableTextListener;
	AccessibleTextExtendedAdapter accTextExtendedAdapter;
	AccessibleAdapter accAdapter;
	
	//block selection
	boolean blockSelection;
	int blockXAnchor = -1, blockYAnchor = -1;
	int blockXLocation = -1, blockYLocation = -1;
	

	final static boolean IS_MAC, IS_GTK;
	static {
		String platform = SWT.getPlatform();
		IS_MAC = "cocoa".equals(platform);
		IS_GTK = "gtk".equals(platform);
	}

	/**
	 * The Printing class implements printing of a range of text.
	 * An instance of <code>Printing</code> is returned in the 
	 * StyledText#print(Printer) API. The run() method may be 
	 * invoked from any thread.
	 */
	static 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;
		StyledTextRenderer printerRenderer;
		StyledTextPrintOptions printOptions;
		Rectangle clientArea;
		FontData fontData;
		Font printerFont;
		Hashtable<Resource, Resource> resources;
		int tabLength;
		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 scope;										// scope of print job
		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
		boolean mirrored;						// indicates the printing gc should be mirrored
		int lineSpacing;
		int printMargin;

	/**
	 * Creates an instance of <code>Printing</code>.
	 * 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 styledText, Printer printer, StyledTextPrintOptions printOptions) {
		this.printer = printer;
		this.printOptions = printOptions;
		this.mirrored = (styledText.getStyle() & SWT.MIRRORED) != 0;
		singleLine = styledText.isSingleLine();
		startPage = 1;
		endPage = Integer.MAX_VALUE;
		PrinterData data = printer.getPrinterData();
		scope = data.scope;
		if (scope == PrinterData.PAGE_RANGE) {
			startPage = data.startPage;
			endPage = data.endPage;
			if (endPage < startPage) {
				int temp = endPage;
				endPage = startPage;
				startPage = temp;
			}
		} else if (scope == PrinterData.SELECTION) {
			selection = styledText.getSelectionRange();
		}
		printerRenderer = new StyledTextRenderer(printer, null);
		printerRenderer.setContent(copyContent(styledText.getContent()));
		cacheLineData(styledText);
	}
	/**
	 * Caches all line data that needs to be requested from a listener.
	 * </p>
	 * @param printerContent <code>StyledTextContent</code> to request 
	 * 	line data for.
	 */
	void cacheLineData(StyledText styledText) {
		StyledTextRenderer renderer = styledText.renderer;
		renderer.copyInto(printerRenderer);
		fontData = styledText.getFont().getFontData()[0];
		tabLength = styledText.tabLength;
		int lineCount = printerRenderer.lineCount;
		if (styledText.isListening(ST.LineGetBackground) || (styledText.isListening(ST.LineGetSegments)) || styledText.isListening(ST.LineGetStyle)) {
			StyledTextContent content = printerRenderer.content;
			for (int i = 0; i < lineCount; i++) {
				String line = content.getLine(i);
				int lineOffset = content.getOffsetAtLine(i);
				StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
				if (event != null && event.lineBackground != null) {
					printerRenderer.setLineBackground(i, 1, event.lineBackground);
				}
				event = styledText.getBidiSegments(lineOffset, line);
				if (event != null) {
					printerRenderer.setLineSegments(i, 1, event.segments);
					printerRenderer.setLineSegmentChars(i, 1, event.segmentsChars);
				}
				event = styledText.getLineStyleData(lineOffset, line);
				if (event != null) {
					printerRenderer.setLineIndent(i, 1, event.indent);
					printerRenderer.setLineAlignment(i, 1, event.alignment);
					printerRenderer.setLineJustify(i, 1, event.justify);
					printerRenderer.setLineBullet(i, 1, event.bullet);
					StyleRange[] styles = event.styles;
					if (styles != null && styles.length > 0) {
						printerRenderer.setStyleRanges(event.ranges, styles);
					}
				}
			}
		}
		Point screenDPI = styledText.getDisplay().getDPI();
		Point printerDPI = printer.getDPI();
		resources = new Hashtable<Resource, Resource> ();
		for (int i = 0; i < lineCount; i++) {
			Color color = printerRenderer.getLineBackground(i, null);
			if (color != null) {
				if (printOptions.printLineBackground) {
					Color printerColor = (Color)resources.get(color);
					if (printerColor == null) {
						printerColor = new Color (printer, color.getRGB());
						resources.put(color, printerColor); 
					}
					printerRenderer.setLineBackground(i, 1, printerColor);
				} else {
					printerRenderer.setLineBackground(i, 1, null);
				}
			}
			int indent = printerRenderer.getLineIndent(i, 0);
			if (indent != 0) {
				printerRenderer.setLineIndent(i, 1, indent * printerDPI.x / screenDPI.x);
			}
		}
		StyleRange[] styles = printerRenderer.styles;
		for (int i = 0; i < printerRenderer.styleCount; i++) {
			StyleRange style = styles[i];
			Font font = style.font;
			if (style.font != null) {
				Font printerFont = (Font)resources.get(font);
				if (printerFont == null) {
					printerFont = new Font (printer, font.getFontData());
					resources.put(font, printerFont);					
				}
				style.font = printerFont;
			}
			Color color = style.foreground;
			if (color != null) {
				Color printerColor = (Color)resources.get(color);
				if (printOptions.printTextForeground) {
					if (printerColor == null) {
						printerColor = new Color (printer, color.getRGB());
						resources.put(color, printerColor); 
					}
					style.foreground = printerColor;
				} else {
					style.foreground = null;
				}
			}
			color = style.background;
			if (color != null) {
				Color printerColor = (Color)resources.get(color);
				if (printOptions.printTextBackground) {
					if (printerColor == null) {
						printerColor = new Color (printer, color.getRGB());
						resources.put(color, printerColor); 
					}
					style.background = printerColor;
				} else {
					style.background = null;
				}
			}
			if (!printOptions.printTextFontStyle) {
				style.fontStyle = SWT.NORMAL;
			}
			style.rise = style.rise * printerDPI.y / screenDPI.y;
			GlyphMetrics metrics = style.metrics;
			if (metrics != null) {
				metrics.ascent = metrics.ascent * printerDPI.y / screenDPI.y;
				metrics.descent = metrics.descent * printerDPI.y / screenDPI.y;
				metrics.width = metrics.width * printerDPI.x / screenDPI.x;
			}
		}
		lineSpacing = styledText.lineSpacing * printerDPI.y / screenDPI.y;
		if (printOptions.printLineNumbers) {
			printMargin = 3 * printerDPI.x / screenDPI.x;
		}
	}
	/**
	 * Copies the text of the specified <code>StyledTextContent</code>.
	 * </p>
	 * @param original the <code>StyledTextContent</code> to copy.
	 */
	StyledTextContent copyContent(StyledTextContent original) {
		StyledTextContent printerContent = new DefaultContent();
		int insertOffset = 0;
		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;
		}
		return printerContent;
	}
	/**
	 * Disposes of the resources and the <code>PrintRenderer</code>.
	 */
	void dispose() {
		if (gc != null) {
			gc.dispose();
			gc = null;
		}
		if (resources != null) {
			Enumeration<Resource> enumeration = resources.elements();			
			while (enumeration.hasMoreElements()) {
				Resource resource = enumeration.nextElement();
				resource.dispose();
			}
			resources = null;
		}
		if (printerFont != null) {
			printerFont.dispose();
			printerFont = null;
		}
		if (printerRenderer != null) {
			printerRenderer.dispose();
			printerRenderer = null;
		}
	}
	void init() {
		Rectangle trim = printer.computeTrim(0, 0, 0, 0);
		Point dpi = printer.getDPI();
		
		printerFont = new Font(printer, fontData.getName(), fontData.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); 

		int style = mirrored ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
		gc = new GC(printer, style);
		gc.setFont(printerFont);
		printerRenderer.setFont(printerFont, tabLength);
		int lineHeight = printerRenderer.getLineHeight();
		if (printOptions.header != null) {
			clientArea.y += lineHeight * 2;
			clientArea.height -= lineHeight * 2;
		}
		if (printOptions.footer != null) {
			clientArea.height -= lineHeight * 2;
		}
		
		// TODO not wrapped
		StyledTextContent content = printerRenderer.content;
		startLine = 0;
		endLine = singleLine ? 0 : content.getLineCount() - 1;
		if (scope == PrinterData.PAGE_RANGE) {
			int pageSize = clientArea.height / lineHeight;//WRONG
			startLine = (startPage - 1) * pageSize;
		} else if (scope == PrinterData.SELECTION) {
			startLine = content.getLineAtOffset(selection.x);
			if (selection.y > 0) {
				endLine = content.getLineAtOffset(selection.x + selection.y - 1);
			} else {
				endLine = startLine - 1;
			}
		}
	}
	/**
	 * Prints the lines in the specified page range.
	 */
	void print() {
		Color background = gc.getBackground();
		Color foreground = gc.getForeground();
		int paintY = clientArea.y;
		int paintX = clientArea.x;
		int width = clientArea.width;
		int page = startPage;
		int pageBottom = clientArea.y + clientArea.height;
		int orientation =  gc.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
		TextLayout printLayout = null;
		if (printOptions.printLineNumbers || printOptions.header != null || printOptions.footer != null) {
			printLayout = new TextLayout(printer);
			printLayout.setFont(printerFont);
		}
		if (printOptions.printLineNumbers) {
			int numberingWidth = 0;
			int count = endLine - startLine + 1;
			String[] lineLabels = printOptions.lineLabels;
			if (lineLabels != null) {
				for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
					if (lineLabels[i] != null) {
						printLayout.setText(lineLabels[i]);
						int lineWidth = printLayout.getBounds().width;
						numberingWidth = Math.max(numberingWidth, lineWidth);
					}
				}
			} else {
				StringBuffer buffer = new StringBuffer("0");
				while ((count /= 10) > 0) buffer.append("0");
				printLayout.setText(buffer.toString());
				numberingWidth = printLayout.getBounds().width;
			}
			numberingWidth += printMargin;
			if (numberingWidth > width) numberingWidth = width;
			paintX += numberingWidth;
			width -= numberingWidth;
		}
		for (int i = startLine; i <= endLine && page <= endPage; i++) {
			if (paintY == clientArea.y) {
				printer.startPage();
				printDecoration(page, true, printLayout);
			}
			TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing);
			Color lineBackground = printerRenderer.getLineBackground(i, background);
			int paragraphBottom = paintY + layout.getBounds().height; 
			if (paragraphBottom <= pageBottom) {
				//normal case, the whole paragraph fits in the current page
				printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
				paintY = paragraphBottom;
			} else {
				int lineCount = layout.getLineCount();
				while (paragraphBottom > pageBottom && lineCount > 0) {
					lineCount--;
					paragraphBottom -= layout.getLineBounds(lineCount).height + layout.getSpacing();
				}
				if (lineCount == 0) {
					//the whole paragraph goes to the next page
					printDecoration(page, false, printLayout);
					printer.endPage();
					page++;
					if (page <= endPage) {
						printer.startPage();
						printDecoration(page, true, printLayout);
						paintY = clientArea.y;
						printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
						paintY += layout.getBounds().height;
					}
				} else {
					//draw paragraph top in the current page and paragraph bottom in the next
					int height = paragraphBottom - paintY;
					gc.setClipping(clientArea.x, paintY, clientArea.width, height);
					printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
					gc.setClipping((Rectangle)null);
					printDecoration(page, false, printLayout);
					printer.endPage();					
					page++;
					if (page <= endPage) {
						printer.startPage();
						printDecoration(page, true, printLayout);
						paintY = clientArea.y - height;
						int layoutHeight = layout.getBounds().height;
						gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height);
						printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
						gc.setClipping((Rectangle)null);
						paintY += layoutHeight;
					}
				}
			}
			printerRenderer.disposeTextLayout(layout);
		}
		if (page <= endPage && paintY > clientArea.y) {
			// close partial page
			printDecoration(page, false, printLayout);
			printer.endPage();
		}
		if (printLayout != null) printLayout.dispose();
	}
	/**
	 * 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, TextLayout layout) {
		String text = header ? printOptions.header : printOptions.footer;
		if (text == null) return;
		int lastSegmentIndex = 0;
		for (int i = 0; i < 3; i++) {
			int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex);
			String segment;
			if (segmentIndex == -1) {
				segment = text.substring(lastSegmentIndex);
				printDecorationSegment(segment, i, page, header, layout);
				break;
			} else {
				segment = text.substring(lastSegmentIndex, segmentIndex);
				printDecorationSegment(segment, i, page, header, layout);
				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, TextLayout layout) {		
		int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG);
		if (pageIndex != -1) {
			int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length();
			StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex));
			buffer.append (page);
			buffer.append (segment.substring(pageIndex + pageTagLength));
			segment = buffer.toString();
		}
		if (segment.length() > 0) {
			layout.setText(segment);
			int segmentWidth = layout.getBounds().width;
			int segmentHeight = printerRenderer.getLineHeight();
			int drawX = 0, drawY;
			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 (header) {
				drawY = clientArea.y - segmentHeight * 2;
			} else {
				drawY = clientArea.y + clientArea.height + segmentHeight;
			}
			layout.draw(gc, drawX, drawY);
		}
	}
	void printLine(int x, int y, GC gc, Color foreground, Color background, TextLayout layout, TextLayout printLayout, int index) {
		if (background != null) {
			Rectangle rect = layout.getBounds();
			gc.setBackground(background);
			gc.fillRectangle(x, y, rect.width, rect.height);
			
//			int lineCount = layout.getLineCount();
//			for (int i = 0; i < lineCount; i++) {
//				Rectangle rect = layout.getLineBounds(i);
//				rect.x += paintX;
//				rect.y += paintY + layout.getSpacing();
//				rect.width = width;//layout bounds
//				gc.fillRectangle(rect);
//			}
		}
		if (printOptions.printLineNumbers) {
			FontMetrics metrics = layout.getLineMetrics(0);
			printLayout.setAscent(metrics.getAscent() + metrics.getLeading());
			printLayout.setDescent(metrics.getDescent());
			String[] lineLabels = printOptions.lineLabels;
			if (lineLabels != null) {
				if (0 <= index && index < lineLabels.length && lineLabels[index] != null) {
					printLayout.setText(lineLabels[index]);
				} else {
					printLayout.setText("");
				}
			} else {
				printLayout.setText(String.valueOf(index));
			}
			int paintX = x - printMargin - printLayout.getBounds().width;
			printLayout.draw(gc, paintX, y);
			printLayout.setAscent(-1);
			printLayout.setDescent(-1);
		}
		gc.setForeground(foreground);
		layout.draw(gc, x, y);
	}
	/**
	 * 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)) {
			init();
			print();
			dispose();
			printer.endJob();
		}
	}	
	}
	/**
	 * 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 {
		static final int DEFAULT_FOREGROUND = 0;
		static final int DEFAULT_BACKGROUND = 1;
		List<Color> colorTable;
		List<Font> fontTable;
		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.
	 *
	 * @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 = new ArrayList<Color>();
		fontTable = new ArrayList<Font>();
		colorTable.add(getForeground());
		colorTable.add(getBackground());
		fontTable.add(getFont());
		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.
	 */
	@Override
	public void close() {
		if (!isClosed()) {
			writeHeader();
			write("\n}}\0");
			super.close();
		}
	}	
	/**
	 * Returns the index of the specified color in the RTF color table.
	 *
	 * @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) {
		if (color == null) return defaultIndex;
		int index = colorTable.indexOf(color);
		if (index == -1) {
			index = colorTable.size();
			colorTable.add(color);
		}
		return index;
	}
	/**
	 * Returns the index of the specified color in the RTF color table.
	 *
	 * @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 getFontIndex(Font font) {
		int index = fontTable.indexOf(font);
		if (index == -1) {
			index = fontTable.size();
			fontTable.add(font);
		}
		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
				}
			}
		}
		WriteUnicode =	!osName.startsWith(Win95) &&
						!osName.startsWith(Win98) &&
						!osName.startsWith(WinME) &&
						(!osName.startsWith(WinNT) || majorVersion > 4);
	}
	/**
	 * Appends the specified segment of "string" to the RTF data.
	 * Copy from <code>start</code> up to, but excluding, <code>end</code>.
	 *
	 * @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 > 0x7F && 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('?');						// ANSI representation (1 byte long, \\uc1)
				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("\\uc1\\deff0{\\fonttbl{\\f0\\fnil ");
		header.append(fontData.getName());
		header.append(";");
		for (int i = 1; i < fontTable.size(); i++) {
			header.append("\\f");
			header.append(i);
			header.append(" ");
			FontData fd = fontTable.get(i).getFontData()[0];
			header.append(fd.getName());
			header.append(";");			
		}
		header.append("}}\n{\\colortbl");
		for (int i = 0; i < colorTable.size(); i++) {
			Color color = colorTable.get(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.
	 *
	 * @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>
	 */
	@Override
	public void writeLine(String line, int lineOffset) {
		if (isClosed()) {
			SWT.error(SWT.ERROR_IO);
		}
		int lineIndex = content.getLineAtOffset(lineOffset);
		int lineAlignment, lineIndent;
		boolean lineJustify;
		int[] ranges;
		StyleRange[] styles;
		StyledTextEvent event = getLineStyleData(lineOffset, line);
		if (event != null) {
			lineAlignment = event.alignment;
			lineIndent = event.indent;
			lineJustify = event.justify;
			ranges = event.ranges;
			styles = event.styles;
		} else {
			lineAlignment = renderer.getLineAlignment(lineIndex, alignment);
			lineIndent =  renderer.getLineIndent(lineIndex, indent);			
			lineJustify = renderer.getLineJustify(lineIndex, justify);
			ranges = renderer.getRanges(lineOffset, line.length());
			styles = renderer.getStyleRanges(lineOffset, line.length(), false);
		}
		if (styles == null) styles = new StyleRange[0];		
		Color lineBackground = renderer.getLineBackground(lineIndex, null);
		event = getLineBackgroundData(lineOffset, line);
		if (event != null && event.lineBackground != null) lineBackground = event.lineBackground;
		writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, lineAlignment, lineJustify);
	}
	/**
	 * Appends the specified line delimiter to the RTF data.
	 *
	 * @param lineDelimiter line delimiter to write as RTF.
	 * @exception SWTException <ul>
	 *   <li>ERROR_IO when the writer is closed.</li>
	 * </ul>
	 */
	@Override
	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.
	 * <p>
	 * 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, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, boolean justify) {
		int lineLength = line.length();
		int startOffset = getStart();
		int writeOffset = startOffset - lineOffset;
		if (writeOffset >= lineLength) return;
		int lineIndex = Math.max(0, writeOffset);
			
		write("\\fi");
		write(indent);
		switch (alignment) {
			case SWT.LEFT: write("\\ql"); break;
			case SWT.CENTER: write("\\qc"); break;
			case SWT.RIGHT: write("\\qr"); break;
		}
		if (justify) write("\\qj");
		write(" ");
		
		if (lineBackground != null) {
			write("{\\highlight");
			write(getColorIndex(lineBackground, DEFAULT_BACKGROUND));
			write(" "); 
		}
		int endOffset = startOffset + super.getCharCount();
		int lineEndOffset = Math.min(lineLength, endOffset - lineOffset);
		for (int i = 0; i < styles.length; i++) {
			StyleRange style = styles[i];
			int start, end;
			if (ranges != null) {
				start = ranges[i << 1] - lineOffset;
				end = start + ranges[(i << 1) + 1];
			} else {
				start = style.start - lineOffset;
				end = start + style.length;
			}
			// 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 beyond end of write range or end of line 
				// is guarded against above.
				write(line, lineIndex, start);
				lineIndex = start;
			}
			// write styled text
			write("{\\cf");
			write(getColorIndex(style.foreground, DEFAULT_FOREGROUND));
			int colorIndex = getColorIndex(style.background, DEFAULT_BACKGROUND);
			if (colorIndex != DEFAULT_BACKGROUND) {
				write("\\highlight");
				write(colorIndex);
			}
			int fontStyle = style.fontStyle;
			Font font = style.font;
			if (font != null) {
				int fontIndex = getFontIndex(font);
				write("\\f");
				write(fontIndex);
				FontData fontData = font.getFontData()[0];
				write("\\fs");
				write(fontData.getHeight() * 2);
				fontStyle = fontData.getStyle();
			}
			if ((fontStyle & SWT.BOLD) != 0) {
				write("\\b");
			}
			if ((fontStyle & SWT.ITALIC) != 0) {
				write("\\i");
			}
			if (style.underline) {
				write("\\ul");
			}
			if (style.strikeout) {
				write("\\strike");
			}
			write(" "); 
			// copy to end of style or end of write range or end of line
			int copyEnd = Math.min(end, lineEndOffset);
			// guard against invalid styles and let style processing continue
			copyEnd = Math.max(copyEnd, lineIndex);
			write(line, lineIndex, copyEnd);
			if ((fontStyle & SWT.BOLD) != 0) {
				write("\\b0");
			}
			if ((style.fontStyle & SWT.ITALIC) != 0) {
				write("\\i0");
			}
			if (style.underline) {
				write("\\ul0");
			}
			if (style.strikeout) {
				write("\\strike0");
			}
			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.
	 * </p>
	 */
	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.
	 *
	 * @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) {
			isClosed = true;
		}
	}
	/** 
	 * Returns the number of characters to write.
	 * @return the integer 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.
	 * @return the integer offset where writing starts
	 */
	public int getStart() {
		return startOffset;
	}
	/**
	 * Returns whether the writer is closed.
	 * @return a boolean specifying whether or not 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.
	 *
	 * @return the string
	 */
	@Override
	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.
	 * <p>
	 * 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.
	 *
	 * @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) {	
		if (isClosed) {
			SWT.error(SWT.ERROR_IO);
		}		
		int writeOffset = startOffset - lineOffset;
		int lineLength = line.length();
		int lineIndex;
		if (writeOffset >= lineLength) {
			return;							// whole line is outside write range
		} else if (writeOffset > 0) {
			lineIndex = writeOffset;		// line starts before write start
		} else {
			lineIndex = 0;
		}
		int copyEnd = Math.min(lineLength, endOffset - lineOffset);
		if (lineIndex < copyEnd) {
			write(line.substring(lineIndex, copyEnd));
		}
	}
	/**
	 * Appends the specified line delimiter to the data.
	 *
	 * @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);
	}
	}

/**
 * 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));
	// set the 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.setDragDetect(false);
	Display display = getDisplay();
	fixedLineHeight = true;
	if ((style & SWT.READ_ONLY) != 0) {
		setEditable(false);
	}
	leftMargin = rightMargin = isBidiCaret() ? BIDI_CARET_WIDTH - 1: 0;
	if ((style & SWT.SINGLE) != 0 && (style & SWT.BORDER) != 0) {
		leftMargin = topMargin = rightMargin = bottomMargin = 2;
	}
	alignment = style & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
	if (alignment == 0) alignment = SWT.LEFT;
	clipboard = new Clipboard(display);
	installDefaultContent();
	renderer = new StyledTextRenderer(getDisplay(), this);
	renderer.setContent(content);
	renderer.setFont(getFont(), tabLength);
	ime = new IME(this, SWT.NONE);
	defaultCaret = new Caret(this, SWT.NONE);
	if ((style & SWT.WRAP) != 0) {
		setWordWrap(true);
	}
	if (isBidiCaret()) {
		createCaretBitmaps();
		Runnable runnable = new Runnable() {
			public void run() {
				int direction = BidiUtil.getKeyboardLanguage() == BidiUtil.KEYBOARD_BIDI ? SWT.RIGHT : SWT.LEFT;
				if (direction == caretDirection) return;
				if (getCaret() != defaultCaret) return;
				Point newCaretPos = getPointAtOffset(caretOffset);
				setCaretLocation(newCaretPos, direction);
			}
		};
		BidiUtil.addLanguageListener(this, runnable);
	}
	setCaret(defaultCaret);	
	calculateScrollBars();
	createKeyBindings();
	super.setCursor(display.getSystemCursor(SWT.CURSOR_IBEAM));
	installListeners();
	initializeAccessible();
	setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this));
}
/**	 
 * Adds an extended modify listener. An ExtendedModify event is sent by the 
 * widget when the widget text has changed.
 *
 * @param extendedModifyListener 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(ST.ExtendedModify, typedListener);
}
/**
 * Adds a bidirectional segment listener.
 * <p>
 * A BidiSegmentEvent is sent 
 * whenever a line of text is measured or rendered. You 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);
	addListener(ST.LineGetSegments, new StyledTextListener(listener));
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}
/**
 * Adds a caret listener. CaretEvent is sent when the caret offset changes.
 * 
 * @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 3.5
 */
public void addCaretListener(CaretListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	addListener(ST.CaretMoved, new StyledTextListener(listener));
}
/**
 * Adds a line background listener. A LineGetBackground event is sent by the 
 * widget to determine the background color for a line.
 *
 * @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 (!isListening(ST.LineGetBackground)) {
		renderer.clearLineBackground(0, content.getLineCount());
	}
	addListener(ST.LineGetBackground, new StyledTextListener(listener));
}
/**
 * Adds a line style listener. A LineGetStyle event is sent by the widget to 
 * determine the styles for a line.
 *
 * @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 (!isListening(ST.LineGetStyle)) {
		setStyleRanges(0, 0, null, null, true);
		renderer.clearLineStyle(0, content.getLineCount());
	}
	addListener(ST.LineGetStyle, new StyledTextListener(listener));
	setCaretLocation();
}
/**	 
 * Adds a modify listener. A Modify event is sent by the widget when the widget text 
 * has changed.
 *
 * @param modifyListener 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);
	addListener(SWT.Modify, new TypedListener(modifyListener));
}
/**	 
 * Adds a paint object listener. A paint object event is sent by the widget when an object
 * needs to be drawn.
 *
 * @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 3.2
 * 
 * @see PaintObjectListener
 * @see PaintObjectEvent
 */
public void addPaintObjectListener(PaintObjectListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	addListener(ST.PaintObject, new StyledTextListener(listener));
}
/**	 
 * Adds a selection listener. A Selection event is sent by the widget when the 
 * user changes the selection.
 * <p>
 * When <code>widgetSelected</code> is called, the event x and y fields contain
 * the start and end caret indices of the selection.
 * <code>widgetDefaultSelected</code> is not called for StyledTexts.
 * </p>
 * 
 * @param listener the listener which should be notified when the user changes the receiver's selection

 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</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>
 *
 * @see SelectionListener
 * @see #removeSelectionListener
 * @see SelectionEvent
 */
public void addSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	addListener(SWT.Selection, new TypedListener(listener));
}
/**	 
 * 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. 
 *
 * @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);
	addListener(ST.VerifyKey, new StyledTextListener(listener));
}
/**	 
 * 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.
 *
 * @param verifyListener 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);
	addListener(SWT.Verify, new TypedListener(verifyListener));
}
/**	 
 * Adds a word movement listener. A movement event is sent when the boundary 
 * of a word is needed. For example, this occurs during word next and word 
 * previous actions.
 *
 * @param movementListener 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 MovementEvent
 * @see MovementListener
 * @see #removeWordMovementListener
 * 
 * @since 3.3 
 */
public void addWordMovementListener(MovementListener movementListener) {
	checkWidget();
	if (movementListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	addListener(ST.WordNext, new StyledTextListener(movementListener));
	addListener(ST.WordPrevious, new StyledTextListener(movementListener));
}
/** 
 * Appends a string to the text at the end of the widget.
 *
 * @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 scroll bars
 */
void calculateScrollBars() {
	ScrollBar horizontalBar = getHorizontalBar();
	ScrollBar verticalBar = getVerticalBar();
	setScrollBars(true);
	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 delta) {
	int oldTopIndex = topIndex;
	int oldTopIndexY = topIndexY;
	if (isFixedLineHeight()) {
		int verticalIncrement = getVerticalIncrement();
		if (verticalIncrement == 0) {
			return;
		}
		topIndex = Compatibility.ceil(getVerticalScrollOffset(), 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 = getVerticalScrollOffset() + 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;
			}
		}
	} else {
		if (delta >= 0) {
			delta -= topIndexY;
			int lineIndex = topIndex;
			int lineCount = content.getLineCount();
			while (lineIndex < lineCount) {
				if (delta <= 0) break;
				delta -= renderer.getLineHeight(lineIndex++);
			}
			if (lineIndex < lineCount && -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
				topIndex = lineIndex;
				topIndexY = -delta;
			} else {
				topIndex = lineIndex - 1;
				topIndexY = -renderer.getLineHeight(topIndex) - delta;
			}
		} else {
			delta -= topIndexY;
			int lineIndex = topIndex;
			while (lineIndex > 0) {
				int lineHeight = renderer.getLineHeight(lineIndex - 1);
				if (delta + lineHeight > 0) break;
				delta += lineHeight;
				lineIndex--;
			}
			if (lineIndex == 0 || -delta + renderer.getLineHeight(lineIndex) <= clientAreaHeight - topMargin - bottomMargin) {
				topIndex = lineIndex;
				topIndexY = - delta;
			} else {
				topIndex = lineIndex - 1;
				topIndexY = - renderer.getLineHeight(topIndex) - delta;
			}
		}
	}
	if (topIndex != oldTopIndex || oldTopIndexY != topIndexY) {
		int width = renderer.getWidth();
		renderer.calculateClientArea();
		if (width != renderer.getWidth()) {
			setScrollBars(false);
		}
	}
}
/**
 * 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 | SWT.WRAP | SWT.MULTI);
	} else {
		style |= SWT.MULTI;
		if ((style & SWT.WRAP) != 0) {
			style &= ~SWT.H_SCROLL;
		}
	}
	style |= SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND;
	/* Clear SWT.CENTER to avoid the conflict with SWT.EMBEDDED */
	return style & ~SWT.CENTER;
}
/**
 * Scrolls down the text to use new space made available by a resize or by 
 * deleted lines.
 */
void claimBottomFreeSpace() {
	if (ime.getCompositionOffset() != -1) return;
	if (isFixedLineHeight()) {
		int newVerticalOffset = Math.max(0, renderer.getHeight() - clientAreaHeight);
		if (newVerticalOffset < getVerticalScrollOffset()) {
			scrollVertical(newVerticalOffset - getVerticalScrollOffset(), true);
		}
	} else {
		int bottomIndex = getPartialBottomIndex();
		int height = getLinePixel(bottomIndex + 1);
		if (clientAreaHeight > height) {
			scrollVertical(-getAvailableHeightAbove(clientAreaHeight - height), true);
		}
	}
}
/**
 * Scrolls text to the right to use new space made available by a resize.
 */
void claimRightFreeSpace() {
	int newHorizontalOffset = Math.max(0, renderer.getWidth() - clientAreaWidth);
	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).
		scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true);					
	}
}
void clearBlockSelection(boolean reset, boolean sendEvent) {
	if (reset) resetSelection();
	blockXAnchor = blockYAnchor = -1;
	blockXLocation = blockYLocation = -1;
	caretDirection = SWT.NULL;
	updateCaretVisibility();
	super.redraw();
	if (sendEvent) sendSelectionEvent();
}
/**
 * Removes the widget selection.
 *
 * @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;	
	resetSelection();
	// redraw old selection, if any
	if (selectionEnd - selectionStart > 0) {
		int length = content.getCharCount();
		// 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);
		}
		if (sendEvent) {
			sendSelectionEvent();
		}
	}
}
@Override
public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	int lineCount = (getStyle() & SWT.SINGLE) != 0 ? 1 : content.getLineCount();
	int width = 0;
	int height = 0;
	if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
		Display display = getDisplay();
		int maxHeight = display.getClientArea().height;
		for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
			TextLayout layout = renderer.getTextLayout(lineIndex);
			int wrapWidth = layout.getWidth();
			if (wordWrap) layout.setWidth(wHint == 0 ? 1 : wHint == SWT.DEFAULT ? SWT.DEFAULT : Math.max(1, wHint - leftMargin - rightMargin));
			Rectangle rect = layout.getBounds();
			height += rect.height;
			width = Math.max(width, rect.width);
			layout.setWidth(wrapWidth);
			renderer.disposeTextLayout(layout);
			if (isFixedLineHeight() && height > maxHeight) break;
		}
		if (isFixedLineHeight()) {
			height = lineCount * renderer.getLineHeight();
		}
	}
	// Use default values if no text is defined.
	if (width == 0) width = DEFAULT_WIDTH;
	if (height == 0) height = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	int wTrim = leftMargin + rightMargin + getCaretWidth();
	int hTrim = topMargin + bottomMargin;
	Rectangle rect = computeTrim(0, 0, width + wTrim, height + hTrim);
	return new Point (rect.width, rect.height);
}
/**
 * Copies the selected text to the <code>DND.CLIPBOARD</code> clipboard.
 * <p>
 * The text will be put on the clipboard in plain text format and RTF format.
 * The <code>DND.CLIPBOARD</code> clipboard is used for data that is
 * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or 
 * by menu action.
 * </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();
	copySelection(DND.CLIPBOARD);
}
/**
 * Copies the selected text to the specified clipboard.  The text will be put in the 
 * clipboard in plain text format and RTF format.
 * <p>
 * The clipboardType is  one of the clipboard constants defined in class 
 * <code>DND</code>.  The <code>DND.CLIPBOARD</code>  clipboard is 
 * used for data that is transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) 
 * or by menu action.  The <code>DND.SELECTION_CLIPBOARD</code> 
 * clipboard is used for data that is transferred by selecting text and pasting 
 * with the middle mouse button.
 * </p>
 * 
 * @param clipboardType indicates the type of clipboard
 *
 * @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 3.1
 */
public void copy(int clipboardType) {
	checkWidget();
	copySelection(clipboardType);
}
boolean copySelection(int type) {
	if (type != DND.CLIPBOARD && type != DND.SELECTION_CLIPBOARD) return false;
	try {
		if (blockSelection && blockXLocation != -1) {
			String text = getBlockSelectionText(PlatformLineDelimiter);
			if (text.length() > 0) {
				//TODO RTF support
				TextTransfer plainTextTransfer = TextTransfer.getInstance();
				Object[] data = new Object[]{text};
				Transfer[] types = new Transfer[]{plainTextTransfer};
				clipboard.setContents(data, types, type);
				return true;
			}
		} else {
			int length = selection.y - selection.x;
			if (length > 0) {
				setClipboardContent(selection.x, length, type);
				return true;
			}
		}
	} catch (SWTError error) {
		// Copy to clipboard failed. This happens when another application 
		// is accessing the clipboard while we copy. Ignore the error.
		// Rethrow all other errors. Fixes bug 17578.
		if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) {
			throw error;
		}
	}
	return false;
}
/**
 * Returns the alignment of the widget.
 * 
 * @return the alignment
 * 
 * @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 #getLineAlignment(int)
 * 
 * @since 3.2
 */
public int getAlignment() {
	checkWidget();
	return alignment;
}
/**
 * Returns the Always Show Scrollbars flag.  True if the scrollbars are 
 * always shown even if they are not required.  False if the scrollbars are only 
 * visible when some part of the content needs to be scrolled to be seen.
 * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the 
 * horizontal and vertical directions.
 * 
 * @return the Always Show Scrollbars flag value
 * 
 * @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 3.8
 */
public boolean getAlwaysShowScrollBars() {
	checkWidget();
	return alwaysShowScroll;
}
int getAvailableHeightAbove(int height) {
	int maxHeight = verticalScrollOffset;
	if (maxHeight == -1) {
		int lineIndex = topIndex - 1;
		maxHeight = -topIndexY;
		if (topIndexY > 0) {
			maxHeight += renderer.getLineHeight(lineIndex--);
		}
		while (height > maxHeight && lineIndex >= 0) {
			maxHeight += renderer.getLineHeight(lineIndex--);
		}
	}
	return Math.min(height, maxHeight);
}
int getAvailableHeightBellow(int height) {
	int partialBottomIndex = getPartialBottomIndex();
	int topY = getLinePixel(partialBottomIndex);
	int lineHeight = renderer.getLineHeight(partialBottomIndex);
	int availableHeight = 0;
	int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin;
	if (topY + lineHeight > clientAreaHeight) {
		availableHeight = lineHeight - (clientAreaHeight - topY);
	}
	int lineIndex = partialBottomIndex + 1;
	int lineCount = content.getLineCount();
	while (height > availableHeight && lineIndex < lineCount) {
		availableHeight += renderer.getLineHeight(lineIndex++);
	}
	return Math.min(height, availableHeight);
}
/** 
 * Returns the color of the margins.
 * 
 * @return the color of the margins.
 * @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 3.5
 */
public Color getMarginColor() {
	checkWidget();
	return marginColor != null ? marginColor : getBackground();
}
/**
 * Returns a string that uses only the line delimiter specified by the 
 * StyledTextContent implementation.
 * <p>
 * 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) {	
	int length = text.length();
	if (length == 0) {
		return text;
	}	
	int crIndex = 0;
	int lfIndex = 0;
	int i = 0;
	StringBuffer convertedText = new StringBuffer(length);
	String delimiter = getLineDelimiter();
	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 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() || convertedText.length() == 0)) {
		convertedText.append(text.substring(i));
	}
	return convertedText.toString();
}
boolean checkDragDetect(Event event) {
	if (!isListening(SWT.DragDetect)) return false;
	if (event.button != 1) return false;
	if (blockSelection && blockXLocation != -1) {
		Rectangle rect = getBlockSelectionRectangle();
		if (rect.contains(event.x, event.y)) {
			return dragDetect(event);
		}
	} else {
		if (selection.x == selection.y) return false;
		int offset = getOffsetAtPoint(event.x, event.y, null, true);
		if (selection.x <= offset && offset < selection.y) {
			return dragDetect(event);
		}
	}
	return false;
}
/**
 * Creates default key bindings.
 */
void createKeyBindings() {
	int nextKey = isMirrored() ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
	int previousKey = isMirrored() ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
	
	// Navigation
	setKeyBinding(SWT.ARROW_UP, ST.LINE_UP);	
	setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN);
	if (IS_MAC) {
		setKeyBinding(previousKey | SWT.MOD1, ST.LINE_START);
		setKeyBinding(nextKey | SWT.MOD1, ST.LINE_END);
		setKeyBinding(SWT.HOME, ST.TEXT_START);
		setKeyBinding(SWT.END, ST.TEXT_END);
		setKeyBinding(SWT.ARROW_UP | SWT.MOD1, ST.TEXT_START);
		setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1, ST.TEXT_END);
		setKeyBinding(nextKey | SWT.MOD3, ST.WORD_NEXT);
		setKeyBinding(previousKey | SWT.MOD3, ST.WORD_PREVIOUS);
	} else {
		setKeyBinding(SWT.HOME, ST.LINE_START);
		setKeyBinding(SWT.END, ST.LINE_END);
		setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START);
		setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END);
		setKeyBinding(nextKey | SWT.MOD1, ST.WORD_NEXT);
		setKeyBinding(previousKey | SWT.MOD1, ST.WORD_PREVIOUS);
	}
	setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP);
	setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN);
	setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END);
	setKeyBinding(nextKey, ST.COLUMN_NEXT);
	setKeyBinding(previousKey, ST.COLUMN_PREVIOUS);
	
	// Selection
	setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP);	
	setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN);
	if (IS_MAC) {
		setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_START);
		setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_LINE_END);
		setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_TEXT_START);	
		setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_TEXT_END);
		setKeyBinding(SWT.ARROW_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);	
		setKeyBinding(SWT.ARROW_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
		setKeyBinding(nextKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_NEXT);
		setKeyBinding(previousKey | SWT.MOD2 | SWT.MOD3, ST.SELECT_WORD_PREVIOUS);
	} else  {
		setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START);
		setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END);
		setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START);	
		setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END);
		setKeyBinding(nextKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
		setKeyBinding(previousKey | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
	}
	setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN);
	setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START);
	setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END);
	setKeyBinding(nextKey | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
	setKeyBinding(previousKey | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);	
           	  	
	// Modification
	// Cut, Copy, Paste
	setKeyBinding('X' | SWT.MOD1, ST.CUT);
	setKeyBinding('C' | SWT.MOD1, ST.COPY);
	setKeyBinding('V' | SWT.MOD1, ST.PASTE);
	if (IS_MAC) {
		setKeyBinding(SWT.DEL | SWT.MOD2, ST.DELETE_NEXT);
		setKeyBinding(SWT.BS | SWT.MOD3, ST.DELETE_WORD_PREVIOUS);
		setKeyBinding(SWT.DEL | SWT.MOD3, ST.DELETE_WORD_NEXT);
	} else {
		// 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;
	Display display = getDisplay();
	if (leftCaretBitmap != null) {
		if (defaultCaret != null && leftCaretBitmap.equals(defaultCaret.getImage())) {
			defaultCaret.setImage(null);
		}
		leftCaretBitmap.dispose();
	}
	int lineHeight = renderer.getLineHeight();
	leftCaretBitmap = new Image(display, caretWidth, lineHeight);
	GC gc = new GC (leftCaretBitmap); 
	gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
	gc.fillRectangle(0, 0, caretWidth, lineHeight);
	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) {
		if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
			defaultCaret.setImage(null);
		}
		rightCaretBitmap.dispose();
	}
	rightCaretBitmap = new Image(display, caretWidth, lineHeight);
	gc = new GC (rightCaretBitmap); 
	gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
	gc.fillRectangle(0, 0, caretWidth, lineHeight);
	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.
 *
 * @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();
	// Abort cut operation if copy to clipboard fails.
	// Fixes bug 21030.
	if (copySelection(DND.CLIPBOARD)) {
		if (blockSelection && blockXLocation != -1) {
			insertBlockSelectionText((char)0, SWT.NULL);
		} else {
			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) {
	int caretLine = getCaretLine();
	if (event.y > clientAreaHeight - bottomMargin && caretLine != content.getLineCount() - 1) {
		doAutoScroll(SWT.DOWN, event.y - (clientAreaHeight - bottomMargin));
	} else if (event.y < topMargin && caretLine != 0) {
		doAutoScroll(SWT.UP, topMargin - event.y);
	} else if (event.x < leftMargin && !wordWrap) {
		doAutoScroll(ST.COLUMN_PREVIOUS, leftMargin - event.x);
	} else if (event.x > clientAreaWidth - rightMargin && !wordWrap) {
		doAutoScroll(ST.COLUMN_NEXT, event.x - (clientAreaWidth - rightMargin));
	} else {
		endAutoScroll();
	}
}
/** 
 * Initiates autoscrolling.
 *
 * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
 */
void doAutoScroll(int direction, int distance) {
	autoScrollDistance = distance;
	// If we're already autoscrolling in the given direction do nothing
	if (autoScrollDirection == direction) {
		return;
	}
	
	Runnable timer = null;
	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() {
				/* Bug 437357 - NPE in StyledText.getCaretLine
				 * StyledText.content is null at times, probably because the
				 * widget itself has been disposed.
				 */
				if (isDisposed()) return;
				if (autoScrollDirection == SWT.UP) {
					if (blockSelection) {
						int verticalScrollOffset = getVerticalScrollOffset();
						int y = blockYLocation - verticalScrollOffset;
						int pixels = Math.max(-autoScrollDistance, -verticalScrollOffset);
						if (pixels != 0) {
							setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
							scrollVertical(pixels, true);
						}
					} else {
						doSelectionPageUp(autoScrollDistance);
					}
					display.timerExec(V_SCROLL_RATE, this);
				}
			}
		};
		autoScrollDirection = direction;
		display.timerExec(V_SCROLL_RATE, timer);
	} else if (direction == SWT.DOWN) {
		timer = new Runnable() {
			public void run() {
				/* Bug 437357 - NPE in StyledText.getCaretLine
				 * StyledText.content is null at times, probably because the
				 * widget itself has been disposed.
				 */
				if (isDisposed()) return;
				if (autoScrollDirection == SWT.DOWN) {
					if (blockSelection) {
						int verticalScrollOffset = getVerticalScrollOffset();
						int y = blockYLocation - verticalScrollOffset;
						int max = renderer.getHeight() - verticalScrollOffset - clientAreaHeight;
						int pixels = Math.min(autoScrollDistance, Math.max(0,max));
						if (pixels != 0) {
							setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y + pixels, true);
							scrollVertical(pixels, true);
						}
					} else {
						doSelectionPageDown(autoScrollDistance);
					}
					display.timerExec(V_SCROLL_RATE, this);
				}
			}
		};
		autoScrollDirection = direction;
		display.timerExec(V_SCROLL_RATE, timer);
	} else if (direction == ST.COLUMN_NEXT) {
		timer = new Runnable() {
			public void run() {
				/* Bug 437357 - NPE in StyledText.getCaretLine
				 * StyledText.content is null at times, probably because the
				 * widget itself has been disposed.
				 */
				if (isDisposed()) return;
				if (autoScrollDirection == ST.COLUMN_NEXT) {
					if (blockSelection) {
						int x = blockXLocation - horizontalScrollOffset;
						int max = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth;
						int pixels = Math.min(autoScrollDistance, Math.max(0,max));
						if (pixels != 0) {
							setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
							scrollHorizontal(pixels, true);
						}
					} else {
						doVisualNext();
						setMouseWordSelectionAnchor();
						doMouseSelection();
					}
					display.timerExec(H_SCROLL_RATE, this);
				}
			}
		};
		autoScrollDirection = direction;
		display.timerExec(H_SCROLL_RATE, timer);
	} else if (direction == ST.COLUMN_PREVIOUS) {
		timer = new Runnable() {
			public void run() {
				/* Bug 437357 - NPE in StyledText.getCaretLine
				 * StyledText.content is null at times, probably because the
				 * widget itself has been disposed.
				 */
				if (isDisposed()) return;
				if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
					if (blockSelection) {
						int x = blockXLocation - horizontalScrollOffset;
						int pixels = Math.max(-autoScrollDistance, -horizontalScrollOffset);
						if (pixels != 0) {
							setBlockSelectionLocation(x + pixels, blockYLocation - getVerticalScrollOffset(), true);
							scrollHorizontal(pixels, true);
						}
					} else {
						doVisualPrevious();
						setMouseWordSelectionAnchor();
						doMouseSelection();
					}
					display.timerExec(H_SCROLL_RATE, this);
				}
			}
		};
		autoScrollDirection = direction;
		display.timerExec(H_SCROLL_RATE, 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 lineIndex = content.getLineAtOffset(caretOffset);
		int lineOffset = content.getOffsetAtLine(lineIndex);
		if (caretOffset == lineOffset) {
			lineOffset = content.getOffsetAtLine(lineIndex - 1);
			event.start = lineOffset + content.getLine(lineIndex - 1).length();
			event.end = caretOffset;
		} else {
			boolean isSurrogate = false;
			String lineText = content.getLine(lineIndex);
			char ch = lineText.charAt(caretOffset - lineOffset - 1);
			if (0xDC00 <= ch && ch <= 0xDFFF) {
				if (caretOffset - lineOffset - 2 >= 0) {
					ch = lineText.charAt(caretOffset - lineOffset - 2);
					isSurrogate = 0xD800 <= ch && ch <= 0xDBFF;
				}
			}
			TextLayout layout = renderer.getTextLayout(lineIndex);
			int start = layout.getPreviousOffset(caretOffset - lineOffset, isSurrogate ? SWT.MOVEMENT_CLUSTER : SWT.MOVEMENT_CHAR);
			renderer.disposeTextLayout(layout);
			event.start = start + lineOffset;
			event.end = caretOffset;
		}
		sendKeyEvent(event);
	}
}
void doBlockColumn(boolean next) {
	if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
	int x = blockXLocation - horizontalScrollOffset;
	int y = blockYLocation - getVerticalScrollOffset();
	int[] trailing = new int[1];
	int offset = getOffsetAtPoint(x, y, trailing, true);
	if (offset != -1) {
		offset += trailing[0];
		int lineIndex = content.getLineAtOffset(offset);
		int newOffset;
		if (next) {
			newOffset = getClusterNext(offset, lineIndex);
		} else {
			newOffset = getClusterPrevious(offset, lineIndex);
		}
		offset = newOffset != offset ? newOffset : -1;
	}
	if (offset != -1) {
		setBlockSelectionOffset(offset, true);
		showCaret();
	} else {
		int width = next ? renderer.averageCharWidth : -renderer.averageCharWidth;
		int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
		x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
		setBlockSelectionLocation(x, y, true);
		Rectangle rect = new Rectangle(x, y, 0, 0);
		showLocation(rect, true);
	}
}
void doBlockContentStartEnd(boolean end) {
	if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
	int offset = end ? content.getCharCount() : 0;
	setBlockSelectionOffset(offset, true);
	showCaret();
}
void doBlockWord(boolean next) {
	if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
	int x = blockXLocation - horizontalScrollOffset;
	int y = blockYLocation - getVerticalScrollOffset();
	int[] trailing = new int[1];
	int offset = getOffsetAtPoint(x, y, trailing, true);
	if (offset != -1) {
		offset += trailing[0];
		int lineIndex = content.getLineAtOffset(offset);
		int lineOffset = content.getOffsetAtLine(lineIndex);
		String lineText = content.getLine(lineIndex);
		int lineLength = lineText.length();
		int newOffset = offset;
		if (next) {
			if (offset < lineOffset + lineLength) {
				newOffset = getWordNext(offset, SWT.MOVEMENT_WORD);
			}
		} else {
			if (offset > lineOffset) {
				newOffset = getWordPrevious(offset, SWT.MOVEMENT_WORD);
			}
		}
		offset = newOffset != offset ? newOffset : -1;
	}
	if (offset != -1) {
		setBlockSelectionOffset(offset, true);
		showCaret();
	} else {
		int width = (next ? renderer.averageCharWidth : -renderer.averageCharWidth) * 6;
		int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
		x = Math.max(0, Math.min(blockXLocation + width, maxWidth)) - horizontalScrollOffset;
		setBlockSelectionLocation(x, y, true);
		Rectangle rect = new Rectangle(x, y, 0, 0);
		showLocation(rect, true);
	}
}
void doBlockLineVertical(boolean up) {
	if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
	int y = blockYLocation - getVerticalScrollOffset();
	int lineIndex = getLineIndex(y);
	if (up) {
		if (lineIndex > 0) {
			y = getLinePixel(lineIndex - 1);
			setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
			if (y < topMargin) {
				scrollVertical(y - topMargin, true);
			}
		}
	} else {
		int lineCount = content.getLineCount();
		if (lineIndex + 1 < lineCount) {
			y = getLinePixel(lineIndex + 2) - 1;
			setBlockSelectionLocation(blockXLocation - horizontalScrollOffset, y, true);
			int bottom = clientAreaHeight - bottomMargin; 
			if (y > bottom) {
				scrollVertical(y - bottom, true);
			}
		}
	}
}
void doBlockLineHorizontal(boolean end) {
	if (blockXLocation == -1) setBlockSelectionOffset(caretOffset, false);
	int x = blockXLocation - horizontalScrollOffset;
	int y = blockYLocation - getVerticalScrollOffset();
	int lineIndex = getLineIndex(y);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	String lineText = content.getLine(lineIndex);
	int lineLength = lineText.length();
	int[] trailing = new int[1];
	int offset = getOffsetAtPoint(x, y, trailing, true);
	if (offset != -1) {
		offset += trailing[0];
		int newOffset = offset;
		if (end) {
			if (offset < lineOffset + lineLength) {
				newOffset = lineOffset + lineLength;
			}
		} else {
			if (offset > lineOffset) {
				newOffset = lineOffset;
			}
		}
		offset = newOffset != offset ? newOffset : -1;
	} else {
		if (!end) offset = lineOffset + lineLength;
	}
	if (offset != -1) {
		setBlockSelectionOffset(offset, true);
		showCaret();
	} else {
		int maxWidth = Math.max(clientAreaWidth - rightMargin - leftMargin, renderer.getWidth());
		x = (end ? maxWidth : 0) - horizontalScrollOffset;
		setBlockSelectionLocation(x, y, true);
		Rectangle rect = new Rectangle(x, y, 0, 0);
		showLocation(rect, true);
	}
}
void doBlockSelection(boolean sendEvent) {
	if (caretOffset > selectionAnchor) {
		selection.x = selectionAnchor;
		selection.y = caretOffset;
	} else {
		selection.x = caretOffset;
		selection.y = selectionAnchor;
	}
	updateCaretVisibility();
	setCaretLocation();
	super.redraw();
	if (sendEvent) {
		sendSelectionEvent();
	}
	sendAccessibleTextCaretMoved();
}
/**
 * Replaces the selection with the character or insert the character at the 
 * current caret position if no selection exists.
 * <p>
 * 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) {
	if (blockSelection && blockXLocation != -1) {
		insertBlockSelectionText(key, SWT.NULL);
		return;
	}
	
	Event 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()) {
			event.text = getLineDelimiter();
		}
	} else if (selection.x == selection.y && overwrite && key != TAB) {
		// no selection and overwrite mode is on and the typed key is not a
		// tab character (tabs are always inserted without overwriting)?	
		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) {
		if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) {
			return;
		}
		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();		
		setCaretOffset(length, SWT.DEFAULT);
		showCaret();
	}
}
/**
 * Moves the caret in front of the first character of the widget content.
 */
void doContentStart() {
	setCaretOffset(0, SWT.DEFAULT);
	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.
 *
 * @see #doSelectionCursorPrevious
 */
void doCursorPrevious() {
	if (selection.y - selection.x > 0) {
		setCaretOffset(selection.x, OFFSET_LEADING);
		showCaret();
	} 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.
 *
 * @see #doSelectionCursorNext
 */
void doCursorNext() {
	if (selection.y - selection.x > 0) {
		setCaretOffset(selection.y, PREVIOUS_OFFSET_TRAILING);
		showCaret();
	} 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 = getClusterNext(caretOffset, line);
		}
		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 = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
		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 = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
		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. Moves the caret to
 * the end of the text if the caret already is on the last line.
 */
void doLineDown(boolean select) {
	int caretLine = getCaretLine();
	int lineCount = content.getLineCount();
	int y = 0;
	boolean lastLine = false;
	if (wordWrap || visualWrap) {
		int lineOffset = content.getOffsetAtLine(caretLine);
		int offsetInLine = caretOffset - lineOffset;
		TextLayout layout = renderer.getTextLayout(caretLine);
		int lineIndex = getVisualLineIndex(layout, offsetInLine);
		int layoutLineCount = layout.getLineCount();
		if (lineIndex == layoutLineCount - 1) {
			lastLine = caretLine == lineCount - 1;
			caretLine++;
		} else {
			y = layout.getLineBounds(lineIndex + 1).y;
		}
		renderer.disposeTextLayout(layout);
	} else {
		lastLine = caretLine == lineCount - 1;
		caretLine++;
	}
	if (lastLine) {
		setCaretOffset(content.getCharCount(), SWT.DEFAULT);
	} else {
		int[] alignment = new int[1];
		int offset = getOffsetAtPoint(columnX, y, caretLine, alignment); 
		setCaretOffset(offset, alignment[0]);
	}
	int oldColumnX = columnX;
	int oldHScrollOffset = horizontalScrollOffset;
	if (select) {
		setMouseWordSelectionAnchor();	
		// select first and then scroll to reduce flash when key 
		// repeat scrolls lots of lines
		doSelection(ST.COLUMN_NEXT);
	}
	showCaret();
	int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
	columnX = oldColumnX + hScrollChange;
}
/**
 * Moves the caret to the end of the line.
 */
void doLineEnd() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);	
	int lineEndOffset;
	if (wordWrap || visualWrap) {
		TextLayout layout = renderer.getTextLayout(caretLine);
		int offsetInLine = caretOffset - lineOffset;
		int lineIndex = getVisualLineIndex(layout, offsetInLine);
		int[] offsets = layout.getLineOffsets();
		lineEndOffset = lineOffset + offsets[lineIndex + 1];
		renderer.disposeTextLayout(layout);
	} else {
		int lineLength = content.getLine(caretLine).length();
		lineEndOffset = lineOffset + lineLength;
	}
	setCaretOffset(lineEndOffset, PREVIOUS_OFFSET_TRAILING);
	showCaret();
}
/**
 * Moves the caret to the beginning of the line.
 */
void doLineStart() {
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);
	if (wordWrap || visualWrap) {
		TextLayout layout = renderer.getTextLayout(caretLine);
		int offsetInLine = caretOffset - lineOffset;
		int lineIndex = getVisualLineIndex(layout, offsetInLine);
		int[] offsets = layout.getLineOffsets();
		lineOffset += offsets[lineIndex];
		renderer.disposeTextLayout(layout);
	}
	setCaretOffset(lineOffset, OFFSET_LEADING);
	showCaret();
}
/**
 * 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. Moves the caret to
 * the beginning of the document if it is already on the first line.
 */
void doLineUp(boolean select) {
	int caretLine = getCaretLine(), y = 0;
	boolean firstLine = false;
	if (wordWrap || visualWrap) {
		int lineOffset = content.getOffsetAtLine(caretLine);
		int offsetInLine = caretOffset - lineOffset;
		TextLayout layout = renderer.getTextLayout(caretLine);
		int lineIndex = getVisualLineIndex(layout, offsetInLine);
		if (lineIndex == 0) {
			firstLine = caretLine == 0;
			if (!firstLine) {
				caretLine--;
				y = renderer.getLineHeight(caretLine) - 1;
			}
		} else {
			y = layout.getLineBounds(lineIndex - 1).y;
		}
		renderer.disposeTextLayout(layout);
	} else {
		firstLine = caretLine == 0;
		caretLine--;
	}
	if (firstLine) {
		setCaretOffset(0, SWT.DEFAULT);
	} else {
		int[] alignment = new int[1];
		int offset = getOffsetAtPoint(columnX, y, caretLine, alignment); 
		setCaretOffset(offset, alignment[0]);
	}
	int oldColumnX = columnX;
	int oldHScrollOffset = horizontalScrollOffset;
	if (select) setMouseWordSelectionAnchor();
	showCaret();
	if (select) doSelection(ST.COLUMN_PREVIOUS);
	int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
	columnX = oldColumnX + hScrollChange;
}
void doMouseLinkCursor() {
	Display display = getDisplay();
	Point point = display.getCursorLocation();
	point = display.map(null, this, point);
	doMouseLinkCursor(point.x, point.y);
}
void doMouseLinkCursor(int x, int y) {
	int offset = getOffsetAtPoint(x, y, null, true);
	Display display = getDisplay();
	Cursor newCursor = cursor;
	if (renderer.hasLink(offset)) {
		newCursor = display.getSystemCursor(SWT.CURSOR_HAND);
	} else {
		if (cursor == null) {
			int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM;
			newCursor = display.getSystemCursor(type);
		}
	}
	if (newCursor != getCursor()) super.setCursor(newCursor);
}
/**
 * Moves the caret to the specified location.
 *
 * @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 = getLineIndex(y);

	updateCaretDirection = true;
	
	if (blockSelection) {
		x = Math.max(leftMargin, Math.min(x, clientAreaWidth - rightMargin));
		y = Math.max(topMargin, Math.min(y, clientAreaHeight - bottomMargin));
		if (doubleClickEnabled && clickCount > 1) {
			boolean wordSelect = (clickCount & 1) == 0;
			if (wordSelect) {
				Point left = getPointAtOffset(doubleClickSelection.x);
				int[] trailing = new int[1]; 
				int offset = getOffsetAtPoint(x, y, trailing, true);
				if (offset != -1) {
					if (x > left.x) {
						offset = getWordNext(offset + trailing[0], SWT.MOVEMENT_WORD_END);
						setBlockSelectionOffset(doubleClickSelection.x, offset, true);
					} else {
						offset = getWordPrevious(offset + trailing[0], SWT.MOVEMENT_WORD_START);
						setBlockSelectionOffset(doubleClickSelection.y, offset, true);
					}
				} else {
					if (x > left.x) {
						setBlockSelectionLocation(left.x, left.y, x, y, true);
					} else {
						Point right = getPointAtOffset(doubleClickSelection.y);
						setBlockSelectionLocation(right.x, right.y, x, y, true);
					}
				}
			} else {
				setBlockSelectionLocation(blockXLocation, y, true);
			}
			return;
		} else {
			if (select) {
				if (blockXLocation == -1) {
					setBlockSelectionOffset(caretOffset, false);
				}
			} else {
				clearBlockSelection(true, false);
			}
			int[] trailing = new int[1]; 
			int offset = getOffsetAtPoint(x, y, trailing, true);
			if (offset != -1) {
				if (select) {
					setBlockSelectionOffset(offset + trailing[0], true);
					return;
				}
			} else {
				if (isFixedLineHeight() && renderer.fixedPitch) {
					int avg = renderer.averageCharWidth; 
					x = ((x + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
				}
				setBlockSelectionLocation(x, y, true);
				return;
			}
		}
	}
	
	// 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;
	}
	int[] alignment = new int[1];
	int newCaretOffset = getOffsetAtPoint(x, y, alignment);
	int newCaretAlignemnt = alignment[0];
	
	if (doubleClickEnabled && clickCount > 1) {
		newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
	}
	
	int 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
	boolean vchange = 0 <= y && y < clientAreaHeight || newCaretLine == 0 || newCaretLine == content.getLineCount() - 1;
	boolean hchange = 0 <= x && x < clientAreaWidth || wordWrap || newCaretLine != content.getLineAtOffset(caretOffset); 
	if (vchange && hchange && (newCaretOffset != caretOffset || newCaretAlignemnt != caretAlignment)) {
		setCaretOffset(newCaretOffset, newCaretAlignemnt);
		if (select) doMouseSelection();
		showCaret();
	}
	if (!select) {
		setCaretOffset(newCaretOffset, newCaretAlignemnt);
		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 selection on 
 * non-bidi platforms) the start offset of the word preceding 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) {
	// 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 (0 <= x && x < clientAreaWidth) {
		boolean wordSelect = (clickCount & 1) == 0;
		if (caretOffset == selection.x) {
			if (wordSelect) {
				newCaretOffset = getWordPrevious(newCaretOffset, SWT.MOVEMENT_WORD_START);
			} else {
				newCaretOffset = content.getOffsetAtLine(line);
			}
		} else {
			if (wordSelect) {
				newCaretOffset = getWordNext(newCaretOffset, SWT.MOVEMENT_WORD_END);
			} else {
				int lineEnd = content.getCharCount();
				if (line + 1 < content.getLineCount()) {
					lineEnd = content.getOffsetAtLine(line + 1);
				}
				newCaretOffset = lineEnd; 
			}
		}
	}
	return newCaretOffset;
}
/**
 * Scrolls one page down so that the last line (truncated or whole)
 * of the current page becomes the fully visible top line.
 * <p>
 * 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 height) {
	if (isSingleLine()) return;
	int oldColumnX = columnX;
	int oldHScrollOffset = horizontalScrollOffset;
	if (isFixedLineHeight()) {
		int lineCount = content.getLineCount();
		int caretLine = getCaretLine();
		if (caretLine < lineCount - 1) {
			int lineHeight = renderer.getLineHeight();
			int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
			int scrollLines = Math.min(lineCount - caretLine - 1, lines);
			// ensure that scrollLines never gets negative and at least one 
			// line is scrolled. fixes bug 5602.
			scrollLines = Math.max(1, scrollLines);
			int[] alignment = new int[1];
			int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines), alignment);
			setCaretOffset(offset, alignment[0]);
			if (select) {
				doSelection(ST.COLUMN_NEXT);
			}
			// scroll one page down or to the bottom
			int verticalMaximum = lineCount * getVerticalIncrement();
			int pageSize = clientAreaHeight;
			int verticalScrollOffset = getVerticalScrollOffset();
			int scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
			if (scrollOffset + pageSize > verticalMaximum) {
				scrollOffset = verticalMaximum - pageSize;
			}
			if (scrollOffset > verticalScrollOffset) {
				scrollVertical(scrollOffset - verticalScrollOffset, true);
			}
		}
	} else {
		int lineCount = content.getLineCount();
		int caretLine = getCaretLine();
		int lineIndex, lineHeight;
		if (height == -1) {
			lineIndex = getPartialBottomIndex();
			int topY = getLinePixel(lineIndex);
			lineHeight = renderer.getLineHeight(lineIndex);
			height = topY;
			if (topY + lineHeight <= clientAreaHeight) {
				height += lineHeight;
			} else {
				if (wordWrap || visualWrap) {
					TextLayout layout = renderer.getTextLayout(lineIndex);
					int y = clientAreaHeight - topY;
					for (int i = 0; i < layout.getLineCount(); i++) {
						Rectangle bounds = layout.getLineBounds(i);
						if (bounds.contains(bounds.x, y)) {
							height += bounds.y;
							break;
						}
					}
					renderer.disposeTextLayout(layout);
				}
			}
		} else {
			lineIndex = getLineIndex(height);
			int topLineY = getLinePixel(lineIndex);
			if (wordWrap || visualWrap) {
				TextLayout layout = renderer.getTextLayout(lineIndex);
				int y = height - topLineY;
				for (int i = 0; i < layout.getLineCount(); i++) {
					Rectangle bounds = layout.getLineBounds(i);
					if (bounds.contains(bounds.x, y)) {
						height = topLineY + bounds.y + bounds.height;
						break;
					}
				}
				renderer.disposeTextLayout(layout);
			} else {
				height = topLineY + renderer.getLineHeight(lineIndex);
			}
		}
		int caretHeight = height;
		if (wordWrap || visualWrap) {
			TextLayout layout = renderer.getTextLayout(caretLine);
			int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
			lineIndex = getVisualLineIndex(layout, offsetInLine);
			caretHeight += layout.getLineBounds(lineIndex).y;
			renderer.disposeTextLayout(layout);
		}
		lineIndex = caretLine;
		lineHeight = renderer.getLineHeight(lineIndex);
		while (caretHeight - lineHeight >= 0 && lineIndex < lineCount - 1) {
			caretHeight -= lineHeight;
			lineHeight = renderer.getLineHeight(++lineIndex);
		}
		int[] alignment = new int[1];
		int offset = getOffsetAtPoint(columnX, caretHeight, lineIndex, alignment);
		setCaretOffset(offset, alignment[0]);
		if (select) doSelection(ST.COLUMN_NEXT);
		height = getAvailableHeightBellow(height);
		scrollVertical(height, true);
		if (height == 0) setCaretLocation();
	}	
	showCaret();
	int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
	columnX = oldColumnX + hScrollChange;	
}
/**
 * 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 bottomOffset;
		if (wordWrap || visualWrap) {
			int lineIndex = getPartialBottomIndex();
			TextLayout layout = renderer.getTextLayout(lineIndex);
			int y = (clientAreaHeight - bottomMargin) - getLinePixel(lineIndex);
			int index = layout.getLineCount() - 1;
			while (index >= 0) {
				Rectangle bounds = layout.getLineBounds(index);
				if (y >= bounds.y + bounds.height) break;
				index--;
			}
			if (index == -1 && lineIndex > 0) {
				bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length();
			} else {
				bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1);
			}
			renderer.disposeTextLayout(layout);
		} else {
			int lineIndex = getBottomIndex();
			bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length();
		}
		if (caretOffset < bottomOffset) {
			setCaretOffset(bottomOffset, OFFSET_LEADING);
			showCaret();
		}
	}
}
/**
 * Moves the cursor to the beginning of the first fully visible line.
 */
void doPageStart() {
	int topOffset;
	if (wordWrap || visualWrap) {
		int y, lineIndex;
		if (topIndexY > 0) {
			lineIndex = topIndex - 1;
			y = renderer.getLineHeight(lineIndex) - topIndexY;
		} else {
			lineIndex = topIndex;
			y = -topIndexY;
		}
		TextLayout layout = renderer.getTextLayout(lineIndex);
		int index = 0;
		int lineCount = layout.getLineCount();
		while (index < lineCount) {
			Rectangle bounds = layout.getLineBounds(index);
			if (y <= bounds.y) break;
			index++;
		}
		if (index == lineCount) {
			topOffset = content.getOffsetAtLine(lineIndex + 1);
		} else {
			topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index];
		}
		renderer.disposeTextLayout(layout);		
	} else {
		topOffset = content.getOffsetAtLine(topIndex);
	}
	if (caretOffset > topOffset) {
		setCaretOffset(topOffset, OFFSET_LEADING);
		showCaret();
	}
}
/**
 * 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(boolean select, int height) {
	if (isSingleLine()) return;
	int oldHScrollOffset = horizontalScrollOffset;
	int oldColumnX = columnX;	
	if (isFixedLineHeight()) {
		int caretLine = getCaretLine();	
		if (caretLine > 0) {
			int lineHeight = renderer.getLineHeight();
			int lines = (height == -1 ? clientAreaHeight : height) / lineHeight;
			int scrollLines = Math.max(1, Math.min(caretLine, lines));
			caretLine -= scrollLines;
			int[] alignment = new int[1];
			int offset = getOffsetAtPoint(columnX, getLinePixel(caretLine), alignment);
			setCaretOffset(offset, alignment[0]);
			if (select) {
				doSelection(ST.COLUMN_PREVIOUS);
			}
			int verticalScrollOffset = getVerticalScrollOffset();
			int scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement());
			if (scrollOffset < verticalScrollOffset) {
				scrollVertical(scrollOffset - verticalScrollOffset, true);
			}
		}
	} else {
		int caretLine = getCaretLine();
		int lineHeight, lineIndex;
		if (height == -1) {
			if (topIndexY == 0) {
				height = clientAreaHeight;
			} else {
				int y;
				if (topIndex > 0) {
					lineIndex = topIndex - 1;
					lineHeight = renderer.getLineHeight(lineIndex);
					height = clientAreaHeight - topIndexY;
					y = lineHeight - topIndexY;
				} else {
					lineIndex = topIndex;
					lineHeight = renderer.getLineHeight(lineIndex);
					height = clientAreaHeight - (lineHeight + topIndexY);
					y = -topIndexY;
				}
				if (wordWrap || visualWrap) {
					TextLayout layout = renderer.getTextLayout(lineIndex);
					for (int i = 0; i < layout.getLineCount(); i++) {
						Rectangle bounds = layout.getLineBounds(i);
						if (bounds.contains(bounds.x, y)) {
							height += lineHeight - (bounds.y + bounds.height);
							break;
						}
					}
					renderer.disposeTextLayout(layout);
				}
			}
		} else {
			lineIndex = getLineIndex(clientAreaHeight - height);
			int topLineY = getLinePixel(lineIndex);
			if (wordWrap || visualWrap) {
				TextLayout layout = renderer.getTextLayout(lineIndex);
				int y = topLineY;
				for (int i = 0; i < layout.getLineCount(); i++) {
					Rectangle bounds = layout.getLineBounds(i);
					if (bounds.contains(bounds.x, y)) {
						height = clientAreaHeight - (topLineY + bounds.y);
						break;
					}
				}
				renderer.disposeTextLayout(layout);
			} else {
				height = clientAreaHeight - topLineY;
			}
		}
		int caretHeight = height;
		if (wordWrap || visualWrap) {
			TextLayout layout = renderer.getTextLayout(caretLine);
			int offsetInLine = caretOffset - content.getOffsetAtLine(caretLine);
			lineIndex = getVisualLineIndex(layout, offsetInLine);
			caretHeight += layout.getBounds().height - layout.getLineBounds(lineIndex).y;
			renderer.disposeTextLayout(layout);
		}
		lineIndex = caretLine;
		lineHeight = renderer.getLineHeight(lineIndex);
		while (caretHeight - lineHeight >= 0 && lineIndex > 0) {
			caretHeight -= lineHeight;
			lineHeight = renderer.getLineHeight(--lineIndex);
		}
		lineHeight = renderer.getLineHeight(lineIndex);
		int[] alignment = new int[1];
		int offset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex, alignment);
		setCaretOffset(offset, alignment[0]);
		if (select) doSelection(ST.COLUMN_PREVIOUS);
		height = getAvailableHeightAbove(height);
		scrollVertical(-height, true);
		if (height == 0) setCaretLocation();	
	}
	showCaret();
	int hScrollChange = oldHScrollOffset - horizontalScrollOffset;
	columnX = oldColumnX + hScrollChange;
}
/**
 * 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;
			}
		// test whether selection actually changed. Fixes 1G71EO1
		} else 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;
			}
		// test whether selection actually changed. Fixes 1G71EO1	
		} else 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);
		sendSelectionEvent();
	}
	sendAccessibleTextCaretMoved();
}
/**
 * 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;
	int offset, alignment;
	if (offsetInLine < content.getLine(caretLine).length()) {
		TextLayout layout = renderer.getTextLayout(caretLine);
		offsetInLine = layout.getNextOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
		int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)];
		renderer.disposeTextLayout(layout);
		offset = offsetInLine + lineOffset;
		alignment = offsetInLine == lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING;
		setCaretOffset(offset, alignment);
		showCaret();
	} else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) {
		caretLine++;		
		offset = content.getOffsetAtLine(caretLine);
		alignment = PREVIOUS_OFFSET_TRAILING;
		setCaretOffset(offset, alignment);
		showCaret();
	}
}
/**
 * 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) {
		int offset = getClusterPrevious(caretOffset, caretLine);
		setCaretOffset(offset, OFFSET_LEADING);
		showCaret();
	} else if (caretLine > 0) {
		caretLine--;
		lineOffset = content.getOffsetAtLine(caretLine);
		int offset = lineOffset + content.getLine(caretLine).length();
		setCaretOffset(offset, OFFSET_LEADING);
		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 = columnX = getPointAtOffset(caretOffset).x;
	doLineDown(true);
	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 = columnX = getPointAtOffset(caretOffset).x;	
	doLineUp(true);	
	columnX = oldColumnX;
}
/**
 * Scrolls one page down so that the last line (truncated or whole)
 * of the current page becomes the fully visible top line.
 * <p>
 * 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></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 pixels) {
	int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
	doPageDown(true, pixels);
	columnX = oldColumnX;
}
/**
 * Scrolls one page up so that the first line (truncated or whole)
 * of the current page becomes the fully visible last line.
 * <p>
 * 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><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 pixels) {
	int oldColumnX = columnX = getPointAtOffset(caretOffset).x;
	doPageUp(true, pixels);
	columnX = oldColumnX;
}
/**
 * Moves the caret to the end of the next word .
 */
void doSelectionWordNext() {
	int offset = getWordNext(caretOffset, SWT.MOVEMENT_WORD);
	// don't change caret position if in single line mode and the cursor 
	// would be on a different line. fixes 5673
	if (!isSingleLine() || 
		content.getLineAtOffset(caretOffset) == content.getLineAtOffset(offset)) {
		// Force symmetrical movement for word next and previous. Fixes 14536
		setCaretOffset(offset, OFFSET_LEADING);
		showCaret();
	}
}
/**
 * Moves the caret to the start of the previous word.
 */
void doSelectionWordPrevious() {
	int offset = getWordPrevious(caretOffset, SWT.MOVEMENT_WORD);
	setCaretOffset(offset, OFFSET_LEADING);
	showCaret();
}
/**
 * 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 offset = getClusterPrevious(caretOffset, getCaretLine());
	setCaretOffset(offset, SWT.DEFAULT);
	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 offset = getClusterNext(caretOffset, getCaretLine());
	setCaretOffset(offset, SWT.DEFAULT);
	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) {
		setCaretOffset(selection.y, SWT.DEFAULT);
		showCaret();
	} 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) {
		setCaretOffset(selection.x, SWT.DEFAULT);
		showCaret();
	} else {
		doSelectionWordPrevious();
	}
}
/** 
 * Ends the autoscroll process.
 */
void endAutoScroll() {
	autoScrollDirection = SWT.NULL;
}
@Override
public Color getBackground() {
	checkWidget();
	if (background == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
	}
	return background;
}
/**
 * Returns the baseline, in pixels.
 *  
 * Note: this API should not be used if a StyleRange attribute causes lines to 
 * have different heights (i.e. different fonts, rise, etc). 
 *
 * @return baseline the baseline
 * @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 3.0
 * 
 * @see #getBaseline(int)
 */
public int getBaseline() {
	checkWidget();
	return renderer.getBaseline();
}
/**
 * Returns the baseline at the given offset, in pixels. 
 *
 * @param offset the offset
 * 
 * @return baseline the baseline
 * 
 * @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 3.2
 */
public int getBaseline(int offset) {
	checkWidget();
	if (!(0 <= offset && offset <= content.getCharCount())) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	if (isFixedLineHeight()) {
		return renderer.getBaseline();
	}
	int lineIndex = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	TextLayout layout = renderer.getTextLayout(lineIndex);
	int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
	FontMetrics metrics = layout.getLineMetrics(lineInParagraph);
	renderer.disposeTextLayout(layout);
	return metrics.getAscent() + metrics.getLeading();
}
/**
 * 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>
 * 
 * @deprecated use BidiSegmentListener instead.
 */
@Deprecated
public boolean getBidiColoring() {
	checkWidget();
	return bidiColoring;
}
/**
 * Returns whether the widget is in block selection mode.
 *
 * @return true if widget is in block selection mode, 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>
 * 
 * @since 3.5
 */
public boolean getBlockSelection() {
	checkWidget();
	return blockSelection;
}
Rectangle getBlockSelectionPosition() {
	int firstLine = getLineIndex(blockYAnchor - getVerticalScrollOffset());
	int lastLine = getLineIndex(blockYLocation - getVerticalScrollOffset()); 
	if (firstLine > lastLine) {
		int temp = firstLine;
		firstLine = lastLine;
		lastLine = temp;
	}
	int left = blockXAnchor;
	int right = blockXLocation;
	if (left > right) {
		left = blockXLocation;
		right = blockXAnchor;
	}
	return new Rectangle (left - horizontalScrollOffset, firstLine, right - horizontalScrollOffset, lastLine);
}
/** 
 * Returns the block selection bounds. The bounds is 
 * relative to the upper left corner of the document.
 * 
 * @return the block selection bounds
 * 
 * @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 3.5
 */
public Rectangle getBlockSelectionBounds() {
	Rectangle rect;
	if (blockSelection && blockXLocation != -1) {
		rect = getBlockSelectionRectangle();
	} else {
		Point startPoint = getPointAtOffset(selection.x);
		Point endPoint = getPointAtOffset(selection.y);
		int height = getLineHeight(selection.y);
		rect = new Rectangle(startPoint.x, startPoint.y, endPoint.x - startPoint.x, endPoint.y + height - startPoint.y);
		if (selection.x == selection.y) {
			rect.width = getCaretWidth();
		}
	}
	rect.x += horizontalScrollOffset;
	rect.y += getVerticalScrollOffset();
	return rect;
}
Rectangle getBlockSelectionRectangle() {
	Rectangle rect = getBlockSelectionPosition();
	rect.y = getLinePixel(rect.y);
	rect.width = rect.width - rect.x;
	rect.height =  getLinePixel(rect.height + 1) - rect.y;
	return rect;
}
String getBlockSelectionText(String delimiter) {
	Rectangle rect = getBlockSelectionPosition();
	int firstLine = rect.y;
	int lastLine = rect.height;
	int left = rect.x;
	int right = rect.width;
	StringBuffer buffer = new StringBuffer();
	for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
		int start = getOffsetAtPoint(left, 0, lineIndex, null);
		int end = getOffsetAtPoint(right, 0, lineIndex, null);
		if (start > end) {
			int temp = start;
			start = end;
			end = temp;
		}
		String text = content.getTextRange(start, end - start);
		buffer.append(text);
		if (lineIndex < lastLine) buffer.append(delimiter); 
	}
	return buffer.toString();
}
/** 
 * Returns the index of the last fully visible line.
 *
 * @return index of the last fully visible line.
 */
int getBottomIndex() {
	int bottomIndex;
	if (isFixedLineHeight()) {
		int lineCount = 1;
		int lineHeight = renderer.getLineHeight();
		if (lineHeight != 0) {
			// calculate the number of lines that are fully visible
			int partialTopLineHeight = topIndex * lineHeight - getVerticalScrollOffset();
			lineCount = (clientAreaHeight - partialTopLineHeight) / lineHeight;
		}
		bottomIndex = Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1));
	} else {
		int clientAreaHeight = this.clientAreaHeight - bottomMargin;
		bottomIndex = getLineIndex(clientAreaHeight);
		if (bottomIndex > 0) {
			int linePixel = getLinePixel(bottomIndex);
			int lineHeight = renderer.getLineHeight(bottomIndex);
			if (linePixel + lineHeight > clientAreaHeight) {
				if (getLinePixel(bottomIndex - 1) >= topMargin) {
					bottomIndex--;
				}
			}
		}
	}
	return bottomIndex;
}
/** 
 * Returns the bottom margin.
 *
 * @return the bottom margin.
 * @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 3.5
 */
public int getBottomMargin() {
	checkWidget();
	return bottomMargin;
}
Rectangle getBoundsAtOffset(int offset) {
	int lineIndex = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	String line = content.getLine(lineIndex);
	Rectangle bounds;
	if (line.length() != 0) {
		int offsetInLine = Math.max (0, offset - lineOffset);
		TextLayout layout = renderer.getTextLayout(lineIndex);
		if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
			offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); 
			Point point = layout.getLocation(offsetInLine, true);
			bounds = new Rectangle (point.x, point.y, 0, renderer.getLineHeight());
		} else {
			bounds = layout.getBounds(offsetInLine, offsetInLine);
		}
		renderer.disposeTextLayout(layout);
	} else {
		bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
	}
	if (offset == caretOffset && !(wordWrap || visualWrap)) {
		int lineEnd = lineOffset + line.length();
		if (offset == lineEnd) {
			bounds.width += getCaretWidth();
		}
	}
	bounds.x += leftMargin - horizontalScrollOffset;
	bounds.y += getLinePixel(lineIndex);
	return bounds;
}
/**
 * Returns the caret position relative to the start of the text.
 *
 * @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 width.
 *
 * @return the caret width, 0 if caret is null.
 */
int getCaretWidth() {
	Caret caret = getCaret();
	if (caret == null) return 0;
	return caret.getSize().x;
}
Object getClipboardContent(int clipboardType) {
	TextTransfer plainTextTransfer = TextTransfer.getInstance();
	return clipboard.getContents(plainTextTransfer, clipboardType);
}
int getClusterNext(int offset, int lineIndex) {
	int lineOffset = content.getOffsetAtLine(lineIndex);	
	TextLayout layout = renderer.getTextLayout(lineIndex);
	offset -= lineOffset;
	offset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
	offset += lineOffset;
	renderer.disposeTextLayout(layout);
	return offset;
}
int getClusterPrevious(int offset, int lineIndex) {
	int lineOffset = content.getOffsetAtLine(lineIndex);	
	TextLayout layout = renderer.getTextLayout(lineIndex);
	offset -= lineOffset;
	offset = layout.getPreviousOffset(offset, SWT.MOVEMENT_CLUSTER);
	offset += lineOffset;
	renderer.disposeTextLayout(layout);
	return offset;
}
/**
 * Returns the content implementation that is used for text storage.
 * 
 * @return content the user defined content implementation that is used for
 * text storage or the default content implementation 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 content;
}
@Override
public boolean getDragDetect () {
	checkWidget ();
	return dragDetect;
}
/** 
 * Returns whether the widget implements double click mouse behavior.
 *
 * @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.
 *
 * @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;
}
@Override
public Color getForeground() {
	checkWidget();
	if (foreground == null) {
		return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
	}
	return foreground;
}
/** 
 * Returns the horizontal scroll increment.
 *
 * @return horizontal scroll increment.
 */
int getHorizontalIncrement() {	
	return renderer.averageCharWidth;
}
/** 
 * Returns the horizontal scroll offset relative to the start of the line.
 *
 * @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.
 *
 * @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 line indentation of the widget.
 * 
 * @return the line indentation
 * 
 * @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 #getLineIndent(int)
 * 
 * @since 3.2
 */
public int getIndent() {
	checkWidget();
	return indent;
}
/**
 * Returns whether the widget justifies lines.
 * 
 * @return whether lines are justified
 * 
 * @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 #getLineJustify(int)
 * 
 * @since 3.2
 */
public boolean getJustify() {
	checkWidget();
	return justify;
}
/** 
 * Returns the action assigned to the key.
 * Returns SWT.NULL if there is no action associated with the key.
 *
 * @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 = keyActionMap.get(new Integer(key));	
	return action == null ? SWT.NULL : action.intValue();
}
/**
 * Gets the number of characters.
 *
 * @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 line at the given line index without delimiters.
 * Index 0 is the first line of the content. When there are not
 * any lines, getLine(0) is a valid call that answers an empty string.
 * <p>
 *
 * @param lineIndex index of the line to return.
 * @return the line text without delimiters
 * 
 * @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 line index is outside the valid range (< 0 or >= getLineCount())</li> 
 * </ul>
 * @since 3.4
 */
public String getLine(int lineIndex) {
	checkWidget();
	if (lineIndex < 0 || 
		(lineIndex > 0 && lineIndex >= content.getLineCount())) {
		SWT.error(SWT.ERROR_INVALID_RANGE);		
	}
	return content.getLine(lineIndex);
}
/**
 * Returns the alignment of the line at the given index.
 * 
 * @param index the index of the line
 * 
 * @return the line alignment
 * 
 * @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>
 * 
 * @see #getAlignment()
 * 
 * @since 3.2
 */
public int getLineAlignment(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return renderer.getLineAlignment(index, alignment);
}
/**
 * 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 content.getLineAtOffset(offset);
}
/**
 * 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.
 * 
 * @param index the index of the line
 * @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();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetBackground) ? null : renderer.getLineBackground(index, null);
}
/**
 * Returns the bullet of the line at the given index.
 * 
 * @param index the index of the line
 * 
 * @return the line bullet
 * 
 * @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>
 * 
 * @since 3.2
 */
public Bullet getLineBullet(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetStyle) ? null : renderer.getLineBullet(index, null);
}
/**
 * Returns the line background data for the given line or null if 
 * there is none.
 * 
 * @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(ST.LineGetBackground, lineOffset, line);
}
/** 
 * Gets the number of text lines.
 *
 * @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 content.getLineCount();
}
/**
 * Returns the number of lines that can be completely displayed in the 
 * widget client area.
 *
 * @return number of lines that can be completely displayed in the widget 
 * 	client area.
 */
int getLineCountWhole() {
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		return lineHeight != 0 ? clientAreaHeight / lineHeight : 1;
	}
	return getBottomIndex() - topIndex + 1;
}
/**
 * Returns the line delimiter used for entering new lines by key down
 * or paste operation.
 *
 * @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 the line height.
 * <p>
 * Note: this API should not be used if a StyleRange attribute causes lines to 
 * have different heights (i.e. different fonts, rise, etc).
 * </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>
 * @see #getLineHeight(int)
 */
public int getLineHeight() {
	checkWidget();
	return renderer.getLineHeight();
}
/**
 * Returns the line height at the given offset.
 *
 * @param offset the offset
 *  
 * @return line height in pixels
 * 
 * @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 3.2
 */
public int getLineHeight(int offset) {
	checkWidget();
	if (!(0 <= offset && offset <= content.getCharCount())) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	if (isFixedLineHeight()) {
		return renderer.getLineHeight();
	}
	int lineIndex = content.getLineAtOffset(offset);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	TextLayout layout = renderer.getTextLayout(lineIndex);
	int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length()));
	int height = layout.getLineBounds(lineInParagraph).height;
	renderer.disposeTextLayout(layout);
	return height;
}
/**
 * Returns the indentation of the line at the given index.
 * 
 * @param index the index of the line
 * 
 * @return the line indentation
 * 
 * @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>
 * 
 * @see #getIndent()
 * 
 * @since 3.2
 */
public int getLineIndent(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetStyle) ? 0 : renderer.getLineIndent(index, indent);
}
/**
 * Returns whether the line at the given index is justified.
 * 
 * @param index the index of the line
 * 
 * @return whether the line is justified 
 * 
 * @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>
 * 
 * @see #getJustify()
 * 
 * @since 3.2
 */
public boolean getLineJustify(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetStyle) ? false : renderer.getLineJustify(index, justify);	
}
/**
 * Returns the line spacing of the widget.
 * 
 * @return the line spacing
 *  
 * @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 3.2
 */
public int getLineSpacing() {
	checkWidget();
	return lineSpacing;
}
/**
 * Returns the line style data for the given line or null if there is 
 * none.
 * <p>
 * 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(ST.LineGetStyle, lineOffset, line);
}
/**
 * Returns the top pixel, relative to the client area, of a given line.
 * Clamps out of ranges index.
 *  
 * @param lineIndex the line index, the max value is lineCount. If
 * lineIndex == lineCount it returns the bottom pixel of the last line.
 * It means this function can be used to retrieve the bottom pixel of any line.
 * 
 * @return the top pixel of a given line index
 * 
 * @since 3.2
 */
public int getLinePixel(int lineIndex) {
	checkWidget();
	int lineCount = content.getLineCount();
	lineIndex = Math.max(0, Math.min(lineCount, lineIndex));
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		return lineIndex * lineHeight - getVerticalScrollOffset() + topMargin;
	}
	if (lineIndex == topIndex) return topIndexY + topMargin;
	int height = topIndexY;
	if (lineIndex > topIndex) {
		for (int i = topIndex; i < lineIndex; i++) {
			height += renderer.getLineHeight(i);
		}
	} else {
		for (int i = topIndex - 1; i >= lineIndex; i--) {
			height -= renderer.getLineHeight(i);
		}
	}
	return height + topMargin;
}
/**
 * Returns the line index for a y, relative to the client area.
 * The line index returned is always in the range 0..lineCount - 1.
 * 
 * @param y the y-coordinate pixel
 * 
 * @return the line index for a given y-coordinate pixel
 *
 * @since 3.2
 */
public int getLineIndex(int y) {
	checkWidget();
	y -= topMargin;
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		int lineIndex = (y + getVerticalScrollOffset()) / lineHeight;
		int lineCount = content.getLineCount();
		lineIndex = Math.max(0, Math.min(lineCount - 1, lineIndex));
		return lineIndex;
	}
	if (y == topIndexY) return topIndex;
	int line = topIndex;
	if (y < topIndexY) {
		while (y < topIndexY && line > 0) {
			y += renderer.getLineHeight(--line);
		}
	} else {
		int lineCount = content.getLineCount();
		int lineHeight = renderer.getLineHeight(line);
		while (y - lineHeight >= topIndexY && line < lineCount - 1) {
			y -= lineHeight;
			lineHeight = renderer.getLineHeight(++line);
		}
	}
	return line;
}
/**
 * Returns the tab stops of the line at the given <code>index</code>.
 * 
 * @param index the index of the line
 * 
 * @return the tab stops for 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>
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT when the index is invalid</li>
 * </ul>
 * 
 * @see #getTabStops()
 * 
 * @since 3.6
 */
public int[] getLineTabStops(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (isListening(ST.LineGetStyle)) return null;
	int[] tabs = renderer.getLineTabStops(index, null);
	if (tabs == null) tabs = this.tabs;
	if (tabs == null) return new int [] {renderer.tabWidth};
	int[] result = new int[tabs.length];
	System.arraycopy(tabs, 0, result, 0, tabs.length);
	return result;
}
/**
 * Returns the wrap indentation of the line at the given <code>index</code>.
 * 
 * @param index the index of the line
 * 
 * @return the wrap indentation
 * 
 * @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>
 * 
 * @see #getWrapIndent()
 * 
 * @since 3.6
 */
public int getLineWrapIndent(int index) {
	checkWidget();
	if (index < 0 || index > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetStyle) ? 0 : renderer.getLineWrapIndent(index, wrapIndent);
}
/** 
 * Returns the left margin.
 *
 * @return the left margin.
 * @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 3.5
 */
public int getLeftMargin() {
	checkWidget();
	return leftMargin - alignmentMargin;
}
/**
 * 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.
 *
 * @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);		
	}
	return getPointAtOffset(offset);
}
/**
 * Returns the character offset of the first character of the given line.
 *
 * @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 line index is outside the valid range (< 0 or >= getLineCount())</li> 
 * </ul>
 * @since 2.0
 */
public int getOffsetAtLine(int lineIndex) {
	checkWidget();
	if (lineIndex < 0 || 
		(lineIndex > 0 && lineIndex >= content.getLineCount())) {
		SWT.error(SWT.ERROR_INVALID_RANGE);		
	}
	return content.getOffsetAtLine(lineIndex);
}
/**
 * Returns the offset of the character at the given location relative 
 * to the first character in the document.
 * <p>
 * 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();
	if (point == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	int[] trailing = new int[1];
	int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
	if (offset == -1) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return offset + trailing[0];
}
int getOffsetAtPoint(int x, int y, int[] alignment) {
	int lineIndex = getLineIndex(y);
	y -= getLinePixel(lineIndex);
	return getOffsetAtPoint(x, y, lineIndex, alignment);
}
int getOffsetAtPoint(int x, int y, int lineIndex, int[] alignment) {
	TextLayout layout = renderer.getTextLayout(lineIndex);
	x += horizontalScrollOffset - leftMargin;
	int[] trailing = new int[1];	
	int offsetInLine = layout.getOffset(x, y, trailing);
	if (alignment != null) alignment[0] = OFFSET_LEADING;
	if (trailing[0] != 0) {
		int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
		int lineStart = layout.getLineOffsets()[lineInParagraph];
		if (offsetInLine + trailing[0] == lineStart) {
			offsetInLine += trailing[0];
			if (alignment != null) alignment[0] = PREVIOUS_OFFSET_TRAILING;
		} else {
			String line = content.getLine(lineIndex);
			int level = 0;
			if (alignment != null) {
				int offset = offsetInLine;
				while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
				if (offset == 0 && Character.isDigit(line.charAt(offset))) {
					level = isMirrored() ? 1 : 0;
				} else {
					level = layout.getLevel(offset) & 0x1;
				}
			}
			offsetInLine += trailing[0];
			if (alignment != null) {
				int trailingLevel = layout.getLevel(offsetInLine) & 0x1;
				if ((level ^ trailingLevel) != 0) {
					alignment[0] = PREVIOUS_OFFSET_TRAILING;
				} else {
					alignment[0] = OFFSET_LEADING;
				}
			}
		}
	}
	renderer.disposeTextLayout(layout);
	return offsetInLine + content.getOffsetAtLine(lineIndex);
}
int getOffsetAtPoint(int x, int y, int[] trailing, boolean inTextOnly) {
	if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) {
		return -1;
	}
	int bottomIndex = getPartialBottomIndex();
	int height = getLinePixel(bottomIndex + 1);
	if (inTextOnly && y > height) {
		return -1;
	}
	int lineIndex = getLineIndex(y);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	TextLayout layout = renderer.getTextLayout(lineIndex);	
	x += horizontalScrollOffset - leftMargin;
	y -= getLinePixel(lineIndex);
	int offset = layout.getOffset(x, y, trailing);
	Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset));
	renderer.disposeTextLayout(layout);
	if (inTextOnly && !(rect.x  <= x && x <=  rect.x + rect.width)) {
		return -1;
	}
	return offset + lineOffset;
}
/**
 * Returns the orientation of the receiver.
 *
 * @return the orientation style
 * 
 * @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.2
 */
@Override
public int getOrientation () {
	return super.getOrientation ();
}
/** 
 * Returns the index of the last partially visible line.
 *
 * @return index of the last partially visible line.
 */
int getPartialBottomIndex() {
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
		return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1);
	}
	return getLineIndex(clientAreaHeight - bottomMargin);
}
/** 
 * Returns the index of the first partially visible line.
 *
 * @return index of the first partially visible line.
 */
int getPartialTopIndex() {
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		return getVerticalScrollOffset() / lineHeight;
	}
	return topIndexY <= 0 ? topIndex : topIndex - 1;
}
/**
 * Returns the content in the specified range using the platform line 
 * delimiter to separate lines.
 *
 * @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 = content.getLineAtOffset(writer.getStart());
	int endLine = content.getLineAtOffset(end);
	String endLineText = content.getLine(endLine);
	int endLineOffset = content.getOffsetAtLine(endLine);
	
	for (int i = startLine; i <= endLine; i++) {
		writer.writeLine(content.getLine(i), content.getOffsetAtLine(i));
		if (i < endLine) {
			writer.writeLineDelimiter(PlatformLineDelimiter);
		}
	}
	if (end > endLineOffset + endLineText.length()) {
		writer.writeLineDelimiter(PlatformLineDelimiter);
	}
	writer.close();
	return writer.toString();
}
/**
 * Returns all the ranges of text that have an associated StyleRange.
 * 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>
 * The ranges array contains start and length pairs.  Each pair refers to
 * the corresponding style in the styles array.  For example, the pair
 * that starts at ranges[n] with length ranges[n+1] uses the style
 * at styles[n/2] returned by <code>getStyleRanges(int, int, boolean)</code>.
 * </p>
 * 
 * @return the ranges or an empty array 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>
 * 
 * @since 3.2
 * 
 * @see #getStyleRanges(boolean)
 */
public int[] getRanges() {
	checkWidget();
	if (!isListening(ST.LineGetStyle)) {
		int[] ranges = renderer.getRanges(0, content.getCharCount());
		if (ranges != null) return ranges;
	}
	return new int[0];
}
/**
 * Returns the ranges of text that have an associated StyleRange.
 * 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>
 * The ranges array contains start and length pairs.  Each pair refers to
 * the corresponding style in the styles array.  For example, the pair
 * that starts at ranges[n] with length ranges[n+1] uses the style
 * at styles[n/2] returned by <code>getStyleRanges(int, int, boolean)</code>.
 * </p>
 *
 * @param start the start offset of the style ranges to return
 * @param length the number of style ranges to return
 * 
 * @return the ranges or an empty array 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>
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_INVALID_RANGE if start or length are outside the widget content</li> 
 * </ul> 
 * 
 * @since 3.2
 * 
 * @see #getStyleRanges(int, int, boolean)
 */
public int[] getRanges(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);
	}
	if (!isListening(ST.LineGetStyle)) {
		int[] ranges = renderer.getRanges(start, length);
		if (ranges != null) return ranges;
	}
	return new int[0];
}
/** 
 * Returns the right margin.
 *
 * @return the right margin.
 * @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 3.5
 */
public int getRightMargin() {
	checkWidget();
	return rightMargin;
}
/**
 * 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.
 *
 * @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 ranges of text that are inside the block selection rectangle.
 * <p>
 * The ranges array contains start and length pairs. When the receiver is not
 * in block selection mode the return arrays contains the start and length of
 * the regular selection.
 *
 * @return the ranges array
 * 
 * @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 3.5
 */
public int[] getSelectionRanges() {
	checkWidget();
	if (blockSelection && blockXLocation != -1) {
		Rectangle rect = getBlockSelectionPosition();
		int firstLine = rect.y;
		int lastLine = rect.height;
		int left = rect.x;
		int right = rect.width;
		int[] ranges = new int[(lastLine - firstLine + 1) * 2];
		int index = 0;
		for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
			int start = getOffsetAtPoint(left, 0, lineIndex, null);
			int end = getOffsetAtPoint(right, 0, lineIndex, null);
			if (start > end) {
				int temp = start;
				start = end;
				end = temp;
			}
			ranges[index++] = start;
			ranges[index++] = end - start;
		}
		return ranges;
	}
	return new int[] {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.
 *
 * @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();
	if (blockSelection && blockXLocation != -1) {
		return getBlockSelectionText(content.getLineDelimiter()).length();
	}
	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.
 *
 * @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();
	if (blockSelection && blockXLocation != -1) {
		return getBlockSelectionText(content.getLineDelimiter());
	}
	return content.getTextRange(selection.x, selection.y - selection.x);
}
StyledTextEvent getBidiSegments(int lineOffset, String line) {
	if (!isListening(ST.LineGetSegments)) {
		if (!bidiColoring) return null;
		StyledTextEvent event = new StyledTextEvent(content);
		event.segments = getBidiSegmentsCompatibility(line, lineOffset);
		return event;
	}
	StyledTextEvent event = sendLineEvent(ST.LineGetSegments, lineOffset, line);
	if (event == null || event.segments == null || event.segments.length == 0) return null;
	int lineLength = line.length();
	int[] segments = event.segments;
	if (segments[0] > lineLength) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	char[] segmentsChars = event.segmentsChars;
	boolean hasSegmentsChars = segmentsChars != null;
	for (int i = 1; i < segments.length; i++) {
		if ((hasSegmentsChars ? segments[i] < segments[i - 1] : segments[i] <= segments[i - 1]) || segments[i] > lineLength) {
			SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	if (hasSegmentsChars && !visualWrap) {
		for (int i= 0; i < segmentsChars.length; i++) {
			if (segmentsChars[i] == '\n' || segmentsChars[i] == '\r') {
				visualWrap = true;
				setVariableLineHeight();
				break;
			}
		}
	}
	return event;
}
/**
 * @see #getBidiSegments
 * Supports deprecated setBidiColoring API. Remove when API is removed.
 */
int [] getBidiSegmentsCompatibility(String line, int lineOffset) {
	int lineLength = line.length();
	StyleRange [] styles = null;
	StyledTextEvent event = getLineStyleData(lineOffset, line);
	if (event != null) {
		styles = event.styles;
	} else {
		styles = renderer.getStyleRanges(lineOffset, lineLength, true);
	}
	if (styles == null || 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.
 * <p>
 * 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 (!isListening(ST.LineGetStyle)) {
		StyleRange[] ranges = renderer.getStyleRanges(offset, 1, true);
		if (ranges != null) return ranges[0];
	}
	return null;
}
/**
 * Returns the styles.
 * <p>
 * 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></p>
 * Note: Because a StyleRange includes the start and length, the
 * same instance cannot occur multiple times in the array of styles.
 * If the same style attributes, such as font and color, occur in
 * multiple StyleRanges, <code>getStyleRanges(boolean)</code>
 * can be used to get the styles without the ranges.
 * </p>
 *
 * @return the styles or an empty array 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>
 * 
 * @see #getStyleRanges(boolean)
 */
public StyleRange[] getStyleRanges() {
	checkWidget();
	return getStyleRanges(0, content.getCharCount(), true);
}
/**
 * Returns the styles.
 * <p>
 * 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><p>
 * Note: When <code>includeRanges</code> is true, the start and length
 * fields of each StyleRange will be valid, however the StyleRange
 * objects may need to be cloned. When <code>includeRanges</code> is
 * false, <code>getRanges(int, int)</code> can be used to get the
 * associated ranges.
 * </p>
 * 
 * @param includeRanges whether the start and length field of the StyleRanges should be set.
 * 
 * @return the styles or an empty array 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>
 * 
 * @since 3.2
 * 
 * @see #getRanges(int, int)
 * @see #setStyleRanges(int[], StyleRange[])
 */
public StyleRange[] getStyleRanges(boolean includeRanges) {
	checkWidget();
	return getStyleRanges(0, content.getCharCount(), includeRanges);
}
/**
 * Returns the styles for the given text range.
 * <p>
 * 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><p>
 * Note: Because the StyleRange includes the start and length, the
 * same instance cannot occur multiple times in the array of styles.
 * If the same style attributes, such as font and color, occur in
 * multiple StyleRanges, <code>getStyleRanges(int, int, boolean)</code>
 * can be used to get the styles without the ranges.
 * </p>
 * @param start the start offset of the style ranges to return
 * @param length the number of style ranges to return
 *
 * @return the styles or an empty array if a LineStyleListener has 
 *  been set.  The returned styles will reflect the given range.  The first 
 *  returned <code>StyleRange</code> will have a starting offset >= start 
 *  and the last returned <code>StyleRange</code> will have an ending 
 *  offset <= start + length - 1
 *
 * @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>
 * 
 * @see #getStyleRanges(int, int, boolean)
 * 
 * @since 3.0
 */
public StyleRange[] getStyleRanges(int start, int length) {
	checkWidget();
	return getStyleRanges(start, length, true);
}
/**
 * Returns the styles for the given text range.
 * <p>
 * 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><p>
 * Note: When <code>includeRanges</code> is true, the start and length
 * fields of each StyleRange will be valid, however the StyleRange
 * objects may need to be cloned. When <code>includeRanges</code> is
 * false, <code>getRanges(int, int)</code> can be used to get the
 * associated ranges.
 * </p>
 * 
 * @param start the start offset of the style ranges to return
 * @param length the number of style ranges to return
 * @param includeRanges whether the start and length field of the StyleRanges should be set.
 *
 * @return the styles or an empty array if a LineStyleListener has 
 *  been set.  The returned styles will reflect the given range.  The first 
 *  returned <code>StyleRange</code> will have a starting offset >= start 
 *  and the last returned <code>StyleRange</code> will have an ending 
 *  offset <= start + length - 1
 *
 * @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>
 * 
 * @since 3.2
 * 
 * @see #getRanges(int, int)
 * @see #setStyleRanges(int[], StyleRange[])
 */
public StyleRange[] getStyleRanges(int start, int length, boolean includeRanges) {
	checkWidget();
	int contentLength = getCharCount();
	int end = start + length;
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	if (!isListening(ST.LineGetStyle)) {
		StyleRange[] ranges = renderer.getStyleRanges(start, length, includeRanges);
		if (ranges != null) return ranges;
	}
	return new StyleRange[0];
}
/**
 * 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>
 * 
 * @see #getTabStops()
 */
public int getTabs() {
	checkWidget();
	return tabLength;
}

/**
 * Returns the tab list of the receiver.
 *
 * @return the tab list
 * @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 3.6
 */
public int[] getTabStops() {
	checkWidget();
	if (tabs == null) return new int [] {renderer.tabWidth};
	int[] result = new int[tabs.length];
	System.arraycopy(tabs, 0, result, 0, tabs.length);
	return result;
}

/**
 * Returns a copy of the widget content.
 *
 * @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.
 *
 * @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 smallest bounding rectangle that includes the characters between two offsets.
 *
 * @param start offset of the first character included in the bounding box
 * @param end offset of the last character included in the bounding box 
 * @return bounding box of the text between start and end
 * @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>
 * @since 3.1
 */
public Rectangle getTextBounds(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);
	}
	int lineStart = content.getLineAtOffset(start);
	int lineEnd = content.getLineAtOffset(end);
	Rectangle rect;
	int y = getLinePixel(lineStart);
	int height = 0;
	int left = 0x7fffffff, right = 0;
	for (int i = lineStart; i <= lineEnd; i++) {
		int lineOffset = content.getOffsetAtLine(i);		
		TextLayout layout = renderer.getTextLayout(i);
		int length = layout.getText().length();
		if (length > 0) {
			if (i == lineStart) {
				if (i == lineEnd) {
					rect = layout.getBounds(start - lineOffset, end - lineOffset);
				} else {
					rect = layout.getBounds(start - lineOffset, length);
				}
				y += rect.y;
			} else if (i == lineEnd) {
				rect = layout.getBounds(0, end - lineOffset);
			} else {
				rect = layout.getBounds();
			}
			left = Math.min(left, rect.x);
			right = Math.max(right, rect.x + rect.width);
			height += rect.height;
		} else {
			height += renderer.getLineHeight();
		}
		renderer.disposeTextLayout(layout);
	}
	rect = new Rectangle (left, y, right-left, height);
	rect.x += leftMargin - horizontalScrollOffset;
	return rect;
}
/**
 * Returns the widget content starting at start for length characters.
 *
 * @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);
}
/**
 * Returns the maximum number of characters that the receiver is capable of holding.
 * 
 * @return the 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>
 */
public int getTextLimit() {
	checkWidget();
	return textLimit;
}
/**
 * Gets the top index.
 * <p>
 * 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();
	return topIndex;
}
/** 
 * Returns the top margin.
 *
 * @return the top margin.
 * @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 3.5
 */
public int getTopMargin() {
	checkWidget();
	return topMargin;
}
/**
 * Gets the top pixel.
 * <p>
 * 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 getVerticalScrollOffset();
}
/** 
 * Returns the vertical scroll increment.
 *
 * @return vertical scroll increment.
 */
int getVerticalIncrement() {
	return renderer.getLineHeight();
}
int getVerticalScrollOffset() {
	if (verticalScrollOffset == -1) {
		renderer.calculate(0, topIndex);
		int height = 0;
		for (int i = 0; i < topIndex; i++) {
			height += renderer.getLineHeight(i);
		}
		height -= topIndexY;
		verticalScrollOffset = height;
	}
	return verticalScrollOffset;
}
int getVisualLineIndex(TextLayout layout, int offsetInLine) {
	int lineIndex = layout.getLineIndex(offsetInLine);
	int[] offsets = layout.getLineOffsets();
	Caret caret = getCaret();
	if (caret != null && lineIndex != 0 && offsetInLine == offsets[lineIndex]) {
		int lineY = layout.getLineBounds(lineIndex).y;
		int caretY = caret.getLocation().y - getLinePixel(getCaretLine());
		if (lineY > caretY) lineIndex--;
		caretAlignment = OFFSET_LEADING;
 	}
	return lineIndex;
}
int getCaretDirection() {
	if (!isBidiCaret()) return SWT.DEFAULT;
	if (ime.getCompositionOffset() != -1) return SWT.DEFAULT;
	if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection;
	updateCaretDirection = false;
	int caretLine = getCaretLine();
	int lineOffset = content.getOffsetAtLine(caretLine);
	String line = content.getLine(caretLine);
	int offset = caretOffset - lineOffset;
	int lineLength = line.length();
	if (lineLength == 0) return isMirrored() ? SWT.RIGHT : SWT.LEFT;
	if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offset > 0) offset--;
	if (offset == lineLength && offset > 0) offset--;
	while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--;
	if (offset == 0 && Character.isDigit(line.charAt(offset))) {
		return isMirrored() ? SWT.RIGHT : SWT.LEFT;
	}
	TextLayout layout = renderer.getTextLayout(caretLine);
	int level = layout.getLevel(offset);
	renderer.disposeTextLayout(layout);
	return ((level & 1) != 0) ? SWT.RIGHT : SWT.LEFT;
}
/*
 * Returns the index of the line the caret is on.
 */
int getCaretLine() {
	return content.getLineAtOffset(caretOffset);
}
int getWrapWidth () {
	if (wordWrap && !isSingleLine()) {
		int width = clientAreaWidth - leftMargin - rightMargin;
		return width > 0 ? width : 1;
	}
	return -1;
}
int getWordNext (int offset, int movement) {
	return getWordNext(offset, movement, false);
}
int getWordNext (int offset, int movement, boolean ignoreListener) {
	int newOffset, lineOffset;
	String lineText;
	if (offset >= getCharCount()) {
		newOffset = offset;
		int lineIndex = content.getLineCount() - 1;
		lineOffset = content.getOffsetAtLine(lineIndex);
		lineText = content.getLine(lineIndex);
	} else {
		int lineIndex = content.getLineAtOffset(offset);
		lineOffset = content.getOffsetAtLine(lineIndex);
		lineText = content.getLine(lineIndex);
		int lineLength = lineText.length();
		if (offset >= lineOffset + lineLength) {
			newOffset = content.getOffsetAtLine(lineIndex + 1);
		} else {
			TextLayout layout = renderer.getTextLayout(lineIndex);
			newOffset = lineOffset + layout.getNextOffset(offset - lineOffset, movement);
			renderer.disposeTextLayout(layout);
		}
	}
	if (ignoreListener) return newOffset; 
	return sendWordBoundaryEvent(ST.WordNext, movement, offset, newOffset, lineText, lineOffset);
}
int getWordPrevious(int offset, int movement) {
	return getWordPrevious(offset, movement, false); 
}
int getWordPrevious(int offset, int movement, boolean ignoreListener) {
	int newOffset, lineOffset;
	String lineText;
	if (offset <= 0) {
		newOffset = 0;
		int lineIndex = content.getLineAtOffset(newOffset);
		lineOffset = content.getOffsetAtLine(lineIndex);
		lineText = content.getLine(lineIndex);
	} else {
		int lineIndex = content.getLineAtOffset(offset);
		lineOffset = content.getOffsetAtLine(lineIndex);
		lineText = content.getLine(lineIndex);
		if (offset == lineOffset) {
			String nextLineText = content.getLine(lineIndex - 1);
			int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); 
			newOffset = nextLineOffset + nextLineText.length();
		} else {
			int layoutOffset = Math.min(offset - lineOffset, lineText.length());
			TextLayout layout = renderer.getTextLayout(lineIndex);
			newOffset = lineOffset + layout.getPreviousOffset(layoutOffset, movement);
			renderer.disposeTextLayout(layout); 
		}
	}
	if (ignoreListener) return newOffset;
	return sendWordBoundaryEvent(ST.WordPrevious, movement, offset, newOffset, lineText, lineOffset);
}
/**
 * Returns whether the widget wraps lines.
 *
 * @return true if widget wraps lines, false otherwise
 * @since 2.0
 */
public boolean getWordWrap() {
	checkWidget();
	return wordWrap;
}
/**
 * Returns the wrap indentation of the widget.
 * 
 * @return the wrap indentation
 * 
 * @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 #getLineWrapIndent(int)
 * 
 * @since 3.6
 */
public int getWrapIndent() {
	checkWidget();
	return wrapIndent;
}
/** 
 * Returns the location of the given offset.
 * <p>
 * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts).
 * </p>
 *
 * @return location of the character at the given offset in the line.
 */
Point getPointAtOffset(int offset) {
	int lineIndex = content.getLineAtOffset(offset);
	String line = content.getLine(lineIndex);
	int lineOffset = content.getOffsetAtLine(lineIndex);
	int offsetInLine = Math.max (0, offset - lineOffset);
	int lineLength = line.length();
	if (lineIndex < content.getLineCount() - 1) {
		int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1;
		if (lineLength < offsetInLine && offsetInLine <= endLineOffset) {
			offsetInLine = lineLength;
		}
	}
	Point point;
	TextLayout layout = renderer.getTextLayout(lineIndex);
	if (lineLength != 0  && offsetInLine <= lineLength) {
		if (offsetInLine == lineLength) {
			offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); 
			point = layout.getLocation(offsetInLine, true);
		} else {
			switch (caretAlignment) {
				case OFFSET_LEADING:
					point = layout.getLocation(offsetInLine, false);
					break;
				case PREVIOUS_OFFSET_TRAILING:
				default:
					if (offsetInLine == 0) {
						point = layout.getLocation(offsetInLine, false);
					} else {
						offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER); 
						point = layout.getLocation(offsetInLine, true);
					}
					break;
			}
		}
	} else {
		point = new Point(layout.getIndent(), 0);
	}
	renderer.disposeTextLayout(layout);
	point.x += leftMargin - horizontalScrollOffset;
	point.y += getLinePixel(lineIndex);
	return point;
}
/** 
 * Inserts a string.  The old selection is replaced with the new text.  
 *
 * @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);
	}
	if (blockSelection) {
		insertBlockSelectionText(string, false); 
	} else {
		Point sel = getSelectionRange();
		replaceTextRange(sel.x, sel.y, string);
	}
}
int insertBlockSelectionText(String text, boolean fillWithSpaces) {
	int lineCount = 1;
	for (int i = 0; i < text.length(); i++) {
		char ch = text.charAt(i);
		if (ch == '\n' || ch == '\r') {
			lineCount++;
			if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
				i++;
			}
		}
	}
	String[] lines = new String[lineCount];
	int start = 0;
	lineCount = 0;
	for (int i = 0; i < text.length(); i++) {
		char ch = text.charAt(i);
		if (ch == '\n' || ch == '\r') {
			lines[lineCount++] = text.substring(start, i);
			if (ch == '\r' && i + 1 < text.length() && text.charAt(i + 1) == '\n') {
				i++;
			}
			start = i + 1;
		}
	}
	lines[lineCount++] = text.substring(start);
	if (fillWithSpaces) {
		int maxLength = 0;
		for (int i = 0; i < lines.length; i++) {
			int length = lines[i].length();
			maxLength = Math.max(maxLength, length);
		}
		for (int i = 0; i < lines.length; i++) {
			String line = lines[i];
			int length = line.length();
			if (length < maxLength) {
				int numSpaces = maxLength - length;
				StringBuffer buffer = new StringBuffer(length + numSpaces);
				buffer.append(line);
				for (int j = 0; j < numSpaces; j++) buffer.append(' ');
				lines[i] = buffer.toString();
			}
		}
	}
	int firstLine, lastLine, left, right;
	if (blockXLocation != -1) {
		Rectangle rect = getBlockSelectionPosition();
		firstLine = rect.y;
		lastLine = rect.height;
		left = rect.x;
		right = rect.width;
	} else {
		firstLine = lastLine = getCaretLine();
		left = right = getPointAtOffset(caretOffset).x;
	}
	start = caretOffset;
	int caretLine = getCaretLine();
	int index = 0, lineIndex = firstLine;
	while (lineIndex <= lastLine) {
		String string = index < lineCount ? lines[index++] : "";
		int lineStart = sendTextEvent(left, right, lineIndex, string, fillWithSpaces);
		if (lineIndex == caretLine) start = lineStart;
		lineIndex++;
	}
	while (index < lineCount) {
		int lineStart = sendTextEvent(left, left, lineIndex, lines[index++], fillWithSpaces);
		if (lineIndex == caretLine) start = lineStart;
		lineIndex++;
	}
	return start;
}
void insertBlockSelectionText(char key, int action) {
	if (key == SWT.CR || key == SWT.LF) return;
	Rectangle rect = getBlockSelectionPosition();
	int firstLine = rect.y;
	int lastLine = rect.height;
	int left = rect.x;
	int right = rect.width;
	int[] trailing = new int[1];
	int offset = 0, delta = 0;
	String text = key != 0 ? new String(new char[] {key}) : "";
	int length = text.length();
	for (int lineIndex = firstLine; lineIndex <= lastLine; lineIndex++) {
		String line = content.getLine(lineIndex);
		int lineOffset = content.getOffsetAtLine(lineIndex);
		int lineEndOffset = lineOffset + line.length();
		int linePixel = getLinePixel(lineIndex);
		int start = getOffsetAtPoint(left, linePixel, trailing, true);
		boolean outOfLine = start == -1;
		if (outOfLine) {
			start = left < leftMargin ? lineOffset : lineEndOffset;
		} else {
			start += trailing[0];
		}
		int end = getOffsetAtPoint(right, linePixel, trailing, true);
		if (end == -1) {
			end = right < leftMargin ? lineOffset : lineEndOffset; 
		} else {
			end += trailing[0];
		}
		if (start > end) {
			int temp = start;
			start = end;
			end = temp;
		}
		if (start == end && !outOfLine) {
			switch (action) {
				case ST.DELETE_PREVIOUS: 
					if (start > lineOffset) start = getClusterPrevious(start, lineIndex);
					break;
				case ST.DELETE_NEXT: 
					if (end < lineEndOffset) end = getClusterNext(end, lineIndex);
					break;
			}
		}
		if (outOfLine) {
			if (line.length() >= delta) {
				delta = line.length();
				offset = lineEndOffset + length;
			}
		} else {
			offset = start + length;
			delta = content.getCharCount();
		}
		Event event = new Event();
		event.text = text;
		event.start = start;
		event.end = end;
		sendKeyEvent(event);
	}
	int x = getPointAtOffset(offset).x;
	int verticalScrollOffset = getVerticalScrollOffset();
	setBlockSelectionLocation(x, blockYAnchor - verticalScrollOffset, x, blockYLocation - verticalScrollOffset, false);
}
/**
 * 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);
		}
	};
	content = new DefaultContent();
	content.addTextChangeListener(textChangeListener);
}
/** 
 * Adds event listeners
 */
void installListeners() {
	ScrollBar verticalBar = getVerticalBar();
	ScrollBar horizontalBar = getHorizontalBar();
	
	listener = new Listener() {
		public void handleEvent(Event event) {
			switch (event.type) {
				case SWT.Dispose: handleDispose(event); break;
				case SWT.KeyDown: handleKeyDown(event); break;
				case SWT.KeyUp: handleKeyUp(event); break;
				case SWT.MenuDetect: handleMenuDetect(event); break;
				case SWT.MouseDown: handleMouseDown(event); break;
				case SWT.MouseUp: handleMouseUp(event); break;
				case SWT.MouseMove: handleMouseMove(event); break;
				case SWT.Paint: handlePaint(event); break;
				case SWT.Resize: handleResize(event); break;
				case SWT.Traverse: handleTraverse(event); break;
			}
		}		
	};
	addListener(SWT.Dispose, listener);
	addListener(SWT.KeyDown, listener);
	addListener(SWT.KeyUp, listener);
	addListener(SWT.MenuDetect, listener);
	addListener(SWT.MouseDown, listener);
	addListener(SWT.MouseUp, listener);
	addListener(SWT.MouseMove, listener);
	addListener(SWT.Paint, listener);
	addListener(SWT.Resize, listener);
	addListener(SWT.Traverse, listener);
	ime.addListener(SWT.ImeComposition, new Listener() {
		public void handleEvent(Event event) {
			switch (event.detail) {
				case SWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
				case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
				case SWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
			}
		}
	});
	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);
			}
		});
	}
}
void internalRedrawRange(int start, int length) {
	if (length <= 0) return;
	int end = start + length;
	int startLine = content.getLineAtOffset(start);
	int endLine = content.getLineAtOffset(end);
	int partialBottomIndex = getPartialBottomIndex();
	int partialTopIndex = getPartialTopIndex();
	if (startLine > partialBottomIndex || endLine < partialTopIndex) {
		return;
	}
	if (partialTopIndex > startLine) {
		startLine = partialTopIndex;
		start = 0;
	} else {
		start -= content.getOffsetAtLine(startLine);
	}
	if (partialBottomIndex < endLine) {
		endLine = partialBottomIndex + 1;
		end = 0;
	} else {
		end -= content.getOffsetAtLine(endLine);
	}

	TextLayout layout = renderer.getTextLayout(startLine);
	int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine);
	int[] offsets = layout.getLineOffsets();
	int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length()));
	
	/* Redraw end of line before start line if wrapped and start offset is first char */
	if ((wordWrap || visualWrap) && startIndex > 0 && offsets[startIndex] == start) {
		Rectangle rect = layout.getLineBounds(startIndex - 1);
		rect.x = rect.width;
		rect.width = clientAreaWidth - rightMargin - rect.x;
		rect.x += lineX;
		rect.y += startLineY;
		super.redraw(rect.x, rect.y, rect.width, rect.height, false);
	}
	
	if (startLine == endLine) {
		int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
		if (startIndex == endIndex) {
			/* Redraw rect between start and end offset if start and end offsets are in same wrapped line */
			Rectangle rect = layout.getBounds(start, end - 1);
			rect.x += lineX;
			rect.y += startLineY;
			super.redraw(rect.x, rect.y, rect.width, rect.height, false);
			renderer.disposeTextLayout(layout);
			return;
		}
	}

	/* Redraw start line from the start offset to the end of client area */
	Rectangle startRect = layout.getBounds(start, offsets[startIndex + 1] - 1);
	if (startRect.height == 0) {
		Rectangle bounds = layout.getLineBounds(startIndex);
		startRect.x = bounds.width;
		startRect.y = bounds.y;
		startRect.height = bounds.height;
	}
	startRect.x += lineX;
	startRect.y += startLineY;
	startRect.width = clientAreaWidth - rightMargin - startRect.x;
	super.redraw(startRect.x, startRect.y, startRect.width, startRect.height, false);

	/* Redraw end line from the beginning of the line to the end offset */
	if (startLine != endLine) {
		renderer.disposeTextLayout(layout);
		layout = renderer.getTextLayout(endLine);
		offsets = layout.getLineOffsets();
	}
	int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length()));
	Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1);
	if (endRect.height == 0) {
		Rectangle bounds = layout.getLineBounds(endIndex);
		endRect.y = bounds.y;
		endRect.height = bounds.height;
	}
	endRect.x += lineX;
	endRect.y += getLinePixel(endLine);
	super.redraw(endRect.x, endRect.y, endRect.width, endRect.height, false);
	renderer.disposeTextLayout(layout);

	/* Redraw all lines in between start and end line */
	int y = startRect.y + startRect.height;
	if (endRect.y > y) {
		super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false);
	}
}
void handleCompositionOffset (Event event) {
	int[] trailing = new int [1];
	event.index = getOffsetAtPoint(event.x, event.y, trailing, true);
	event.count = trailing[0];
}
void handleCompositionSelection (Event event) {
	if (event.start != event.end) {
		int charCount = getCharCount();
		event.start = Math.max(0, Math.min(event.start, charCount));
		event.end = Math.max(0, Math.min(event.end, charCount));
		if (event.text != null) {
			setSelection(event.start, event.end);
		} else {
			event.text = getTextRange(event.start, event.end - event.start);
		}
	} else {
		event.start = selection.x;
		event.end = selection.y;
		event.text = getSelectionText();
	}
}
void handleCompositionChanged(Event event) {
	String text = event.text;
	int start = event.start;
	int end = event.end;
	int charCount = content.getCharCount();
	start = Math.min(start, charCount);
	end = Math.min(end, charCount);
	int length = text.length();
	if (length == ime.getCommitCount()) {
		content.replaceTextRange(start, end - start, "");
		setCaretOffset(ime.getCompositionOffset(), SWT.DEFAULT);
		caretWidth = 0;
		caretDirection = SWT.NULL;
	} else {
		content.replaceTextRange(start, end - start, text);
		int alignment = SWT.DEFAULT;
		if (ime.getWideCaret()) {
			start = ime.getCompositionOffset();
			int lineIndex = getCaretLine();
			int lineOffset = content.getOffsetAtLine(lineIndex);
			TextLayout layout = renderer.getTextLayout(lineIndex);	
			caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width;
			renderer.disposeTextLayout(layout);
			alignment = OFFSET_LEADING;
		}
		setCaretOffset(ime.getCaretOffset(), alignment);
	}
	showCaret();
}
/** 
 * Frees resources.
 */
void handleDispose(Event event) {
	removeListener(SWT.Dispose, listener);
	notifyListeners(SWT.Dispose, event);
	event.type = SWT.None;

	clipboard.dispose();
	if (renderer != null) {
		renderer.dispose();
		renderer = null;
	}
	if (content != null) {
		content.removeTextChangeListener(textChangeListener);
		content = null;
	}
	if (defaultCaret != null) {
		defaultCaret.dispose();
		defaultCaret = null;
	}
	if (leftCaretBitmap != null) {
		leftCaretBitmap.dispose();
		leftCaretBitmap = null;
	}
	if (rightCaretBitmap != null) {
		rightCaretBitmap.dispose();
		rightCaretBitmap = null;
	}
	if (isBidiCaret()) {
		BidiUtil.removeLanguageListener(this);
	}
	selectionBackground = null;
	selectionForeground = null;
	marginColor = null;
	textChangeListener = null;
	selection = null;
	doubleClickSelection = null;
	keyActionMap = null;
	background = null;
	foreground = null;
	clipboard = null;
	tabs = null;
}
/** 
 * Scrolls the widget horizontally.
 */
void handleHorizontalScroll(Event event) {
	int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset;
	scrollHorizontal(scrollPixel, false);
}
/**
 * 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.
 *
 * @param event keyboard event
 */
void handleKey(Event event) {
	int action;
	caretAlignment = PREVIOUS_OFFSET_TRAILING;
	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 <= 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 (IS_MAC) {
			// Ignore accelerator key combinations (we do not want to 
			// insert a character in the text in this instance).
			ignore = (event.stateMask & (SWT.COMMAND | SWT.CTRL)) != 0;
		} else {
			// Ignore accelerator 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);
			update();
		}
	} else {
		invokeAction(action);
	}
}
/**
 * If a VerifyKey listener exists, verify that the key that was entered
 * should be processed.
 *
 * @param event keyboard event
 */
void handleKeyDown(Event event) {
	if (clipboardSelection == null) {
		clipboardSelection = new Point(selection.x, selection.y);
	}
	newOrientation = SWT.NONE;
	event.stateMask &= SWT.MODIFIER_MASK;
	
	Event verifyEvent = new Event();
	verifyEvent.character = event.character;
	verifyEvent.keyCode = event.keyCode;
	verifyEvent.keyLocation = event.keyLocation;
	verifyEvent.stateMask = event.stateMask;
	verifyEvent.doit = event.doit;
	notifyListeners(ST.VerifyKey, verifyEvent);
	if (verifyEvent.doit) {
		if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL && event.keyCode == SWT.SHIFT && isBidiCaret()) {
			newOrientation = event.keyLocation == SWT.LEFT ? SWT.LEFT_TO_RIGHT : SWT.RIGHT_TO_LEFT; 
		}
		handleKey(event);
	}
}
/**
 * Update the Selection Clipboard.
 *
 * @param event keyboard event
 */
void handleKeyUp(Event event) {
	if (clipboardSelection != null) {
		if (clipboardSelection.x != selection.x || clipboardSelection.y != selection.y) {
			copySelection(DND.SELECTION_CLIPBOARD);
		}
	}
	clipboardSelection = null;
	
	if (newOrientation != SWT.NONE) {
		if (newOrientation != getOrientation()) {
			Event e = new Event();
			e.doit = true;
			notifyListeners(SWT.OrientationChange, e);
			if (e.doit) {
				setOrientation(newOrientation);
			}
		}
		newOrientation = SWT.NONE;
	}
}
/**
 * Update the event location for focus-based context menu triggers.
 *
 * @param event menu detect event
 */
void handleMenuDetect(Event event) {
	if (event.detail == SWT.MENU_KEYBOARD) {
		Point point = getDisplay().map(this, null, getPointAtOffset(caretOffset));
		event.x = point.x;
		event.y = point.y + getLineHeight(caretOffset);
	}
}
/** 
 * Updates the caret location and selection if mouse button 1 has been 
 * pressed.
 */
void handleMouseDown(Event event) {
	//force focus (object support)
	forceFocus();
		
	//drag detect
	if (dragDetect && checkDragDetect(event)) return;
		
	//paste clipboard selection
	if (event.button == 2) {
		String text = (String)getClipboardContent(DND.SELECTION_CLIPBOARD);
		if (text != null && text.length() > 0) {
			// position cursor
			doMouseLocationChange(event.x, event.y, false);
			// insert text
			Event e = new Event();
			e.start = selection.x;
			e.end = selection.y;
			e.text = getModelDelimitedText(text);
			sendKeyEvent(e);
		}
	}
	
	//set selection
	if ((event.button != 1) || (IS_MAC && (event.stateMask & SWT.MOD4) != 0)) {
		return;	
	}
	clickCount = event.count;
	if (clickCount == 1) {
		boolean select = (event.stateMask & SWT.MOD2) != 0;
		doMouseLocationChange(event.x, event.y, select);
	} else {
		if (doubleClickEnabled) {
			boolean wordSelect = (clickCount & 1) == 0;
			int offset = getOffsetAtPoint(event.x, event.y, null);
			int lineIndex = content.getLineAtOffset(offset);
			int lineOffset = content.getOffsetAtLine(lineIndex);
			if (wordSelect) {
				int min = blockSelection ? lineOffset : 0;
				int max = blockSelection ? lineOffset + content.getLine(lineIndex).length() : content.getCharCount();
				int start = Math.max(min, getWordPrevious(offset, SWT.MOVEMENT_WORD_START));
				int end = Math.min(max, getWordNext(start, SWT.MOVEMENT_WORD_END));
				setSelection(start, end - start, false, true);
				sendSelectionEvent();
			} else {
				if (blockSelection) {
					setBlockSelectionLocation(leftMargin, event.y, clientAreaWidth - rightMargin, event.y, true);
				} else {
					int lineEnd = content.getCharCount();
					if (lineIndex + 1 < content.getLineCount()) {
						lineEnd = content.getOffsetAtLine(lineIndex + 1);
					}
					setSelection(lineOffset, lineEnd - lineOffset, false, false);
					sendSelectionEvent();
				}
			}
			doubleClickSelection = new Point(selection.x, selection.y);
			showCaret();
		}
	}
}
/** 
 * Updates the caret location and selection if mouse button 1 is pressed 
 * during the mouse move.
 */
void handleMouseMove(Event event) {
	if (clickCount > 0) {
		update();
		doAutoScroll(event);
		doMouseLocationChange(event.x, event.y, true);
	} 
	if (renderer.hasLinks) {
		doMouseLinkCursor(event.x, event.y);
	}
}
/** 
 * Autoscrolling ends when the mouse button is released.
 */
void handleMouseUp(Event event) {
	clickCount = 0;
	endAutoScroll();
	if (event.button == 1) {
		copySelection(DND.SELECTION_CLIPBOARD);
	}
}
/**
 * Renders the invalidated area specified in the paint event.
 *
 * @param event paint event
 */
void handlePaint(Event event) {
	if (event.width == 0 || event.height == 0) return;
	if (clientAreaWidth == 0 || clientAreaHeight == 0) return;

	int startLine = getLineIndex(event.y);
	int y = getLinePixel(startLine);
	int endY = event.y + event.height;
	GC gc = event.gc;
	Color background = getBackground();
	Color foreground = getForeground();
	if (endY > 0) {
		int lineCount = isSingleLine() ? 1 : content.getLineCount();
		int x = leftMargin - horizontalScrollOffset;
		for (int i = startLine; y < endY && i < lineCount; i++) {
			y += renderer.drawLine(i, x, y, gc, background, foreground);
		}
		if (y < endY) {
			gc.setBackground(background);
			drawBackground(gc, 0, y, clientAreaWidth, endY - y);
		}
	}
	if (blockSelection && blockXLocation != -1) {
		gc.setBackground(getSelectionBackground());
		Rectangle rect = getBlockSelectionRectangle();
		gc.drawRectangle(rect.x, rect.y, Math.max(1, rect.width - 1), Math.max(1, rect.height - 1));
		gc.setAdvanced(true);
		if (gc.getAdvanced()) {
			gc.setAlpha(100);
			gc.fillRectangle(rect);
			gc.setAdvanced(false);
		}
	}
	
	// fill the margin background
	gc.setBackground(marginColor != null ? marginColor : background);
	if (topMargin > 0) {
		drawBackground(gc, 0, 0, clientAreaWidth, topMargin);
	}
	if (bottomMargin > 0) {
		drawBackground(gc, 0, clientAreaHeight - bottomMargin, clientAreaWidth, bottomMargin);
	}
	if (leftMargin - alignmentMargin > 0) {
		drawBackground(gc, 0, 0, leftMargin - alignmentMargin, clientAreaHeight);
	}
	if (rightMargin > 0) {
		drawBackground(gc, clientAreaWidth - rightMargin, 0, rightMargin, clientAreaHeight);
	}
}
/**
 * Recalculates the scroll bars. Rewraps all lines when in word 
 * wrap mode.
 *
 * @param event resize event
 */
void handleResize(Event event) {
	int oldHeight = clientAreaHeight;
	int oldWidth = clientAreaWidth;
	Rectangle clientArea = getClientArea();
	clientAreaHeight = clientArea.height;
	clientAreaWidth = clientArea.width;
	if (!alwaysShowScroll && ignoreResize != 0) return;
	
	redrawMargins(oldHeight, oldWidth);
	if (wordWrap) {
		if (oldWidth != clientAreaWidth) {
			renderer.reset(0, content.getLineCount());
			verticalScrollOffset = -1;
			renderer.calculateIdle();
			super.redraw();
		}
		if (oldHeight != clientAreaHeight) {
			if (oldHeight == 0) topIndexY = 0;
			setScrollBars(true);
		}
		setCaretLocation();
	} else  {
		renderer.calculateClientArea();
		setScrollBars(true);
		claimRightFreeSpace();
		// StyledText allows any value for horizontalScrollOffset when clientArea is zero
		// in setHorizontalPixel() and setHorisontalOffset(). Fixes bug 168429.
		if (clientAreaWidth != 0) {
			ScrollBar horizontalBar = getHorizontalBar();
			if (horizontalBar != null && horizontalBar.getVisible()) {
				if (horizontalScrollOffset != horizontalBar.getSelection()) {
					horizontalBar.setSelection(horizontalScrollOffset);
					horizontalScrollOffset = horizontalBar.getSelection();
				}
			}
		}
	}
	updateCaretVisibility();
	claimBottomFreeSpace();
	setAlignment();
	//TODO FIX TOP INDEX DURING RESIZE
//	if (oldHeight != clientAreaHeight || wordWrap) {
//		calculateTopIndex(0);
//	}
}
/**
 * Updates the caret position and selection and the scroll bars to reflect 
 * the content change.
 */
void handleTextChanged(TextChangedEvent event) {
	int offset = ime.getCompositionOffset();
	if (offset != -1 && lastTextChangeStart < offset) {
		ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount);
	}
	int firstLine = content.getLineAtOffset(lastTextChangeStart);
	resetCache(firstLine, 0);
	if (!isFixedLineHeight() && topIndex > firstLine) {
		topIndex = firstLine;
		topIndexY = 0;
		super.redraw();
	} else {
		int lastLine = firstLine + lastTextChangeNewLineCount;
		int firstLineTop = getLinePixel(firstLine);
		int newLastLineBottom = getLinePixel(lastLine + 1);
		if (lastLineBottom != newLastLineBottom) {
			super.redraw();
		} else {
			super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false);
			redrawLinesBullet(renderer.redrawLines);
		}
	}
	renderer.redrawLines = null;
	// 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.
	if (!(blockSelection && blockXLocation != -1)) {
		updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount);
	}
	if (lastTextChangeReplaceLineCount > 0 || wordWrap || visualWrap) {
		claimBottomFreeSpace();
	}
	if (lastTextChangeReplaceCharCount > 0) {
		claimRightFreeSpace();
	}
	
	sendAccessibleTextChanged(lastTextChangeStart, lastTextChangeNewCharCount, 0);
	lastCharCount += lastTextChangeNewCharCount;
	lastCharCount -= lastTextChangeReplaceCharCount;
	setAlignment();
}
/**
 * Updates the screen to reflect a pending content change.
 *
 * @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) {
	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;	
	int lineIndex = content.getLineAtOffset(event.start);
	int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1);
	int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight();
	lastLineBottom = destY;
	if (srcY < 0 && destY < 0) {
		lastLineBottom += srcY - destY;
		verticalScrollOffset += destY - srcY;
		calculateTopIndex(destY - srcY);
		setScrollBars(true);
	} else {
		scrollText(srcY, destY);
	}
	sendAccessibleTextChanged(lastTextChangeStart, 0, lastTextChangeReplaceCharCount);
	renderer.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) setCaretOffset(newEndOfText, SWT.DEFAULT); 
}
/**
 * Called when the widget content is set programmatically, overwriting 
 * the old content. Resets the caret position, selection and scroll offsets. 
 * Recalculates the content width and scroll bars. Redraws the widget.
 *
 * @param event text change event. 
 */
void handleTextSet(TextChangedEvent event) {
	reset();
	int newCharCount = getCharCount();
	sendAccessibleTextChanged(0, newCharCount, lastCharCount);
	lastCharCount = newCharCount;
	setAlignment();
}
/**
 * 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.
 *
 * @param event the event
 */
void handleTraverse(Event event) {
	switch (event.detail) {
		case SWT.TRAVERSE_ESCAPE:
		case SWT.TRAVERSE_PAGE_NEXT:
		case SWT.TRAVERSE_PAGE_PREVIOUS:
			event.doit = true;
			break;
		case SWT.TRAVERSE_RETURN:
		case SWT.TRAVERSE_TAB_NEXT:
		case SWT.TRAVERSE_TAB_PREVIOUS:
			if ((getStyle() & SWT.SINGLE) != 0) {
				event.doit = true;
			} else {
				if (!editable || (event.stateMask & SWT.MODIFIER_MASK) != 0) {
					event.doit = true;
				}
			}
			break;
	}
}
/** 
 * Scrolls the widget vertically.
 */
void handleVerticalScroll(Event event) {
	int scrollPixel = getVerticalBar().getSelection() - getVerticalScrollOffset();
	scrollVertical(scrollPixel, false);
}
/**
 * Add accessibility support for the widget.
 */
void initializeAccessible() {
	acc = getAccessible();

	accAdapter = new AccessibleAdapter() {
		@Override
		public void getName (AccessibleEvent e) {
			String name = null;
			String text = getAssociatedLabel ();
			if (text != null) {
				name = stripMnemonic (text);
			}
			e.result = name;
		}
		@Override
		public void getHelp(AccessibleEvent e) {
			e.result = getToolTipText();
		}
		@Override
		public void getKeyboardShortcut(AccessibleEvent e) {
			String shortcut = null;
			String text = getAssociatedLabel ();
			if (text != null) {
				char mnemonic = _findMnemonic (text);
				if (mnemonic != '\0') {
					shortcut = "Alt+"+mnemonic; //$NON-NLS-1$
				}
			}
			e.result = shortcut;
		}
	};
	acc.addAccessibleListener(accAdapter);

	accTextExtendedAdapter = new AccessibleTextExtendedAdapter() {
		@Override
		public void getCaretOffset(AccessibleTextEvent e) {
			e.offset = StyledText.this.getCaretOffset();
		}
		@Override
		public void setCaretOffset(AccessibleTextEvent e) {
			StyledText.this.setCaretOffset(e.offset);
			e.result = ACC.OK;
		}
		@Override
		public void getSelectionRange(AccessibleTextEvent e) {
			Point selection = StyledText.this.getSelectionRange();
			e.offset = selection.x;
			e.length = selection.y;
		}
		@Override
		public void addSelection(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			Point point = st.getSelection();
			if (point.x == point.y) {
				int end = e.end;
				if (end == -1) end = st.getCharCount();
				st.setSelection(e.start, end);
				e.result = ACC.OK;
			}
		}
		@Override
		public void getSelection(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			if (st.blockSelection && st.blockXLocation != -1) {
				Rectangle rect = st.getBlockSelectionPosition();
				int lineIndex = rect.y + e.index;
				int linePixel = st.getLinePixel(lineIndex);
				e.ranges = getRanges(rect.x, linePixel, rect.width, linePixel);
				if (e.ranges.length > 0) {
					e.start = e.ranges[0];
					e.end = e.ranges[e.ranges.length - 1];
				}
			} else {
				if (e.index == 0) {
					Point point = st.getSelection();
					e.start = point.x;
					e.end = point.y;
					if (e.start > e.end) {
						int temp = e.start;
						e.start = e.end;
						e.end = temp;
					}
				}
			}
		}
		@Override
		public void getSelectionCount(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			if (st.blockSelection && st.blockXLocation != -1) {
				Rectangle rect = st.getBlockSelectionPosition();
				e.count = rect.height - rect.y + 1;
			} else {
				Point point = st.getSelection();
				e.count = point.x == point.y ? 0 : 1; 
			}
		}
		@Override
		public void removeSelection(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			if (e.index == 0) {
				if (st.blockSelection) {
					st.clearBlockSelection(true, false);
				} else {
					st.clearSelection(false);
				}
				e.result = ACC.OK;
			}
		}
		@Override
		public void setSelection(AccessibleTextEvent e) {
			if (e.index != 0) return;
			StyledText st = StyledText.this;
			Point point = st.getSelection();
			if (point.x == point.y) return;
			int end = e.end;
			if (end == -1) end = st.getCharCount();
			st.setSelection(e.start, end);
			e.result = ACC.OK;
		}
		@Override
		public void getCharacterCount(AccessibleTextEvent e) {
			e.count = StyledText.this.getCharCount();
		}
		@Override
		public void getOffsetAtPoint(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			Point point = new Point (e.x, e.y);
			Display display = st.getDisplay();
			point = display.map(null, st, point);
			e.offset = st.getOffsetAtPoint(point.x, point.y, null, true);
		}
		@Override
		public void getTextBounds(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			int start = e.start;
			int end = e.end;
			int contentLength = st.getCharCount();
			start = Math.max(0, Math.min(start, contentLength));
			end = Math.max(0, Math.min(end, contentLength));
			if (start > end) {
				int temp = start;
				start = end;
				end = temp;
			}
			int startLine = st.getLineAtOffset(start);
			int endLine = st.getLineAtOffset(end);
			Rectangle[] rects = new Rectangle[endLine - startLine + 1];
			Rectangle bounds = null;
			int index = 0;
			Display display = st.getDisplay();
			for (int lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
				Rectangle rect = new Rectangle(0, 0, 0, 0);
				rect.y = st.getLinePixel(lineIndex);
				rect.height = st.renderer.getLineHeight(lineIndex);
				if (lineIndex == startLine) {
					rect.x = st.getPointAtOffset(start).x;
				} else {
					rect.x = st.leftMargin - st.horizontalScrollOffset;
				}
				if (lineIndex == endLine) {
					rect.width = st.getPointAtOffset(end).x - rect.x;
				} else {
					TextLayout layout = st.renderer.getTextLayout(lineIndex);
					rect.width = layout.getBounds().width - rect.x;
					st.renderer.disposeTextLayout(layout);
				}
				rects [index++] = rect = display.map(st, null, rect);
				if (bounds == null) {
					bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
				} else {
					bounds.add(rect);
				}
			}
			e.rectangles = rects;
			if (bounds != null) {
				e.x = bounds.x;
				e.y = bounds.y;
				e.width = bounds.width;
				e.height = bounds.height;
			}
		}
		int[] getRanges(int left, int top, int right, int bottom) {
			StyledText st = StyledText.this;
			int lineStart = st.getLineIndex(top);
			int lineEnd = st.getLineIndex(bottom);
			int count = lineEnd - lineStart + 1;
			int[] ranges = new int [count * 2];
			int index = 0;
			for (int lineIndex = lineStart; lineIndex <= lineEnd; lineIndex++) {
				String line = st.content.getLine(lineIndex);
				int lineOffset = st.content.getOffsetAtLine(lineIndex);
				int lineEndOffset = lineOffset + line.length();
				int linePixel = st.getLinePixel(lineIndex);
				int start = st.getOffsetAtPoint(left, linePixel, null, true);
				if (start == -1) {
					start = left < st.leftMargin ? lineOffset : lineEndOffset;
				}
				int[] trailing = new int[1];
				int end = st.getOffsetAtPoint(right, linePixel, trailing, true);
				if (end == -1) {
					end = right < st.leftMargin ? lineOffset : lineEndOffset; 
				} else {
					end += trailing[0];
				}
				if (start > end) {
					int temp = start;
					start = end;
					end = temp;
				}
				ranges[index++] = start;
				ranges[index++] = end;
			}
			return ranges;
		}
		@Override
		public void getRanges(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			Point point = new Point (e.x, e.y);
			Display display = st.getDisplay();
			point = display.map(null, st, point);
			e.ranges = getRanges(point.x, point.y, point.x + e.width, point.y + e.height);
			if (e.ranges.length > 0) {
				e.start = e.ranges[0];
				e.end = e.ranges[e.ranges.length - 1];
			}
		}
		@Override
		public void getText(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			int start = e.start;
			int end = e.end;
			int contentLength = st.getCharCount();
			if (end == -1) end = contentLength;
			start = Math.max(0, Math.min(start, contentLength));
			end = Math.max(0, Math.min(end, contentLength));
			if (start > end) {
				int temp = start;
				start = end;
				end = temp;
			}
			int count = e.count;
			switch (e.type) {
				case ACC.TEXT_BOUNDARY_ALL:
					//nothing to do
					break;
				case ACC.TEXT_BOUNDARY_CHAR: {
					int newCount = 0;
					if (count > 0) {
						while (count-- > 0) {
							int newEnd = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
							if (newEnd == contentLength) break;
							if (newEnd == end) break;
							end = newEnd;
							newCount++;
						}
						start = end;
						end = st.getWordNext(end, SWT.MOVEMENT_CLUSTER);
					} else {
						while (count++ < 0) {
							int newStart = st.getWordPrevious(start, SWT.MOVEMENT_CLUSTER);
							if (newStart == start) break;
							start = newStart;
							newCount--;
						}
						end = st.getWordNext(start, SWT.MOVEMENT_CLUSTER);
					}
					count = newCount;
					break;
				}
				case ACC.TEXT_BOUNDARY_WORD: {
					int newCount = 0;
					if (count > 0) {
						while (count-- > 0) { 
							int newEnd = st.getWordNext(end, SWT.MOVEMENT_WORD_START, true);
							if (newEnd == end) break;
							newCount++;
							end = newEnd;
						}
						start = end;
						end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
					} else {
						if (st.getWordPrevious(Math.min(start + 1, contentLength), SWT.MOVEMENT_WORD_START, true) == start) {
							//start is a word start already
							count++;
						}
						while (count <= 0) {
							int newStart = st.getWordPrevious(start, SWT.MOVEMENT_WORD_START, true);
							if (newStart == start) break;
							count++;
							start = newStart;
							if (count != 0) newCount--;
						}
						if (count <= 0 && start == 0) {
							end = start;
						} else {
							end = st.getWordNext(start, SWT.MOVEMENT_WORD_END, true);
						}
					}
					count = newCount;
					break;
				}
				case ACC.TEXT_BOUNDARY_LINE:
					//TODO implement line
				case ACC.TEXT_BOUNDARY_PARAGRAPH:
				case ACC.TEXT_BOUNDARY_SENTENCE: {
					int offset = count > 0 ? end : start;
					int lineIndex = st.getLineAtOffset(offset) + count;
					lineIndex = Math.max(0, Math.min(lineIndex, st.getLineCount() - 1));
					start = st.getOffsetAtLine(lineIndex);
					String line = st.getLine(lineIndex);
					end = start + line.length();
					count = lineIndex - st.getLineAtOffset(offset);
					break;
				}
			}
			e.start = start;
			e.end = end;
			e.count = count;
			e.result = st.content.getTextRange(start, end - start);
		}
		@Override
		public void getVisibleRanges(AccessibleTextEvent e) {
			e.ranges = getRanges(leftMargin, topMargin, clientAreaWidth - rightMargin, clientAreaHeight - bottomMargin);
			if (e.ranges.length > 0) {
				e.start = e.ranges[0];
				e.end = e.ranges[e.ranges.length - 1];
			}
		}
		@Override
		public void scrollText(AccessibleTextEvent e) {
			StyledText st = StyledText.this;
			int topPixel = getTopPixel(), horizontalPixel = st.getHorizontalPixel();
			switch (e.type) {
				case ACC.SCROLL_TYPE_ANYWHERE:
				case ACC.SCROLL_TYPE_TOP_LEFT:
				case ACC.SCROLL_TYPE_LEFT_EDGE:
				case ACC.SCROLL_TYPE_TOP_EDGE: {
					Rectangle rect = st.getBoundsAtOffset(e.start);
					if (e.type != ACC.SCROLL_TYPE_TOP_EDGE) {
						horizontalPixel = horizontalPixel + rect.x - st.leftMargin;
					}
					if (e.type != ACC.SCROLL_TYPE_LEFT_EDGE) {
						topPixel = topPixel + rect.y - st.topMargin;
					}
					break;
				}
				case ACC.SCROLL_TYPE_BOTTOM_RIGHT:
				case ACC.SCROLL_TYPE_BOTTOM_EDGE:
				case ACC.SCROLL_TYPE_RIGHT_EDGE: {
					Rectangle rect = st.getBoundsAtOffset(e.end - 1);
					if (e.type != ACC.SCROLL_TYPE_BOTTOM_EDGE) {
						horizontalPixel = horizontalPixel - st.clientAreaWidth + rect.x + rect.width + st.rightMargin;
					}
					if (e.type != ACC.SCROLL_TYPE_RIGHT_EDGE) {
						topPixel = topPixel - st.clientAreaHeight + rect.y +rect.height + st.bottomMargin;
					}
					break;
				}
				case ACC.SCROLL_TYPE_POINT: {
					Point point = new Point(e.x, e.y);
					Display display = st.getDisplay();
					point = display.map(null, st, point);
					Rectangle rect = st.getBoundsAtOffset(e.start);
					topPixel = topPixel - point.y + rect.y;
					horizontalPixel = horizontalPixel - point.x + rect.x;
					break;
				}
			}
			st.setTopPixel(topPixel);
			st.setHorizontalPixel(horizontalPixel);
			e.result = ACC.OK;
		}
	};
	acc.addAccessibleTextListener(accTextExtendedAdapter);

	accEditableTextListener = new AccessibleEditableTextListener() {
		public void setTextAttributes(AccessibleTextAttributeEvent e) {
			// This method must be implemented by the application
			e.result = ACC.OK;
		}
		public void replaceText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.replaceTextRange(e.start, e.end - e.start, e.string);
            e.result = ACC.OK;
		}
		public void pasteText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.setSelection(e.start);
            st.paste();
            e.result = ACC.OK;
		}
		public void cutText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.setSelection(e.start, e.end);
            st.cut();
            e.result = ACC.OK;
		}
		public void copyText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.setSelection(e.start, e.end);
            st.copy();
            e.result = ACC.OK;
		}
	};
	acc.addAccessibleEditableTextListener(accEditableTextListener);

	accAttributeAdapter = new AccessibleAttributeAdapter() {
		@Override
		public void getAttributes(AccessibleAttributeEvent e) {
			StyledText st = StyledText.this;
			e.leftMargin = st.getLeftMargin();
			e.topMargin = st.getTopMargin();
			e.rightMargin = st.getRightMargin();
			e.bottomMargin = st.getBottomMargin();
			e.tabStops = st.getTabStops();
			e.justify = st.getJustify();
			e.alignment = st.getAlignment();
			e.indent = st.getIndent(); 
		}
		@Override
		public void getTextAttributes(AccessibleTextAttributeEvent e) {
			StyledText st = StyledText.this;
			int contentLength = st.getCharCount();
			if (!isListening(ST.LineGetStyle) && st.renderer.styleCount == 0) {
				e.start = 0;
				e.end = contentLength;
				e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
				return;
			}
			int offset = Math.max(0, Math.min(e.offset, contentLength - 1));
			int lineIndex = st.getLineAtOffset(offset);
			int lineOffset = st.getOffsetAtLine(lineIndex);
			int lineCount = st.getLineCount();
			offset = offset - lineOffset;
			
			TextLayout layout = st.renderer.getTextLayout(lineIndex);
			int lineLength = layout.getText().length();
			if (lineLength > 0) {
				e.textStyle = layout.getStyle(Math.max(0, Math.min(offset, lineLength - 1)));
			}
			
			// If no override info available, use defaults. Don't supply default colors, though.
			if (e.textStyle == null) {
				e.textStyle = new TextStyle(st.getFont(), st.foreground, st.background);
			} else {
				if (e.textStyle.foreground == null || e.textStyle.background == null || e.textStyle.font == null) {
					TextStyle textStyle = new TextStyle(e.textStyle);
					if (textStyle.foreground == null) textStyle.foreground = st.foreground;
					if (textStyle.background == null) textStyle.background = st.background;
					if (textStyle.font == null) textStyle.font = st.getFont();
					e.textStyle = textStyle;
				}
			}
			
			//offset at line delimiter case
			if (offset >= lineLength) {
				e.start = lineOffset + lineLength;
				if (lineIndex + 1 < lineCount) {
					e.end = st.getOffsetAtLine(lineIndex + 1);
				} else  {
					e.end = contentLength;
				}
				return;
			}
			
			int[] ranges = layout.getRanges();
			st.renderer.disposeTextLayout(layout);
			int index = 0;
			int end = 0;
			while (index < ranges.length) {
				int styleStart = ranges[index++];
				int styleEnd = ranges[index++];
				if (styleStart <= offset && offset <= styleEnd) {
					e.start = lineOffset + styleStart;
					e.end = lineOffset + styleEnd + 1;
					return;
				}
				if (styleStart > offset) {
					e.start = lineOffset + end;
					e.end = lineOffset + styleStart;
					return;
				}
				end = styleEnd + 1;
			}
			if (index == ranges.length) {
				e.start = lineOffset + end;
				if (lineIndex + 1 < lineCount) {
					e.end = st.getOffsetAtLine(lineIndex + 1);
				} else  {
					e.end = contentLength;
				}
			}
		}
	};
	acc.addAccessibleAttributeListener(accAttributeAdapter);

	accControlAdapter = new AccessibleControlAdapter() {
		@Override
		public void getRole(AccessibleControlEvent e) {
			e.detail = ACC.ROLE_TEXT;
		}
		@Override
		public void getState(AccessibleControlEvent e) {
			int state = 0;
			if (isEnabled()) state |= ACC.STATE_FOCUSABLE;
			if (isFocusControl()) state |= ACC.STATE_FOCUSED;
			if (!isVisible()) state |= ACC.STATE_INVISIBLE;
			if (!getEditable()) state |= ACC.STATE_READONLY;
			if (isSingleLine()) state |= ACC.STATE_SINGLELINE;
			else state |= ACC.STATE_MULTILINE;
			e.detail = state;
		}
		@Override
		public void getValue(AccessibleControlEvent e) {
			e.result = StyledText.this.getText();
		}
	};
	acc.addAccessibleControlListener(accControlAdapter);

	addListener(SWT.FocusIn, new Listener() {
		public void handleEvent(Event event) {
			acc.setFocus(ACC.CHILDID_SELF);
		}
	});	
}

@Override
public void dispose() {
	/*
	 * Note: It is valid to attempt to dispose a widget more than once.
	 * Added check for this.
	 */
	if (!isDisposed()) {
		acc.removeAccessibleControlListener(accControlAdapter);
		acc.removeAccessibleAttributeListener(accAttributeAdapter);
		acc.removeAccessibleEditableTextListener(accEditableTextListener);
		acc.removeAccessibleTextListener(accTextExtendedAdapter);
		acc.removeAccessibleListener(accAdapter);
	}
	super.dispose();
}

/* 
 * Return the Label immediately preceding the receiver in the z-order, 
 * or null if none. 
 */
String getAssociatedLabel () {
	Control[] siblings = getParent ().getChildren ();
	for (int i = 0; i < siblings.length; i++) {
		if (siblings [i] == StyledText.this) {
			if (i > 0) {
				Control sibling = siblings [i-1];
				if (sibling instanceof Label) return ((Label) sibling).getText();
				if (sibling instanceof CLabel) return ((CLabel) sibling).getText();
			}
			break;
		}
	}
	return null;
}
String stripMnemonic (String string) {
	int index = 0;
	int length = string.length ();
	do {
		while ((index < length) && (string.charAt (index) != '&')) index++;
		if (++index >= length) return string;
		if (string.charAt (index) != '&') {
			return string.substring(0, index-1) + string.substring(index, length);
		}
		index++;
	} while (index < length);
 	return string;
}
/*
 * Return the lowercase of the first non-'&' character following
 * an '&' character in the given string. If there are no '&'
 * characters in the given string, return '\0'.
 */
char _findMnemonic (String string) {
	if (string == null) return '\0';
	int index = 0;
	int length = string.length ();
	do {
		while (index < length && string.charAt (index) != '&') index++;
		if (++index >= length) return '\0';
		if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
		index++;
	} while (index < length);
 	return '\0';
}
/**
 * Executes the action.
 *
 * @param action one of the actions defined in ST.java
 */
public void invokeAction(int action) {
	checkWidget();
	if (blockSelection && invokeBlockAction(action)) return;
	updateCaretDirection = true;
	switch (action) {
		// Navigation
		case ST.LINE_UP:
			doLineUp(false);
			clearSelection(true);
			break;
		case ST.LINE_DOWN:
			doLineDown(false);
			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(false, -1);
			clearSelection(true);
			break;
		case ST.PAGE_DOWN:
			doPageDown(false, -1);
			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_ALL:
			selectAll();
			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(-1);
			break;
		case ST.SELECT_PAGE_DOWN:
			doSelectionPageDown(-1);
			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;
		case ST.TOGGLE_BLOCKSELECTION:
			setBlockSelection(!blockSelection);
			break;
	}
}
/**
* Returns true if an action should not be performed when block
* selection in active  
*/
boolean invokeBlockAction(int action) {
	switch (action) {
		// Navigation
		case ST.LINE_UP:
		case ST.LINE_DOWN:
		case ST.LINE_START:
		case ST.LINE_END:
		case ST.COLUMN_PREVIOUS:
		case ST.COLUMN_NEXT:
		case ST.PAGE_UP:
		case ST.PAGE_DOWN:
		case ST.WORD_PREVIOUS:
		case ST.WORD_NEXT:
		case ST.TEXT_START:
		case ST.TEXT_END:
		case ST.WINDOW_START:
		case ST.WINDOW_END:
			clearBlockSelection(false, false);
			return false;
		// Selection
		case ST.SELECT_LINE_UP:
			doBlockLineVertical(true);
			return true;
		case ST.SELECT_LINE_DOWN:
			doBlockLineVertical(false);
			return true;
		case ST.SELECT_LINE_START:
			doBlockLineHorizontal(false);
			return true;
		case ST.SELECT_LINE_END:
			doBlockLineHorizontal(true);
			return false;
		case ST.SELECT_COLUMN_PREVIOUS:
			doBlockColumn(false);
			return true;
		case ST.SELECT_COLUMN_NEXT:
			doBlockColumn(true);
			return true;
		case ST.SELECT_WORD_PREVIOUS:
			doBlockWord(false);
			return true;
		case ST.SELECT_WORD_NEXT:
			doBlockWord(true);
			return true;
		case ST.SELECT_ALL:
			return false;
		case ST.SELECT_TEXT_START:
			doBlockContentStartEnd(false);
			break;
		case ST.SELECT_TEXT_END:
			doBlockContentStartEnd(true);
			break;
		case ST.SELECT_PAGE_UP:
		case ST.SELECT_PAGE_DOWN:
		case ST.SELECT_WINDOW_START:
		case ST.SELECT_WINDOW_END:
			//blocked actions
			return true;
		// Modification			
		case ST.CUT:
		case ST.COPY:
		case ST.PASTE:
			return false;
		case ST.DELETE_PREVIOUS:
		case ST.DELETE_NEXT:
			if (blockXLocation != -1) {
				insertBlockSelectionText((char)0, action);
				return true;
			}
			return false;
		case ST.DELETE_WORD_PREVIOUS:
		case ST.DELETE_WORD_NEXT:
			//blocked actions
			return blockXLocation != -1;
	}
	return false;
}
boolean isBidiCaret() {
	return BidiUtil.isBidiPlatform();
}
boolean isFixedLineHeight() {
	return fixedLineHeight;
}
/**
 * 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 the widget is mirrored (right oriented/right to left 
 * writing order). 
 * 
 * @return isMirrored true=the widget is right oriented, false=the widget 
 * 	is left oriented
 */
boolean isMirrored() {
	return (getStyle() & SWT.MIRRORED) != 0;
}
/**
 * Returns <code>true</code> if any text in the widget is selected,
 * and <code>false</code> otherwise.
 * 
 * @return the text selection state
 * @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 3.103
 */
public boolean isTextSelected() {
	checkWidget();
	if (blockSelection && blockXLocation != -1) {
		Rectangle rect = getBlockSelectionPosition();
		return !rect.isEmpty();
	}
	return selection.y != selection.x;
}
/**
 * Returns whether the widget can have only one line.
 *
 * @return true if widget can have only one line, false if widget can have 
 * 	multiple lines
 */
boolean isSingleLine() {
	return (getStyle() & SWT.SINGLE) != 0;
}
/**
 * Sends the specified verify event, replace/insert text as defined by 
 * the event and send a modify event.
 *
 * @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;
		if (isListening(ST.ExtendedModify)) {
			styledTextEvent = new StyledTextEvent(content);
			styledTextEvent.start = event.start;
			styledTextEvent.end = event.start + event.text.length();
			styledTextEvent.text = content.getTextRange(event.start, replacedLength);
		}
		if (updateCaret) {
			//Fix advancing flag for delete/backspace key on direction boundary
			if (event.text.length() == 0) {
				int lineIndex = content.getLineAtOffset(event.start);
				int lineOffset = content.getOffsetAtLine(lineIndex);
				TextLayout layout = renderer.getTextLayout(lineIndex);
				int levelStart = layout.getLevel(event.start - lineOffset);
				int lineIndexEnd = content.getLineAtOffset(event.end);
				if (lineIndex != lineIndexEnd) {
					renderer.disposeTextLayout(layout);
					lineOffset = content.getOffsetAtLine(lineIndexEnd);
					layout = renderer.getTextLayout(lineIndexEnd);
				}
				int levelEnd = layout.getLevel(event.end - lineOffset);
				renderer.disposeTextLayout(layout);
				if (levelStart != levelEnd) {
					caretAlignment = PREVIOUS_OFFSET_TRAILING;
				} else {
					caretAlignment = OFFSET_LEADING;
				}
			}
		}
		content.replaceTextRange(event.start, replacedLength, event.text);
		// set the caret position prior to sending the modify event.
		// fixes 1GBB8NJ
		if (updateCaret && !(blockSelection && blockXLocation != -1)) {
			// always update the caret location. fixes 1G8FODP
			setSelection(event.start + event.text.length(), 0, true, false);
			showCaret();
		}
		notifyListeners(SWT.Modify, event);
		if (isListening(ST.ExtendedModify)) {
			notifyListeners(ST.ExtendedModify, styledTextEvent);
		}
	}
}
void paintObject(GC gc, int x, int y, int ascent, int descent, StyleRange style, Bullet bullet, int bulletIndex) {
	if (isListening(ST.PaintObject)) {
		StyledTextEvent event = new StyledTextEvent (content) ;
		event.gc = gc;
		event.x = x;
		event.y = y;
		event.ascent = ascent;
		event.descent = descent;
		event.style = style;
		event.bullet = bullet;
		event.bulletIndex = bulletIndex;
		notifyListeners(ST.PaintObject, event);
	}
}
/** 
 * Replaces the selection with the text on the <code>DND.CLIPBOARD</code>  
 * clipboard  or, if there is no selection,  inserts the text at the current 
 * caret offset.   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.
 *
 * @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();	
	String text = (String) getClipboardContent(DND.CLIPBOARD);
	if (text != null && text.length() > 0) {
		if (blockSelection) {
			boolean fillWithSpaces = isFixedLineHeight() && renderer.fixedPitch;
			int offset = insertBlockSelectionText(text, fillWithSpaces);
			setCaretOffset(offset, SWT.DEFAULT);
			clearBlockSelection(true, true);
			setCaretLocation();
			return;
		}
		Event event = new Event();
		event.start = selection.x;
		event.end = selection.y;
		String delimitedText = getModelDelimitedText(text);
		if (textLimit > 0) {
			int uneditedTextLength = getCharCount() - (selection.y - selection.x);
			if ((uneditedTextLength + delimitedText.length()) > textLimit) {
				int endIndex = textLimit - uneditedTextLength;
				delimitedText = delimitedText.substring(0, Math.max(endIndex, 0));
			}
		}
		event.text = delimitedText;
		sendKeyEvent(event);
	}
}
/** 
 * 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
 *
 * @return a <code>Runnable</code> for printing the receiver's 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_NULL_ARGUMENT when printer is null</li>
 * </ul>
 */
public Runnable print(Printer printer) {
	checkWidget();	
	if (printer == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	StyledTextPrintOptions options = new StyledTextPrintOptions();
	options.printTextForeground = true;
	options.printTextBackground = true;
	options.printTextFontStyle = true;
	options.printLineBackground = true;
	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
 *
 * @return a <code>Runnable</code> for printing the receiver's 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_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()
 */
@Override
public void redraw() {
	super.redraw();
	int itemCount = getPartialBottomIndex() - topIndex + 1;
	renderer.reset(topIndex, itemCount);
	renderer.calculate(topIndex, itemCount);
	setScrollBars(false);
	doMouseLinkCursor();
}
/**
 * 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()
 */
@Override
public void redraw(int x, int y, int width, int height, boolean all) {
	super.redraw(x, y, width, height, all);
	if (height > 0) {
		int firstLine = getLineIndex(y);
		int lastLine = getLineIndex(y + height);
		resetCache(firstLine, lastLine - firstLine + 1);
		doMouseLinkCursor();
	}
}
void redrawLines(int startLine, int lineCount, boolean bottomChanged) {
	// do nothing if redraw range is completely invisible
	int endLine = startLine + lineCount - 1;
	int partialBottomIndex = getPartialBottomIndex();
	int partialTopIndex = getPartialTopIndex();
	if (startLine > partialBottomIndex || endLine < partialTopIndex) {
		return;
	}
	// only redraw visible lines
	if (startLine < partialTopIndex) {
		startLine = partialTopIndex;
	}
	if (endLine > partialBottomIndex) {
		endLine = partialBottomIndex;
	}
	int redrawTop = getLinePixel(startLine);
	int redrawBottom = getLinePixel(endLine + 1);
	if (bottomChanged) redrawBottom = clientAreaHeight - bottomMargin;
	int redrawWidth = clientAreaWidth - leftMargin - rightMargin; 
	super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true);
}
void redrawLinesBullet (int[] redrawLines) {
	if (redrawLines == null) return;
	int topIndex = getPartialTopIndex();
	int bottomIndex = getPartialBottomIndex();
	for (int i = 0; i < redrawLines.length; i++) {
		int lineIndex = redrawLines[i];
		if (!(topIndex <= lineIndex && lineIndex <= bottomIndex)) continue;
		int width = -1;
		Bullet bullet = renderer.getLineBullet(lineIndex, null);
		if (bullet != null) {
			StyleRange style = bullet.style;
			GlyphMetrics metrics = style.metrics;
			width = metrics.width;
		}
		if (width == -1) width = getClientArea().width;
		int height = renderer.getLineHeight(lineIndex);
		int y = getLinePixel(lineIndex);
		super.redraw(0, y, width, height, false);
	}
}
void redrawMargins(int oldHeight, int oldWidth) {
	/* Redraw the old or new right/bottom margin if needed */
	if (oldWidth != clientAreaWidth) {
		if (rightMargin > 0) {
			int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; 
			super.redraw(x, 0, rightMargin, oldHeight, false);
		}
	}
	if (oldHeight != clientAreaHeight) {
		if (bottomMargin > 0) {
			int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; 
			super.redraw(0, y, oldWidth, bottomMargin, false);
		}
	}
}
/** 
 * Redraws the specified text range.
 *
 * @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();
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	int firstLine = content.getLineAtOffset(start);
	int lastLine = content.getLineAtOffset(end);
	resetCache(firstLine, lastLine - firstLine + 1);
	internalRedrawRange(start, length);
	doMouseLinkCursor();
}
/**
 * Removes the specified bidirectional segment listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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(ST.LineGetSegments, listener);	
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}
/**
 * Removes the specified caret listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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 3.5
 */
public void removeCaretListener(CaretListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(ST.CaretMoved, listener);
}
/**
 * Removes the specified extended modify listener.
 *
 * @param extendedModifyListener the listener which should no longer be notified
 *
 * @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(ST.ExtendedModify, extendedModifyListener);	
}
/**
 * Removes the specified line background listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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(ST.LineGetBackground, listener);
}
/**
 * Removes the specified line style listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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(ST.LineGetStyle, listener);
	setCaretLocation();
}
/**
 * Removes the specified modify listener.
 *
 * @param modifyListener the listener which should no longer be notified
 * 
 * @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 listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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 3.2
 */
public void removePaintObjectListener(PaintObjectListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(ST.PaintObject, listener);
}
/**
 * Removes the listener from the collection of listeners who will
 * be notified when the user changes the receiver's selection.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</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>
 *
 * @see SelectionListener
 * @see #addSelectionListener
 */
public void removeSelectionListener(SelectionListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(SWT.Selection, listener);
}
/**
 * Removes the specified verify listener.
 *
 * @param verifyListener the listener which should no longer be notified
 * 
 * @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.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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(ST.VerifyKey, listener);
}
/**
 * Removes the specified word movement listener.
 *
 * @param listener the listener which should no longer be notified
 * 
 * @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 MovementEvent
 * @see MovementListener
 * @see #addWordMovementListener
 * 
 * @since 3.3
 */

public void removeWordMovementListener(MovementListener listener) {
	checkWidget();
	if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	removeListener(ST.WordNext, listener);	
	removeListener(ST.WordPrevious, 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>
 * Note: Because a StyleRange includes the start and length, the
 * same instance cannot occur multiple times in the array of styles.
 * If the same style attributes, such as font and color, occur in
 * multiple StyleRanges, <code>setStyleRanges(int, int, int[], StyleRange[])</code>
 * can be used to share styles and reduce memory usage.
 * </p><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 ranges is null</li>
 * </ul>
 * 
 * @since 2.0
 * 
 * @see #setStyleRanges(int, int, int[], StyleRange[])
 */
public void replaceStyleRanges(int start, int length, StyleRange[] ranges) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
 	if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	setStyleRanges(start, length, null, ranges, false);
}
/**
 * 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();
	if (text == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	int contentLength = getCharCount();
	int end = start + length;
	if (start > end || start < 0 || end > contentLength) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	Event event = new Event();
	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();
	setCaretOffset(0, SWT.DEFAULT);
	topIndex = 0;
	topIndexY = 0;
	verticalScrollOffset = 0;
	horizontalScrollOffset = 0;
	resetSelection();
	renderer.setContent(content);
	if (verticalBar != null) {
		verticalBar.setSelection(0);
	}
	if (horizontalBar != null) {
		horizontalBar.setSelection(0);	
	}
	resetCache(0, 0);
	setCaretLocation();
	super.redraw();
}
void resetBidiData() {
	caretDirection = SWT.NULL;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	keyActionMap.clear();
	createKeyBindings();
	super.redraw();
}
void resetCache(int firstLine, int count) {
	int maxLineIndex = renderer.maxWidthLineIndex;
	renderer.reset(firstLine, count);
	renderer.calculateClientArea();
	if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
		renderer.calculate(maxLineIndex, 1);
	}
	setScrollBars(true);
	if (!isFixedLineHeight()) {
		if (topIndex > firstLine) {
			verticalScrollOffset = -1;
		}
		renderer.calculateIdle();
	}
}
/**
 * Resets the selection.
 */
void resetSelection() {
	selection.x = selection.y = caretOffset;
	selectionAnchor = -1;
	sendAccessibleTextCaretMoved();
}

@Override
public void scroll(int destX, int destY, int x, int y, int width, int height, boolean all) {
	super.scroll(destX, destY, x, y, width, height, false);
	if (all) {
		int deltaX = destX - x, deltaY = destY - y;
		Control[] children = getChildren();
		for (int i=0; i<children.length; i++) {
			Control child = children[i];
			Rectangle rect = child.getBounds();
			child.setLocation(rect.x + deltaX, rect.y + deltaY);
		}
	}
}

/**
 * Scrolls the widget horizontally.
 *
 * @param pixels number of pixels to scroll, > 0 = scroll left,
 * 	< 0 scroll right
 * @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 scrollHorizontal(int pixels, boolean adjustScrollBar) {
	if (pixels == 0) return false;
	if (wordWrap) return false;
	ScrollBar horizontalBar = getHorizontalBar();
	if (horizontalBar != null && adjustScrollBar) {
		horizontalBar.setSelection(horizontalScrollOffset + pixels);
	}
	int scrollHeight = clientAreaHeight - topMargin - bottomMargin;
	if (pixels > 0) {
		int sourceX = leftMargin + pixels;
		int scrollWidth = clientAreaWidth - sourceX - rightMargin;
		if (scrollWidth > 0) {
			scroll(leftMargin, topMargin, sourceX, topMargin, scrollWidth, scrollHeight, true);
		}
		if (sourceX > scrollWidth) {
			super.redraw(leftMargin + scrollWidth, topMargin, pixels - scrollWidth, scrollHeight, true);
		}
	} else {
		int destinationX = leftMargin - pixels;
		int scrollWidth = clientAreaWidth - destinationX - rightMargin;
		if (scrollWidth > 0) {
			scroll(destinationX, topMargin, leftMargin, topMargin, scrollWidth, scrollHeight, true);
		}
		if (destinationX > scrollWidth) {
			super.redraw(leftMargin + scrollWidth, topMargin, -pixels - scrollWidth, scrollHeight, true);
		}
	}
	horizontalScrollOffset += pixels;
	setCaretLocation();
	return true;
}
/**
 * Scrolls the widget vertically.
 *
 * @param pixel 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
 */
boolean scrollVertical(int pixels, boolean adjustScrollBar) {
	if (pixels == 0) {
		return false;
	}
	if (verticalScrollOffset != -1) {
		ScrollBar verticalBar = getVerticalBar();
		if (verticalBar != null && adjustScrollBar) {
			verticalBar.setSelection(verticalScrollOffset + pixels);
		}
		int scrollWidth = clientAreaWidth - leftMargin - rightMargin;
		if (pixels > 0) {
			int sourceY = topMargin + pixels;
			int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
			if (scrollHeight > 0) {
				scroll(leftMargin, topMargin, leftMargin, sourceY, scrollWidth, scrollHeight, true);
			}
			if (sourceY > scrollHeight) {
				int redrawY = Math.max(0, topMargin + scrollHeight);
				int redrawHeight = Math.min(clientAreaHeight, pixels - scrollHeight);
				super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
			}
		} else {
			int destinationY = topMargin - pixels;
			int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
			if (scrollHeight > 0) {
				scroll(leftMargin, destinationY, leftMargin, topMargin, scrollWidth, scrollHeight, true);
			}
			if (destinationY > scrollHeight) {
				int redrawY = Math.max(0, topMargin + scrollHeight);
				int redrawHeight = Math.min(clientAreaHeight, -pixels - scrollHeight);
				super.redraw(leftMargin, redrawY, scrollWidth, redrawHeight, true);
			}
		}
		verticalScrollOffset += pixels;
		calculateTopIndex(pixels);
	} else {
		calculateTopIndex(pixels);
		super.redraw();
	}
	setCaretLocation();
	return true;
}
void scrollText(int srcY, int destY) {
	if (srcY == destY) return;
	int deltaY = destY - srcY;
	int scrollWidth = clientAreaWidth - leftMargin - rightMargin, scrollHeight;
	if (deltaY > 0) {
		scrollHeight = clientAreaHeight - srcY - bottomMargin;
	} else {
		scrollHeight = clientAreaHeight - destY - bottomMargin;
	}
	scroll(leftMargin, destY, leftMargin, srcY, scrollWidth, scrollHeight, true);
	if ((0 < srcY + scrollHeight) && (topMargin > srcY)) {
		super.redraw(leftMargin, deltaY, scrollWidth, topMargin, false);
	}
	if ((0 < destY + scrollHeight) && (topMargin > destY)) {
		super.redraw(leftMargin, 0, scrollWidth, topMargin, false);
	}
	if ((clientAreaHeight - bottomMargin < srcY + scrollHeight) && (clientAreaHeight > srcY)) {
		super.redraw(leftMargin, clientAreaHeight - bottomMargin + deltaY, scrollWidth, bottomMargin, false);
	}
	if ((clientAreaHeight - bottomMargin < destY + scrollHeight) && (clientAreaHeight > destY)) {
		super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false);
	}
}
void sendAccessibleTextCaretMoved() {
	if (caretOffset != accCaretOffset) {
		accCaretOffset = caretOffset;
		getAccessible().textCaretMoved(caretOffset);
	}
}
void sendAccessibleTextChanged(int start, int newCharCount, int replaceCharCount) {
	Accessible accessible = getAccessible();
	if (replaceCharCount != 0) {
		accessible.textChanged(ACC.TEXT_DELETE, start, replaceCharCount);
	}
	if (newCharCount != 0) {
		accessible.textChanged(ACC.TEXT_INSERT, start, newCharCount);
	}
}
/** 
 * Selects all 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 void selectAll() {
	checkWidget();
	if (blockSelection) {
		renderer.calculate(0, content.getLineCount());
		setScrollBars(false);
		int verticalScrollOffset = getVerticalScrollOffset();
		int left = leftMargin - horizontalScrollOffset;
		int top = topMargin - verticalScrollOffset;
		int right = renderer.getWidth() - rightMargin - horizontalScrollOffset;
		int bottom = renderer.getHeight() - bottomMargin - verticalScrollOffset;
		setBlockSelectionLocation(left, top, right, bottom, false);
		return;
	}
	setSelection(0, Math.max(getCharCount(),0));
}
/**
 * Replaces/inserts text as defined by the event.
 *
 * @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) {
		modifyContent(event, true);
	}
}
/**
 * Returns a StyledTextEvent that can be used to request data such 
 * as styles and background color for a line.
 * <p>
 * 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 visual line 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(content);
		event.detail = lineOffset;
		event.text = line;
		event.alignment = alignment;
		event.indent = indent;
		event.wrapIndent = wrapIndent;
		event.justify = justify;
		notifyListeners(eventType, event);
	}
	return event;
}
/**
 * Sends the specified selection event.
 */
void sendSelectionEvent() {
	getAccessible().textSelectionChanged();
	Event event = new Event();
	event.x = selection.x;
	event.y = selection.y;
	notifyListeners(SWT.Selection, event);
}
int sendTextEvent(int left, int right, int lineIndex, String text, boolean fillWithSpaces) {
	int lineWidth = 0, start, end;
	StringBuffer buffer = new StringBuffer();
	if (lineIndex < content.getLineCount()) {
		int[] trailing = new int[1];
		start = getOffsetAtPoint(left, getLinePixel(lineIndex), trailing, true);
		if (start == -1) {
			int lineOffset = content.getOffsetAtLine(lineIndex);
			int lineLegth = content.getLine(lineIndex).length();
			start = end = lineOffset + lineLegth;
			if (fillWithSpaces) {
				TextLayout layout = renderer.getTextLayout(lineIndex);
				lineWidth = layout.getBounds().width;
				renderer.disposeTextLayout(layout);
			}
		} else {
			start += trailing[0];
			end = left == right ? start : getOffsetAtPoint(right, 0, lineIndex, null);
			fillWithSpaces = false;
		}
	} else {
		start = end = content.getCharCount();
		buffer.append(content.getLineDelimiter());
	}
	if (start > end) {
		int temp = start;
		start = end;
		end = temp;
	}
	if (fillWithSpaces) {
		int spacesWidth = left - lineWidth + horizontalScrollOffset - leftMargin;
		int spacesCount = spacesWidth / renderer.averageCharWidth;
		for (int i = 0; i < spacesCount; i++) {
			buffer.append(' ');
		}
	}
	buffer.append(text);
	Event event = new Event();
	event.start = start;
	event.end = end;
	event.text = buffer.toString();
	sendKeyEvent(event);
	return event.start + event.text.length();
}
int sendWordBoundaryEvent(int eventType, int movement, int offset, int newOffset, String lineText, int lineOffset) {
	if (isListening(eventType)) {
		StyledTextEvent event = new StyledTextEvent(content);
		event.detail = lineOffset;
		event.text = lineText;
		event.count = movement;
		event.start = offset;
		event.end = newOffset;
		notifyListeners(eventType, event);
		offset = event.end;
		if (offset != newOffset) {
			int length = getCharCount();
			if (offset < 0) {
				offset = 0;
			} else if (offset > length) {
				offset = length;
			} else {
				if (isLineDelimiter(offset)) {
					SWT.error(SWT.ERROR_INVALID_ARGUMENT);
				}
			}
		}
		return offset;
	}
	return newOffset;
}
void setAlignment() {
	if ((getStyle() & SWT.SINGLE) == 0) return;
	int alignment = renderer.getLineAlignment(0, this.alignment);
	int newAlignmentMargin = 0;
	if (alignment != SWT.LEFT) {
		renderer.calculate(0, 1);
		int width = renderer.getWidth() - alignmentMargin;
		newAlignmentMargin = clientAreaWidth - width;
		if (newAlignmentMargin < 0) newAlignmentMargin = 0;
		if (alignment == SWT.CENTER) newAlignmentMargin /= 2;
	}
	if (alignmentMargin != newAlignmentMargin) {
		leftMargin -= alignmentMargin;
		leftMargin += newAlignmentMargin;
		alignmentMargin = newAlignmentMargin;
		resetCache(0, 1);
		setCaretLocation();
		super.redraw();
	}
}
/**
 * Sets the alignment of the widget. The argument should be one of <code>SWT.LEFT</code>, 
 * <code>SWT.CENTER</code> or <code>SWT.RIGHT</code>. The alignment applies for all lines.
 * </p><p>
 * Note that if <code>SWT.MULTI</code> is set, then <code>SWT.WRAP</code> must also be set
 * in order to stabilize the right edge before setting alignment.
 * </p>
 * 
 * @param alignment the new alignment
 *  
 * @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 #setLineAlignment(int, int, int)
 *  
 * @since 3.2
 */
public void setAlignment(int alignment) {
	checkWidget();
	alignment &= (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
	if (alignment == 0 || this.alignment == alignment) return;
	this.alignment = alignment;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	setAlignment();
	super.redraw();
}
/**
 * Set the Always Show Scrollbars flag.  True if the scrollbars are 
 * always shown even if they are not required (default value).  False if the scrollbars are only 
 * visible when some part of the content needs to be scrolled to be seen.
 * The H_SCROLL and V_SCROLL style bits are also required to enable scrollbars in the 
 * horizontal and vertical directions.
 * 
 * @param show true to show the scrollbars even when not required, false to show scrollbars only when required
 * 
 * @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 3.8
 */
public void setAlwaysShowScrollBars(boolean show) {
	checkWidget();
	if (show == alwaysShowScroll) return;
	alwaysShowScroll = show;
	setScrollBars(true);
}
/**
 * @see Control#setBackground(Color)
 */
@Override
public void setBackground(Color color) {
	checkWidget();
	background = color;
	super.setBackground(color);
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}
/**
 * Sets the block selection mode.
 *
 * @param blockSelection true=enable block selection, false=disable block selection
 * 
 * @since 3.5
 */
public void setBlockSelection(boolean blockSelection) {
	checkWidget();
	if ((getStyle() & SWT.SINGLE) != 0) return;
	if (blockSelection == this.blockSelection) return;
	if (wordWrap) return;
	this.blockSelection = blockSelection;
	if (cursor == null) {
		Display display = getDisplay();
		int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; 
		super.setCursor(display.getSystemCursor(type));
	}
	if (blockSelection) {
		int start = selection.x;
		int end = selection.y;
		if (start != end) {
			setBlockSelectionOffset(start, end, false);
		}
	} else {
		clearBlockSelection(false, false);
	}
}
/**
 * Sets the block selection bounds. The bounds is 
 * relative to the upper left corner of the document.
 *  
 * @param rect the new bounds for the block selection
 * 
 * @see #setBlockSelectionBounds(int, int, 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>
 * </ul>
 * 
 * @since 3.5
 */
public void setBlockSelectionBounds(Rectangle rect) {
	checkWidget();
	if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	setBlockSelectionBounds(rect.x, rect.y, rect.width, rect.height);
}
/**
 * Sets the block selection bounds. The bounds is 
 * relative to the upper left corner of the document.
 * 
 * @param x the new x coordinate for the block selection
 * @param y the new y coordinate for the block selection
 * @param width the new width for the block selection
 * @param height the new height for the block 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>
 * 
 * @since 3.5
 */
public void setBlockSelectionBounds(int x, int y, int width, int height) {
	checkWidget();
	int verticalScrollOffset = getVerticalScrollOffset();
	if (!blockSelection) {
		x -= horizontalScrollOffset;
		y -= verticalScrollOffset; 
		int start = getOffsetAtPoint(x, y, null);
		int end = getOffsetAtPoint(x+width-1, y+height-1, null);
		setSelection(start, end - start, false, false);
		setCaretLocation();
		return;
	}
	int minY = topMargin;
	int minX = leftMargin;
	int maxY = renderer.getHeight() - bottomMargin;
	int maxX = Math.max(clientAreaWidth, renderer.getWidth()) - rightMargin;
	int anchorX = Math.max(minX, Math.min(maxX, x)) - horizontalScrollOffset;
	int anchorY = Math.max(minY, Math.min(maxY, y)) - verticalScrollOffset;
	int locationX = Math.max(minX, Math.min(maxX, x + width)) - horizontalScrollOffset;
	int locationY = Math.max(minY, Math.min(maxY, y + height - 1)) - verticalScrollOffset;
	if (isFixedLineHeight() && renderer.fixedPitch) {
		int avg = renderer.averageCharWidth; 
		anchorX = ((anchorX - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
		locationX = ((locationX + avg / 2 - leftMargin + horizontalScrollOffset) / avg * avg) + leftMargin - horizontalScrollOffset;
	}
	setBlockSelectionLocation(anchorX, anchorY, locationX, locationY, false);
}
void setBlockSelectionLocation (int x, int y, boolean sendEvent) {
	int verticalScrollOffset = getVerticalScrollOffset();
	blockXLocation = x + horizontalScrollOffset;
	blockYLocation = y + verticalScrollOffset;
	int[] alignment = new int[1];
	int offset = getOffsetAtPoint(x, y, alignment);
	setCaretOffset(offset, alignment[0]);
	if (blockXAnchor == -1) {
		blockXAnchor = blockXLocation;
		blockYAnchor = blockYLocation;
		selectionAnchor = caretOffset;
	}
	doBlockSelection(sendEvent);
}
void setBlockSelectionLocation (int anchorX, int anchorY, int x, int y, boolean sendEvent) {
	int verticalScrollOffset = getVerticalScrollOffset();
	blockXAnchor = anchorX + horizontalScrollOffset;
	blockYAnchor = anchorY + verticalScrollOffset;
	selectionAnchor = getOffsetAtPoint(anchorX, anchorY, null);
	setBlockSelectionLocation(x, y, sendEvent);
}
void setBlockSelectionOffset (int offset, boolean sendEvent) {
	Point point = getPointAtOffset(offset);
	int verticalScrollOffset = getVerticalScrollOffset();
	blockXLocation = point.x + horizontalScrollOffset;
	blockYLocation = point.y + verticalScrollOffset;
	setCaretOffset(offset, SWT.DEFAULT);
	if (blockXAnchor == -1) {
		blockXAnchor = blockXLocation;
		blockYAnchor = blockYLocation;
		selectionAnchor = caretOffset;
	}
	doBlockSelection(sendEvent);
}
void setBlockSelectionOffset (int anchorOffset, int offset, boolean sendEvent) {
	int verticalScrollOffset = getVerticalScrollOffset();
	Point anchorPoint = getPointAtOffset(anchorOffset);
	blockXAnchor = anchorPoint.x + horizontalScrollOffset;
	blockYAnchor = anchorPoint.y + verticalScrollOffset;
	selectionAnchor = anchorOffset;
	setBlockSelectionOffset(offset, sendEvent);
}
/**
 * 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>
 */
@Override
public void setCaret(Caret caret) {
	checkWidget ();
	super.setCaret(caret);
	caretDirection = SWT.NULL;
	if (caret != null) {
		setCaretLocation();
	}
}
/**
 * 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>
 * 
 * @deprecated use BidiSegmentListener instead.
 */
@Deprecated
public void setBidiColoring(boolean mode) {
	checkWidget();
	bidiColoring = mode;
}
/** 
 * Sets the bottom margin.
 * 
 * @param bottomMargin the bottom margin.
 * @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 3.5
 */
public void setBottomMargin (int bottomMargin) {
	checkWidget();
	setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
}
/**
 * Moves the Caret to the current caret offset.
 */
void setCaretLocation() {
	Point newCaretPos = getPointAtOffset(caretOffset);
	setCaretLocation(newCaretPos, getCaretDirection());
}
void setCaretLocation(Point location, int direction) {
	Caret caret = getCaret();
	if (caret != null) {
		boolean isDefaultCaret = caret == defaultCaret;
		int lineHeight = renderer.getLineHeight();
		int caretHeight = lineHeight;
		if (!isFixedLineHeight() && isDefaultCaret) {
			caretHeight = getBoundsAtOffset(caretOffset).height;
			if (caretHeight != lineHeight) {
				direction = SWT.DEFAULT;
			}
		}
		int imageDirection = direction;
		if (isMirrored()) {
			if (imageDirection == SWT.LEFT) {
				imageDirection = SWT.RIGHT;
			} else if (imageDirection == SWT.RIGHT) {
				imageDirection = SWT.LEFT;
			}
		}
		if (isDefaultCaret && imageDirection == SWT.RIGHT) {
			location.x -= (caret.getSize().x - 1);
		}
		if (isDefaultCaret) {
			caret.setBounds(location.x, location.y, caretWidth, caretHeight);
		} else {
			caret.setLocation(location);
		}
		if (direction != caretDirection) {
			caretDirection = direction;
			if (isDefaultCaret) {
				if (imageDirection == SWT.DEFAULT) {
					defaultCaret.setImage(null);
				} else if (imageDirection == SWT.LEFT) {
					defaultCaret.setImage(leftCaretBitmap);
				} else if (imageDirection == SWT.RIGHT) {
					defaultCaret.setImage(rightCaretBitmap);
				}
			}
			if (caretDirection == SWT.LEFT) {
				BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_NON_BIDI);
			} else if (caretDirection == SWT.RIGHT) {
				BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
			}
		}
		updateCaretVisibility();
	}
	columnX = location.x;
}
/**
 * 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 the offset 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) {
			offset = 0;
		} else if (offset > length) {
			offset = 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);
			}
		}
		setCaretOffset(offset, PREVIOUS_OFFSET_TRAILING);
		// clear the selection if the caret is moved.
		// don't notify listeners about the selection change.
		if (blockSelection) {
			clearBlockSelection(true, false);
		} else {
			clearSelection(false);
		}
	}
	setCaretLocation();
}
void setCaretOffset(int offset, int alignment) {
	if (caretOffset != offset) {
		caretOffset = offset;
		if (isListening(ST.CaretMoved)) {
			StyledTextEvent event = new StyledTextEvent(content);
			event.end = caretOffset;
			notifyListeners(ST.CaretMoved, event);
		}
	}
	if (alignment != SWT.DEFAULT) {
		caretAlignment = alignment;
	}
}
/**
 * Copies the specified text range to the clipboard.  The text will be placed
 * in the clipboard in plain text format and RTF format.
 *
 * @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, int clipboardType) throws SWTError {
	if (clipboardType == DND.SELECTION_CLIPBOARD && !IS_GTK) return;
	TextTransfer plainTextTransfer = TextTransfer.getInstance();
	TextWriter plainTextWriter = new TextWriter(start, length);
	String plainText = getPlatformDelimitedText(plainTextWriter);
	Object[] data;
	Transfer[] types;
	if (clipboardType == DND.SELECTION_CLIPBOARD) {
		data = new Object[]{plainText};
		types = new Transfer[]{plainTextTransfer};
	} else {
		RTFTransfer rtfTransfer = RTFTransfer.getInstance();
		RTFWriter rtfWriter = new RTFWriter(start, length);
		String rtfText = getPlatformDelimitedText(rtfWriter);
		data = new Object[]{rtfText, plainText};
		types = new Transfer[]{rtfTransfer, plainTextTransfer};
	}
	clipboard.setContents(data, types, clipboardType);
}
/**
 * Sets the content implementation to use for text storage.
 *
 * @param newContent 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);
	}
	content = newContent;
	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 Control#setCursor(Cursor)
 */
@Override
public void setCursor (Cursor cursor) {
	checkWidget();
	if (cursor != null && cursor.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	this.cursor = cursor;
	if (cursor == null) {
		Display display = getDisplay();
		int type = blockSelection ? SWT.CURSOR_CROSS : SWT.CURSOR_IBEAM; 
		super.setCursor(display.getSystemCursor(type));
	} 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;
}
@Override
public void setDragDetect (boolean dragDetect) {
	checkWidget ();
	this.dragDetect = dragDetect;
}
/**
 * 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>
 */
@Override
public void setFont(Font font) {
	checkWidget();
	int oldLineHeight = renderer.getLineHeight();
	super.setFont(font);	
	renderer.setFont(getFont(), tabLength);
	// keep the same top line visible. fixes 5815
	if (isFixedLineHeight()) {
		int lineHeight = renderer.getLineHeight();
		if (lineHeight != oldLineHeight) {
			int vscroll = (getVerticalScrollOffset() * lineHeight / oldLineHeight) - getVerticalScrollOffset();
			scrollVertical(vscroll, true);
		}
	}
	resetCache(0, content.getLineCount());
	claimBottomFreeSpace();	
	calculateScrollBars();
	if (isBidiCaret()) createCaretBitmaps();
	caretDirection = SWT.NULL;
	setCaretLocation();
	super.redraw();
}
@Override
public void setForeground(Color color) {
	checkWidget();
	foreground = color;
	super.setForeground(getForeground());
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.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();
	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 = renderer.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);
		}
	}
	scrollHorizontal(offset - horizontalScrollOffset, true);
}
/** 
 * 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();
	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 = renderer.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);
		}
	}
	scrollHorizontal(pixel - horizontalScrollOffset, true);
}
/**
 * Sets the line indentation of the widget.
 * <p>
 * It is the amount of blank space, in pixels, at the beginning of each line. 
 * When a line wraps in several lines only the first one is indented. 
 * </p>
 * 
 * @param indent the new indent
 *  
 * @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 #setLineIndent(int, int, int)
 *  
 * @since 3.2
 */
public void setIndent(int indent) {
	checkWidget();
	if (this.indent == indent || indent < 0) return;
	this.indent = indent;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();	
}
/**
 * Sets whether the widget should justify lines.  
 * 
 * @param justify whether lines should be justified
 *  
 * @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 #setLineJustify(int, int, boolean)
 *  
 * @since 3.2
 */
public void setJustify(boolean justify) {
	checkWidget();
	if (this.justify == justify) return;
	this.justify = justify;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();	
}
/** 
 * Maps a key to an action.
 * <p>
 * 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 modifierValue = key & SWT.MODIFIER_MASK;
	int keyInt = key & SWT.KEY_MASK;
	char keyChar = (char)keyInt;
	/**
	 * Bug 440535: Make sure the key getting mapped to letter is in defiened
	 * character range and filter out incorrect int to char typecasting. For
	 * Example: SWT.KEYPAD_CR int gets wrongly type-cast to char letter 'p'
	 */
	if (Character.isDefined(keyInt) && Compatibility.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));
		}
	}		
}
/** 
 * Sets the left margin.
 * 
 * @param leftMargin the left margin.
 * @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 3.5
 */
public void setLeftMargin (int leftMargin) {
	checkWidget();
	setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
}
/**
 * Sets the alignment of the specified lines. The argument should be one of <code>SWT.LEFT</code>, 
 * <code>SWT.CENTER</code> or <code>SWT.RIGHT</code>.
 * <p><p>
 * Note that if <code>SWT.MULTI</code> is set, then <code>SWT.WRAP</code> must also be set
 * in order to stabilize the right edge before setting alignment.
 * </p>
 * Should not be called if a LineStyleListener has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged. 
 *   
 * @param startLine first line the alignment is applied to, 0 based
 * @param lineCount number of lines the alignment applies to.
 * @param alignment line alignment
 * 
 * @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>
 * @see #setAlignment(int)
 * @since 3.2
 */
public void setLineAlignment(int startLine, int lineCount, int alignment) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}

	renderer.setLineAlignment(startLine, lineCount, alignment);
	resetCache(startLine, lineCount);
	redrawLines(startLine, lineCount, false);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
	setAlignment();
}
/** 
 * Sets the background color of the specified lines.
 * <p>
 * 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. 
 * </p><p>
 * Should not be called if a LineBackgroundListener has been set since the 
 * listener maintains the line backgrounds.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes 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();	
	if (isListening(ST.LineGetBackground)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (background != null) {
		renderer.setLineBackground(startLine, lineCount, background);
	} else {
		renderer.clearLineBackground(startLine, lineCount);
	}
	redrawLines(startLine, lineCount, false);
}
/**
 * Sets the bullet of the specified lines.
 * <p>
 * Should not be called if a LineStyleListener has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged.
 * </p>
 *
 * @param startLine first line the bullet is applied to, 0 based
 * @param lineCount number of lines the bullet applies to.
 * @param bullet line bullet
 * 
 * @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>
 * @since 3.2
 */
public void setLineBullet(int startLine, int lineCount, Bullet bullet) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;	
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	int oldBottom = getLinePixel(startLine + lineCount);
	renderer.setLineBullet(startLine, lineCount, bullet);
	resetCache(startLine, lineCount);
	int newBottom = getLinePixel(startLine + lineCount);
	redrawLines(startLine, lineCount, oldBottom != newBottom);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
}
void setVariableLineHeight () {
	if (!fixedLineHeight) return;
	fixedLineHeight = false;
	renderer.calculateIdle();
}
/**
 * Sets the indent of the specified lines.
 * <p>
 * Should not be called if a LineStyleListener has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged.
 * </p>
 *
 * @param startLine first line the indent is applied to, 0 based
 * @param lineCount number of lines the indent applies to.
 * @param indent line indent
 * 
 * @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>
 * @see #setIndent(int)
 * @since 3.2
 */
public void setLineIndent(int startLine, int lineCount, int indent) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	int oldBottom = getLinePixel(startLine + lineCount);
	renderer.setLineIndent(startLine, lineCount, indent);
	resetCache(startLine, lineCount);
	int newBottom = getLinePixel(startLine + lineCount);
	redrawLines(startLine, lineCount, oldBottom != newBottom);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
}
/**
 * Sets the justify of the specified lines.
 * <p>
 * Should not be called if a LineStyleListener has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged.
 * </p>
 *  
 * @param startLine first line the justify is applied to, 0 based
 * @param lineCount number of lines the justify applies to.
 * @param justify true if lines should be justified
 * 
 * @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>
 * @see #setJustify(boolean)
 * @since 3.2
 */
public void setLineJustify(int startLine, int lineCount, boolean justify) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}

	renderer.setLineJustify(startLine, lineCount, justify);
	resetCache(startLine, lineCount);
	redrawLines(startLine, lineCount, false);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
}
/**
 * Sets the line spacing of the widget. The line spacing applies for all lines.
 * 
 * @param lineSpacing the line spacing
 * @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 3.2
 */
public void setLineSpacing(int lineSpacing) {
	checkWidget();
	if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
	this.lineSpacing = lineSpacing;	
	setVariableLineHeight();
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}
/**
 * Sets the tab stops of the specified lines.
 * <p>
 * Should not be called if a <code>LineStyleListener</code> has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged.
 * </p>
 *  
 * @param startLine first line the justify is applied to, 0 based
 * @param lineCount number of lines the justify applies to.
 * @param tabStops tab stops
 * 
 * @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>
 * @see #setTabStops(int[])
 * @since 3.6
 */
public void setLineTabStops(int startLine, int lineCount, int[] tabStops) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (tabStops != null) {
		int pos = 0;
		int[] newTabs = new int[tabStops.length];
		for (int i = 0; i < tabStops.length; i++) {
			if (tabStops[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			newTabs[i] = pos = tabStops[i];
		}
		renderer.setLineTabStops(startLine, lineCount, newTabs);
	} else {
		renderer.setLineTabStops(startLine, lineCount, null);
	}
	resetCache(startLine, lineCount);
	redrawLines(startLine, lineCount, false);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
}
/**
 * Sets the wrap indent of the specified lines.
 * <p>
 * Should not be called if a <code>LineStyleListener</code> has been set since the listener 
 * maintains the line attributes.
 * </p><p>
 * All line attributes 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 
 * attributes 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 
 * attributes take precedence and the attributes of the bottom line are deleted. 
 * For all other text changes line attributes will remain unchanged.
 * </p>
 *
 * @param startLine first line the wrap indent is applied to, 0 based
 * @param lineCount number of lines the wrap indent applies to.
 * @param wrapIndent line wrap indent
 * 
 * @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>
 * @see #setWrapIndent(int)
 * @since 3.6
 */
public void setLineWrapIndent(int startLine, int lineCount, int wrapIndent) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (startLine < 0 || startLine + lineCount > content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	int oldBottom = getLinePixel(startLine + lineCount);
	renderer.setLineWrapIndent(startLine, lineCount, wrapIndent);
	resetCache(startLine, lineCount);
	int newBottom = getLinePixel(startLine + lineCount);
	redrawLines(startLine, lineCount, oldBottom != newBottom);
	int caretLine = getCaretLine();
	if (startLine <= caretLine && caretLine < startLine + lineCount) {
		setCaretLocation();
	}
}

/** 
 * Sets the color of the margins.
 * 
 * @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 3.5
 */
public void setMarginColor(Color color) {
	checkWidget();
	if (color != null && color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	marginColor = color;
	super.redraw();
}
/** 
 * Sets the margins.
 * 
 * @param leftMargin the left margin.
 * @param topMargin the top margin.
 * @param rightMargin the right margin.
 * @param bottomMargin the bottom margin.
 * @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 3.5
 */
public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
	checkWidget();
	this.leftMargin = Math.max(0, leftMargin);
	this.topMargin = Math.max(0, topMargin);
	this.rightMargin = Math.max(0, rightMargin);
	this.bottomMargin = Math.max(0, bottomMargin);
	resetCache(0, content.getLineCount());
	setScrollBars(true);
	setCaretLocation();
	setAlignment();
	super.redraw();
}
/**
 * Flips selection anchor based on word selection direction.
 */
void setMouseWordSelectionAnchor() {
	if (clickCount > 1) {
		if (caretOffset < doubleClickSelection.x) {
			selectionAnchor = doubleClickSelection.y;
		} else if (caretOffset > doubleClickSelection.y) {
			selectionAnchor = doubleClickSelection.x;
		}
	}
}
/**
 * Sets the orientation of the receiver, which must be one
 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 *
 * @param orientation new orientation style
 * 
 * @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.2
 */
@Override
public void setOrientation(int orientation) {
	int oldOrientation = getOrientation();
	super.setOrientation(orientation);
	int newOrientation = getOrientation();
	if (oldOrientation != newOrientation) {
		resetBidiData();
	}
}
/** 
 * Sets the right margin.
 * 
 * @param rightMargin the right margin.
 * @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 3.5
 */
public void setRightMargin (int rightMargin) {
	checkWidget();
	setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
}
void setScrollBar(ScrollBar bar, int clientArea, int maximum, int margin) {
	int inactive = 1;
	if (clientArea < maximum) {
		bar.setMaximum(maximum - margin);
		bar.setThumb(clientArea - margin);
		bar.setPageIncrement(clientArea - margin);
		if (!alwaysShowScroll) bar.setVisible(true);
	} else if (bar.getThumb() != inactive || bar.getMaximum() != inactive) {
		bar.setValues(bar.getSelection(), bar.getMinimum(), inactive, inactive, bar.getIncrement(), inactive);
	}
}
/**
 * Adjusts the maximum and the page size of the scroll bars to 
 * reflect content width/length changes.
 * 
 * @param vertical indicates if the vertical scrollbar also needs to be set 
 */
void setScrollBars(boolean vertical) {
	ignoreResize++;
	if (!isFixedLineHeight() || !alwaysShowScroll) vertical = true;
	ScrollBar verticalBar = vertical ? getVerticalBar() : null;
	ScrollBar horizontalBar = getHorizontalBar();
	int oldHeight = clientAreaHeight;
	int oldWidth = clientAreaWidth;
	if (!alwaysShowScroll) {
		if (verticalBar != null) verticalBar.setVisible(false);
		if (horizontalBar != null) horizontalBar.setVisible(false);
	}
	if (verticalBar != null) {
		setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
	}
	if (horizontalBar != null && !wordWrap) {
		setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
		if (!alwaysShowScroll && horizontalBar.getVisible() && verticalBar != null) {
			setScrollBar(verticalBar, clientAreaHeight, renderer.getHeight(), topMargin + bottomMargin);
			if (verticalBar.getVisible()) {
				setScrollBar(horizontalBar, clientAreaWidth, renderer.getWidth(), leftMargin + rightMargin);
			}
		}
	}
	if (!alwaysShowScroll) {
		redrawMargins(oldHeight, oldWidth);
	}
	ignoreResize--;
}
/** 
 * Sets the selection to the given position and scrolls it into view.  Equivalent to setSelection(start,start).
 *
 * @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_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_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;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.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. 
 * <p>
 * Note that this is a <em>HINT</em>. Some platforms do not allow the application
 * to change the selection foreground color.
 * </p>
 * @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;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.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_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) {
	setSelectionRange(start, end - start);
	showSelection();
}
/** 
 * Sets the selection.
 * <p>
 * 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 setSelection(int start, int length, boolean sendEvent, boolean doBlock) {
	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)) {
		if (blockSelection && doBlock) {
			if (length < 0) {
				setBlockSelectionOffset(end, start, sendEvent);
			} else {
				setBlockSelectionOffset(start, end, sendEvent);
			}
		} else {
			int charCount = content.getCharCount();
			// called internally to remove selection after text is removed
			// therefore make sure redraw range is valid.
			int redrawX = Math.min(selection.x, charCount);
			int redrawY = Math.min(selection.y, charCount);
			if (length < 0) {
				selectionAnchor = selection.y = end;
				selection.x = start;
				setCaretOffset(start, PREVIOUS_OFFSET_TRAILING);
			} else {
				selectionAnchor = selection.x = start;
				selection.y = end;
				setCaretOffset(end, PREVIOUS_OFFSET_TRAILING);
			}
			redrawX = Math.min(redrawX, selection.x);
			redrawY = Math.max(redrawY, selection.y);
			if (redrawY - redrawX > 0) {
				internalRedrawRange(redrawX, redrawY - redrawX);
			}
			if (sendEvent) {
				sendSelectionEvent();
			}
			sendAccessibleTextCaretMoved();
		}
	}
}
/** 
 * Sets the selection.
 * <p>
 * The new selection may not be visible. Call showSelection to scroll the selection
 * into view. A negative length places the caret at the visual start of the selection.
 * </p>
 *
 * @param start offset of the first selected character
 * @param length number of characters to select
 * 
 * @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 setSelectionRange(int start, int length) {
	checkWidget();
	int contentLength = getCharCount();
	start = Math.max(0, Math.min (start, contentLength));
	int end = start + length;
	if (end < 0) {
		length = -start;
	} else {
		if (end > contentLength) length = contentLength - start;
	}
	if (isLineDelimiter(start) || isLineDelimiter(start + length)) {
		// 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);
	}
	setSelection(start, length, false, true);
	setCaretLocation();
}
/** 
 * Adds the specified style.
 * <p>
 * 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><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();
	if (isListening(ST.LineGetStyle)) return;
	if (range != null) {
		if (range.isUnstyled()) {
			setStyleRanges(range.start, range.length, null, null, false);
		} else {
			setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false);
		}
	} else {
		setStyleRanges(0, 0, null, null, true);
	}
}
/** 
 * Clears the styles in the range specified by <code>start</code> and 
 * <code>length</code> and adds the new styles.
 * <p>
 * The ranges array contains start and length pairs.  Each pair refers to
 * the corresponding style in the styles array.  For example, the pair
 * that starts at ranges[n] with length ranges[n+1] uses the style
 * at styles[n/2].  The range fields within each StyleRange are ignored.
 * If ranges or styles is null, the specified range is cleared.
 * </p><p>
 * Note: It is expected that the same instance of a StyleRange will occur
 * multiple times within the styles array, reducing memory usage.
 * </p><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 the array of ranges.  The ranges must not overlap and must be in order.
 * @param styles the array of StyleRanges.  The range fields within the StyleRange are unused.
 * 
 * @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 an element in the styles array is null</li>
 *    <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)</li> 
 *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> 
 *    <li>ERROR_INVALID_RANGE when a range overlaps</li> 
 * </ul>
 * 
 * @since 3.2 
 */
public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (ranges == null || styles == null) {
		setStyleRanges(start, length, null, null, false);
	} else {
		setStyleRanges(start, length, ranges, styles, false);
	}
}
/** 
 * Sets styles to be used for rendering the widget content.
 * <p>
 * All styles in the widget will be replaced with the given set of ranges and styles.
 * The ranges array contains start and length pairs.  Each pair refers to
 * the corresponding style in the styles array.  For example, the pair
 * that starts at ranges[n] with length ranges[n+1] uses the style
 * at styles[n/2].  The range fields within each StyleRange are ignored.
 * If either argument is null, the styles are cleared.
 * </p><p>
 * Note: It is expected that the same instance of a StyleRange will occur
 * multiple times within the styles array, reducing memory usage.
 * </p><p>
 * Should not be called if a LineStyleListener has been set since the 
 * listener maintains the styles.
 * </p>
 *
 * @param ranges the array of ranges.  The ranges must not overlap and must be in order.
 * @param styles the array of StyleRanges.  The range fields within the StyleRange are unused.
 * 
 * @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 an element in the styles array is null</li>
 *    <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 == styles.length)</li> 
 *    <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> 
 *    <li>ERROR_INVALID_RANGE when a range overlaps</li> 
 * </ul>
 * 
 * @since 3.2 
 */
public void setStyleRanges(int[] ranges, StyleRange[] styles) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (ranges == null || styles == null) {
		setStyleRanges(0, 0, null, null, true);
	} else {
		setStyleRanges(0, 0, ranges, styles, true);
	}
}
void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles, boolean reset) {
	int charCount = content.getCharCount();
	int end = start + length;
	if (start > end || start < 0) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	if (styles != null) {
		if (end > charCount) {
			SWT.error(SWT.ERROR_INVALID_RANGE);
		}
		if (ranges != null) {
			if (ranges.length != styles.length << 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
		int lastOffset = 0;
		boolean variableHeight = false; 
		for (int i = 0; i < styles.length; i ++) {
			if (styles[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			int rangeStart, rangeLength;
			if (ranges != null) {
				rangeStart = ranges[i << 1];
				rangeLength = ranges[(i << 1) + 1];
			} else {
				rangeStart = styles[i].start;
				rangeLength = styles[i].length;
			}
			if (rangeLength < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); 
			if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			if (lastOffset > rangeStart) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			variableHeight |= styles[i].isVariableHeight();
			lastOffset = rangeStart + rangeLength;
		}
		if (variableHeight) setVariableLineHeight();
	}
	int rangeStart = start, rangeEnd = end;
	if (styles != null && styles.length > 0) {
		if (ranges != null) {
			rangeStart = ranges[0];
			rangeEnd = ranges[ranges.length - 2] + ranges[ranges.length - 1];
		} else {
			rangeStart = styles[0].start;
			rangeEnd = styles[styles.length - 1].start + styles[styles.length - 1].length;
		}
	}
	int expectedBottom = 0;
	if (!isFixedLineHeight() && !reset) {
		int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
		int partialTopIndex = getPartialTopIndex();
		int partialBottomIndex = getPartialBottomIndex();
		if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
			expectedBottom = getLinePixel(lineEnd + 1);
		}
	}
	if (reset) {
		renderer.setStyleRanges(null, null);
	} else {
		renderer.updateRanges(start, length, length);
	}
	if (styles != null && styles.length > 0) {
		renderer.setStyleRanges(ranges, styles);
	}
	if (reset) {
		resetCache(0, content.getLineCount());
		super.redraw();
	} else {
		int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
		int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
		resetCache(lineStart, lineEnd - lineStart + 1);
		int partialTopIndex = getPartialTopIndex();
		int partialBottomIndex = getPartialBottomIndex();
		if (!(lineStart > partialBottomIndex || lineEnd < partialTopIndex)) {
			int top = 0;
			int bottom = clientAreaHeight;
			if (partialTopIndex <= lineStart && lineStart <= partialBottomIndex) {
				top = Math.max(0, getLinePixel(lineStart));
			}
			if (partialTopIndex <= lineEnd && lineEnd <= partialBottomIndex) {
				bottom = getLinePixel(lineEnd + 1);
			}
			if (!isFixedLineHeight() && bottom != expectedBottom) {
				bottom = clientAreaHeight;
			}
			super.redraw(0, top, clientAreaWidth, bottom - top, false);		
		}
	}
	int oldColumnX = columnX;
	setCaretLocation();
	columnX = oldColumnX;
	doMouseLinkCursor();
}
/** 
 * 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>
 * Note: Because a StyleRange includes the start and length, the
 * same instance cannot occur multiple times in the array of styles.
 * If the same style attributes, such as font and color, occur in
 * multiple StyleRanges, <code>setStyleRanges(int[], StyleRange[])</code>
 * can be used to share styles and reduce memory usage.
 * </p><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. The styles need to be in order.
 * @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 the list of ranges is null</li>
 *    <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> 
 * </ul>
 * 
 * @see #setStyleRanges(int[], StyleRange[])
 */
public void setStyleRanges(StyleRange[] ranges) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
 	if (ranges == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	setStyleRanges(0, 0, null, ranges, true);
}
/** 
 * Sets the tab width. 
 *
 * @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>
 * 
 * @see #setTabStops(int[])
 */
public void setTabs(int tabs) {
	checkWidget();	
	tabLength = tabs;
	renderer.setFont(null, tabs);
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}

/**
 * Sets the receiver's tab list. Each value in the tab list specifies
 * the space in pixels from the origin of the document to the respective
 * tab stop.  The last tab stop width is repeated continuously.
 * 
 * @param tabs the new tab list (or 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_ARGUMENT - if a tab stop is negavite or less than the previous stop in the list</li>
 * </ul>
 * 
 * @see StyledText#getTabStops()
 * 
 * @since 3.6
 */
public void setTabStops(int [] tabs) {
	checkWidget();
	if (tabs != null) {
		int pos = 0;
		int[] newTabs = new int[tabs.length];
		for (int i = 0; i < tabs.length; i++) {
			if (tabs[i] < pos) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			newTabs[i] = pos = tabs[i];
		}
		this.tabs = newTabs;
	} else {
		this.tabs = null;
	}
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.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();
	if (text == null) {
		SWT.error(SWT.ERROR_NULL_ARGUMENT);
	}
	Event event = new Event();
	event.start = 0;
	event.end = getCharCount();
	event.text = text;
	event.doit = true;	
	notifyListeners(SWT.Verify, event);
	if (event.doit) {
		StyledTextEvent styledTextEvent = null;
		if (isListening(ST.ExtendedModify)) {
			styledTextEvent = new StyledTextEvent(content);
			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(ST.ExtendedModify, styledTextEvent);
		}
	}
}

/**
 * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
 * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code> or
 * <code>SWT.RIGHT_TO_LEFT</code>.
 * <p>
 * <code>setOrientation</code> would override this value with the text direction
 * that is consistent with the new orientation.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows.
 * It doesn't set the base text direction on GTK and Cocoa.
 * </p>
 *
 * @param textDirection the base text direction style
 * 
 * @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 SWT#FLIP_TEXT_DIRECTION
 */
@Override
public void setTextDirection(int textDirection) {
	checkWidget();
	int oldStyle = getStyle();
	super.setTextDirection(textDirection);
	if (oldStyle != getStyle()) {
		resetBidiData();
	}
}

/**
 * Sets the text limit to the specified number of characters.
 * <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 topIndex 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();
	if (getCharCount() == 0) {
		return;
	}
	int lineCount = content.getLineCount(), pixel;
	if (isFixedLineHeight()) {
		int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole()));
		if (topIndex < 0) {
			topIndex = 0;
		} else if (topIndex > lineCount - pageSize) {
			topIndex = lineCount - pageSize;
		}
		pixel = getLinePixel(topIndex);
	} else {
		topIndex = Math.max(0, Math.min(lineCount - 1, topIndex));
		pixel = getLinePixel(topIndex);
		if (pixel > 0) {
			pixel = getAvailableHeightBellow(pixel);
		} else {
			pixel = getAvailableHeightAbove(pixel);
		}
	} 
	scrollVertical(pixel, true);
}
/** 
 * Sets the top margin.
 * 
 * @param topMargin the top margin.
 * @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 3.5
 */
public void setTopMargin (int topMargin) {
	checkWidget();
	setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
}
/**
 * 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();
	if (getCharCount() == 0) {
		return;
	}	
	if (pixel < 0) pixel = 0;
	int lineCount = content.getLineCount();
	int height = clientAreaHeight - topMargin - bottomMargin;
	int verticalOffset = getVerticalScrollOffset();
	if (isFixedLineHeight()) {
		int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height);
		if (pixel > maxTopPixel) pixel = maxTopPixel;
		pixel -= verticalOffset; 
	} else {
		pixel -= verticalOffset;
		if (pixel > 0) {
			pixel = getAvailableHeightBellow(pixel);
		}
	}
	scrollVertical(pixel, true);
}
/**
 * Sets whether the widget wraps lines.
 * <p>
 * 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 ((getStyle() & SWT.SINGLE) != 0) return;
	if (wordWrap == wrap) return;
	if (wordWrap && blockSelection) setBlockSelection(false);
	wordWrap = wrap;
	setVariableLineHeight();
	resetCache(0, content.getLineCount());
	horizontalScrollOffset = 0;
	ScrollBar horizontalBar = getHorizontalBar();
	if (horizontalBar != null) {
		horizontalBar.setVisible(!wordWrap);
	}
	setScrollBars(true);
	setCaretLocation();
	super.redraw();
}
/**
 * Sets the wrap line indentation of the widget.
 * <p>
 * It is the amount of blank space, in pixels, at the beginning of each wrapped line.
 * When a line wraps in several lines all the lines but the first one is indented
 * by this amount. 
 * </p>
 * 
 * @param wrapIndent the new wrap indent
 *  
 * @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 #setLineWrapIndent(int, int, int)
 *  
 * @since 3.6
 */
public void setWrapIndent(int wrapIndent) {
	checkWidget();
	if (this.wrapIndent == wrapIndent || wrapIndent < 0) return;
	this.wrapIndent = wrapIndent;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();	
}
boolean showLocation(Rectangle rect, boolean scrollPage) {
	boolean scrolled = false;
	if (rect.y < topMargin) {
		scrolled = scrollVertical(rect.y - topMargin, true);
	} else if (rect.y + rect.height > clientAreaHeight - bottomMargin) {
		if (clientAreaHeight - topMargin - bottomMargin <= 0) {
			scrolled = scrollVertical(rect.y - topMargin, true);
		} else {
			scrolled = scrollVertical(rect.y + rect.height - (clientAreaHeight - bottomMargin), true);
		}
	}
	int width = clientAreaWidth - rightMargin - leftMargin; 
	if (width > 0) {
		int minScroll = scrollPage ? width / 4 : 0;
		if (rect.x < leftMargin) {
			int scrollWidth = Math.max(leftMargin - rect.x, minScroll);
			int maxScroll = horizontalScrollOffset;
			scrolled = scrollHorizontal(-Math.min(maxScroll, scrollWidth), true);
		} else if (rect.x + rect.width > (clientAreaWidth - rightMargin)) {
			int scrollWidth =  Math.max(rect.x + rect.width - (clientAreaWidth - rightMargin), minScroll);
			int maxScroll = renderer.getWidth() - horizontalScrollOffset - clientAreaWidth;
			scrolled = scrollHorizontal(Math.min(maxScroll, scrollWidth), true);
		}
	}
	return scrolled;
}
/**
 * Sets the caret location and scrolls the caret offset into view.
 */
void showCaret() {
	Rectangle bounds = getBoundsAtOffset(caretOffset);
	if (!showLocation(bounds, true)) {
		setCaretLocation();
	}
}
/**
 * Scrolls the selection into view.
 * <p>
 * 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();
	// is selection from right-to-left?
	boolean rightToLeft = caretOffset == selection.x;
	int startOffset, endOffset;
	if (rightToLeft) {
		startOffset = selection.y;
		endOffset = selection.x;
	} else {
		startOffset = selection.x;
		endOffset = selection.y;
	}
	
	Rectangle startBounds = getBoundsAtOffset(startOffset);
	Rectangle endBounds = getBoundsAtOffset(endOffset);
	
	// can the selection be fully displayed within the widget's visible width?
	int w = clientAreaWidth - leftMargin - rightMargin;
	boolean selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w;
	if (selectionFits) {
		// show as much of the selection as possible by first showing
		// the start of the selection
		if (showLocation(startBounds, false)) {
			// endX value could change if showing startX caused a scroll to occur
			endBounds = getBoundsAtOffset(endOffset);
		}
		// the character at endOffset is not part of the selection
		endBounds.width = endOffset == caretOffset ? getCaretWidth() : 0;
		showLocation(endBounds, false);
	} else {
		// just show the end of the selection since the selection start 
		// will not be visible
		showLocation(endBounds, true);
	}
}
void updateCaretVisibility() {
	Caret caret = getCaret();
	if (caret != null) {
		if (blockSelection && blockXLocation != -1) {
			caret.setVisible(false);
		} else {
			Point location = caret.getLocation();
			Point size = caret.getSize();
			boolean visible = 
				topMargin <= location.y + size.y && location.y <= clientAreaHeight - bottomMargin &&
				leftMargin <= location.x + size.x && location.x <= clientAreaWidth - rightMargin;
			caret.setVisible(visible);
		}
	}
}
/**
 * Updates the selection and caret position depending on the text change.
 * <p>
 * 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
		if (wordWrap || visualWrap) setCaretLocation();
		return;
	}
	if (selection.x < startOffset) {
		// clear selection fragment before text change
		internalRedrawRange(selection.x, startOffset - selection.x);
	}
	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);
	}
	if (selection.y > startOffset && selection.x < startOffset + replacedLength) {
		// selection intersects replaced text. set caret behind text change
		setSelection(startOffset + newLength, 0, true, false);
	} else {
		// move selection to keep same text selected
		setSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true, false);
	}
	setCaretLocation();
}
}
