/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Andrey Loskutov <loskutov@gmx.de> - bug 488172
 *     Stefan Xenos (Google) - bug 487254 - StyledText.getTopIndex() can return negative values
 *     Angelo Zerr <angelo.zerr@gmail.com> - Customize different line spacing of StyledText - Bug 522020
 *     Karsten Thoms <thoms@itemis.de> - bug 528746 add getOffsetAtPoint(Point)
 *******************************************************************************/
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:</p>
 * <ul>
 * <li>getStyleRangeAtOffset(int)
 * <li>getStyleRanges()
 * <li>replaceStyleRanges(int,int,StyleRange[])
 * <li>setStyleRange(StyleRange)
 * <li>setStyleRanges(StyleRange[])
 * </ul>
 * <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:</p>
 * <ul>
 * <li>getLineBackground(int)
 * <li>setLineBackground(int,int,Color)
 * </ul>
 * <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>
 * <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>
 * 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;

	static final String STYLEDTEXT_KEY = "org.eclipse.swt.internal.cocoa.styledtext"; //$NON-NLS-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 (x <= y)
	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 hasStyleWithVariableHeight = false;
	boolean hasVerticalIndent = false;
	boolean doubleClickEnabled = true;	// see getDoubleClickEnabled
	boolean overwrite = false;			// insert/overwrite edit mode
	int textLimit = -1;					// limits the number of characters the user can type in the widget. Unlimited by default.
	Map<Integer, Integer> keyActionMap = new HashMap<>();
	Color background = null;			// workaround for bug 4791
	Color foreground = null;			//
	/** True if a non-default background color is set */
	boolean customBackground;
	/** True if a non-default foreground color is set */
	boolean customForeground;
	/** False iff the widget is disabled */
	boolean enabled = true;
	/** True iff the widget is in the midst of being enabled or disabled */
	boolean insideSetEnableCall;
	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 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;
	MouseNavigator mouseNavigator;
	boolean middleClickPressed;

	//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;
		Map<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.
	 *
	 * @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.
	 *
	 * @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 HashMap<> ();
		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>.
	 *
	 * @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) {
			for (Resource resource : resources.values()) {
				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 {
				StringBuilder buffer = new StringBuilder("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();
			StringBuilder buffer = new StringBuilder(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.
	 */
	@Override
	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;

	/**
	 * 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<>();
		fontTable = new ArrayList<>();
		colorTable.add(getForeground());
		colorTable.add(getBackground());
		fontTable.add(getFont());
	}
	/**
	 * 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;
	}
	/**
	 * 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) {
				// 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() {
		StringBuilder header = new StringBuilder();
		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 (Color color : colorTable) {
			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 \chshdng0\chcbpat 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("{\\chshdng0\\chcbpat");
			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("\\chshdng0\\chcbpat");
				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 StringBuilder 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 StringBuilder(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 &lt; 0 or &gt; 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();
	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 = () -> {
			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));
	if (IS_MAC) setData(STYLEDTEXT_KEY);
}
/**
 * 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. The selection values returned are visual
 * (i.e., x will always always be &lt;= y).
 * No event is sent when the caret is moved while the selection length is 0.
 * </p><p>
 * <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 oldDelta = 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 = getVerticalScrollOffset() / verticalIncrement;
				}
			} 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 < 0) {
		// TODO: This logging is in place to determine why topIndex is getting set to negative values.
		// It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
		System.err.println("StyledText: topIndex was " + topIndex
				+ ", isFixedLineHeight() = " + isFixedLineHeight()
				+ ", delta = " + delta
				+ ", content.getLineCount() = " + content.getLineCount()
				+ ", clientAreaHeight = " + clientAreaHeight
				+ ", oldTopIndex = " + oldTopIndex
				+ ", oldTopIndexY = " + oldTopIndexY
				+ ", getVerticalScrollOffset = " + getVerticalScrollOffset()
				+ ", oldDelta = " + oldDelta
				+ ", getVerticalIncrement() = " + getVerticalIncrement());
		topIndex = 0;
	}
	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 = getLeftMargin() + 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;
	StringBuilder convertedText = new StringBuilder(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() {
			@Override
			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() {
			@Override
			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() {
			@Override
			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() {
			@Override
			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 (isWordWrap()) {
		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;
			y++; // bug 485722: workaround for fractional line heights
		}
		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 (isWordWrap()) {
		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 (isWordWrap()) {
		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 (isWordWrap()) {
		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;
				y--; // bug 485722: workaround for fractional line heights
			}
		} else {
			y = layout.getLineBounds(lineIndex - 1).y;
			y++; // bug 485722: workaround for fractional line heights
		}
		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 (isWordWrap()) {
					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 (isWordWrap()) {
				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 (isWordWrap()) {
			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 (isWordWrap()) {
			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 (isWordWrap()) {
		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 (isWordWrap()) {
					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 (isWordWrap()) {
				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 (isWordWrap()) {
			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 points.
 *
 * 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 points.
 *
 * @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 (&lt; 0 or &gt; 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;
	StringBuilder buffer = new StringBuilder();
	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) {
		TextLayout layout = renderer.getTextLayout(lineIndex);
		int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset));
		bounds = layout.getBounds(offsetInLine, offsetInLine);
		if (getListeners(ST.LineGetSegments).length > 0 && 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, bounds.height);
		}
		renderer.disposeTextLayout(layout);
	} else {
		bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
	}
	if (offset == caretOffset && !isWordWrap()) {
		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 &gt; 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 SWT logical point starting at 0, if &gt; 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(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 (&lt; 0 or &gt;= 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 &lt;= offset &lt;= 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 (&lt; 0 or &gt; 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 points.
 * @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 points
 *
 * @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 (&lt; 0 or &gt; 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 the vertical indentation of the line at the given index.
 *
 * @param index the index of the line
 *
 * @return the line vertical 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>
 *
 * @since 3.109
 */
public int getLineVerticalIndent(int index) {
	checkWidget();
	if (index < 0 || index >= content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	return isListening(ST.LineGetStyle) ? 0 : renderer.getLineVerticalIndent(index);
}
/**
 * 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 SWT logical point, 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 SWT logical point of the last line.
 * It means this function can be used to retrieve the bottom SWT logical point of any line.
 *
 * @return the top SWT logical point 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 point
 *
 * @return the line index for a given y-coordinate point
 *
 * @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 &lt;= offset &lt;= 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 (&lt; 0 or &gt; getCharCount())</li>
 * </ul>
 */
public Point getLocationAtOffset(int offset) {
	checkWidget();
	if (offset < 0 || offset > getCharCount()) {
		SWT.error(SWT.ERROR_INVALID_RANGE);
	}
	return getPointAtOffset(offset);
}
/**
 * Returns <code>true</code> if the mouse navigator is enabled.
 * When mouse navigator is enabled, the user can navigate through the widget by pressing the middle button and moving the cursor
 *
 * @return the mouse navigator's enabled 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>
 *
 * @see #getEnabled
 * @since 3.110
 */
public boolean getMouseNavigatorEnabled () {
	checkWidget ();
	return mouseNavigator != null;
}
/**
 * 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 &lt;= lineIndex &lt; 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 (&lt; 0 or &gt;= 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>
 *
 * @deprecated Use {@link #getOffsetAtPoint(Point)} instead for better performance
 */
@Deprecated
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];
}

/**
 * Returns the offset of the character at the given point 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 point.
 * If the x coordinate of the point is beyond the center of a character
 * the returned offset will be behind the character.
 * </p>
 * Note: This method is functionally similar to {@link #getOffsetAtLocation(Point)} except that
 * it does not throw an exception when no character is found and thus performs faster.
 *
 * @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 point relative
 *  to the first character in the document.
 * -1 when there is no character at the specified location.
 * @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 <code>null</code></li>
 * </ul>
 *
 * @since 3.107
 */
public int getOffsetAtPoint(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);
	return offset != -1 ? offset + trailing[0] : -1;
}

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) {
					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
 *  &lt;= 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 (char segmentsChar : segmentsChars) {
			if (segmentsChar == '\n' || segmentsChar == '\r') {
				visualWrap = true;
				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 &lt;= offset &lt; 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 &gt;= start
 *  and the last returned <code>StyleRange</code> will have an ending
 *  offset &lt;= 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 &gt;= start
 *  and the last returned <code>StyleRange</code> will have an ending
 *  offset &gt;= 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 SWT logical point.
 * <p>
 * The top point is the SWT logical point position of the line that is
 * currently at the top of the widget. The text widget can be scrolled by points
 * by dragging the scroll thumb so that a partial line may be displayed at the top
 * the widget.  The top point changes when the widget is scrolled.  The top point
 * does not include the widget trimming.
 * </p>
 *
 * @return SWT logical point 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:
					boolean lineBegin = offsetInLine == 0;
					// If word wrap is enabled, we should also consider offsets
					// of wrapped line parts as line begin and do NOT go back.
					// This prevents clients to jump one line higher than
					// expected, see bug 488172.
					// Respect caretAlignment at the caretOffset, unless there's
					// a non-empty selection, see bug 488172 comment 6.
					if (wordWrap && !lineBegin && (offset != caretOffset || selection.x != selection.y)) {
						int[] offsets = layout.getLineOffsets();
						for (int i : offsets) {
							if (i == offsetInLine) {
								lineBegin = true;
								break;
							}
						}
					}
					if (lineBegin) {
						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(), layout.getVerticalIndent());
	}
	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 (String line : lines) {
			int length = line.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;
				StringBuilder buffer = new StringBuilder(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() {
		@Override
		public void textChanging(TextChangingEvent event) {
			handleTextChanging(event);
		}
		@Override
		public void textChanged(TextChangedEvent event) {
			handleTextChanged(event);
		}
		@Override
		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 = 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, event -> {
		if (!editable) {
			event.doit = false;
			event.start = 0;
			event.end = 0;
			event.text = "";
			return;
		}

		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, event -> handleVerticalScroll(event));
	}
	if (horizontalBar != null) {
		horizontalBar.addListener(SWT.Selection, 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 (isWordWrap() && 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);
	}
	resetSelection();
	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 ||
					event.stateMask == SWT.CTRL ||
					event.stateMask == (SWT.ALT | SWT.SHIFT) ||
					event.stateMask == (SWT.CTRL | SWT.SHIFT);
		}
		// -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) {
		// On GTK, if mouseNavigator is enabled we have to distinguish a short middle-click (to paste content) from
		// a long middle-click (mouse navigation started)
		if (IS_GTK && mouseNavigator != null) {
			middleClickPressed = true;
			getDisplay().timerExec(200, ()->{
				boolean click = middleClickPressed;
				middleClickPressed = false;
				if (click && mouseNavigator !=null) {
					mouseNavigator.onMouseDown(event);
				} else {
					pasteOnMiddleClick(event);
				}
			});
			return;
		} else {
			pasteOnMiddleClick(event);
		}
	}

	//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) {
	middleClickPressed = false;
	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;
		if (topIndex < 0) {
			// TODO: This logging is in place to determine why topIndex is getting set to negative values.
			// It should be deleted once we fix the root cause of this issue. See bug 487254 for details.
			System.err.println("StyledText: topIndex was " + topIndex
					+ ", lastTextChangeStart = " + lastTextChangeStart
					+ ", content.getClass() = " + content.getClass()
					);
			topIndex = 0;
		}
		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() {
		@Override
		public void setTextAttributes(AccessibleTextAttributeEvent e) {
			// This method must be implemented by the application
			e.result = ACC.OK;
		}
		@Override
		public void replaceText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.replaceTextRange(e.start, e.end - e.start, e.string);
			e.result = ACC.OK;
		}
		@Override
		public void pasteText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.setSelection(e.start);
			st.paste();
			e.result = ACC.OK;
		}
		@Override
		public void cutText(AccessibleEditableTextEvent e) {
			StyledText st = StyledText.this;
			st.setSelection(e.start, e.end);
			st.cut();
			e.result = ACC.OK;
		}
		@Override
		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, 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 !isWordWrap() && lineSpacing == 0 && renderer.lineSpacingProvider == null && !hasStyleWithVariableHeight && !hasVerticalIndent;
}
/**
 * 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);
	}
}
private void pasteOnMiddleClick(Event event) {
	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);
	}
}
/**
 * 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 redrawLine : redrawLines) {
		int lineIndex = redrawLine;
		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 &lt;= offset &lt;= 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:
 * </p>
 * <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>
 *
 * @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 &lt;= offset &lt;= 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(SortedSet<Integer> lines) {
	if (lines == null || lines.isEmpty()) return;
	int maxLineIndex = renderer.maxWidthLineIndex;
	renderer.reset(lines);
	renderer.calculateClientArea();
	if (0 <= maxLineIndex && maxLineIndex < content.getLineCount()) {
		renderer.calculate(maxLineIndex, 1);
	}
	setScrollBars(true);
	if (!isFixedLineHeight()) {
		if (topIndex > lines.iterator().next()) {
			verticalScrollOffset = -1;
		}
		renderer.calculateIdle();
	}
}
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;
		for (Control child : getChildren()) {
			Rectangle rect = child.getBounds();
			child.setLocation(rect.x + deltaX, rect.y + deltaY);
		}
	}
}

/**
 * Scrolls the widget horizontally.
 *
 * @param pixels number of SWT logical points to scroll, &gt; 0 = scroll left,
 * 	&lt; 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 deltaY = 0;
		if (pixels > 0) {
			int sourceY = topMargin + pixels;
			int scrollHeight = clientAreaHeight - sourceY - bottomMargin;
			if (scrollHeight > 0) {
				deltaY = -pixels;
			}
		} else {
			int destinationY = topMargin - pixels;
			int scrollHeight = clientAreaHeight - destinationY - bottomMargin;
			if (scrollHeight > 0) {
				deltaY = -pixels;
			}
		}
		Control[] children = getChildren();
		for (Control child : children) {
			Rectangle rect = child.getBounds();
			child.setLocation(rect.x, rect.y + deltaY);
		}
		verticalScrollOffset += pixels;
		calculateTopIndex(pixels);
		super.redraw();
	} 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;
	StringBuilder buffer = new StringBuilder();
	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>
 * 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();
	boolean backgroundDisabled = false;
	if (!this.enabled && color == null) {
		if (background != null) {
			Color disabledBg = getDisplay().getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND);
			if (background.equals(disabledBg)) {
				return;
			} else {
				color = new Color (getDisplay(), disabledBg.getRGBA());
				backgroundDisabled = true;
			}
		}
	}
	customBackground = color != null && !this.insideSetEnableCall && !backgroundDisabled;
	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.
 *
 * @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(getLeftMargin(), topMargin, rightMargin, bottomMargin);
}
/**
 * Moves the Caret to the current caret offset.
 */
void setCaretLocation() {
	Point newCaretPos = getPointAtOffset(caretOffset);
	setCaretLocation(newCaretPos, getCaretDirection());
}
void setCaretLocation(final Point location, int direction) {
	Caret caret = getCaret();
	if (caret != null) {
		final boolean isDefaultCaret = caret == defaultCaret;
		final StyleRange styleAtOffset = content.getCharCount() > 0 ?
			(caretOffset < content.getCharCount() ?
				getStyleRangeAtOffset(caretOffset) :
				getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style
			null;
		final int caretLine = getCaretLine();

		int graphicalLineHeight = getLineHeight();
		final int lineStartOffset = getOffsetAtLine(caretLine);
		int graphicalLineFirstOffset = lineStartOffset;
		final int lineEndOffset = lineStartOffset + getLine(caretLine).length();
		int graphicalLineLastOffset = lineEndOffset;
		if (caretLine < getLineCount() && renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles...
			graphicalLineHeight = getLineHeight(caretOffset);
			final Rectangle characterBounds = getBoundsAtOffset(caretOffset);
			graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y));
			graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1;
			if (graphicalLineLastOffset < graphicalLineFirstOffset) {
				graphicalLineLastOffset = getCharCount();
			}
		}

		int caretHeight = getLineHeight();
		boolean isTextAlignedAtBottom = true;
		if (graphicalLineFirstOffset >= 0) {
			for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) {
				isTextAlignedAtBottom &= (
					(style.font == null || Objects.equals(style.font, getFont())) &&
					style.rise >= 0 &&
					(style.metrics == null || style.metrics.descent <= 0)
				);
			}
		}
		if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) {
			if (isDefaultCaret) {
				direction = SWT.DEFAULT;
				caretHeight = graphicalLineHeight;
			} else {
				caretHeight = caret.getSize().y;
			}
		}
		if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) {
			location.y += (graphicalLineHeight - caretHeight);
		}

		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 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.
 *
 * @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.
 *
 * @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;
}
@Override
public void setEnabled(boolean enabled) {
	super.setEnabled(enabled);
	Display display = getDisplay();
	this.enabled = enabled;
	this.insideSetEnableCall = true;
	try {
		if (enabled) {
			if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
			if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
		} else {
			if (!customBackground) setBackground(display.getSystemColor(SWT.COLOR_TEXT_DISABLED_BACKGROUND));
			if (!customForeground) setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND));
		}
	}
	finally {
		this.insideSetEnableCall = false;
	}
}
/**
 * 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();
	boolean foregroundDisabled = false;
	if (!this.enabled && color == null) {
		if (foreground != null) {
			Color disabledFg = getDisplay().getSystemColor(SWT.COLOR_WIDGET_DISABLED_FOREGROUND);
			if (foreground.equals(disabledFg)) {
				return;
			} else {
				color = new Color (getDisplay(), disabledFg.getRGBA());
				foregroundDisabled = true;
			}
		}
	}
	customForeground = color != null && !this.insideSetEnableCall && !foregroundDisabled;
	foreground = color;
	super.setForeground(color);
	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 &gt; 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 SWT logical point offset relative to the start of the line.
 * Do nothing if there is no text set.
 * <p>
 * <b>NOTE:</b> The horizontal SWT logical point offset is reset to 0 when new text
 * is set in the widget.
 * </p>
 *
 * @param pixel horizontal SWT logical point 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 points, 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) && Character.isLetter(keyChar)) {
		// make the keybinding case insensitive by adding it
		// in its upper and lower case form
		char ch = Character.toUpperCase(keyChar);
		int newKey = ch | modifierValue;
		if (action == SWT.NULL) {
			keyActionMap.remove(newKey);
		} else {
			keyActionMap.put(newKey, action);
		}
		ch = Character.toLowerCase(keyChar);
		newKey = ch | modifierValue;
		if (action == SWT.NULL) {
			keyActionMap.remove(newKey);
		} else {
			keyActionMap.put(newKey, action);
		}
	} else {
		if (action == SWT.NULL) {
			keyActionMap.remove(key);
		} else {
			keyActionMap.put(key, 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>
 * 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><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>
 * 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();
	}
}
/**
 * Returns true if StyledText is in word wrap mode and false otherwise.
 *
 * @return true if StyledText is in word wrap mode and false otherwise.
 */
boolean isWordWrap() {
	return wordWrap || visualWrap;
}
/**
 * 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 vertical 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><p>
 * Setting both line spacing and vertical indent on a line would result in the
 * spacing and indent add up for the line.
 * </p>
 *
 * @param lineIndex line index the vertical indent is applied to, 0 based
 * @param verticalLineIndent vertical 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 index is invalid</li>
 * </ul>
 * @since 3.109
 */
public void setLineVerticalIndent(int lineIndex, int verticalLineIndent) {
	checkWidget();
	if (isListening(ST.LineGetStyle)) return;
	if (lineIndex < 0 || lineIndex >= content.getLineCount()) {
		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	}
	if (verticalLineIndent == renderer.getLineVerticalIndent(lineIndex)) {
			return;
	}
	int oldBottom = getLinePixel(lineIndex + 1);
	if (oldBottom <= getClientArea().height) {
		verticalScrollOffset = -1;
	}
	renderer.setLineVerticalIndent(lineIndex, verticalLineIndent);
	hasVerticalIndent = verticalLineIndent != 0 || renderer.hasVerticalIndent();
	resetCache(lineIndex, 1);
	int newBottom = getLinePixel(lineIndex + 1);
	redrawLines(lineIndex, 1, oldBottom != newBottom);
	int caretLine = getCaretLine();
	if (lineIndex <= caretLine && caretLine < lineIndex + 1) {
		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.
 * In the case of #setLineSpacingProvider(StyledTextLineSpacingProvider) is customized,
 * the line spacing are applied only for the lines which are not managed by {@link StyledTextLineSpacingProvider}.
 *
 * @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>
 * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
 * @since 3.2
 */
public void setLineSpacing(int lineSpacing) {
	checkWidget();
	if (this.lineSpacing == lineSpacing || lineSpacing < 0) return;
	this.lineSpacing = lineSpacing;
	resetCache(0, content.getLineCount());
	setCaretLocation();
	super.redraw();
}
/**
 * Sets the line spacing provider of the widget. The line spacing applies for some lines with customized spacing
 * or reset the customized spacing if the argument is null.
 *
 * @param lineSpacingProvider the line spacing provider (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>
 * @see #setLineSpacingProvider(StyledTextLineSpacingProvider)
 * @since 3.107
 */
public void setLineSpacingProvider(StyledTextLineSpacingProvider lineSpacingProvider) {
	checkWidget();
	boolean wasFixedLineHeight = isFixedLineHeight();
	if (renderer.getLineSpacingProvider() == null && lineSpacingProvider == null
			|| (renderer.getLineSpacingProvider() != null
					&& renderer.getLineSpacingProvider().equals(lineSpacingProvider)))
		return;
	renderer.setLineSpacingProvider(lineSpacingProvider);
	// reset lines cache if needed
	if (lineSpacingProvider == null) {
		if (!wasFixedLineHeight) {
			resetCache(0, content.getLineCount());
		}
	} else {
		if (wasFixedLineHeight) {
			int firstLine = -1;
			for (int i = 0; i < content.getLineCount(); i++) {
				Integer lineSpacing = lineSpacingProvider.getLineSpacing(i);
				if (lineSpacing != null && lineSpacing > 0) {
					// there is a custom line spacing, set StyledText as variable line height mode
					// reset only the line size
					renderer.reset(i, 1);
					if (firstLine == -1) {
						firstLine = i;
					}
				}
			}
			if (firstLine != -1) {
				// call reset cache for the first line which have changed to recompute scrollbars
				resetCache(firstLine, 0);
			}
		}
	}
	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) + alignmentMargin;
	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();
}
/**
 * Sets the enabled state of the mouse navigator. When the mouse navigator is enabled, the user can navigate through the widget
 * by pressing the middle button and moving the cursor.
 *
 * @param enabled if true, the mouse navigator is enabled, if false the mouse navigator is deactivated
 * @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.110
 */
public void setMouseNavigatorEnabled(boolean enabled) {
	checkWidget();
	if ((enabled && mouseNavigator != null) || (!enabled && mouseNavigator == null)) {
		return;
	}
	if (enabled) {
		mouseNavigator = new MouseNavigator(this);
	} else {
		mouseNavigator.dispose();
		mouseNavigator = null;
	}
}
/**
 * Flips selection anchor based on word selection direction.
 */
void setMouseWordSelectionAnchor() {
	if (doubleClickEnabled && 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(getLeftMargin(), 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 &gt; 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 &gt; 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 &gt;= 0 must be true.
 * @param length number of characters to select, 0 &lt;= start + length
 * 	&lt;= 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 oldStart = selection.x;
			int oldLength = selection.y - selection.x;
			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 && (oldLength != end - start || (oldLength != 0 && oldStart != start))) {
				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 (&gt; 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 (&gt; 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 (&gt; 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();
	if (reset) {
		start = 0;
		length = charCount;
	}
	int[] formerRanges = getRanges(start, length);
	StyleRange[] formerStyles = getStyleRanges(start, length);
	int end = start + length;
	final boolean wasFixedLineHeight = isFixedLineHeight();
	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;
		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);
			hasStyleWithVariableHeight |= styles[i].isVariableHeight();
			lastOffset = rangeStart + rangeLength;
		}
	}
	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;
		}
	}

	// This needs to happen before new styles are applied
	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);
	}

	// re-evaluate variable height with all styles (including new ones)
	hasStyleWithVariableHeight = false;
	for (StyleRange style : getStyleRanges(false)) {
		hasStyleWithVariableHeight = style.isVariableHeight();
		if (hasStyleWithVariableHeight) break;
	}

	SortedSet<Integer> modifiedLines = computeModifiedLines(formerRanges, formerStyles, ranges, styles);
	resetCache(modifiedLines);
	if (reset) {
		super.redraw();
	} else {
		int lineStart = content.getLineAtOffset(Math.min(start, rangeStart));
		int lineEnd = content.getLineAtOffset(Math.max(end, rangeEnd));
		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 (!(wasFixedLineHeight && isFixedLineHeight()) && bottom != expectedBottom) {
				bottom = clientAreaHeight;
			}
			super.redraw(0, top, clientAreaWidth, bottom - top, false);
		}
	}
	int oldColumnX = columnX;
	setCaretLocation();
	columnX = oldColumnX;
	doMouseLinkCursor();
}

/**
 *
 * @param referenceRanges former ranges, sorted by order and without overlapping, typically returned {@link #getRanges(int, int)}
 * @param referenceStyles
 * @param newRanges former ranges, sorted by order and without overlapping
 * @param newStyles
 * @return
 */
private SortedSet<Integer> computeModifiedLines(int[] referenceRanges, StyleRange[] referenceStyles, int[] newRanges, StyleRange[] newStyles) {
	if (referenceStyles == null) {
		referenceStyles = new StyleRange[0];
	}
	if (referenceRanges == null) {
		referenceRanges = createRanges(referenceStyles);
	}
	if (newStyles == null) {
		newStyles = new StyleRange[0];
	}
	if (newRanges == null) {
		newRanges = createRanges(newStyles);
	}
	if (referenceRanges.length != 2 * referenceStyles.length) {
		throw new IllegalArgumentException();
	}
	if (newRanges.length != 2 * newStyles.length) {
		throw new IllegalArgumentException();
	}
	SortedSet<Integer> res = new TreeSet<>();
	int referenceRangeIndex = 0;
	int newRangeIndex = 0;
	StyleRange defaultStyle = new StyleRange();
	defaultStyle.foreground = this.foreground;
	defaultStyle.background = this.background;
	defaultStyle.font = getFont();
	int currentOffset = referenceRanges.length > 0 ? referenceRanges[0] : Integer.MAX_VALUE;
	if (newRanges.length > 0) {
		currentOffset = Math.min(currentOffset, newRanges[0]);
	}
	while (currentOffset < content.getCharCount() && (referenceRangeIndex < referenceStyles.length || newRangeIndex < newRanges.length)) {
		int nextMilestoneOffset = Integer.MAX_VALUE; // next new range start/end after current offset

		while (referenceRangeIndex < referenceStyles.length && endRangeOffset(referenceRanges, referenceRangeIndex) <= currentOffset) {
			referenceRangeIndex++;
		}
		StyleRange referenceStyleAtCurrentOffset = defaultStyle;
		if (isInRange(referenceRanges, referenceRangeIndex, currentOffset)) { // has styling
			referenceStyleAtCurrentOffset = referenceStyles[referenceRangeIndex];
			nextMilestoneOffset =  endRangeOffset(referenceRanges, referenceRangeIndex);
		} else if (referenceRangeIndex < referenceStyles.length) { // no range, default styling
			nextMilestoneOffset = referenceRanges[2 * referenceRangeIndex]; // beginning of next range
		}

		while (newRangeIndex < newStyles.length && endRangeOffset(newRanges, newRangeIndex) <= currentOffset) {
			newRangeIndex++;
		}
		StyleRange newStyleAtCurrentOffset = defaultStyle;
		if (isInRange(newRanges, newRangeIndex, currentOffset)) {
			newStyleAtCurrentOffset = newStyles[newRangeIndex];
			nextMilestoneOffset = Math.min(nextMilestoneOffset, endRangeOffset(newRanges, newRangeIndex));
		} else if (newRangeIndex < newStyles.length) {
			nextMilestoneOffset = Math.min(nextMilestoneOffset, newRanges[2 * newRangeIndex]);
		}

		if (!referenceStyleAtCurrentOffset.similarTo(newStyleAtCurrentOffset)) {
			int fromLine = getLineAtOffset(currentOffset);
			int toLine = getLineAtOffset(nextMilestoneOffset - 1);
			for (int line = fromLine; line <= toLine; line++) {
				res.add(line);
			}
			currentOffset = toLine + 1 < getLineCount() ? getOffsetAtLine(toLine + 1) : content.getCharCount();
		} else {
			currentOffset = nextMilestoneOffset;
		}
	}
	return res;
}
private int[] createRanges(StyleRange[] referenceStyles) {
	int[] referenceRanges;
	referenceRanges = new int[2 * referenceStyles.length];
	for (int i = 0; i < referenceStyles.length; i++) {
		referenceRanges[2 * i] = referenceStyles[i].start;
		referenceRanges[2 * i + 1] = referenceStyles[i].length;
	}
	return referenceRanges;
}

private boolean isInRange(int[] ranges, int styleIndex, int offset) {
	if (ranges == null || ranges.length == 0 || styleIndex < 0 || 2 * styleIndex + 1 > ranges.length) {
		return false;
	}
	int start = ranges[2 * styleIndex];
	int length = ranges[2 * styleIndex + 1];
	return offset >= start && offset < start + length;
}

/**
 * The offset on which the range ends (excluded)
 * @param ranges
 * @param styleIndex
 * @return
 */
private int endRangeOffset(int[] ranges, int styleIndex) {
	if (styleIndex < 0 || 2 * styleIndex > ranges.length) {
		throw new IllegalArgumentException();
	}
	int start = ranges[2 * styleIndex];
	int length = ranges[2 * styleIndex + 1];
	return start + length;
}

/**
 * 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 (&gt; 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 points 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 negative 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 (isAutoDirection () || 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(getLeftMargin(), topMargin, rightMargin, bottomMargin);
}
/**
 * Sets the top SWT logical point offset. Do nothing if there is no text set.
 * <p>
 * The top point offset is the vertical SWT logical point offset of the widget. The
 * widget is scrolled so that the given SWT logical point position is at the top.
 * The top index is adjusted to the corresponding top line.
 * Note: The top point is reset to 0 when new text is set in the widget.
 * </p>
 *
 * @param pixel new top point 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;
	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 points, 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 (isWordWrap()) 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();
}
}
