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