Mercurial > projects > dwt-mac
diff dwt/custom/StyledText.d @ 41:6337764516f1
Sync dwt/custom with dwt-linux (took copy of complete folder)
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 07 Oct 2008 16:29:55 +0200 |
parents | db5a898b2119 |
children | 07399639c0c8 |
line wrap: on
line diff
--- a/dwt/custom/StyledText.d Tue Oct 07 14:41:31 2008 +0200 +++ b/dwt/custom/StyledText.d Tue Oct 07 16:29:55 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 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 @@ -7,39 +7,109 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> *******************************************************************************/ -module dwt.custom; +module dwt.custom.StyledText; -import java.util.*; +import dwt.DWT; +import dwt.DWTError; +import dwt.DWTException; +import dwt.accessibility.ACC; +import dwt.accessibility.Accessible; +import dwt.accessibility.AccessibleAdapter; +import dwt.accessibility.AccessibleControlAdapter; +import dwt.accessibility.AccessibleControlEvent; +import dwt.accessibility.AccessibleEvent; +import dwt.accessibility.AccessibleTextAdapter; +import dwt.accessibility.AccessibleTextEvent; +import dwt.dnd.Clipboard; +import dwt.dnd.DND; +import dwt.dnd.RTFTransfer; +import dwt.dnd.TextTransfer; +import dwt.dnd.Transfer; +import dwt.events.ModifyListener; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.events.VerifyListener; +import dwt.graphics.Color; +import dwt.graphics.Cursor; +import dwt.graphics.Font; +import dwt.graphics.FontData; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.graphics.GlyphMetrics; +import dwt.graphics.Image; +import dwt.graphics.Device; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.graphics.Resource; +import dwt.graphics.TextLayout; +import dwt.internal.BidiUtil; +import dwt.internal.Compatibility; +import dwt.printing.Printer; +import dwt.printing.PrinterData; +import dwt.widgets.Canvas; +import dwt.widgets.Caret; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Event; +import dwt.widgets.IME; +import dwt.widgets.Label; +import dwt.widgets.Listener; +import dwt.widgets.ScrollBar; +import dwt.widgets.TypedListener; +import dwt.custom.StyledTextContent; +import dwt.custom.TextChangeListener; +import dwt.custom.StyledTextRenderer; +import dwt.custom.StyledTextPrintOptions; +import dwt.custom.ExtendedModifyListener; +import dwt.custom.BidiSegmentListener; +import dwt.custom.LineBackgroundListener; +import dwt.custom.LineStyleListener; +import dwt.custom.PaintObjectListener; +import dwt.custom.VerifyKeyListener; +import dwt.custom.MovementListener; +import dwt.custom.Bullet; +import dwt.custom.StyledTextEvent; +import dwt.custom.StyleRange; +import dwt.custom.TextChangedEvent; +import dwt.custom.TextChangingEvent; +import dwt.custom.DefaultContent; +import dwt.custom.StyledTextDropTargetEffect; +import dwt.custom.StyledTextListener; +import dwt.custom.ST; +import dwt.dwthelper.Runnable; -import dwt.*; -import dwt.accessibility.*; -import dwt.dnd.*; -import dwt.events.*; -import dwt.graphics.*; -import dwt.internal.*; -import dwt.printing.*; -import dwt.widgets.*; +static import tango.text.Text; +static import tango.text.Util; +static import tango.io.model.IFile; +static import tango.text.convert.Utf; +import tango.util.Convert; +import dwt.dwthelper.utils; -/** - * A StyledText is an editable user interface object that displays lines - * of text. The following style attributes can be defined for the text: +alias tango.text.Text.Text!(char) StringBuffer; + +/** + * 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>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 + * 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 + * 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> @@ -51,11 +121,11 @@ * </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 + * 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) @@ -64,7 +134,7 @@ * </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. + * setContent(StyledTextContent) to initialize the widget. * </p><p> * <dl> * <dt><b>Styles:</b><dd>FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP @@ -73,31 +143,37 @@ * </p><p> * IMPORTANT: This class is <em>not</em> intended to be subclassed. * </p> + * + * @see <a href="http://www.eclipse.org/swt/snippets/#styledtext">StyledText snippets</a> + * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Examples: CustomControlExample, TextEditor</a> + * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> */ public class StyledText : 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; - static final int PaintObject = 3008; - static final int WordNext = 3009; - static final int WordPrevious = 3010; - - static final int PREVIOUS_OFFSET_TRAILING = 0; - static final int OFFSET_LEADING = 1; - + alias Canvas.computeSize computeSize; + + static const char TAB = '\t'; + static const String PlatformLineDelimiter = tango.io.model.IFile.FileConst.NewlineString; + static const int BIDI_CARET_WIDTH = 3; + static const int DEFAULT_WIDTH = 64; + static const int DEFAULT_HEIGHT = 64; + static const int V_SCROLL_RATE = 50; + static const int H_SCROLL_RATE = 10; + + static const int ExtendedModify = 3000; + static const int LineGetBackground = 3001; + static const int LineGetStyle = 3002; + static const int TextChanging = 3003; + static const int TextSet = 3004; + static const int VerifyKey = 3005; + static const int TextChanged = 3006; + static const int LineGetSegments = 3007; + static const int PaintObject = 3008; + static const int WordNext = 3009; + static const int WordPrevious = 3010; + + static const int PREVIOUS_OFFSET_TRAILING = 0; + static const int OFFSET_LEADING = 1; + Color selectionBackground; // selection background color Color selectionForeground; // selection foreground color StyledTextContent content; // native content (default or user specified) @@ -118,30 +194,30 @@ int columnX; // keep track of the horizontal caret position when changing lines/pages. Fixes bug 5935 int caretOffset = 0; int caretAlignment; - Point selection = new Point(0, 0); // x and y are start and end caret offsets of selection + Point selection; // 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 bool editable = true; bool wordWrap = false; - bool doubleClickEnabled = true; // see getDoubleClickEnabled - bool overwrite = false; // insert/overwrite edit mode + bool doubleClickEnabled = true; // see getDoubleClickEnabled + bool 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(); + int[int] keyActionMap; Color background = null; // workaround for bug 4791 Color foreground = null; // Clipboard clipboard; int clickCount; int autoScrollDirection = DWT.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 lastTextChangeStart; // cache data of the + int lastTextChangeNewLineCount; // last text changing + int lastTextChangeNewCharCount; // event for use in the int lastTextChangeReplaceLineCount; // text changed handler int lastTextChangeReplaceCharCount; int lastLineBottom; // the bottom pixel of the last line been replaced - bool isMirrored; - bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color + bool isMirrored_; + bool bidiColoring = false; // apply the BIDI algorithm on text segments of the same color Image leftCaretBitmap = null; Image rightCaretBitmap = null; int caretDirection = DWT.NULL; @@ -149,32 +225,32 @@ Caret defaultCaret = null; bool updateCaretDirection = true; bool fixedLineHeight; - bool dragDetect = true; + bool dragDetect_ = true; IME ime; - + int alignment; bool justify; int indent; int lineSpacing; - final static bool IS_CARBON, IS_GTK, IS_MOTIF; - static { + const static bool IS_CARBON, IS_GTK, IS_MOTIF; + static this(){ String platform = DWT.getPlatform(); - IS_CARBON = "carbon".opEquals(platform); - IS_GTK = "gtk".opEquals(platform); - IS_MOTIF = "motif".opEquals(platform); + IS_CARBON = ("carbon" == platform); + IS_GTK = ("gtk" == platform); + IS_MOTIF = ("motif" == platform); } /** * The Printing class : printing of a range of text. - * An instance of <code>Printing</code> is returned in the - * StyledText#print(Printer) API. The run() method may be + * An instance of <code>Printing</code> is returned in the + * StyledText#print(Printer) API. The run() method may be * invoked from any thread. */ static class Printing : 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 + const static int LEFT = 0; // left aligned header/footer segment + const static int CENTER = 1; // centered header/footer segment + const static int RIGHT = 2; // right aligned header/footer segment Printer printer; StyledTextRenderer printerRenderer; @@ -182,7 +258,7 @@ Rectangle clientArea; FontData fontData; Font printerFont; - Hashtable resources; + Resource[Resource] resources; int tabLength; GC gc; // printer GC int pageWidth; // width of a printer page in pixels @@ -190,30 +266,30 @@ int endPage; // last page to print int startLine; // first (wrapped) line to print int endLine; // last (wrapped) line to print - bool singleLine; // widget single line mode + bool singleLine; // widget single line mode Point selection = null; // selected text - bool mirrored; // indicates the printing gc should be mirrored + bool mirrored; // indicates the printing gc should be mirrored int lineSpacing; int printMargin; /** * Creates an instance of <code>Printing</code>. - * Copies the widget content and rendering data that needs + * 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 - */ + */ this(StyledText styledText, Printer printer, StyledTextPrintOptions printOptions) { this.printer = printer; this.printOptions = printOptions; this.mirrored = (styledText.getStyle() & DWT.MIRRORED) !is 0; singleLine = styledText.isSingleLine(); startPage = 1; - endPage = Integer.MAX_VALUE; + endPage = int.max; PrinterData data = printer.getPrinterData(); - if (data.scope is PrinterData.PAGE_RANGE) { + if (data.scope_ is PrinterData.PAGE_RANGE) { startPage = data.startPage; endPage = data.endPage; if (endPage < startPage) { @@ -221,7 +297,7 @@ endPage = startPage; startPage = temp; } - } else if (data.scope is PrinterData.SELECTION) { + } else if (data.scope_ is PrinterData.SELECTION) { selection = styledText.getSelectionRange(); } printerRenderer = new StyledTextRenderer(printer, null); @@ -231,7 +307,7 @@ /** * Caches all line data that needs to be requested from a listener. * </p> - * @param printerContent <code>StyledTextContent</code> to request + * @param printerContent <code>StyledTextContent</code> to request * line data for. */ void cacheLineData(StyledText styledText) { @@ -252,7 +328,7 @@ if (styledText.isBidi()) { int[] segments = styledText.getBidiSegments(lineOffset, line); printerRenderer.setLineSegments(i, 1, segments); - } + } event = styledText.getLineStyleData(lineOffset, line); if (event !is null) { printerRenderer.setLineIndent(i, 1, event.indent); @@ -268,15 +344,18 @@ } Point screenDPI = styledText.getDisplay().getDPI(); Point printerDPI = printer.getDPI(); - resources = new Hashtable (); + resources = null; for (int i = 0; i < lineCount; i++) { Color color = printerRenderer.getLineBackground(i, null); if (color !is null) { if (printOptions.printLineBackground) { - Color printerColor = cast(Color)resources.get(color); - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } printerRenderer.setLineBackground(i, 1, printerColor); } else { @@ -293,20 +372,26 @@ StyleRange style = styles[i]; Font font = style.font; if (style.font !is null) { - Font printerFont = cast(Font)resources.get(font); - if (printerFont is null) { + Font printerFont; + if ( auto p = font in resources ) { + printerFont = cast(Font)*p; + } + else { printerFont = new Font (printer, font.getFontData()); - resources.put(font, printerFont); + resources[font]= printerFont; } style.font = printerFont; } Color color = style.foreground; if (color !is null) { - Color printerColor = cast(Color)resources.get(color); if (printOptions.printTextForeground) { - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } style.foreground = printerColor; } else { @@ -315,11 +400,14 @@ } color = style.background; if (color !is null) { - Color printerColor = cast(Color)resources.get(color); if (printOptions.printTextBackground) { - if (printerColor is null) { + Color printerColor; + if ( auto p = color in resources ) { + printerColor = cast(Color)*p; + } + else { printerColor = new Color (printer, color.getRGB()); - resources.put(color, printerColor); + resources[color]=printerColor; } style.background = printerColor; } else { @@ -370,14 +458,10 @@ gc.dispose(); gc = null; } - if (resources !is null) { - Enumeration enumeration = resources.elements(); - while (enumeration.hasMoreElements()) { - Resource resource = cast(Resource) enumeration.nextElement(); - resource.dispose(); - } - resources = null; - } + foreach( resource; resources.values ){ + resource.dispose(); + } + resources = null; if (printerFont !is null) { printerFont.dispose(); printerFont = null; @@ -390,15 +474,15 @@ void init_() { Rectangle trim = printer.computeTrim(0, 0, 0, 0); Point dpi = printer.getDPI(); - - printerFont = new Font(printer, fontData.getName(), fontData.getHeight(), DWT.NORMAL); + + printerFont = new Font( cast(Device)printer, fontData.getName(), fontData.getHeight(), DWT.NORMAL); clientArea = printer.getClientArea(); pageWidth = clientArea.width; // one inch margin around text - clientArea.x = dpi.x + trim.x; + clientArea.x = dpi.x + trim.x; clientArea.y = dpi.y + trim.y; clientArea.width -= (clientArea.x + trim.width); - clientArea.height -= (clientArea.y + trim.height); + clientArea.height -= (clientArea.y + trim.height); int style = mirrored ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; gc = new GC(printer, style); @@ -412,16 +496,16 @@ if (printOptions.footer !is null) { clientArea.height -= lineHeight * 2; } - + // TODO not wrapped StyledTextContent content = printerRenderer.content; startLine = 0; endLine = singleLine ? 0 : content.getLineCount() - 1; PrinterData data = printer.getPrinterData(); - if (data.scope is PrinterData.PAGE_RANGE) { + if (data.scope_ is PrinterData.PAGE_RANGE) { int pageSize = clientArea.height / lineHeight;//WRONG startLine = (startPage - 1) * pageSize; - } else if (data.scope is PrinterData.SELECTION) { + } else if (data.scope_ is PrinterData.SELECTION) { startLine = content.getLineAtOffset(selection.x); if (selection.y > 0) { endLine = content.getLineAtOffset(selection.x + selection.y - 1); @@ -477,7 +561,7 @@ } TextLayout layout = printerRenderer.getTextLayout(i, orientation, width, lineSpacing); Color lineBackground = printerRenderer.getLineBackground(i, background); - int paragraphBottom = paintY + layout.getBounds().height; + int paragraphBottom = paintY + layout.getBounds().height; if (paragraphBottom <= pageBottom) { //normal case, the whole paragraph fits in the current page printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); @@ -507,7 +591,7 @@ printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i); gc.setClipping(cast(Rectangle)null); printDecoration(page, false, printLayout); - printer.endPage(); + printer.endPage(); page++; if (page <= endPage) { printer.startPage(); @@ -532,7 +616,7 @@ } /** * 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 */ @@ -541,16 +625,16 @@ if (text is null) return; int lastSegmentIndex = 0; for (int i = 0; i < 3; i++) { - int segmentIndex = text.indexOf(StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); + int segmentIndex = text.indexOf( StyledTextPrintOptions.SEPARATOR, lastSegmentIndex); String segment; - if (segmentIndex is -1) { + if (segmentIndex is -1 ) { segment = text.substring(lastSegmentIndex); printDecorationSegment(segment, i, page, header, layout); break; } else { segment = text.substring(lastSegmentIndex, segmentIndex); printDecorationSegment(segment, i, page, header, layout); - lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length(); + lastSegmentIndex = segmentIndex + StyledTextPrintOptions.SEPARATOR.length; } } } @@ -558,22 +642,22 @@ * 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 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, bool header, TextLayout layout) { + void printDecorationSegment(String segment, int alignment, int page, bool header, TextLayout layout) { int pageIndex = segment.indexOf(StyledTextPrintOptions.PAGE_TAG); - if (pageIndex !is -1) { - int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length(); + if (pageIndex !is -1 ) { + int pageTagLength = StyledTextPrintOptions.PAGE_TAG.length; StringBuffer buffer = new StringBuffer(segment.substring (0, pageIndex)); buffer.append (page); buffer.append (segment.substring(pageIndex + pageTagLength)); - segment = buffer.toString(); - } - if (segment.length() > 0) { + segment = buffer.toString().dup; + } + if (segment.length > 0) { layout.setText(segment); int segmentWidth = layout.getBounds().width; int segmentHeight = printerRenderer.getLineHeight(); @@ -598,7 +682,7 @@ Rectangle rect = layout.getBounds(); gc.setBackground(background); gc.fillRectangle(x, y, rect.width, rect.height); - + // int lineCount = layout.getLineCount(); // for (int i = 0; i < lineCount; i++) { // Rectangle rect = layout.getLineBounds(i); @@ -620,7 +704,7 @@ printLayout.setText(""); } } else { - printLayout.setText(String.valueOf(index)); + printLayout.setText(to!(String)(index)); } int paintX = x - printMargin - printLayout.getBounds().width; printLayout.draw(gc, paintX, y); @@ -639,64 +723,66 @@ jobName = "Printing"; } if (printer.startJob(jobName)) { - init(); + init_(); print(); dispose(); printer.endJob(); } - } + } } /** * The <code>RTFWriter</code> class is used to write widget content as - * rich text. The implementation complies with the RTF specification + * 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. + * 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 + * 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 + * 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 : TextWriter { - static final int DEFAULT_FOREGROUND = 0; - static final int DEFAULT_BACKGROUND = 1; - Vector colorTable, fontTable; + + alias TextWriter.write write; + + static const int DEFAULT_FOREGROUND = 0; + static const int DEFAULT_BACKGROUND = 1; + Color[] colorTable; + Font[] fontTable; bool 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 + * in the document. <code>start</code> and <code>length</code>can be set to specify partial * lines. * - * @param start start offset of content to write, 0 based from + * @param start start offset of content to write, 0 based from * beginning of document * @param length length of content to write */ public this(int start, int length) { super(start, length); - colorTable = new Vector(); - fontTable = new Vector(); - colorTable.addElement(getForeground()); - colorTable.addElement(getBackground()); - fontTable.addElement(getFont()); + colorTable ~= getForeground(); + colorTable ~= getBackground(); + fontTable ~= getFont(); setUnicode(); } /** * Closes the RTF writer. Once closed no more content can be written. - * <b>NOTE:</b> <code>toString()</code> does not return a valid RTF String until + * <b>NOTE:</b> <code>toString()</code> does not return a valid RTF string until * <code>close()</code> has been called. */ - public void close() { + public override void close() { if (!isClosed()) { writeHeader(); write("\n}}\0"); super.close(); } - } + } /** * Returns the index of the specified color in the RTF color table. * @@ -707,10 +793,16 @@ */ int getColorIndex(Color color, int defaultIndex) { if (color is null) return defaultIndex; - int index = colorTable.indexOf(color); + int index = -1; + foreach( i, col; colorTable ){ + if( col == color ){ + index = i; + break; + } + } if (index is -1) { - index = colorTable.size(); - colorTable.addElement(color); + index = colorTable.length; + colorTable ~= color; } return index; } @@ -723,10 +815,16 @@ * or "defaultIndex" if "color" is null. */ int getFontIndex(Font font) { - int index = fontTable.indexOf(font); + int index = -1; + foreach( i, f; colorTable ){ + if( f == font ){ + index = i; + break; + } + } if (index is -1) { - index = fontTable.size(); - fontTable.addElement(font); + index = fontTable.length; + fontTable ~= font; } return index; } @@ -735,68 +833,72 @@ * 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 !is null) { - int majorIndex = osVersion.indexOf('.'); - if (majorIndex !is -1) { - osVersion = osVersion.substring(0, majorIndex); - try { - majorVersion = Integer.parseInt(osVersion); - } catch (NumberFormatException exception) { - // ignore exception. version number remains unknown. - // will write without Unicode - } - } - } - WriteUnicode = !osName.startsWith(Win95) && - !osName.startsWith(Win98) && - !osName.startsWith(WinME) && - (!osName.startsWith(WinNT) || majorVersion > 4); +// const String Win95 = "windows 95"; +// const String Win98 = "windows 98"; +// const String WinME = "windows me"; +// const 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 !is null) { +// int majorIndex = osVersion.indexOf('.'); +// if (majorIndex !is -1) { +// osVersion = osVersion.substring(0, majorIndex); +// try { +// majorVersion = Integer.parseInt(osVersion); +// } catch (NumberFormatException exception) { +// // ignore exception. version number remains unknown. +// // will write without Unicode +// } +// } +// } +// WriteUnicode = !osName.startsWith(Win95) && +// !osName.startsWith(Win98) && +// !osName.startsWith(WinME) && +// (!osName.startsWith(WinNT) || majorVersion > 4); + WriteUnicode = true; // we are on linux-gtk } /** - * Appends the specified segment of "String" to the RTF data. + * Appends the specified segment of "string" to the RTF data. * Copy from <code>start</code> up to, but excluding, <code>end</code>. * - * @param String String to copy a segment from. Must not contain + * @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); + void write(String string, int start, int end) { + start = 0; + end = string.length; + int incr = 1; + for (int index = start; index < end; index+=incr) { + dchar ch = firstCodePoint( string[index .. $], incr ); if (ch > 0xFF && WriteUnicode) { - // write the sub String from the last escaped character + // 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( string[start .. index ] ); } write("\\u"); - write(Integer.toString(cast(short) ch)); + write( to!(String)( cast(short)ch )); write(' '); // control word delimiter - start = index + 1; + start = index + incr; } else if (ch is '}' || ch is '{' || ch is '\\') { - // write the sub String from the last escaped character + // 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(string[start .. index]); } write('\\'); - write(ch); + write(cast(char)ch); // ok because one of {}\ start = index + 1; } } // write from the last escaped character to the end. // Fixes bug 21698. if (start < end) { - write(String.substring(start, end)); + write(string[ start .. end]); } } /** @@ -806,28 +908,31 @@ StringBuffer header = new StringBuffer(); FontData fontData = getFont().getFontData()[0]; header.append("{\\rtf1\\ansi"); - // specify code page, necessary for copy to work in bidi + // specify code page, necessary for copy to work in bidi // systems that don't support Unicode RTF. - String cpg = System.getProperty("file.encoding").toLowerCase(); + // PORTING_TODO: String cpg = System.getProperty("file.encoding").toLowerCase(); + String cpg = "UTF16"; + /+ 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(";"); - for (int i = 1; i < fontTable.size(); i++) { + for (int i = 1; i < fontTable.length; i++) { header.append("\\f"); header.append(i); header.append(" "); - FontData fd = (cast(Font)fontTable.elementAt(i)).getFontData()[0]; + FontData fd = (cast(Font)fontTable[i]).getFontData()[0]; header.append(fd.getName()); - header.append(";"); + header.append(";"); } header.append("}}\n{\\colortbl"); - for (int i = 0; i < colorTable.size(); i++) { - Color color = cast(Color) colorTable.elementAt(i); + for (int i = 0; i < colorTable.length; i++) { + Color color = cast(Color) colorTable[i]; header.append("\\red"); header.append(color.getRed()); header.append("\\green"); @@ -836,7 +941,7 @@ header.append(color.getBlue()); header.append(";"); } - // some RTF readers ignore the deff0 font tag. Explicitly + // 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 @@ -845,20 +950,20 @@ 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 + * Appends the specified line text to the RTF data. Lines will be formatted + * using the styles queried from the LineStyleListener, if set, or those set * directly in the widget. * * @param line line text to write as RTF. Must not contain line breaks * Line breaks should be written using writeLineDelimiter() - * @param lineOffset offset of the line. 0 based from the start of the - * widget document. Any text occurring before the start offset or after the + * @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 DWTException <ul> * <li>ERROR_IO when the writer is closed.</li> * </ul> */ - public void writeLine(String line, int lineOffset) { + public override void writeLine(String line, int lineOffset) { if (isClosed()) { DWT.error(DWT.ERROR_IO); } @@ -876,12 +981,12 @@ styles = event.styles; } else { lineAlignment = renderer.getLineAlignment(lineIndex, alignment); - lineIndent = renderer.getLineIndent(lineIndex, indent); + lineIndent = renderer.getLineIndent(lineIndex, indent); lineJustify = renderer.getLineJustify(lineIndex, justify); - ranges = renderer.getRanges(lineOffset, line.length()); - styles = renderer.getStyleRanges(lineOffset, line.length(), false); - } - if (styles is null) styles = new StyleRange[0]; + ranges = renderer.getRanges(lineOffset, line.length); + styles = renderer.getStyleRanges(lineOffset, line.length, false); + } + if (styles is null) styles = new StyleRange[0]; Color lineBackground = renderer.getLineBackground(lineIndex, null); event = getLineBackgroundData(lineOffset, line); if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground; @@ -895,11 +1000,11 @@ * <li>ERROR_IO when the writer is closed.</li> * </ul> */ - public void writeLineDelimiter(String lineDelimiter) { + public override void writeLineDelimiter(String lineDelimiter) { if (isClosed()) { DWT.error(DWT.ERROR_IO); } - write(lineDelimiter, 0, lineDelimiter.length()); + write(lineDelimiter, 0, lineDelimiter.length); write("\\par "); } /** @@ -913,34 +1018,35 @@ * * @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 + * @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. + * @param lineBackground line background color to use for formatting. * May be null. */ void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int alignment, bool justify) { - int lineLength = line.length(); + int lineLength = line.length; int startOffset = getStart(); int writeOffset = startOffset - lineOffset; if (writeOffset >= lineLength) return; int lineIndex = Math.max(0, writeOffset); - + write("\\fi"); write(indent); switch (alignment) { case DWT.LEFT: write("\\ql"); break; case DWT.CENTER: write("\\qc"); break; case DWT.RIGHT: write("\\qr"); break; + default: } if (justify) write("\\qj"); write(" "); - + if (lineBackground !is null) { write("{\\highlight"); write(getColorIndex(lineBackground, DEFAULT_BACKGROUND)); - write(" "); + write(" "); } int endOffset = startOffset + super.getCharCount(); int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); @@ -965,7 +1071,7 @@ // write any unstyled text if (lineIndex < start) { // copy to start of style - // style starting beyond end of write range or end of line + // style starting beyond end of write range or end of line // is guarded against above. write(line, lineIndex, start); lineIndex = start; @@ -988,10 +1094,10 @@ write(fontData.getHeight() * 2); } else { if ((style.fontStyle & DWT.BOLD) !is 0) { - write("\\b"); + write("\\b"); } if ((style.fontStyle & DWT.ITALIC) !is 0) { - write("\\i"); + write("\\i"); } } if (style.underline) { @@ -1000,7 +1106,7 @@ if (style.strikeout) { write("\\strike"); } - write(" "); + write(" "); // copy to end of style or end of write range or end of line int copyEnd = Math.min(end, lineEndOffset); // guard against invalid styles and let style processing continue @@ -1008,10 +1114,10 @@ write(line, lineIndex, copyEnd); if (font is null) { if ((style.fontStyle & DWT.BOLD) !is 0) { - write("\\b0"); + write("\\b0"); } if ((style.fontStyle & DWT.ITALIC) !is 0) { - write("\\i0"); + write("\\i0"); } } if (style.underline) { @@ -1032,21 +1138,21 @@ } /** * 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 + * 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() + * </b>NOTE:</b> <code>toString()</code> is guaranteed to return a valid string only after close() * has been called. * </p> */ class TextWriter { private StringBuffer buffer; private int startOffset; // offset of first character that will be written - private int endOffset; // offset of last character that will be written. - // 0 based from the beginning of the widget text. - private bool isClosed = false; - + private int endOffset; // offset of last character that will be written. + // 0 based from the beginning of the widget text. + private bool 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. @@ -1061,23 +1167,23 @@ } /** * 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 + * <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; - } - } - /** + 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 + } + /** + * 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 */ @@ -1089,37 +1195,38 @@ * @return a bool specifying whether or not the writer is closed */ public bool isClosed() { - return isClosed; + return isClosed_; } /** - * Returns the String. <code>close()</code> must be called before <code>toString()</code> - * is guaranteed to return a valid String. + * Returns the string. <code>close()</code> must be called before <code>toString()</code> + * is guaranteed to return a valid string. * - * @return the String + * @return the string */ - public String toString() { + public override String toString() { return buffer.toString(); } /** - * Appends the given String to the data. + * Appends the given string to the data. */ - void write(String String) { - buffer.append(String); + void write(String string) { + buffer.append(string); } /** - * Inserts the given String to the data at the specified offset. + * Inserts the given string to the data at the specified offset. * <p> * Do nothing if "offset" is < 0 or > getCharCount() * </p> * - * @param String text to insert - * @param offset offset in the existing data to insert "String" at. + * @param string text to insert + * @param offset offset in the existing data to insert "string" at. */ - void write(String String, int offset) { + void write(String string, int offset) { if (offset < 0 || offset > buffer.length()) { return; } - buffer.insert(offset, String); + buffer.select( offset ); + buffer.prepend( string ); } /** * Appends the given int to the data. @@ -1138,19 +1245,19 @@ * * @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 + * @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 DWTException <ul> * <li>ERROR_IO when the writer is closed.</li> * </ul> */ - public void writeLine(String line, int lineOffset) { - if (isClosed) { + public void writeLine(String line, int lineOffset) { + if (isClosed_) { DWT.error(DWT.ERROR_IO); - } + } int writeOffset = startOffset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; int lineIndex; if (writeOffset >= lineLength) { return; // whole line is outside write range @@ -1173,7 +1280,7 @@ * </ul> */ public void writeLineDelimiter(String lineDelimiter) { - if (isClosed) { + if (isClosed_) { DWT.error(DWT.ERROR_IO); } write(lineDelimiter); @@ -1186,7 +1293,7 @@ * <p> * The style value is either one of the style constants defined in * class <code>DWT</code> which is applicable to instances of this - * class, or must be built by <em>bitwise OR</em>'ing together + * 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>DWT</code> style constants. The class description * lists the style constants that are applicable to the class. @@ -1211,13 +1318,14 @@ * @see #getStyle */ public this(Composite parent, int style) { + selection = new Point(0, 0); super(parent, checkStyle(style)); // set the fg in the OS to ensure that these are the same as StyledText, necessary // for ensuring that the bg/fg the IME box uses is the same as what StyledText uses super.setForeground(getForeground()); super.setDragDetect(false); Display display = getDisplay(); - isMirrored = (super.getStyle() & DWT.MIRRORED) !is 0; + isMirrored_ = (super.getStyle() & DWT.MIRRORED) !is 0; fixedLineHeight = true; if ((style & DWT.READ_ONLY) !is 0) { setEditable(false); @@ -1240,7 +1348,7 @@ } if (isBidiCaret()) { createCaretBitmaps(); - Runnable runnable = new Runnable() { + Runnable runnable = new class() Runnable { public void run() { int direction = BidiUtil.getKeyboardLanguage() is BidiUtil.KEYBOARD_BIDI ? DWT.RIGHT : DWT.LEFT; if (direction is caretDirection) return; @@ -1251,7 +1359,7 @@ }; BidiUtil.addLanguageListener(this, runnable); } - setCaret(defaultCaret); + setCaret(defaultCaret); calculateScrollBars(); createKeyBindings(); setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); @@ -1259,8 +1367,8 @@ initializeAccessible(); setData("DEFAULT_DROP_TARGET_EFFECT", new StyledTextDropTargetEffect(this)); } -/** - * Adds an extended modify listener. An ExtendedModify event is sent by the +/** + * Adds an extended modify listener. An ExtendedModify event is sent by the * widget when the widget text has changed. * * @param extendedModifyListener the listener @@ -1281,15 +1389,15 @@ /** * Adds a bidirectional segment listener. * <p> - * 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 + * 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 + * 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. + * way they are stored. * </p> * * @param listener the listener @@ -1309,7 +1417,7 @@ addListener(LineGetSegments, new StyledTextListener(listener)); } /** - * Adds a line background listener. A LineGetBackground event is sent by the + * Adds a line background listener. A LineGetBackground event is sent by the * widget to determine the background color for a line. * * @param listener the listener @@ -1330,7 +1438,7 @@ addListener(LineGetBackground, new StyledTextListener(listener)); } /** - * Adds a line style listener. A LineGetStyle event is sent by the widget to + * Adds a line style listener. A LineGetStyle event is sent by the widget to * determine the styles for a line. * * @param listener the listener @@ -1351,8 +1459,8 @@ } addListener(LineGetStyle, new StyledTextListener(listener)); } -/** - * Adds a modify listener. A Modify event is sent by the widget when the widget text +/** + * Adds a modify listener. A Modify event is sent by the widget when the widget text * has changed. * * @param modifyListener the listener @@ -1369,7 +1477,7 @@ if (modifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Modify, new TypedListener(modifyListener)); } -/** +/** * Adds a paint object listener. A paint object event is sent by the widget when an object * needs to be drawn. * @@ -1381,9 +1489,9 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when listener is null</li> * </ul> - * + * * @since 3.2 - * + * * @see PaintObjectListener * @see PaintObjectEvent */ @@ -1392,15 +1500,15 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(PaintObject, new StyledTextListener(listener)); } -/** - * Adds a selection listener. A Selection event is sent by the widget when the +/** + * Adds a selection listener. A Selection event is sent by the widget when the * user changes the selection. * <p> * When <code>widgetSelected</code> is called, the event x and y fields contain * the start and end caret indices of the selection. * <code>widgetDefaultSelected</code> is not called for StyledTexts. * </p> - * + * * @param listener the listener which should be notified when the user changes the receiver's selection * @exception IllegalArgumentException <ul> @@ -1420,10 +1528,10 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Selection, new TypedListener(listener)); } -/** - * Adds a verify key listener. A VerifyKey event is sent by the widget when a key - * is pressed. The widget ignores the key press if the listener sets the doit field - * of the event to false. +/** + * Adds a verify key listener. A VerifyKey event is sent by the widget when a key + * is pressed. The widget ignores the key press if the listener sets the doit field + * of the event to false. * * @param listener the listener * @exception DWTException <ul> @@ -1439,10 +1547,10 @@ if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(VerifyKey, new StyledTextListener(listener)); } -/** - * Adds a verify listener. A Verify event is sent by the widget when the widget text - * is about to change. The listener can set the event text and the doit field to - * change the text that is set in the widget or to force the widget to ignore the +/** + * Adds a verify listener. A Verify event is sent by the widget when the widget text + * is about to change. The listener can set the event text and the doit field to + * change the text that is set in the widget or to force the widget to ignore the * text change. * * @param verifyListener the listener @@ -1459,9 +1567,9 @@ if (verifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); addListener(DWT.Verify, new TypedListener(verifyListener)); } -/** - * Adds a word movement listener. A movement event is sent when the boundary - * of a word is needed. For example, this occurs during word next and word +/** + * Adds a word movement listener. A movement event is sent when the boundary + * of a word is needed. For example, this occurs during word next and word * previous actions. * * @param movementListener the listener @@ -1472,12 +1580,12 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when listener is null</li> * </ul> - * + * * @see MovementEvent * @see MovementListener * @see #removeWordMovementListener - * - * @since 3.3 + * + * @since 3.3 */ public void addWordMovementListener(MovementListener movementListener) { checkWidget(); @@ -1485,26 +1593,24 @@ addListener(WordNext, new StyledTextListener(movementListener)); addListener(WordPrevious, new StyledTextListener(movementListener)); } -/** - * Appends a String to the text at the end of the widget. - * - * @param String the String to be appended +/** + * Appends a string to the text at the end of the widget. + * + * @param string the string to be appended * @see #replaceTextRange(int,int,String) * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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 is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + */ +public void append(String string) { + checkWidget(); + // DWT extension: allow null for zero length string +// if (string is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } int lastChar = Math.max(getCharCount(), 0); - replaceTextRange(lastChar, 0, String); + replaceTextRange(lastChar, 0, string); } /** * Calculates the scroll bars @@ -1515,7 +1621,7 @@ setScrollBars(true); if (verticalBar !is null) { verticalBar.setIncrement(getVerticalIncrement()); - } + } if (horizontalBar !is null) { horizontalBar.setIncrement(getHorizontalIncrement()); } @@ -1535,7 +1641,7 @@ return; } topIndex = Compatibility.ceil(getVerticalScrollOffset(), verticalIncrement); - // Set top index to partially visible top line if no line is fully + // 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) { @@ -1543,7 +1649,7 @@ int bottomPixel = getVerticalScrollOffset() + clientAreaHeight; int fullLineTopPixel = topIndex * verticalIncrement; int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; - // set top index to partially visible line if no line fully fits in + // 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) { @@ -1608,7 +1714,7 @@ return style; } /** - * Scrolls down the text to use new space made available by a resize or by + * Scrolls down the text to use new space made available by a resize or by * deleted lines. */ void claimBottomFreeSpace() { @@ -1632,11 +1738,11 @@ */ void claimRightFreeSpace() { int newHorizontalOffset = Math.max(0, renderer.getWidth() - (clientAreaWidth - leftMargin - rightMargin)); - if (newHorizontalOffset < horizontalScrollOffset) { + 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 + // align the right end of the item with the right border of the // client area (window is scrolled right). - scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); + scrollHorizontal(newHorizontalOffset - horizontalScrollOffset, true); } } /** @@ -1646,7 +1752,7 @@ */ void clearSelection(bool sendEvent) { int selectionStart = selection.x; - int selectionEnd = selection.y; + int selectionEnd = selection.y; resetSelection(); // redraw old selection, if any if (selectionEnd - selectionStart > 0) { @@ -1663,7 +1769,7 @@ } } } -public Point computeSize (int wHint, int hHint, bool changed) { +public override Point computeSize (int wHint, int hHint, bool changed) { checkWidget(); int lineCount = (getStyle() & DWT.SINGLE) !is 0 ? 1 : content.getLineCount(); int width = 0; @@ -1701,7 +1807,7 @@ * <p> * The text will be put on the clipboard in plain text format and RTF format. * The <code>DND.CLIPBOARD</code> clipboard is used for data that is - * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or + * transferred by keyboard accelerator (such as Ctrl+C/Ctrl+V) or * by menu action. * </p> * @@ -1715,24 +1821,24 @@ copy(DND.CLIPBOARD); } /** - * Copies the selected text to the specified clipboard. The text will be put in the + * 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 + * 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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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) { @@ -1743,7 +1849,7 @@ try { setClipboardContent(selection.x, length, clipboardType); } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // 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. @@ -1755,16 +1861,16 @@ } /** * Returns the alignment of the widget. - * + * * @return the alignment - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #getLineAlignment(int) - * + * * @since 3.2 */ public int getAlignment() { @@ -1802,24 +1908,24 @@ return Math.min(height, availableHeight); } /** - * Returns a String that uses only the line delimiter specified by the + * Returns a string that uses only the line delimiter specified by the * StyledTextContent implementation. * <p> * Returns only the first line if the widget has the DWT.SINGLE style. * </p> * - * @param text the text that may have line delimiters that don't - * match the model line delimiter. Possible line delimiters + * @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 + * @return the converted text that only uses the line delimiter + * specified by the model. Returns only the first line if the widget * has the DWT.SINGLE style. */ -String getModelDelimitedText(String text) { - int length = text.length(); +String getModelDelimitedText(String text) { + int length = text.length; if (length is 0) { return text; - } + } int crIndex = 0; int lfIndex = 0; int i = 0; @@ -1827,10 +1933,10 @@ String delimiter = getLineDelimiter(); while (i < length) { if (crIndex !is -1) { - crIndex = text.indexOf(DWT.CR, i); + crIndex = text.indexOf (DWT.CR, i); } if (lfIndex !is -1) { - lfIndex = text.indexOf(DWT.LF, i); + lfIndex = text.indexOf (DWT.LF, i); } if (lfIndex is -1 && crIndex is -1) { // no more line breaks? break; @@ -1850,7 +1956,7 @@ } convertedText.append(delimiter); } - // copy remaining text if any and if not in single line mode or no + // 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() is 0)) { convertedText.append(text.substring(i)); @@ -1877,9 +1983,9 @@ void createKeyBindings() { int nextKey = isMirrored() ? DWT.ARROW_LEFT : DWT.ARROW_RIGHT; int previousKey = isMirrored() ? DWT.ARROW_RIGHT : DWT.ARROW_LEFT; - + // Navigation - setKeyBinding(DWT.ARROW_UP, ST.LINE_UP); + setKeyBinding(DWT.ARROW_UP, ST.LINE_UP); setKeyBinding(DWT.ARROW_DOWN, ST.LINE_DOWN); if (IS_CARBON) { setKeyBinding(previousKey | DWT.MOD1, ST.LINE_START); @@ -1904,23 +2010,23 @@ setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1, ST.WINDOW_END); setKeyBinding(nextKey, ST.COLUMN_NEXT); setKeyBinding(previousKey, ST.COLUMN_PREVIOUS); - + // Selection - setKeyBinding(DWT.ARROW_UP | DWT.MOD2, ST.SELECT_LINE_UP); + setKeyBinding(DWT.ARROW_UP | DWT.MOD2, ST.SELECT_LINE_UP); setKeyBinding(DWT.ARROW_DOWN | DWT.MOD2, ST.SELECT_LINE_DOWN); if (IS_CARBON) { setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_START); setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_LINE_END); - setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_TEXT_START); setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_TEXT_END); - setKeyBinding(DWT.ARROW_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.ARROW_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); setKeyBinding(DWT.ARROW_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); setKeyBinding(nextKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_NEXT); setKeyBinding(previousKey | DWT.MOD2 | DWT.MOD3, ST.SELECT_WORD_PREVIOUS); } else { setKeyBinding(DWT.HOME | DWT.MOD2, ST.SELECT_LINE_START); setKeyBinding(DWT.END | DWT.MOD2, ST.SELECT_LINE_END); - setKeyBinding(DWT.HOME | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(DWT.HOME | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_START); setKeyBinding(DWT.END | DWT.MOD1 | DWT.MOD2, ST.SELECT_TEXT_END); setKeyBinding(nextKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_NEXT); setKeyBinding(previousKey | DWT.MOD1 | DWT.MOD2, ST.SELECT_WORD_PREVIOUS); @@ -1930,8 +2036,8 @@ setKeyBinding(DWT.PAGE_UP | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_START); setKeyBinding(DWT.PAGE_DOWN | DWT.MOD1 | DWT.MOD2, ST.SELECT_WINDOW_END); setKeyBinding(nextKey | DWT.MOD2, ST.SELECT_COLUMN_NEXT); - setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); - + setKeyBinding(previousKey | DWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); + // Modification // Cut, Copy, Paste setKeyBinding('X' | DWT.MOD1, ST.CUT); @@ -1952,7 +2058,7 @@ setKeyBinding(DWT.DEL, ST.DELETE_NEXT); setKeyBinding(DWT.BS | DWT.MOD1, ST.DELETE_WORD_PREVIOUS); setKeyBinding(DWT.DEL | DWT.MOD1, ST.DELETE_WORD_NEXT); - + // Miscellaneous setKeyBinding(DWT.INSERT, ST.TOGGLE_OVERWRITE); } @@ -1965,30 +2071,30 @@ int caretWidth = BIDI_CARET_WIDTH; Display display = getDisplay(); if (leftCaretBitmap !is null) { - if (defaultCaret !is null && leftCaretBitmap.opEquals(defaultCaret.getImage())) { + if (defaultCaret !is null && leftCaretBitmap==/*eq*/defaultCaret.getImage()) { defaultCaret.setImage(null); } leftCaretBitmap.dispose(); } int lineHeight = renderer.getLineHeight(); leftCaretBitmap = new Image(display, caretWidth, lineHeight); - GC gc = new GC (leftCaretBitmap); + GC gc = new GC (leftCaretBitmap); gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); gc.fillRectangle(0, 0, caretWidth, lineHeight); gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); gc.drawLine(0,0,0,lineHeight); gc.drawLine(0,0,caretWidth-1,0); gc.drawLine(0,1,1,1); - gc.dispose(); - + gc.dispose(); + if (rightCaretBitmap !is null) { - if (defaultCaret !is null && rightCaretBitmap.opEquals(defaultCaret.getImage())) { + if (defaultCaret !is null && rightCaretBitmap==/*eq*/defaultCaret.getImage()) { defaultCaret.setImage(null); } rightCaretBitmap.dispose(); } rightCaretBitmap = new Image(display, caretWidth, lineHeight); - gc = new GC (rightCaretBitmap); + gc = new GC (rightCaretBitmap); gc.setBackground(display.getSystemColor(DWT.COLOR_BLACK)); gc.fillRectangle(0, 0, caretWidth, lineHeight); gc.setForeground(display.getSystemColor(DWT.COLOR_WHITE)); @@ -1998,7 +2104,7 @@ gc.dispose(); } /** - * Moves the selected text to the clipboard. The text will be put in the + * Moves the selected text to the clipboard. The text will be put in the * clipboard in plain text format and RTF format. * * @exception DWTException <ul> @@ -2013,7 +2119,7 @@ try { setClipboardContent(selection.x, length, DND.CLIPBOARD); } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // 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. @@ -2027,9 +2133,9 @@ 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. + * 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) { @@ -2045,7 +2151,7 @@ endAutoScroll(); } } -/** +/** * Initiates autoscrolling. * * @param direction DWT.UP, DWT.DOWN, DWT.COLUMN_NEXT, DWT.COLUMN_PREVIOUS @@ -2056,13 +2162,15 @@ if (autoScrollDirection is direction) { return; } - + Runnable timer = null; - final Display display = getDisplay(); + final Display disp = getDisplay(); // Set a timer that will simulate the user pressing and holding // down a cursor key (i.e., arrowUp, arrowDown). if (direction is DWT.UP) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is DWT.UP) { doSelectionPageUp(autoScrollDistance); @@ -2073,7 +2181,9 @@ autoScrollDirection = direction; display.timerExec(V_SCROLL_RATE, timer); } else if (direction is DWT.DOWN) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is DWT.DOWN) { doSelectionPageDown(autoScrollDistance); @@ -2084,7 +2194,9 @@ autoScrollDirection = direction; display.timerExec(V_SCROLL_RATE, timer); } else if (direction is ST.COLUMN_NEXT) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is ST.COLUMN_NEXT) { doVisualNext(); @@ -2097,7 +2209,9 @@ autoScrollDirection = direction; display.timerExec(H_SCROLL_RATE, timer); } else if (direction is ST.COLUMN_PREVIOUS) { - timer = new Runnable() { + timer = new class(disp) Runnable { + Display display; + this( Display d ){ this.display = d; } public void run() { if (autoScrollDirection is ST.COLUMN_PREVIOUS) { doVisualPrevious(); @@ -2126,13 +2240,14 @@ int lineIndex = content.getLineAtOffset(caretOffset); int lineOffset = content.getOffsetAtLine(lineIndex); if (caretOffset is lineOffset) { + // DWT: on line start, delete line break lineOffset = content.getOffsetAtLine(lineIndex - 1); - event.start = lineOffset + content.getLine(lineIndex - 1).length(); + event.start = lineOffset + content.getLine(lineIndex - 1).length; event.end = caretOffset; } else { TextLayout layout = renderer.getTextLayout(lineIndex); - int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CHAR); - renderer.disposeTextLayout(layout); + int start = layout.getPreviousOffset(caretOffset - lineOffset, DWT.MOVEMENT_CLUSTER); + renderer.disposeTextLayout(layout); event.start = start + lineOffset; event.end = caretOffset; } @@ -2140,16 +2255,16 @@ } } /** - * Replaces the selection with the character or insert the character at the + * Replaces the selection with the character or insert the character at the * current caret position if no selection exists. * <p> - * If a carriage return was typed replace it with the line break character + * 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) { +void doContent(dchar key) { Event event = new Event(); event.start = selection.x; event.end = selection.y; @@ -2162,18 +2277,18 @@ } } else if (selection.x is selection.y && overwrite && key !is TAB) { // no selection and overwrite mode is on and the typed key is not a - // tab character (tabs are always inserted without overwriting)? + // tab character (tabs are always inserted without overwriting)? int lineIndex = content.getLineAtOffset(event.end); int lineOffset = content.getOffsetAtLine(lineIndex); String line = content.getLine(lineIndex); - // replace character at caret offset if the caret is not at the + // 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}); + if (event.end < lineOffset + line.length) { + event.end+=dcharToString( key ).length; + } + event.text = dcharToString( key ); } else { - event.text = new String(new char[] {key}); + event.text = dcharToString( key ); } if (event.text !is null) { if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) { @@ -2186,12 +2301,12 @@ * 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 + // place caret at end of first line if receiver is in single // line mode. fixes 4820. if (isSingleLine()) { doLineEnd(); } else { - int length = content.getCharCount(); + int length = content.getCharCount(); if (caretOffset < length) { caretOffset = length; showCaret(); @@ -2209,7 +2324,7 @@ } /** * Moves the caret to the start of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. * * @see #doSelectionCursorPrevious @@ -2225,7 +2340,7 @@ } /** * Moves the caret to the end of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. * * @see #doSelectionCursorNext @@ -2252,7 +2367,7 @@ } else if (caretOffset < content.getCharCount()) { int line = content.getLineAtOffset(caretOffset); int lineOffset = content.getOffsetAtLine(line); - int lineLength = content.getLine(line).length(); + int lineLength = content.getLine(line).length; if (caretOffset is lineOffset + lineLength) { event.start = caretOffset; event.end = content.getOffsetAtLine(line + 1); @@ -2268,7 +2383,7 @@ */ void doDeleteWordNext() { if (selection.x !is selection.y) { - // if a selection exists, treat the as if + // if a selection exists, treat the as if // only the delete key was pressed doDelete(); } else { @@ -2284,7 +2399,7 @@ */ void doDeleteWordPrevious() { if (selection.x !is selection.y) { - // if a selection exists, treat as if + // if a selection exists, treat as if // only the backspace key was pressed doBackspace(); } else { @@ -2296,8 +2411,8 @@ } } /** - * 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 + * 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. */ void doLineDown(bool select) { @@ -2330,8 +2445,8 @@ int oldColumnX = columnX; int oldHScrollOffset = horizontalScrollOffset; if (select) { - setMouseWordSelectionAnchor(); - // select first and then scroll to reduce flash when key + setMouseWordSelectionAnchor(); + // select first and then scroll to reduce flash when key // repeat scrolls lots of lines doSelection(ST.COLUMN_NEXT); } @@ -2344,7 +2459,7 @@ */ void doLineEnd() { int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); + int lineOffset = content.getOffsetAtLine(caretLine); int lineEndOffset; if (wordWrap) { TextLayout layout = renderer.getTextLayout(caretLine); @@ -2354,7 +2469,7 @@ lineEndOffset = lineOffset + offsets[lineIndex + 1]; renderer.disposeTextLayout(layout); } else { - int lineLength = content.getLine(caretLine).length(); + int lineLength = content.getLine(caretLine).length; lineEndOffset = lineOffset + lineLength; } if (caretOffset < lineEndOffset) { @@ -2384,8 +2499,8 @@ } } /** - * 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 + * 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. */ void doLineUp(bool select) { @@ -2435,25 +2550,25 @@ int line = getLineIndex(y); updateCaretDirection = true; - // allow caret to be placed below first line only if receiver is + // allow caret to be placed below first line only if receiver is // not in single line mode. fixes 4820. if (line < 0 || (isSingleLine() && line > 0)) { return; } int oldCaretAlignment = caretAlignment; int newCaretOffset = getOffsetAtPoint(x, y); - + if (doubleClickEnabled && clickCount > 1) { newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); } - + int newCaretLine = content.getLineAtOffset(newCaretOffset); - - // Is the mouse within the left client area border or on - // a different line? If not the autoscroll selection + + // 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 (0 <= y && y < clientAreaHeight && - (0 <= x && x < clientAreaWidth || wordWrap || + if (0 <= y && y < clientAreaHeight && + (0 <= x && x < clientAreaWidth || wordWrap || newCaretLine !is content.getLineAtOffset(caretOffset))) { if (newCaretOffset !is caretOffset || caretAlignment !is oldCaretAlignment) { caretOffset = newCaretOffset; @@ -2470,8 +2585,8 @@ * Updates the selection based on the caret position */ void doMouseSelection() { - if (caretOffset <= selection.x || - (caretOffset > selection.x && + if (caretOffset <= selection.x || + (caretOffset > selection.x && caretOffset < selection.y && selectionAnchor is selection.x)) { doSelection(ST.COLUMN_PREVIOUS); } else { @@ -2479,20 +2594,20 @@ } } /** - * Returns the offset of the word at the specified offset. - * If the current selection : from high index to low index - * (i.e., right to left, or caret is at left border of selection on + * Returns the offset of the word at the specified offset. + * If the current selection extends from high index to low index + * (i.e., right to left, or caret is at left border of selection on * non-bidi platforms) the start offset of the word preceding the - * selection is returned. If the current selection : from - * low index to high index the end offset of the word following + * selection is returned. If the current selection extends from + * low index to high index the end offset of the word following * the selection is returned. - * + * * @param x mouse x location * @param newCaretOffset caret offset of the mouse cursor location * @param line line index of the mouse cursor location */ int doMouseWordSelect(int x, int newCaretOffset, int line) { - // flip selection anchor based on word selection direction from + // 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) @@ -2517,7 +2632,7 @@ if (line + 1 < content.getLineCount()) { lineEnd = content.getOffsetAtLine(line + 1); } - newCaretOffset = lineEnd; + newCaretOffset = lineEnd; } } } @@ -2527,9 +2642,9 @@ * Scrolls one page down so that the last line (truncated or whole) * of the current page becomes the fully visible top line. * <p> - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the end - * of the text where a full page scroll is not possible. In this case + * The caret is 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> * @@ -2546,7 +2661,7 @@ int lineHeight = renderer.getLineHeight(); int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; int scrollLines = Math.min(lineCount - caretLine - 1, lines); - // ensure that scrollLines never gets negative and at least one + // ensure that scrollLines never gets negative and at least one // line is scrolled. fixes bug 5602. scrollLines = Math.max(1, scrollLines); caretOffset = getOffsetAtPoint(columnX, getLinePixel(caretLine + scrollLines)); @@ -2627,10 +2742,10 @@ height = getAvailableHeightBellow(height); scrollVertical(height, true); if (height is 0) setCaretLocation(); - } + } showCaret(); int hScrollChange = oldHScrollOffset - horizontalScrollOffset; - columnX = oldColumnX + hScrollChange; + columnX = oldColumnX + hScrollChange; } /** * Moves the cursor to the end of the last fully visible line. @@ -2652,14 +2767,14 @@ index--; } if (index is -1 && lineIndex > 0) { - bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length(); + bottomOffset = content.getOffsetAtLine(lineIndex - 1) + content.getLine(lineIndex - 1).length; } else { bottomOffset = content.getOffsetAtLine(lineIndex) + Math.max(0, layout.getLineOffsets()[index + 1] - 1); } renderer.disposeTextLayout(layout); } else { int lineIndex = getBottomIndex(); - bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length(); + bottomOffset = content.getOffsetAtLine(lineIndex) + content.getLine(lineIndex).length; } if (caretOffset < bottomOffset) { caretOffset = bottomOffset; @@ -2695,7 +2810,7 @@ } else { topOffset = content.getOffsetAtLine(lineIndex) + layout.getLineOffsets()[index]; } - renderer.disposeTextLayout(layout); + renderer.disposeTextLayout(layout); } else { topOffset = content.getOffsetAtLine(topIndex); } @@ -2708,17 +2823,17 @@ /** * 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 + * 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(bool select, int height) { if (isSingleLine()) return; int oldHScrollOffset = horizontalScrollOffset; - int oldColumnX = columnX; + int oldColumnX = columnX; if (isFixedLineHeight()) { - int caretLine = getCaretLine(); + int caretLine = getCaretLine(); if (caretLine > 0) { int lineHeight = renderer.getLineHeight(); int lines = (height is -1 ? clientAreaHeight : height) / lineHeight; @@ -2798,11 +2913,11 @@ lineHeight = renderer.getLineHeight(--lineIndex); } lineHeight = renderer.getLineHeight(lineIndex); - caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); + caretOffset = getOffsetAtPoint(columnX, lineHeight - caretHeight, lineIndex); if (select) doSelection(ST.COLUMN_PREVIOUS); height = getAvailableHeightAbove(height); scrollVertical(-height, true); - if (height is 0) setCaretLocation(); + if (height is 0) setCaretLocation(); } showCaret(); int hScrollChange = oldHScrollOffset - horizontalScrollOffset; @@ -2813,15 +2928,15 @@ */ void doSelection(int direction) { int redrawStart = -1; - int redrawEnd = -1; + int redrawEnd = -1; if (selectionAnchor is -1) { selectionAnchor = selection.x; - } + } if (direction is ST.COLUMN_PREVIOUS) { if (caretOffset < selection.x) { // grow selection - redrawEnd = selection.x; - redrawStart = selection.x = caretOffset; + redrawEnd = selection.x; + redrawStart = selection.x = caretOffset; // check if selection has reversed direction if (selection.y !is selectionAnchor) { redrawEnd = selection.y; @@ -2829,10 +2944,10 @@ } // test whether selection actually changed. Fixes 1G71EO1 } else if (selectionAnchor is selection.x && caretOffset < selection.y) { - // caret moved towards selection anchor (left side of selection). - // shrink selection + // caret moved towards selection anchor (left side of selection). + // shrink selection redrawEnd = selection.y; - redrawStart = selection.y = caretOffset; + redrawStart = selection.y = caretOffset; } } else { if (caretOffset > selection.y) { @@ -2841,15 +2956,15 @@ redrawEnd = selection.y = caretOffset; // check if selection has reversed direction if (selection.x !is selectionAnchor) { - redrawStart = selection.x; + redrawStart = selection.x; selection.x = selectionAnchor; } - // test whether selection actually changed. Fixes 1G71EO1 + // test whether selection actually changed. Fixes 1G71EO1 } else if (selectionAnchor is selection.y && caretOffset > selection.x) { - // caret moved towards selection anchor (right side of selection). - // shrink selection + // caret moved towards selection anchor (right side of selection). + // shrink selection redrawStart = selection.x; - redrawEnd = selection.x = caretOffset; + redrawEnd = selection.x = caretOffset; } } if (redrawStart !is -1 && redrawEnd !is -1) { @@ -2858,14 +2973,14 @@ } } /** - * Moves the caret to the next character or to the beginning of the + * Moves the caret to the next character or to the beginning of the * next line if the cursor is at the end of a line. */ void doSelectionCursorNext() { int caretLine = getCaretLine(); int lineOffset = content.getOffsetAtLine(caretLine); int offsetInLine = caretOffset - lineOffset; - if (offsetInLine < content.getLine(caretLine).length()) { + if (offsetInLine < content.getLine(caretLine).length) { TextLayout layout = renderer.getTextLayout(caretLine); offsetInLine = layout.getNextOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); int lineStart = layout.getLineOffsets()[layout.getLineIndex(offsetInLine)]; @@ -2874,14 +2989,14 @@ caretAlignment = offsetInLine is lineStart ? OFFSET_LEADING : PREVIOUS_OFFSET_TRAILING; showCaret(); } else if (caretLine < content.getLineCount() - 1 && !isSingleLine()) { - caretLine++; + caretLine++; caretOffset = content.getOffsetAtLine(caretLine); caretAlignment = PREVIOUS_OFFSET_TRAILING; showCaret(); } } /** - * Moves the caret to the previous character or to the end of the previous + * 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() { @@ -2889,21 +3004,22 @@ int lineOffset = content.getOffsetAtLine(caretLine); int offsetInLine = caretOffset - lineOffset; caretAlignment = OFFSET_LEADING; + if (offsetInLine > 0) { caretOffset = getClusterPrevious(caretOffset, caretLine); showCaret(); } else if (caretLine > 0) { caretLine--; lineOffset = content.getOffsetAtLine(caretLine); - caretOffset = lineOffset + content.getLine(caretLine).length(); + 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 + * 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 + * 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 @@ -2915,8 +3031,8 @@ 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 + * 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. @@ -2925,17 +3041,17 @@ * direction. */ void doSelectionLineUp() { - int oldColumnX = columnX = getPointAtOffset(caretOffset).x; - doLineUp(true); + int oldColumnX = columnX = getPointAtOffset(caretOffset).x; + doLineUp(true); columnX = oldColumnX; } /** * Scrolls one page down so that the last line (truncated or whole) * of the current page becomes the fully visible top line. * <p> - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the end - * of the text where a full page scroll is not possible. In this case + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the end + * of the text where a full page scroll is not possible. In this case * the caret is moved after the last character. * <p></p> * Adjusts the selection according to the caret change. This can either add @@ -2952,8 +3068,8 @@ * Scrolls one page up so that the first line (truncated or whole) * of the current page becomes the fully visible last line. * <p> - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the beginning + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the beginning * of the text where a full page scroll is not possible. In this case the * caret is moved in front of the first character. * </p><p> @@ -2974,9 +3090,9 @@ int newCaretOffset = getWordNext(caretOffset, DWT.MOVEMENT_WORD); // Force symmetrical movement for word next and previous. Fixes 14536 caretAlignment = OFFSET_LEADING; - // don't change caret position if in single line mode and the cursor + // don't change caret position if in single line mode and the cursor // would be on a different line. fixes 5673 - if (!isSingleLine() || + if (!isSingleLine() || content.getLineAtOffset(caretOffset) is content.getLineAtOffset(newCaretOffset)) { caretOffset = newCaretOffset; showCaret(); @@ -2999,8 +3115,8 @@ } /** * 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 + * 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() { @@ -3009,8 +3125,8 @@ } /** * 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 + * 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() { @@ -3043,13 +3159,13 @@ doSelectionWordPrevious(); } } -/** +/** * Ends the autoscroll process. */ void endAutoScroll() { autoScrollDirection = DWT.NULL; } -public Color getBackground() { +public override Color getBackground() { checkWidget(); if (background is null) { return getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND); @@ -3058,9 +3174,9 @@ } /** * Returns the baseline, in pixels. - * - * Note: this API should not be used if a StyleRange attribute causes lines to - * have different heights (i.e. different fonts, rise, etc). + * + * Note: this API should not be used if a StyleRange attribute causes lines to + * have different heights (i.e. different fonts, rise, etc). * * @return baseline the baseline * @exception DWTException <ul> @@ -3068,7 +3184,7 @@ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @since 3.0 - * + * * @see #getBaseline(int) */ public int getBaseline() { @@ -3076,20 +3192,20 @@ return renderer.getBaseline(); } /** - * Returns the baseline at the given offset, in pixels. + * Returns the baseline at the given offset, in pixels. * * @param offset the offset - * + * * @return baseline the baseline - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> - * + * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> + * </ul> + * * @since 3.2 */ public int getBaseline(int offset) { @@ -3103,7 +3219,7 @@ int lineIndex = content.getLineAtOffset(offset); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); FontMetrics metrics = layout.getLineMetrics(lineInParagraph); renderer.disposeTextLayout(layout); return metrics.getAscent() + metrics.getLeading(); @@ -3118,14 +3234,14 @@ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> - * + * * @deprecated use BidiSegmentListener instead. */ public bool getBidiColoring() { checkWidget(); return bidiColoring; } -/** +/** * Returns the index of the last fully visible line. * * @return index of the last fully visible line. @@ -3161,7 +3277,7 @@ int lineOffset = content.getOffsetAtLine(lineIndex); String line = content.getLine(lineIndex); Rectangle bounds; - if (line.length() !is 0) { + if (line.length !is 0) { int offsetInLine = offset - lineOffset; TextLayout layout = renderer.getTextLayout(lineIndex); bounds = layout.getBounds(offsetInLine, offsetInLine); @@ -3170,7 +3286,7 @@ bounds = new Rectangle (0, 0, 0, renderer.getLineHeight()); } if (offset is caretOffset) { - int lineEnd = lineOffset + line.length(); + int lineEnd = lineOffset + line.length; if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) { bounds.width += getCaretWidth(); } @@ -3207,7 +3323,7 @@ return clipboard.getContents(plainTextTransfer, clipboardType); } int getClusterNext(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); offset -= lineOffset; offset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER); @@ -3216,7 +3332,7 @@ return offset; } int getClusterPrevious(int offset, int lineIndex) { - int lineOffset = content.getOffsetAtLine(lineIndex); + int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); offset -= lineOffset; offset = layout.getPreviousOffset(offset, DWT.MOVEMENT_CLUSTER); @@ -3226,9 +3342,9 @@ } /** * Returns the content implementation that is used for text storage. - * + * * @return content the user defined content implementation that is used for - * text storage or the default content implementation if no user defined + * text storage or the default content implementation if no user defined * content implementation has been set. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -3239,12 +3355,12 @@ checkWidget(); return content; } -public bool getDragDetect () { +public override bool getDragDetect () { checkWidget (); - return dragDetect; -} -/** - * Returns whether the widget : double click mouse behavior. + return dragDetect_; +} +/** + * Returns whether the widget implements double click mouse behavior. * * @return true if double clicking a word selects the word, false if double clicks * have the same effect as regular mouse clicks @@ -3270,22 +3386,22 @@ checkWidget(); return editable; } -public Color getForeground() { +public override Color getForeground() { checkWidget(); if (foreground is null) { return getDisplay().getSystemColor(DWT.COLOR_LIST_FOREGROUND); } return foreground; } -/** +/** * Returns the horizontal scroll increment. * * @return horizontal scroll increment. */ -int getHorizontalIncrement() { +int getHorizontalIncrement() { return renderer.averageCharWidth; } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. * * @return horizontal scroll offset relative to the start of the line, @@ -3299,7 +3415,7 @@ checkWidget(); return horizontalScrollOffset / getHorizontalIncrement(); } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. * * @return the horizontal scroll offset relative to the start of the line, @@ -3315,16 +3431,16 @@ } /** * Returns the line indentation of the widget. - * + * * @return the line indentation - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #getLineIndent(int) - * + * * @since 3.2 */ public int getIndent() { @@ -3333,32 +3449,32 @@ } /** * Returns whether the widget justifies lines. - * + * * @return whether lines are justified - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #getLineJustify(int) - * + * * @since 3.2 */ public bool getJustify() { checkWidget(); return justify; } -/** +/** * Returns the action assigned to the key. * Returns DWT.NULL if there is no action associated with the key. * - * @param key a key code defined in DWT.java or a character. + * @param key a key code defined in DWT.java or a character. * Optionally ORd with a state mask. Preferred state masks are one or more of - * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform + * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform * differences. However, there may be cases where using the specific state masks * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. - * @return one of the predefined actions defined in ST.java or DWT.NULL + * @return one of the predefined actions defined in ST.java or DWT.NULL * if there is no action associated with the key. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -3367,8 +3483,10 @@ */ public int getKeyBinding(int key) { checkWidget(); - Integer action = cast(Integer) keyActionMap.get(new Integer(key)); - return action is null ? DWT.NULL : action.intValue(); + if( auto p = key in keyActionMap ){ + return *p; + } + return DWT.NULL; } /** * Gets the number of characters. @@ -3386,36 +3504,36 @@ /** * Returns the line at the given line index without delimiters. * Index 0 is the first line of the content. When there are not - * any lines, getLine(0) is a valid call that answers an empty String. + * any lines, getLine(0) is a valid call that answers an empty string. * <p> * * @param lineIndex index of the line to return. * @return the line text without delimiters - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> + * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> * </ul> * @since 3.4 */ public String getLine(int lineIndex) { checkWidget(); - if (lineIndex < 0 || + if (lineIndex < 0 || (lineIndex > 0 && lineIndex >= content.getLineCount())) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getLine(lineIndex); } /** * Returns the alignment of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line alignment - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3423,9 +3541,9 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> * </ul> - * + * * @see #getAlignment() - * + * * @since 3.2 */ public int getLineAlignment(int index) { @@ -3440,7 +3558,7 @@ * where 0 < offset < getCharCount() so that getLineAtOffset(getCharCount()) * returns the line of the insert location. * - * @param offset offset relative to the start of the content. + * @param offset offset relative to the start of the content. * 0 <= offset <= getCharCount() * @return line at the specified offset in the text * @exception DWTException <ul> @@ -3448,26 +3566,26 @@ * <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> + * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> * </ul> */ public int getLineAtOffset(int offset) { - checkWidget(); + checkWidget(); if (offset < 0 || offset > getCharCount()) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getLineAtOffset(offset); } /** * Returns the background color of the line at the given index. - * Returns null if a LineBackgroundListener has been set or if no background + * 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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3485,11 +3603,11 @@ } /** * Returns the bullet of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line bullet - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3497,7 +3615,7 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> * </ul> - * + * * @since 3.2 */ public Bullet getLineBullet(int index) { @@ -3508,9 +3626,9 @@ return isListening(LineGetStyle) ? null : renderer.getLineBullet(index, null); } /** - * Returns the line background data for the given line or null if + * Returns the line background data for the given line or null if * there is none. - * + * * @param lineOffset offset of the line start relative to the start * of the content. * @param line line to get line background data for @@ -3519,7 +3637,7 @@ StyledTextEvent getLineBackgroundData(int lineOffset, String line) { return sendLineEvent(LineGetBackground, lineOffset, line); } -/** +/** * Gets the number of text lines. * * @return the number of lines in the widget @@ -3533,10 +3651,10 @@ return content.getLineCount(); } /** - * Returns the number of lines that can be completely displayed in the + * Returns the number of lines that can be completely displayed in the * widget client area. * - * @return number of lines that can be completely displayed in the widget + * @return number of lines that can be completely displayed in the widget * client area. */ int getLineCountWhole() { @@ -3564,7 +3682,7 @@ /** * Returns the line height. * <p> - * Note: this API should not be used if a StyleRange attribute causes lines to + * Note: this API should not be used if a StyleRange attribute causes lines to * have different heights (i.e. different fonts, rise, etc). * </p> * @@ -3583,17 +3701,17 @@ * Returns the line height at the given offset. * * @param offset the offset - * + * * @return line height in pixels - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> - * + * <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li> + * </ul> + * * @since 3.2 */ public int getLineHeight(int offset) { @@ -3607,18 +3725,18 @@ int lineIndex = content.getLineAtOffset(offset); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); - int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length())); + int lineInParagraph = layout.getLineIndex(Math.min(offset - lineOffset, layout.getText().length)); int height = layout.getLineBounds(lineInParagraph).height; renderer.disposeTextLayout(layout); return height; } /** * Returns the indentation of the line at the given index. - * + * * @param index the index of the line - * + * * @return the line indentation - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3626,9 +3744,9 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> * </ul> - * + * * @see #getIndent() - * + * * @since 3.2 */ public int getLineIndent(int index) { @@ -3640,11 +3758,11 @@ } /** * Returns whether the line at the given index is justified. - * + * * @param index the index of the line - * - * @return whether the line is justified - * + * + * @return whether the line is justified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -3652,9 +3770,9 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_INVALID_ARGUMENT when the index is invalid</li> * </ul> - * + * * @see #getJustify() - * + * * @since 3.2 */ public bool getLineJustify(int index) { @@ -3662,18 +3780,18 @@ if (index < 0 || index > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); + return isListening(LineGetStyle) ? false : renderer.getLineJustify(index, justify); } /** * Returns the line spacing of the widget. - * + * * @return the line spacing - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @since 3.2 */ public int getLineSpacing() { @@ -3681,18 +3799,18 @@ return lineSpacing; } /** - * Returns the line style data for the given line or null if there is + * Returns the line style data for the given line or null if there is * none. * <p> - * If there is a LineStyleListener but it does not set any styles, - * the StyledTextEvent.styles field will be initialized to an empty + * 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 + * + * @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 + * @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) { @@ -3701,11 +3819,13 @@ /** * Returns the top pixel, relative to the client area, of a given line. * Clamps out of ranges index. - * + * * @param lineIndex the line index, the max value is lineCount. If * lineIndex is lineCount it returns the bottom pixel of the last line. - * It means this function can be used to retrieve the bottom pixel of any line. - * + * It means this function can be used to retrieve the bottom pixel of any line. + * + * @return the top pixel of a given line index + * * @since 3.2 */ public int getLinePixel(int lineIndex) { @@ -3733,6 +3853,10 @@ * Returns the line index for a y, relative to the client area. * The line index returned is always in the range 0..lineCount - 1. * + * @param y the y-coordinate pixel + * + * @return the line index for a given y-coordinate pixel + * * @since 3.2 */ public int getLineIndex(int y) { @@ -3762,59 +3886,59 @@ return 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 + * Returns the x, y location of the upper left corner of the character + * bounding box at the specified offset in the text. The point is * relative to the upper left corner of the widget client area. * - * @param offset offset relative to the start of the content. + * @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 + * @return x, y location of the upper left corner of the character * bounding box at the specified offset in the text. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> + * <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()) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return getPointAtOffset(offset); } /** * Returns the character offset of the first character of the given line. * - * @param lineIndex index of the line, 0 based relative to the first + * @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 + * at offset 0. + * When there are not any lines, getOffsetAtLine(0) is a valid call that * answers 0. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> + * <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li> * </ul> * @since 2.0 */ public int getOffsetAtLine(int lineIndex) { checkWidget(); - if (lineIndex < 0 || + if (lineIndex < 0 || (lineIndex > 0 && lineIndex >= content.getLineCount())) { - DWT.error(DWT.ERROR_INVALID_RANGE); + DWT.error(DWT.ERROR_INVALID_RANGE); } return content.getOffsetAtLine(lineIndex); } /** - * Returns the offset of the character at the given location relative + * Returns the offset of the character at the given location relative * to the first character in the document. * <p> * The return value reflects the character offset that the caret will @@ -3823,9 +3947,9 @@ * the returned offset will be behind the character. * </p> * - * @param point the origin of character bounding box relative to + * @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 + * @return offset of the character at the given location relative * to the first character in the document. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -3864,7 +3988,7 @@ int getOffsetAtPoint(int x, int y, int lineIndex) { TextLayout layout = renderer.getTextLayout(lineIndex); x += horizontalScrollOffset - leftMargin; - int[] trailing = new int[1]; + int[1] trailing; int offsetInLine = layout.getOffset(x, y, trailing); caretAlignment = OFFSET_LEADING; if (trailing[0] !is 0) { @@ -3874,11 +3998,11 @@ offsetInLine += trailing[0]; caretAlignment = PREVIOUS_OFFSET_TRAILING; } else { - String line = content.getLine(lineIndex); + String line = content.getLine(lineIndex); int level; int offset = offsetInLine; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset is 0 && Character.isDigit(line.charAt(offset))) { + while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; + if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { level = isMirrored() ? 1 : 0; } else { level = layout.getLevel(offset) & 0x1; @@ -3906,7 +4030,7 @@ } int lineIndex = getLineIndex(y); int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); x += horizontalScrollOffset - leftMargin ; y -= getLinePixel(lineIndex); int offset = layout.getOffset(x, y, trailing); @@ -3921,19 +4045,19 @@ * Returns the orientation of the receiver. * * @return the orientation style - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - 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() ? DWT.RIGHT_TO_LEFT : DWT.LEFT_TO_RIGHT; } -/** +/** * Returns the index of the last partially visible line. * * @return index of the last partially visible line. @@ -3946,7 +4070,7 @@ } return getLineIndex(clientAreaHeight - bottomMargin); } -/** +/** * Returns the index of the first partially visible line. * * @return index of the first partially visible line. @@ -3959,11 +4083,11 @@ return topIndexY <= 0 ? topIndex : topIndex - 1; } /** - * Returns the content in the specified range using the platform line + * Returns the content in the specified range using the platform line * delimiter to separate lines. * * @param writer the TextWriter to write line text into - * @return the content in the specified range using the platform line + * @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) { @@ -3972,14 +4096,14 @@ int endLine = content.getLineAtOffset(end); String endLineText = content.getLine(endLine); int endLineOffset = content.getOffsetAtLine(endLine); - + for (int i = startLine; i <= endLine; i++) { writer.writeLine(content.getLine(i), content.getOffsetAtLine(i)); if (i < endLine) { writer.writeLineDelimiter(PlatformLineDelimiter); } } - if (end > endLineOffset + endLineText.length()) { + if (end > endLineOffset + endLineText.length) { writer.writeLineDelimiter(PlatformLineDelimiter); } writer.close(); @@ -3987,8 +4111,8 @@ } /** * Returns all the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * <p> * The ranges array contains start and length pairs. Each pair refers to @@ -3996,16 +4120,16 @@ * that starts at ranges[n] with length ranges[n+1] uses the style * at styles[n/2] returned by <code>getStyleRanges(int, int, bool)</code>. * </p> - * + * * @return the ranges or an empty array if a LineStyleListener has been set. - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @since 3.2 - * + * * @see #getStyleRanges(bool) */ public int[] getRanges() { @@ -4018,8 +4142,8 @@ } /** * Returns the ranges of text that have an associated StyleRange. - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * <p> * The ranges array contains start and length pairs. Each pair refers to @@ -4030,19 +4154,19 @@ * * @param start the start offset of the style ranges to return * @param length the number of style ranges to return - * + * * @return the ranges or an empty array if a LineStyleListener has been set. - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_RANGE if start or length are outside the widget content</li> - * </ul> - * + * <li>ERROR_INVALID_RANGE if start or length are outside the widget content</li> + * </ul> + * * @since 3.2 - * + * * @see #getStyleRanges(int, int, bool) */ public int[] getRanges(int start, int length) { @@ -4062,15 +4186,15 @@ * 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, + * 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 + * @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 cast(RtoL) vs. left-to-right - * cast(LtoR), compare the caretOffset to the start and end of the selection + * 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 is start of selection implies that the selection is RtoL). * @see #getSelectionRange * @exception DWTException <ul> @@ -4085,12 +4209,12 @@ /** * Returns the selection. * - * @return start and length of the selection, x is the offset of the - * first selected character, relative to the first character of the - * widget content. y is the length of the selection. - * The selection values returned are visual (i.e., length will always always be - * positive). To determine if a selection is right-to-left cast(RtoL) vs. left-to-right - * cast(LtoR), compare the caretOffset to the start and end of the selection + * @return start and length of the selection, x is the offset of the + * first selected character, relative to the first character of the + * widget content. y is the length of the selection. + * The selection values returned are visual (i.e., length will always always be + * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection * (e.g., caretOffset is start of selection implies that the selection is RtoL). * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -4163,7 +4287,7 @@ checkWidget(); return content.getTextRange(selection.x, selection.y - selection.x); } -public int getStyle() { +public override int getStyle() { int style = super.getStyle(); style &= ~(DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT | DWT.MIRRORED); if (isMirrored()) { @@ -4175,18 +4299,18 @@ } /** - * Returns the text segments that should be treated as if they + * Returns the text segments that should be treated as if they * had a different direction than the surrounding text. * - * @param lineOffset offset of the first character in the line. + * @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. + * 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 + * <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> @@ -4197,21 +4321,21 @@ return getBidiSegmentsCompatibility(line, lineOffset); } StyledTextEvent event = sendLineEvent(LineGetSegments, lineOffset, line); - int lineLength = line.length(); + int lineLength = line.length; int[] segments; if (event is null || event.segments is null || event.segments.length is 0) { - segments = new int[] {0, lineLength}; + segments = [0, lineLength]; } else { int segmentCount = event.segments.length; - + // test segment index consistency if (event.segments[0] !is 0) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } + } for (int i = 1; i < segmentCount; i++) { if (event.segments[i] <= event.segments[i - 1] || event.segments[i] > lineLength) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); - } + } } // ensure that last segment index is line end offset if (event.segments[segmentCount - 1] !is lineLength) { @@ -4229,9 +4353,9 @@ * Supports deprecated setBidiColoring API. Remove when API is removed. */ int [] getBidiSegmentsCompatibility(String line, int lineOffset) { - int lineLength = line.length(); + int lineLength = line.length; if (!bidiColoring) { - return new int[] {0, lineLength}; + return [0, lineLength]; } StyleRange [] styles = null; StyledTextEvent event = getLineStyleData(lineOffset, line); @@ -4241,7 +4365,7 @@ styles = renderer.getStyleRanges(lineOffset, lineLength, true); } if (styles is null || styles.length is 0) { - return new int[] {0, lineLength}; + return [0, lineLength]; } int k=0, count = 1; while (k < styles.length && styles[k].start is 0 && styles[k].length is lineLength) { @@ -4252,7 +4376,7 @@ 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 ()); + 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])) && @@ -4284,15 +4408,15 @@ * Returns the style range at the given offset. * <p> * Returns null if a LineStyleListener has been set or if a style is not set - * for the offset. - * Should not be called if a LineStyleListener has been set since the + * 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. + * @param offset the offset to return the style for. * 0 <= offset < getCharCount() must be true. * @return a StyleRange with start is offset and length is 1, indicating - * the style at the given offset. null if a LineStyleListener has been set + * 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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -4316,8 +4440,8 @@ /** * Returns the styles. * <p> - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * <p></p> * Note: Because a StyleRange includes the start and length, the @@ -4333,7 +4457,7 @@ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> - * + * * @see #getStyleRanges(bool) */ public StyleRange[] getStyleRanges() { @@ -4343,8 +4467,8 @@ /** * Returns the styles. * <p> - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p><p> * Note: When <code>includeRanges</code> is true, the start and length @@ -4353,18 +4477,18 @@ * false, <code>getRanges(int, int)</code> can be used to get the * associated ranges. * </p> - * + * * @param includeRanges whether the start and length field of the StyleRanges should be set. - * + * * @return the styles or an empty array if a LineStyleListener has been set. - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @since 3.2 - * + * * @see #getRanges(int, int) * @see #setStyleRanges(int[], StyleRange[]) */ @@ -4375,8 +4499,8 @@ /** * Returns the styles for the given text range. * <p> - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p><p> * Note: Because the StyleRange includes the start and length, the @@ -4388,10 +4512,10 @@ * @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 + * @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 DWTException <ul> @@ -4399,11 +4523,11 @@ * <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> - * + * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> + * </ul> + * * @see #getStyleRanges(int, int, bool) - * + * * @since 3.0 */ public StyleRange[] getStyleRanges(int start, int length) { @@ -4413,8 +4537,8 @@ /** * Returns the styles for the given text range. * <p> - * Returns an empty array if a LineStyleListener has been set. - * Should not be called if a LineStyleListener has been set since the + * Returns an empty array if a LineStyleListener has been set. + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p><p> * Note: When <code>includeRanges</code> is true, the start and length @@ -4423,15 +4547,15 @@ * false, <code>getRanges(int, int)</code> can be used to get the * associated ranges. * </p> - * + * * @param start the start offset of the style ranges to return * @param length the number of style ranges to return * @param includeRanges whether the start and length field of the StyleRanges should be set. * - * @return the styles or an empty array if a LineStyleListener has - * been set. The returned styles will reflect the given range. The first - * returned <code>StyleRange</code> will have a starting offset >= start - * and the last returned <code>StyleRange</code> will have an ending + * @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 DWTException <ul> @@ -4439,11 +4563,11 @@ * <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> - * + * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> + * </ul> + * * @since 3.2 - * + * * @see #getRanges(int, int) * @see #setStyleRanges(int[], StyleRange[]) */ @@ -4490,7 +4614,7 @@ * Returns the widget content between the two offsets. * * @param start offset of the first character in the returned String - * @param end offset of the last character in the returned String + * @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 DWTException <ul> @@ -4498,7 +4622,7 @@ * <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> + * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> * </ul> */ public String getText(int start, int end) { @@ -4513,20 +4637,20 @@ * Returns the smallest bounding rectangle that includes the characters between two offsets. * * @param start offset of the first character included in the bounding box - * @param end offset of the last character included in the bounding box + * @param end offset of the last character included in the bounding box * @return bounding box of the text between start and end * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> + * <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(); + checkWidget(); + int contentLength = getCharCount(); if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { DWT.error(DWT.ERROR_INVALID_RANGE); } @@ -4537,9 +4661,9 @@ int height = 0; int left = 0x7fffffff, right = 0; for (int i = lineStart; i <= lineEnd; i++) { - int lineOffset = content.getOffsetAtLine(i); + int lineOffset = content.getOffsetAtLine(i); TextLayout layout = renderer.getTextLayout(i); - int length = layout.getText().length(); + int length = layout.getText().length; if (length > 0) { if (i is lineStart) { if (i is lineEnd) { @@ -4569,14 +4693,14 @@ * Returns the widget content starting at start for length characters. * * @param start offset of the first character in the returned String - * @param length number of characters to return + * @param length number of characters to return * @return widget content starting at start and extending length characters. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> + * <li>ERROR_INVALID_RANGE when start and/or length are outside the widget content</li> * </ul> */ public String getTextRange(int start, int length) { @@ -4585,12 +4709,12 @@ int end = start + length; if (start > end || start < 0 || end > contentLength) { DWT.error(DWT.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 DWTException <ul> @@ -4605,8 +4729,8 @@ /** * Gets the top index. * <p> - * The top index is the index of the fully visible line that is currently - * at the top of the widget or the topmost partially visible line if no line is fully visible. + * The top index 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> * @@ -4623,10 +4747,10 @@ /** * Gets the top pixel. * <p> - * The top pixel is the pixel position of the line that is - * currently at the top of the widget. The text widget can be scrolled by pixels - * by dragging the scroll thumb so that a partial line may be displayed at the top - * the widget. The top pixel changes when the widget is scrolled. The top pixel + * 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> * @@ -4640,7 +4764,7 @@ checkWidget(); return getVerticalScrollOffset(); } -/** +/** * Returns the vertical scroll increment. * * @return vertical scroll increment. @@ -4679,12 +4803,12 @@ int lineOffset = content.getOffsetAtLine(caretLine); String line = content.getLine(caretLine); int offset = caretOffset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; if (lineLength is 0) return isMirrored() ? DWT.RIGHT : DWT.LEFT; if (caretAlignment is PREVIOUS_OFFSET_TRAILING && offset > 0) offset--; if (offset is lineLength && offset > 0) offset--; - while (offset > 0 && Character.isDigit(line.charAt(offset))) offset--; - if (offset is 0 && Character.isDigit(line.charAt(offset))) { + while (offset > 0 && tango.text.Unicode.isDigit(line[offset])) offset--; + if (offset is 0 && tango.text.Unicode.isDigit(line[offset])) { return isMirrored() ? DWT.RIGHT : DWT.LEFT; } TextLayout layout = renderer.getTextLayout(caretLine); @@ -4717,7 +4841,7 @@ int lineIndex = content.getLineAtOffset(offset); lineOffset = content.getOffsetAtLine(lineIndex); lineText = content.getLine(lineIndex); - int lineLength = lineText.length(); + int lineLength = lineText.length; if (offset is lineOffset + lineLength) { newOffset = content.getOffsetAtLine(lineIndex + 1); } else { @@ -4742,12 +4866,12 @@ lineText = content.getLine(lineIndex); if (offset is lineOffset) { String nextLineText = content.getLine(lineIndex - 1); - int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); - newOffset = nextLineOffset + nextLineText.length(); + int nextLineOffset = content.getOffsetAtLine(lineIndex - 1); + newOffset = nextLineOffset + nextLineText.length; } else { TextLayout layout = renderer.getTextLayout(lineIndex); newOffset = lineOffset + layout.getPreviousOffset(offset - lineOffset, movement); - renderer.disposeTextLayout(layout); + renderer.disposeTextLayout(layout); } } return sendWordBoundaryEvent(WordPrevious, movement, offset, newOffset, lineText, lineOffset); @@ -4762,7 +4886,7 @@ checkWidget(); return wordWrap; } -/** +/** * Returns the location of the given offset. * <p> * <b>NOTE:</b> Does not return correct values for true italic fonts (vs. slanted fonts). @@ -4775,7 +4899,7 @@ String line = content.getLine(lineIndex); int lineOffset = content.getOffsetAtLine(lineIndex); int offsetInLine = offset - lineOffset; - int lineLength = line.length(); + int lineLength = line.length; if (lineIndex < content.getLineCount() - 1) { int endLineOffset = content.getOffsetAtLine(lineIndex + 1) - 1; if (lineLength < offsetInLine && offsetInLine <= endLineOffset) { @@ -4786,7 +4910,9 @@ TextLayout layout = renderer.getTextLayout(lineIndex); if (lineLength !is 0 && offsetInLine <= lineLength) { if (offsetInLine is lineLength) { - point = layout.getLocation(offsetInLine - 1, true); + // DWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, true); } else { switch (caretAlignment) { case OFFSET_LEADING: @@ -4797,7 +4923,9 @@ if (offsetInLine is 0) { point = layout.getLocation(offsetInLine, false); } else { - point = layout.getLocation(offsetInLine - 1, true); + // DWT: Instead of go back one byte, go back one codepoint + int offsetInLine_m1 = layout.getPreviousOffset(offsetInLine, DWT.MOVEMENT_CLUSTER); + point = layout.getLocation(offsetInLine_m1, true); } break; } @@ -4810,32 +4938,30 @@ point.y += getLinePixel(lineIndex); return point; } -/** - * Inserts a String. The old selection is replaced with the new text. - * - * @param String the String +/** + * Inserts a string. The old selection is replaced with the new text. + * + * @param string the string * @see #replaceTextRange(int,int,String) * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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 is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + */ +public void insert(String string) { + checkWidget(); + // DWT extension: allow null for zero length string +// if (string is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } Point sel = getSelectionRange(); - replaceTextRange(sel.x, sel.y, String); + replaceTextRange(sel.x, sel.y, string); } /** * Creates content change listeners and set the default content model. */ void installDefaultContent() { - textChangeListener = new TextChangeListener() { + textChangeListener = new class() TextChangeListener { public void textChanging(TextChangingEvent event) { handleTextChanging(event); } @@ -4849,14 +4975,14 @@ content = new DefaultContent(); content.addTextChangeListener(textChangeListener); } -/** +/** * Adds event listeners */ void installListeners() { ScrollBar verticalBar = getVerticalBar(); ScrollBar horizontalBar = getHorizontalBar(); - - listener = new Listener() { + + listener = new class() Listener { public void handleEvent(Event event) { switch (event.type) { case DWT.Dispose: handleDispose(event); break; @@ -4868,8 +4994,9 @@ case DWT.Paint: handlePaint(event); break; case DWT.Resize: handleResize(event); break; case DWT.Traverse: handleTraverse(event); break; + default: } - } + } }; addListener(DWT.Dispose, listener); addListener(DWT.KeyDown, listener); @@ -4880,24 +5007,25 @@ addListener(DWT.Paint, listener); addListener(DWT.Resize, listener); addListener(DWT.Traverse, listener); - ime.addListener(DWT.ImeComposition, new Listener() { + ime.addListener(DWT.ImeComposition, new class() Listener { public void handleEvent(Event event) { switch (event.detail) { case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break; case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break; + default: } } }); if (verticalBar !is null) { - verticalBar.addListener(DWT.Selection, new Listener() { + verticalBar.addListener(DWT.Selection, new class() Listener { public void handleEvent(Event event) { handleVerticalScroll(event); } }); } if (horizontalBar !is null) { - horizontalBar.addListener(DWT.Selection, new Listener() { + horizontalBar.addListener(DWT.Selection, new class() Listener { public void handleEvent(Event event) { handleHorizontalScroll(event); } @@ -4930,8 +5058,8 @@ TextLayout layout = renderer.getTextLayout(startLine); int lineX = leftMargin - horizontalScrollOffset, startLineY = getLinePixel(startLine); int[] offsets = layout.getLineOffsets(); - int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length())); - + int startIndex = layout.getLineIndex(Math.min(start, layout.getText().length)); + /* Redraw end of line before start line if wrapped and start offset is first char */ if (wordWrap && startIndex > 0 && offsets[startIndex] is start) { Rectangle rect = layout.getLineBounds(startIndex - 1); @@ -4941,9 +5069,9 @@ rect.y += startLineY; super.redraw(rect.x, rect.y, rect.width, rect.height, false); } - + if (startLine is endLine) { - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); if (startIndex is endIndex) { /* Redraw rect between start and end offset if start and end offsets are in same wrapped line */ Rectangle rect = layout.getBounds(start, end - 1); @@ -4974,7 +5102,7 @@ layout = renderer.getTextLayout(endLine); offsets = layout.getLineOffsets(); } - int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length())); + int endIndex = layout.getLineIndex(Math.min(end, layout.getText().length)); Rectangle endRect = layout.getBounds(offsets[endIndex], end - 1); if (endRect.height is 0) { Rectangle bounds = layout.getLineBounds(endIndex); @@ -5006,26 +5134,27 @@ String text = event.text; int start = event.start; int end = event.end; - int length = text.length(); + int length = text.length; if (length is ime.getCommitCount()) { content.replaceTextRange(start, end - start, ""); - caretOffset = start; + caretOffset = ime.getCompositionOffset(); caretWidth = 0; caretDirection = DWT.NULL; } else { content.replaceTextRange(start, end - start, text); caretOffset = ime.getCaretOffset(); if (ime.getWideCaret()) { + start = ime.getCompositionOffset(); int lineIndex = getCaretLine(); int lineOffset = content.getOffsetAtLine(lineIndex); - TextLayout layout = renderer.getTextLayout(lineIndex); + TextLayout layout = renderer.getTextLayout(lineIndex); caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; renderer.disposeTextLayout(layout); } } showCaret(); } -/** +/** * Frees resources. */ void handleDispose(Event event) { @@ -5067,7 +5196,7 @@ foreground = null; clipboard = null; } -/** +/** * Scrolls the widget horizontally. */ void handleHorizontalScroll(Event event) { @@ -5101,35 +5230,35 @@ } if (action is DWT.NULL) { bool 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 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 ^ DWT.COMMAND) is 0 || (event.stateMask ^ (DWT.COMMAND | DWT.SHIFT)) is 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 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 ^ DWT.CTRL) is 0 || (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 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 ^ DWT.ALT) is 0 || + // 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 ^ DWT.ALT) is 0 || (event.stateMask ^ DWT.CTRL) is 0 || (event.stateMask ^ (DWT.ALT | DWT.SHIFT)) is 0 || (event.stateMask ^ (DWT.CTRL | DWT.SHIFT)) is 0; } // -ignore anything below SPACE except for line delimiter keys and tab. - // -ignore DEL - if (!ignore && event.character > 31 && event.character !is DWT.DEL || - event.character is DWT.CR || event.character is DWT.LF || + // -ignore DEL + if (!ignore && event.character > 31 && event.character !is DWT.DEL || + event.character is DWT.CR || event.character is DWT.LF || event.character is TAB) { doContent(event.character); update(); @@ -5148,7 +5277,7 @@ if (clipboardSelection is null) { clipboardSelection = new Point(selection.x, selection.y); } - + Event verifyEvent = new Event(); verifyEvent.character = event.character; verifyEvent.keyCode = event.keyCode; @@ -5172,7 +5301,7 @@ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); } } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // 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. @@ -5184,21 +5313,22 @@ } clipboardSelection = null; } -/** - * Updates the caret location and selection if mouse button 1 has been +/** + * Updates the caret location and selection if mouse button 1 has been * pressed. */ void handleMouseDown(Event event) { //force focus (object support) forceFocus(); - + //drag detect - if (dragDetect && checkDragDetect(event)) return; - + if (dragDetect_ && checkDragDetect(event)) return; + //paste clipboard selection if (event.button is 2) { - String text = cast(String)getClipboardContent(DND.SELECTION_CLIPBOARD); - if (text !is null && text.length() > 0) { + auto o = cast(ArrayWrapperString)getClipboardContent(DND.SELECTION_CLIPBOARD); + String text = o.array; + if (text !is null && text.length > 0) { // position cursor doMouseLocationChange(event.x, event.y, false); // insert text @@ -5209,10 +5339,10 @@ sendKeyEvent(e); } } - + //set selection if ((event.button !is 1) || (IS_CARBON && (event.stateMask & DWT.MOD4) !is 0)) { - return; + return; } clickCount = event.count; if (clickCount is 1) { @@ -5245,8 +5375,8 @@ } } } -/** - * Updates the caret location and selection if mouse button 1 is pressed +/** + * Updates the caret location and selection if mouse button 1 is pressed * during the mouse move. */ void handleMouseMove(Event event) { @@ -5255,7 +5385,7 @@ update(); doAutoScroll(event); } -/** +/** * Autoscrolling ends when the mouse button is released. */ void handleMouseUp(Event event) { @@ -5267,7 +5397,7 @@ setClipboardContent(selection.x, selection.y - selection.x, DND.SELECTION_CLIPBOARD); } } catch (DWTError error) { - // Copy to clipboard failed. This happens when another application + // 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. @@ -5319,7 +5449,7 @@ } } /** - * Recalculates the scroll bars. Rewraps all lines when in word + * Recalculates the scroll bars. Rewraps all lines when in word * wrap mode. * * @param event resize event @@ -5333,13 +5463,13 @@ /* Redraw the old or new right/bottom margin if needed */ if (oldWidth !is clientAreaWidth) { if (rightMargin > 0) { - int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; + int x = (oldWidth < clientAreaWidth ? oldWidth : clientAreaWidth) - rightMargin; super.redraw(x, 0, rightMargin, oldHeight, false); } } if (oldHeight !is clientAreaHeight) { if (bottomMargin > 0) { - int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; + int y = (oldHeight < clientAreaHeight ? oldHeight : clientAreaHeight) - bottomMargin; super.redraw(0, y, oldWidth, bottomMargin, false); } } @@ -5378,10 +5508,14 @@ // } } /** - * Updates the caret position and selection and the scroll bars to reflect + * Updates the caret position and selection and the scroll bars to reflect * the content change. */ void handleTextChanged(TextChangedEvent event) { + int offset = ime.getCompositionOffset(); + if (offset !is -1 && lastTextChangeStart < offset) { + ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount); + } int firstLine = content.getLineAtOffset(lastTextChangeStart); resetCache(firstLine, 0); if (!isFixedLineHeight() && topIndex > firstLine) { @@ -5394,7 +5528,6 @@ int newLastLineBottom = getLinePixel(lastLine + 1); if (lastLineBottom !is newLastLineBottom) { super.redraw(); - if (wordWrap) setCaretLocation(); } else { super.redraw(0, firstLineTop, clientAreaWidth, newLastLineBottom - firstLineTop, false); redrawLinesBullet(renderer.redrawLines); @@ -5403,10 +5536,10 @@ renderer.redrawLines = null; // update selection/caret location after styles have been changed. // otherwise any text measuring could be incorrect - // - // also, this needs to be done after all scrolling. Otherwise, + // + // 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 + // in some cases new text would be drawn in scroll source area even // though the intent is to scroll it. updateSelection(lastTextChangeStart, lastTextChangeReplaceCharCount, lastTextChangeNewCharCount); if (lastTextChangeReplaceLineCount > 0 || wordWrap) { @@ -5420,7 +5553,7 @@ * Updates the screen to reflect a pending content change. * * @param event .start the start offset of the change - * @param event .newText text that is going to be inserted or empty String + * @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 @@ -5436,7 +5569,7 @@ lastTextChangeNewLineCount = event.newLineCount; lastTextChangeNewCharCount = event.newCharCount; lastTextChangeReplaceLineCount = event.replaceLineCount; - lastTextChangeReplaceCharCount = event.replaceCharCount; + lastTextChangeReplaceCharCount = event.replaceCharCount; int lineIndex = content.getLineAtOffset(event.start); int srcY = getLinePixel(lineIndex + event.replaceLineCount + 1); int destY = getLinePixel(lineIndex + 1) + event.newLineCount * renderer.getLineHeight(); @@ -5451,7 +5584,7 @@ } renderer.textChanging(event); - + // Update the caret offset if it is greater than the length of the content. // This is necessary since style range API may be called between the // handleTextChanging and handleTextChanged events and this API sets the @@ -5460,20 +5593,20 @@ if (caretOffset > newEndOfText) caretOffset = newEndOfText; } /** - * Called when the widget content is set programmatically, overwriting - * the old content. Resets the caret position, selection and scroll offsets. + * Called when the widget content is set programmatically, overwriting + * the old content. Resets the caret position, selection and scroll offsets. * Recalculates the content width and scroll bars. Redraws the widget. * - * @param event text change event. + * @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 + * Allow tab next traversal to occur when the widget is in single + * line mode or in multi line and non-editable mode . + * When in editable multi line mode we want to prevent the tab * traversal and receive the tab key event instead. * * @param event the event @@ -5496,9 +5629,10 @@ } } break; - } -} -/** + default: + } +} +/** * Scrolls the widget vertically. */ void handleVerticalScroll(Event event) { @@ -5510,7 +5644,7 @@ */ void initializeAccessible() { final Accessible accessible = getAccessible(); - accessible.addAccessibleListener(new AccessibleAdapter() { + accessible.addAccessibleListener(new class() AccessibleAdapter { public void getName (AccessibleEvent e) { String name = null; Label label = getAssociatedLabel (); @@ -5528,26 +5662,26 @@ if (label !is null) { String text = label.getText (); if (text !is null) { - char mnemonic = _findMnemonic (text); + dchar mnemonic = _findMnemonic (text); if (mnemonic !is '\0') { - shortcut = "Alt+"+mnemonic; //$NON-NLS-1$ + shortcut = "Alt+"~tango.text.convert.Utf.toString( [mnemonic] ); //$NON-NLS-1$ } } } e.result = shortcut; } }); - accessible.addAccessibleTextListener(new AccessibleTextAdapter() { + accessible.addAccessibleTextListener(new class() AccessibleTextAdapter { public void getCaretOffset(AccessibleTextEvent e) { - e.offset = StyledText.this.getCaretOffset(); + e.offset = this.outer.getCaretOffset(); } public void getSelectionRange(AccessibleTextEvent e) { - Point selection = StyledText.this.getSelectionRange(); + Point selection = this.outer.getSelectionRange(); e.offset = selection.x; e.length = selection.y; } }); - accessible.addAccessibleControlListener(new AccessibleControlAdapter() { + accessible.addAccessibleControlListener(new class() AccessibleControlAdapter { public void getRole(AccessibleControlEvent e) { e.detail = ACC.ROLE_TEXT; } @@ -5560,58 +5694,60 @@ e.detail = state; } public void getValue(AccessibleControlEvent e) { - e.result = StyledText.this.getText(); - } - }); - addListener(DWT.FocusIn, new Listener() { + e.result = this.outer.getText(); + } + }); + addListener(DWT.FocusIn, new class(accessible) Listener { + Accessible acc; + this( Accessible acc ){ this.acc = acc; } public void handleEvent(Event event) { - accessible.setFocus(ACC.CHILDID_SELF); - } - }); -} -/* - * Return the Label immediately preceding the receiver in the z-order, - * or null if none. + acc.setFocus(ACC.CHILDID_SELF); + } + }); +} +/* + * Return the Label immediately preceding the receiver in the z-order, + * or null if none. */ Label getAssociatedLabel () { Control[] siblings = getParent ().getChildren (); for (int i = 0; i < siblings.length; i++) { - if (siblings [i] is StyledText.this) { - if (i > 0 && siblings [i-1] instanceof Label) { + if (siblings [i] is this) { + if (i > 0 && ( null !is cast(Label)siblings [i-1])) { return cast(Label) siblings [i-1]; } } } return null; } -String stripMnemonic (String String) { +String stripMnemonic (String string) { int index = 0; - int length = String.length (); + int length_ = string.length; do { - while ((index < length) && (String.charAt (index) !is '&')) index++; - if (++index >= length) return String; - if (String.charAt (index) !is '&') { - return String.substring(0, index-1) + String.substring(index, length); + while ((index < length_) && (string[index] !is '&')) index++; + if (++index >= length_) return string; + if (string[index] !is '&') { + return string.substring(0, index-1) ~ string.substring(index, length_); } index++; - } while (index < length); - return String; + } while (index < length_); + return string; } /* * Return the lowercase of the first non-'&' character following - * an '&' character in the given String. If there are no '&' - * characters in the given String, return '\0'. - */ -char _findMnemonic (String String) { - if (String is null) return '\0'; + * an '&' character in the given string. If there are no '&' + * characters in the given string, return '\0'. + */ +dchar _findMnemonic (String string) { + if (string is null) return '\0'; int index = 0; - int length = String.length (); + int length_ = string.length; do { - while (index < length && String.charAt (index) !is '&') index++; - if (++index >= length) return '\0'; - if (String.charAt (index) !is '&') return Character.toLowerCase (String.charAt (index)); + while (index < length_ && string[index] !is '&') index++; + if (++index >= length_) return '\0'; + if (string[index] !is '&') return CharacterFirstToLower(string[index .. $ ] ); index++; - } while (index < length); + } while (index < length_); return '\0'; } /** @@ -5680,7 +5816,7 @@ doPageEnd(); clearSelection(true); break; - // Selection + // Selection case ST.SELECT_LINE_UP: doSelectionLineUp(); break; @@ -5736,7 +5872,7 @@ doPageEnd(); doSelection(ST.COLUMN_NEXT); break; - // Modification + // Modification case ST.CUT: cut(); break; @@ -5762,13 +5898,14 @@ case ST.TOGGLE_OVERWRITE: overwrite = !overwrite; // toggle insert/overwrite mode break; + default: } } /** * Temporary until DWT provides this */ bool isBidi() { - return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored; + return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_; } bool isBidiCaret() { return BidiUtil.isBidiPlatform(); @@ -5778,45 +5915,45 @@ } /** * Returns whether the given offset is inside a multi byte line delimiter. - * Example: + * Example: * "Line1\r\n" isLineDelimiter(5) is false but isLineDelimiter(6) is 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. */ bool isLineDelimiter(int offset) { int line = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(line); + int lineOffset = content.getOffsetAtLine(line); int offsetInLine = offset - lineOffset; - // offsetInLine will be greater than line length if the line + // 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 + 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 */ bool isMirrored() { - return isMirrored; + return isMirrored_; } /** * Returns whether the widget can have only one line. * - * @return true if widget can have only one line, false if widget can have + * @return true if widget can have only one line, false if widget can have * multiple lines */ bool isSingleLine() { return (getStyle() & DWT.SINGLE) !is 0; } /** - * Sends the specified verify event, replace/insert text as defined by + * Sends the specified verify event, replace/insert text as defined by * the event and send a modify event. * - * @param event the text change event. + * @param event the text change event. * <ul> * <li>event.start - the replace start offset</li> * <li>event.end - the replace end offset</li> @@ -5834,12 +5971,12 @@ if (isListening(ExtendedModify)) { styledTextEvent = new StyledTextEvent(content); styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); + 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() is 0) { + if (event.text.length is 0) { int lineIndex = content.getLineAtOffset(event.start); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); @@ -5864,7 +6001,7 @@ // fixes 1GBB8NJ if (updateCaret) { // always update the caret location. fixes 1G8FODP - setSelection(event.start + event.text.length(), 0, true); + setSelection(event.start + event.text.length, 0, true); showCaret(); } sendModifyEvent(event); @@ -5887,10 +6024,10 @@ notifyListeners(PaintObject, event); } } -/** - * Replaces the selection with the text on the <code>DND.CLIPBOARD</code> - * clipboard or, if there is no selection, inserts the text at the current - * caret offset. If the widget has the DWT.SINGLE style and the +/** + * 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 DWT.SINGLE style and the * clipboard text contains more than one line, only the first line without * line delimiters is inserted in the widget. * @@ -5900,9 +6037,12 @@ * </ul> */ public void paste(){ - checkWidget(); - String text = cast(String) getClipboardContent(DND.CLIPBOARD); - if (text !is null && text.length() > 0) { + checkWidget(); + String text = null; + if( auto o = cast(ArrayWrapperString) getClipboardContent(DND.CLIPBOARD)){ + text = o.array; + } + if (text !is null && text.length > 0) { Event event = new Event(); event.start = selection.x; event.end = selection.y; @@ -5910,7 +6050,7 @@ sendKeyEvent(event); } } -/** +/** * Prints the widget's text to the default printer. * * @exception DWTException <ul> @@ -5925,18 +6065,21 @@ options.printTextForeground = true; options.printTextBackground = true; options.printTextFontStyle = true; - options.printLineBackground = true; - new Printing(this, printer, options).run(); + options.printLineBackground = true; + (new Printing(this, printer, options)).run(); printer.dispose(); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. * <p> * The runnable may be run in a non-UI thread. * </p> - * + * * @param printer the printer to print to + * + * @return a <code>Runnable</code> for printing the receiver's text + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -5946,7 +6089,7 @@ * </ul> */ public Runnable print(Printer printer) { - checkWidget(); + checkWidget(); if (printer is null) { DWT.error(DWT.ERROR_NULL_ARGUMENT); } @@ -5957,15 +6100,18 @@ options.printLineBackground = true; return print(printer, options); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. * <p> * The runnable may be run in a non-UI thread. * </p> - * + * * @param printer the printer to print to * @param options print options to use during printing + * + * @return a <code>Runnable</code> for printing the receiver's text + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -5988,8 +6134,8 @@ * 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 + * 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> * @@ -6000,7 +6146,7 @@ * * @see Control#update() */ -public void redraw() { +public override void redraw() { super.redraw(); int itemCount = getPartialBottomIndex() - topIndex + 1; renderer.reset(topIndex, itemCount); @@ -6009,18 +6155,18 @@ } /** * Causes the rectangular area of the receiver specified by - * the arguments to be marked as needing to be redrawn. + * 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 + * 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 + * 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> * @@ -6037,7 +6183,7 @@ * * @see Control#update() */ -public void redraw(int x, int y, int width, int height, bool all) { +public override void redraw(int x, int y, int width, int height, bool all) { super.redraw(x, y, width, height, all); if (height > 0) { int firstLine = getLineIndex(y); @@ -6046,7 +6192,7 @@ } } void redrawLines(int startLine, int lineCount) { - // do nothing if redraw range is completely invisible + // do nothing if redraw range is completely invisible int partialBottomIndex = getPartialBottomIndex(); if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { return; @@ -6062,7 +6208,7 @@ startLine -= topIndex; int redrawTop = getLinePixel(startLine); int redrawBottom = getLinePixel(startLine + lineCount); - int redrawWidth = clientAreaWidth - leftMargin - rightMargin; + int redrawWidth = clientAreaWidth - leftMargin - rightMargin; super.redraw(leftMargin, redrawTop, redrawWidth, redrawBottom - redrawTop, true); } void redrawLinesBullet (int[] redrawLines) { @@ -6085,7 +6231,7 @@ super.redraw(0, y, width, height, false); } } -/** +/** * Redraws the specified text range. * * @param start offset of the first character to redraw @@ -6093,20 +6239,20 @@ * @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 + * 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. + * 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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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> + * <li>ERROR_INVALID_RANGE when start and/or end are outside the widget content</li> * </ul> */ public void redrawRange(int start, int length, bool clearBackground) { @@ -6124,7 +6270,8 @@ /** * Removes the specified bidirectional segment listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6132,17 +6279,19 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when listener is null</li> * </ul> + * * @since 2.0 */ public void removeBidiSegmentListener(BidiSegmentListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(LineGetSegments, listener); + removeListener(LineGetSegments, listener); } /** * Removes the specified extended modify listener. * - * @param extendedModifyListener the listener + * @param extendedModifyListener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6154,12 +6303,13 @@ public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { checkWidget(); if (extendedModifyListener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(ExtendedModify, extendedModifyListener); + removeListener(ExtendedModify, extendedModifyListener); } /** * Removes the specified line background listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6176,7 +6326,8 @@ /** * Removes the specified line style listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6193,7 +6344,8 @@ /** * Removes the specified modify listener. * - * @param modifyListener the listener + * @param modifyListener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6210,7 +6362,8 @@ /** * Removes the specified listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6250,7 +6403,8 @@ /** * Removes the specified verify listener. * - * @param verifyListener the listener + * @param verifyListener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6267,7 +6421,8 @@ /** * Removes the specified key verify listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6283,7 +6438,8 @@ /** * Removes the specified word movement listener. * - * @param listener the listener + * @param listener the listener which should no longer be notified + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -6291,24 +6447,24 @@ * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when listener is null</li> * </ul> - * + * * @see MovementEvent * @see MovementListener * @see #addWordMovementListener - * + * * @since 3.3 */ public void removeWordMovementListener(MovementListener listener) { checkWidget(); if (listener is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - removeListener(WordNext, listener); + removeListener(WordNext, listener); removeListener(WordPrevious, listener); } -/** +/** * Replaces the styles in the given range with new styles. This method * effectively deletes the styles in the given range and then adds the - * the new styles. + * the new styles. * <p> * Note: Because a StyleRange includes the start and length, the * same instance cannot occur multiple times in the array of styles. @@ -6316,14 +6472,14 @@ * multiple StyleRanges, <code>setStyleRanges(int, int, int[], StyleRange[])</code> * can be used to share styles and reduce memory usage. * </p><p> - * Should not be called if a LineStyleListener has been set since the + * 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 + * 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 DWTException <ul> @@ -6331,33 +6487,33 @@ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> - * <li>ERROR_NULL_ARGUMENT when ranges is null</li> - * </ul> - * + * <li>ERROR_INVALID_RANGE when either start or end is outside the valid range (0 <= offset <= getCharCount())</li> + * </ul> + * * @since 2.0 - * + * * @see #setStyleRanges(int, int, int[], StyleRange[]) */ public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { checkWidget(); if (isListening(LineGetStyle)) return; - if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); setStyleRanges(start, length, null, ranges, false); } /** * Replaces the given text range with new text. - * If the widget has the DWT.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 + * If the widget has the DWT.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 DWT.SINGLE style is used. * <p> * <b>NOTE:</b> During the replace operation the current selection is * changed as follows: - * <ul> + * <ul> * <li>selection before replaced text: selection unchanged - * <li>selection after replaced text: adjust the selection so that same text + * <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 @@ -6372,17 +6528,17 @@ * <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> + * <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> * </ul> */ public void replaceTextRange(int start, int length, String text) { checkWidget(); - if (text is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + // DWT extension: allow null for zero length string +// if (text is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } int contentLength = getCharCount(); int end = start + length; if (start > end || start < 0 || end > contentLength) { @@ -6405,14 +6561,14 @@ topIndex = 0; topIndexY = 0; verticalScrollOffset = 0; - horizontalScrollOffset = 0; + horizontalScrollOffset = 0; resetSelection(); renderer.setContent(content); if (verticalBar !is null) { verticalBar.setSelection(0); } if (horizontalBar !is null) { - horizontalBar.setSelection(0); + horizontalBar.setSelection(0); } resetCache(0, 0); setCaretLocation(); @@ -6441,7 +6597,7 @@ selectionAnchor = -1; } -public void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { +public override void scroll(int destX, int destY, int x, int y, int width, int height, bool all) { super.scroll(destX, destY, x, y, width, height, false); if (all) { int deltaX = destX - x, deltaY = destY - y; @@ -6459,11 +6615,11 @@ * * @param pixels number of pixels to scroll, > 0 = scroll left, * < 0 scroll right - * @param adjustScrollBar + * @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 + * @return + * true=the widget was scrolled * false=the widget was not scrolled, the given offset is not valid. */ bool scrollHorizontal(int pixels, bool adjustScrollBar) { @@ -6502,11 +6658,11 @@ * Scrolls the widget vertically. * * @param pixel the new vertical scroll offset - * @param adjustScrollBar + * @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 + * @return + * true=the widget was scrolled * false=the widget was not scrolled */ bool scrollVertical(int pixels, bool adjustScrollBar) { @@ -6574,7 +6730,7 @@ super.redraw(leftMargin, clientAreaHeight - bottomMargin, scrollWidth, bottomMargin, false); } } -/** +/** * Selects all the text. * * @exception DWTException <ul> @@ -6589,7 +6745,7 @@ /** * Replaces/inserts text as defined by the event. * - * @param event the text change event. + * @param event the text change event. * <ul> * <li>event.start - the replace start offset</li> * <li>event.end - the replace end offset</li> @@ -6602,19 +6758,19 @@ } } /** - * Returns a StyledTextEvent that can be used to request data such + * Returns a StyledTextEvent that can be used to request data such * as styles and background color for a line. * <p> - * The specified line may be a visual (wrapped) line if in word - * wrap mode. The returned object will always be for a logical + * The specified line may be a visual (wrapped) line if in word + * wrap mode. The returned object will always be for a logical * (unwrapped) line. * </p> * * @param lineOffset offset of the line. This may be the offset of * a visual line if the widget is in word wrap mode. - * @param line line text. This may be the text of a visual line if + * @param line line text. This may be the text of a visual line if * the widget is in word wrap mode. - * @return StyledTextEvent that can be used to request line data + * @return StyledTextEvent that can be used to request line data * for the given line. */ StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { @@ -6632,14 +6788,14 @@ } void sendModifyEvent(Event event) { Accessible accessible = getAccessible(); - if (event.text.length() is 0) { + if (event.text.length is 0) { accessible.textChanged(ACC.TEXT_DELETE, event.start, event.end - event.start); } else { if (event.start is event.end) { - accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length()); + 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()); + accessible.textChanged(ACC.TEXT_INSERT, event.start, event.text.length); } } notifyListeners(DWT.Modify, event); @@ -6681,22 +6837,22 @@ return newOffset; } /** - * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>, + * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>, * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. The alignment applies for all lines. * </p><p> * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set * in order to stabilize the right edge before setting alignment. * </p> - * + * * @param alignment the new alignment - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #setLineAlignment(int, int, int) - * + * * @since 3.2 */ public void setAlignment(int alignment) { @@ -6711,7 +6867,7 @@ /** * @see Control#setBackground(Color) */ -public void setBackground(Color color) { +public override void setBackground(Color color) { checkWidget(); background = color; super.setBackground(color); @@ -6719,7 +6875,7 @@ } /** * Sets the receiver's caret. Set the caret's height and location. - * + * * </p> * @param caret the new caret for the receiver * @@ -6728,7 +6884,7 @@ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ -public void setCaret(Caret caret) { +public override void setCaret(Caret caret) { checkWidget (); super.setCaret(caret); caretDirection = DWT.NULL; @@ -6746,7 +6902,7 @@ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> - * + * * @deprecated use BidiSegmentListener instead. */ public void setBidiColoring(bool mode) { @@ -6818,7 +6974,7 @@ * <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 + * <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> */ @@ -6832,7 +6988,7 @@ caretOffset = length; } else { if (isLineDelimiter(offset)) { - // offset is inside a multi byte line delimiter. This is an + // offset is inside a multi byte line delimiter. This is an // illegal operation and an exception is thrown. Fixes 1GDKK3R DWT.error(DWT.ERROR_INVALID_ARGUMENT); } @@ -6844,14 +7000,14 @@ clearSelection(false); } setCaretLocation(); -} +} /** * Copies the specified text range to the clipboard. The text will be placed * in the clipboard in plain text format and RTF format. * * @param start start index of the text * @param length length of text to place in clipboard - * + * * @exception DWTError, see Clipboard.setContents * @see dwt.dnd.Clipboard#setContents */ @@ -6863,14 +7019,14 @@ Object[] data; Transfer[] types; if (clipboardType is DND.SELECTION_CLIPBOARD) { - data = new Object[]{plainText}; - types = new Transfer[]{plainTextTransfer}; + data = [ cast(Object) new ArrayWrapperString(plainText) ]; + types = [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}; + data = [ cast(Object) new ArrayWrapperString(rtfText), new ArrayWrapperString(plainText) ]; + types = [ cast(Transfer)rtfTransfer, plainTextTransfer]; } clipboard.setContents(data, types, clipboardType); } @@ -6887,7 +7043,7 @@ * </ul> */ public void setContent(StyledTextContent newContent) { - checkWidget(); + checkWidget(); if (newContent is null) { DWT.error(DWT.ERROR_NULL_ARGUMENT); } @@ -6900,12 +7056,12 @@ } /** * Sets the receiver's cursor to the cursor specified by the - * argument. Overridden to handle the null case since the + * argument. Overridden to handle the null case since the * StyledText widget uses an ibeam as its default cursor. * * @see Control#setCursor(Cursor) */ -public void setCursor (Cursor cursor) { +public override void setCursor (Cursor cursor) { if (cursor is null) { Display display = getDisplay(); super.setCursor(display.getSystemCursor(DWT.CURSOR_IBEAM)); @@ -6913,7 +7069,7 @@ super.setCursor(cursor); } } -/** +/** * Sets whether the widget : double click mouse behavior. * </p> * @@ -6928,15 +7084,15 @@ checkWidget(); doubleClickEnabled = enable; } -public void setDragDetect (bool dragDetect) { +public override void setDragDetect (bool dragDetect_) { checkWidget (); - this.dragDetect = dragDetect; + this.dragDetect_ = dragDetect_; } /** * Sets whether the widget content can be edited. * </p> * - * @param editable if true content can be edited, if false content can not be + * @param editable if true content can be edited, if false content can not be * edited * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -6960,10 +7116,10 @@ * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */ -public void setFont(Font font) { +public override void setFont(Font font) { checkWidget(); int oldLineHeight = renderer.getLineHeight(); - super.setFont(font); + super.setFont(font); renderer.setFont(getFont(), tabLength); // keep the same top line visible. fixes 5815 if (isFixedLineHeight()) { @@ -6974,32 +7130,29 @@ } } resetCache(0, content.getLineCount()); - claimBottomFreeSpace(); + claimBottomFreeSpace(); calculateScrollBars(); if (isBidiCaret()) createCaretBitmaps(); caretDirection = DWT.NULL; setCaretLocation(); super.redraw(); } -/** - * @see dwt.widgets.Control#setForeground - */ -public void setForeground(Color color) { +public override void setForeground(Color color) { checkWidget(); foreground = color; super.setForeground(getForeground()); super.redraw(); } -/** +/** * Sets the horizontal scroll offset relative to the start of the line. * Do nothing if there is no text set. * <p> - * <b>NOTE:</b> The horizontal index is reset to 0 when new text is set in the + * <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 + * @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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7010,14 +7163,14 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (offset < 0) { offset = 0; } offset *= getHorizontalIncrement(); - // allow any value if client area width is unknown or 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 + // don't use isVisible since width is known even if widget // is temporarily invisible if (clientAreaWidth > 0) { int width = renderer.getWidth(); @@ -7030,15 +7183,15 @@ } scrollHorizontal(offset - horizontalScrollOffset, true); } -/** +/** * Sets the horizontal pixel offset relative to the start of the line. * Do nothing if there is no text set. * <p> - * <b>NOTE:</b> The horizontal pixel offset is reset to 0 when new text + * <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 + * @param pixel horizontal pixel offset relative to the start * of the line. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7050,13 +7203,13 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (pixel < 0) { pixel = 0; } - // allow any value if client area width is unknown or 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 + // don't use isVisible since width is known even if widget // is temporarily invisible if (clientAreaWidth > 0) { int width = renderer.getWidth(); @@ -7072,19 +7225,19 @@ /** * Sets the line indentation of the widget. * <p> - * It is the amount of blank space, in pixels, at the beginning of each line. - * When a line wraps in several lines only the first one is indented. + * It is the amount of blank space, in pixels, at the beginning of each line. + * When a line wraps in several lines only the first one is indented. * </p> - * + * * @param indent the new indent - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #setLineIndent(int, int, int) - * + * * @since 3.2 */ public void setIndent(int indent) { @@ -7093,20 +7246,20 @@ this.indent = indent; resetCache(0, content.getLineCount()); setCaretLocation(); - super.redraw(); -} -/** - * Sets whether the widget should justify lines. - * + super.redraw(); +} +/** + * Sets whether the widget should justify lines. + * * @param justify whether lines should be justified - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * * @see #setLineJustify(int, int, bool) - * + * * @since 3.2 */ public void setJustify(bool justify) { @@ -7115,21 +7268,21 @@ this.justify = justify; resetCache(0, content.getLineCount()); setCaretLocation(); - super.redraw(); -} -/** + super.redraw(); +} +/** * Maps a key to an action. * <p> - * One action can be associated with N keys. However, each key can only + * 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 DWT.java or a character. + * @param key a key code defined in DWT.java or a character. * Optionally ORd with a state mask. Preferred state masks are one or more of - * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform + * DWT.MOD1, DWT.MOD2, DWT.MOD3, since these masks account for modifier platform * differences. However, there may be cases where using the specific state masks * (i.e., DWT.CTRL, DWT.SHIFT, DWT.ALT, DWT.COMMAND) makes sense. - * @param action one of the predefined actions defined in ST.java. + * @param action one of the predefined actions defined in ST.java. * Use DWT.NULL to remove a key binding. * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7139,58 +7292,58 @@ public void setKeyBinding(int key, int action) { checkWidget(); int modifierValue = key & DWT.MODIFIER_MASK; - char keyChar = cast(wchar)(key & DWT.KEY_MASK); + char keyChar = cast(char)(key & DWT.KEY_MASK); if (Compatibility.isLetter(keyChar)) { // make the keybinding case insensitive by adding it // in its upper and lower case form - char ch = Character.toUpperCase(keyChar); + char ch = CharacterToUpper(keyChar); int newKey = ch | modifierValue; if (action is DWT.NULL) { - keyActionMap.remove(new Integer(newKey)); + keyActionMap.remove(newKey); } else { - keyActionMap.put(new Integer(newKey), new Integer(action)); - } - ch = Character.toLowerCase(keyChar); + keyActionMap[newKey] = action; + } + ch = CharacterToLower(keyChar); newKey = ch | modifierValue; if (action is DWT.NULL) { - keyActionMap.remove(new Integer(newKey)); + keyActionMap.remove(newKey); } else { - keyActionMap.put(new Integer(newKey), new Integer(action)); + keyActionMap[newKey] = action; } } else { if (action is DWT.NULL) { - keyActionMap.remove(new Integer(key)); + keyActionMap.remove(key); } else { - keyActionMap.put(new Integer(key), new Integer(action)); - } - } -} -/** - * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>, + keyActionMap[key]=action; + } + } +} +/** + * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>, * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. * <p><p> * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set * in order to stabilize the right edge before setting alignment. * </p> - * Should not be called if a LineStyleListener has been set since the listener + * Should not be called if a LineStyleListener has been set since the listener * maintains the line attributes. * </p><p> - * All line attributes are maintained relative to the line text, not the + * All line attributes are maintained relative to the line text, not the * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. * </p><p> - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. - * + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. + * * @param startLine first line the alignment is applied to, 0 based * @param lineCount number of lines the alignment applies to. * @param alignment line alignment - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -7216,30 +7369,30 @@ setCaretLocation(); } } -/** +/** * Sets the background color of the specified lines. * <p> * The background color is drawn for the width of the widget. All * line background colors are discarded when setText is called. - * The text background color if defined in a StyleRange overlays the - * line background color. + * The text background color if defined in a StyleRange overlays the + * line background color. * </p><p> - * Should not be called if a LineBackgroundListener has been set since the + * Should not be called if a LineBackgroundListener has been set since the * listener maintains the line backgrounds. * </p><p> - * All line attributes are maintained relative to the line text, not the + * All line attributes are maintained relative to the line text, not the * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. * </p><p> - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. - * For all other text changes line attributes will remain unchanged. + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. + * For all other text changes line attributes will remain unchanged. * </p> - * + * * @param startLine first line the color is applied to, 0 based * @param lineCount number of lines the color applies to. * @param background line background color @@ -7252,7 +7405,7 @@ * </ul> */ public void setLineBackground(int startLine, int lineCount, Color background) { - checkWidget(); + checkWidget(); if (isListening(LineGetBackground)) return; if (startLine < 0 || startLine + lineCount > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); @@ -7267,26 +7420,26 @@ /** * Sets the bullet of the specified lines. * <p> - * Should not be called if a LineStyleListener has been set since the listener + * Should not be called if a LineStyleListener has been set since the listener * maintains the line attributes. * </p><p> - * All line attributes are maintained relative to the line text, not the + * All line attributes are maintained relative to the line text, not the * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. * </p><p> - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. * For all other text changes line attributes will remain unchanged. * </p> * * @param startLine first line the bullet is applied to, 0 based * @param lineCount number of lines the bullet applies to. * @param bullet line bullet - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -7298,7 +7451,7 @@ */ public void setLineBullet(int startLine, int lineCount, Bullet bullet) { checkWidget(); - if (isListening(LineGetStyle)) return; + if (isListening(LineGetStyle)) return; if (startLine < 0 || startLine + lineCount > content.getLineCount()) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } @@ -7319,26 +7472,26 @@ /** * Sets the indent of the specified lines. * <p> - * Should not be called if a LineStyleListener has been set since the listener + * Should not be called if a LineStyleListener has been set since the listener * maintains the line attributes. * </p><p> - * All line attributes are maintained relative to the line text, not the + * All line attributes are maintained relative to the line text, not the * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. * </p><p> - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. * For all other text changes line attributes will remain unchanged. * </p> * * @param startLine first line the indent is applied to, 0 based * @param lineCount number of lines the indent applies to. * @param indent line indent - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -7367,26 +7520,26 @@ /** * Sets the justify of the specified lines. * <p> - * Should not be called if a LineStyleListener has been set since the listener + * Should not be called if a LineStyleListener has been set since the listener * maintains the line attributes. * </p><p> - * All line attributes are maintained relative to the line text, not the + * All line attributes are maintained relative to the line text, not the * line index that is specified in this method call. - * During text changes, when entire lines are inserted or removed, the line - * attributes that are associated with the lines after the change - * will "move" with their respective text. An entire line is defined as - * extending from the first character on a line to the last and including the - * line delimiter. + * During text changes, when entire lines are inserted or removed, the line + * attributes that are associated with the lines after the change + * will "move" with their respective text. An entire line is defined as + * extending from the first character on a line to the last and including the + * line delimiter. * </p><p> - * When two lines are joined by deleting a line delimiter, the top line - * attributes take precedence and the attributes of the bottom line are deleted. + * When two lines are joined by deleting a line delimiter, the top line + * attributes take precedence and the attributes of the bottom line are deleted. * For all other text changes line attributes will remain unchanged. * </p> - * + * * @param startLine first line the justify is applied to, 0 based * @param lineCount number of lines the justify applies to. * @param justify true if lines should be justified - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> @@ -7414,7 +7567,7 @@ } /** * Sets the line spacing of the widget. The line spacing applies for all lines. - * + * * @param lineSpacing the line spacing * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7425,7 +7578,7 @@ public void setLineSpacing(int lineSpacing) { checkWidget(); if (this.lineSpacing is lineSpacing || lineSpacing < 0) return; - this.lineSpacing = lineSpacing; + this.lineSpacing = lineSpacing; setVariableLineHeight(); resetCache(0, content.getLineCount()); setCaretLocation(); @@ -7456,43 +7609,43 @@ * of the constants <code>DWT.LEFT_TO_RIGHT</code> or <code>DWT.RIGHT_TO_LEFT</code>. * * @param orientation new orientation style - * - * @exception DWTException <ul> - * <li>ERROR_WIDGET_DISPOSED - 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 DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - 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 & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { + if ((orientation & (DWT.RIGHT_TO_LEFT | DWT.LEFT_TO_RIGHT)) is 0) { return; } if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && (orientation & DWT.LEFT_TO_RIGHT) !is 0) { - return; + return; } if ((orientation & DWT.RIGHT_TO_LEFT) !is 0 && isMirrored()) { - return; - } + return; + } if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) { return; } if (!BidiUtil.setOrientation(this, orientation)) { return; } - isMirrored = (orientation & DWT.RIGHT_TO_LEFT) !is 0; + isMirrored_ = (orientation & DWT.RIGHT_TO_LEFT) !is 0; caretDirection = DWT.NULL; resetCache(0, content.getLineCount()); setCaretLocation(); - keyActionMap.clear(); + keyActionMap = null; createKeyBindings(); super.redraw(); } /** - * Adjusts the maximum and the page size of the scroll bars to + * Adjusts the maximum and the page size of the scroll bars to * reflect content width/length changes. - * - * @param vertical indicates if the vertical scrollbar also needs to be set + * + * @param vertical indicates if the vertical scrollbar also needs to be set */ void setScrollBars(bool vertical) { int inactive = 1; @@ -7500,7 +7653,7 @@ ScrollBar verticalBar = getVerticalBar(); if (verticalBar !is null) { int maximum = renderer.getHeight(); - // only set the real values if the scroll bar can be used + // 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 (clientAreaHeight < maximum) { @@ -7521,7 +7674,7 @@ ScrollBar horizontalBar = getHorizontalBar(); if (horizontalBar !is null && horizontalBar.getVisible()) { int maximum = renderer.getWidth(); - // only set the real values if the scroll bar can be used + // 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 (clientAreaWidth < maximum) { @@ -7539,7 +7692,7 @@ } } } -/** +/** * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). * * @param start new caret position @@ -7549,19 +7702,19 @@ * <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 + * <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> + * </ul> */ public void setSelection(int start) { - // checkWidget test done in setSelectionRange + // 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 + * caret positions. In a text widget that contains N characters, there are * N+1 caret positions, ranging from 0..N * </p> * @@ -7574,13 +7727,13 @@ * </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 + * <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> + * </ul> */ public void setSelection(Point point) { checkWidget(); - if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); + if (point is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); setSelection(point.x, point.y); } /** @@ -7591,7 +7744,7 @@ * @param color the new color (or null) * * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> + * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7610,7 +7763,7 @@ /** * 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. + * if the argument is null. * <p> * Note that this is a <em>HINT</em>. Some platforms do not allow the application * to change the selection foreground color. @@ -7618,7 +7771,7 @@ * @param color the new color (or null) * * @exception IllegalArgumentException <ul> - * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> + * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> * </ul> * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -7634,15 +7787,15 @@ selectionForeground = color; super.redraw(); } -/** +/** * Sets the selection and scrolls it into view. * <p> * Indexing is zero based. Text selections are specified in terms of - * caret positions. In a text widget that contains N characters, there are + * 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 + * @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) @@ -7651,7 +7804,7 @@ * <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 + * <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> */ @@ -7659,31 +7812,33 @@ setSelectionRange(start, end - start); showSelection(); } -/** +/** * Sets the selection. * <p> - * The new selection may not be visible. Call showSelection to scroll + * 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. + * @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 + * @param sendEvent a Selection event is sent when set to true and when * the selection is reset. */ void setSelection(int start, int length, bool sendEvent) { int end = start + length; + start = content.utf8AdjustOffset(start); + end = content.utf8AdjustOffset(end); if (start > end) { int temp = end; end = start; start = temp; } - // is the selection range different or is the selection direction + // is the selection range different or is the selection direction // different? - if (selection.x !is start || selection.y !is end || - (length > 0 && selectionAnchor !is selection.x) || + if (selection.x !is start || selection.y !is end || + (length > 0 && selectionAnchor !is selection.x) || (length < 0 && selectionAnchor !is selection.y)) { clearSelection(sendEvent); if (length < 0) { @@ -7697,7 +7852,7 @@ internalRedrawRange(selection.x, selection.y - selection.x); } } -/** +/** * Sets the selection. * <p> * The new selection may not be visible. Call showSelection to scroll the selection @@ -7706,13 +7861,13 @@ * * @param start offset of the first selected character * @param length number of characters to select - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - 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 + * <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> */ @@ -7727,23 +7882,23 @@ 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 + // 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 DWT.error(DWT.ERROR_INVALID_ARGUMENT); } setSelection(start, length, false); setCaretLocation(); } -/** +/** * Adds the specified style. * <p> * The new style overwrites existing styles for the specified range. - * Existing style ranges are adjusted if they partially overlap with - * the new style. To clear an individual style, call setStyleRange - * with a StyleRange that has null attributes. + * Existing style ranges are adjusted if they partially overlap with + * the new style. To clear an individual style, call setStyleRange + * with a StyleRange that has null attributes. * </p><p> - * Should not be called if a LineStyleListener has been set since the + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p> * @@ -7755,7 +7910,7 @@ * <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> + * <li>ERROR_INVALID_RANGE when the style range is outside the valid range (> getCharCount())</li> * </ul> */ public void setStyleRange(StyleRange range) { @@ -7765,14 +7920,14 @@ if (range.isUnstyled()) { setStyleRanges(range.start, range.length, null, null, false); } else { - setStyleRanges(range.start, 0, null, new StyleRange[]{range}, false); + setStyleRanges(range.start, 0, null, [range], false); } } else { setStyleRanges(0, 0, null, null, true); } } -/** - * Clears the styles in the range specified by <code>start</code> and +/** + * Clears the styles in the range specified by <code>start</code> and * <code>length</code> and adds the new styles. * <p> * The ranges array contains start and length pairs. Each pair refers to @@ -7784,7 +7939,7 @@ * Note: It is expected that the same instance of a StyleRange will occur * multiple times within the styles array, reducing memory usage. * </p><p> - * Should not be called if a LineStyleListener has been set since the + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p> * @@ -7792,19 +7947,19 @@ * @param length length of the range to delete styles in * @param ranges the array of ranges. The ranges must not overlap and must be in order. * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> - * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> - * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> - * <li>ERROR_INVALID_RANGE when a range overlaps</li> - * </ul> - * - * @since 3.2 + * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> + * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> + * <li>ERROR_INVALID_RANGE when a range overlaps</li> + * </ul> + * + * @since 3.2 */ public void setStyleRanges(int start, int length, int[] ranges, StyleRange[] styles) { checkWidget(); @@ -7815,7 +7970,7 @@ setStyleRanges(start, length, ranges, styles, false); } } -/** +/** * Sets styles to be used for rendering the widget content. * <p> * All styles in the widget will be replaced with the given set of ranges and styles. @@ -7828,25 +7983,25 @@ * Note: It is expected that the same instance of a StyleRange will occur * multiple times within the styles array, reducing memory usage. * </p><p> - * Should not be called if a LineStyleListener has been set since the + * Should not be called if a LineStyleListener has been set since the * listener maintains the styles. * </p> * * @param ranges the array of ranges. The ranges must not overlap and must be in order. * @param styles the array of StyleRanges. The range fields within the StyleRange are unused. - * + * * @exception DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT when an element in the styles array is null</li> - * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> - * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> - * <li>ERROR_INVALID_RANGE when a range overlaps</li> - * </ul> - * - * @since 3.2 + * <li>ERROR_INVALID_RANGE when the number of ranges and style do not match (ranges.length * 2 is styles.length)</li> + * <li>ERROR_INVALID_RANGE when a range is outside the valid range (> getCharCount() or less than zero)</li> + * <li>ERROR_INVALID_RANGE when a range overlaps</li> + * </ul> + * + * @since 3.2 */ public void setStyleRanges(int[] ranges, StyleRange[] styles) { checkWidget(); @@ -7871,7 +8026,7 @@ if (ranges.length !is styles.length << 1) DWT.error(DWT.ERROR_INVALID_ARGUMENT); } int lastOffset = 0; - bool variableHeight = false; + bool variableHeight = false; for (int i = 0; i < styles.length; i ++) { if (styles[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT); int rangeStart, rangeLength; @@ -7882,7 +8037,7 @@ rangeStart = styles[i].start; rangeLength = styles[i].length; } - if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + if (rangeLength < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (!(0 <= rangeStart && rangeStart + rangeLength <= charCount)) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (lastOffset > rangeStart) DWT.error(DWT.ERROR_INVALID_ARGUMENT); variableHeight |= styles[i].isVariableHeight(); @@ -7941,13 +8096,13 @@ } height = newLastLineBottom - y; } - super.redraw(0, y, clientAreaWidth, height, false); + super.redraw(0, y, clientAreaWidth, height, false); } } setCaretLocation(); } -/** - * Sets styles to be used for rendering the widget content. All styles +/** + * Sets styles to be used for rendering the widget content. All styles * in the widget will be replaced with the given set of styles. * <p> * Note: Because a StyleRange includes the start and length, the @@ -7956,32 +8111,32 @@ * multiple StyleRanges, <code>setStyleRanges(int[], StyleRange[])</code> * can be used to share styles and reduce memory usage. * </p><p> - * Should not be called if a LineStyleListener has been set since the + * 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 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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * @exception IllegalArgumentException <ul> - * <li>ERROR_NULL_ARGUMENT when the list of ranges is null</li> - * <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> - * </ul> - * + * <li>ERROR_INVALID_RANGE when the last of the style ranges is outside the valid range (> getCharCount())</li> + * </ul> + * * @see #setStyleRanges(int[], StyleRange[]) */ public void setStyleRanges(StyleRange[] ranges) { checkWidget(); if (isListening(LineGetStyle)) return; - if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + // DWT extension: allow null for zero length string + //if (ranges is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); setStyleRanges(0, 0, null, ranges, true); } -/** - * Sets the tab width. +/** + * Sets the tab width. * * @param tabs tab width measured in characters. * @exception DWTException <ul> @@ -7990,56 +8145,54 @@ * </ul> */ public void setTabs(int tabs) { - checkWidget(); + checkWidget(); tabLength = tabs; renderer.setFont(null, tabs); resetCache(0, content.getLineCount()); setCaretLocation(); super.redraw(); } -/** - * Sets the widget content. - * If the widget has the DWT.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 +/** + * Sets the widget content. + * If the widget has the DWT.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 DWT.SINGLE + * <b>Note:</b> Only a single line of text should be set when the DWT.SINGLE * style is used. * </p> * - * @param text new widget content. Replaces existing content. Line styles + * @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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> - * @exception IllegalArgumentException <ul> - * <li>ERROR_NULL_ARGUMENT when String is null</li> - * </ul> */ public void setText(String text) { checkWidget(); - if (text is null) { - DWT.error(DWT.ERROR_NULL_ARGUMENT); - } + // DWT extension: allow null for zero length string +// if (text is null) { +// DWT.error(DWT.ERROR_NULL_ARGUMENT); +// } Event event = new Event(); event.start = 0; event.end = getCharCount(); event.text = text; - event.doit = true; + event.doit = true; notifyListeners(DWT.Verify, event); if (event.doit) { StyledTextEvent styledTextEvent = null; if (isListening(ExtendedModify)) { styledTextEvent = new StyledTextEvent(content); styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.end = event.start + event.text.length; styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); } content.setText(event.text); - sendModifyEvent(event); + sendModifyEvent(event); if (styledTextEvent !is null) { notifyListeners(ExtendedModify, styledTextEvent); } @@ -8071,15 +8224,15 @@ /** * 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 + * 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 + * @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 DWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> @@ -8108,7 +8261,7 @@ } else { pixel = getAvailableHeightAbove(pixel); } - } + } scrollVertical(pixel, true); } /** @@ -8120,7 +8273,7 @@ * 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 + * @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 DWTException <ul> @@ -8133,7 +8286,7 @@ checkWidget(); if (getCharCount() is 0) { return; - } + } if (pixel < 0) pixel = 0; int lineCount = content.getLineCount(); int height = clientAreaHeight - topMargin - bottomMargin; @@ -8141,7 +8294,7 @@ if (isFixedLineHeight()) { int maxTopPixel = Math.max(0, lineCount * getVerticalIncrement() - height); if (pixel > maxTopPixel) pixel = maxTopPixel; - pixel -= verticalOffset; + pixel -= verticalOffset; } else { pixel -= verticalOffset; if (pixel > 0) { @@ -8175,6 +8328,7 @@ setCaretLocation(); super.redraw(); } +// DWT: If necessary, scroll to show the location bool showLocation(Rectangle rect, bool scrollPage) { int clientAreaWidth = this.clientAreaWidth - leftMargin - rightMargin; int clientAreaHeight = this.clientAreaHeight - topMargin - bottomMargin; @@ -8236,10 +8390,10 @@ startOffset = selection.x; endOffset = selection.y; } - + Rectangle startBounds = getBoundsAtOffset(startOffset); Rectangle endBounds = getBoundsAtOffset(endOffset); - + // can the selection be fully displayed within the widget's visible width? int w = clientAreaWidth - leftMargin - rightMargin; bool selectionFits = rightToLeft ? startBounds.x - endBounds.x <= w : endBounds.x - startBounds.x <= w; @@ -8254,7 +8408,7 @@ endBounds.width = 0; showLocation(endBounds, false); } else { - // just show the end of the selection since the selection start + // just show the end of the selection since the selection start // will not be visible showLocation(endBounds, true); } @@ -8262,10 +8416,10 @@ /** * Updates the selection and caret position depending on the text change. * <p> - * If the selection intersects with the replaced text, the selection is + * 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 + * same text remains selected. If the selection is before the replaced text * it is left unchanged. * </p> * @@ -8276,6 +8430,7 @@ void updateSelection(int startOffset, int replacedLength, int newLength) { if (selection.y <= startOffset) { // selection ends before text change + if (wordWrap) setCaretLocation(); return; } if (selection.x < startOffset) { @@ -8284,7 +8439,7 @@ } 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 + // 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;