Index: StyledText.java =================================================================== RCS file: /home/eclipse/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java,v retrieving revision 1.138 diff -u -r1.138 StyledText.java --- StyledText.java 24 Jan 2003 17:20:41 -0000 1.138 +++ StyledText.java 27 Jan 2003 02:30:40 -0000 @@ -1,9 +1,9 @@ package org.eclipse.swt.custom; /* - * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. - * This file is made available under the terms of the Common Public License v1.0 - * which accompanies this distribution, and is available at + * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. + * This file is made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html */ @@ -18,22 +18,22 @@ import org.eclipse.swt.widgets.*; /** - * A StyledText is an editable user interface object that displays lines - * of text. The following style attributes can be defined for the text: + * A StyledText is an editable user interface object that displays lines + * of text. The following style attributes can be defined for the text: * *

- * 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. *

*

- * 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: *

*/ public void addLineBackgroundListener(LineBackgroundListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - if (userLineBackground == false) { - removeLineBackgroundListener(defaultLineStyler); - defaultLineStyler.setLineBackground(0, logicalContent.getLineCount(), null); - userLineBackground = true; - } - StyledTextListener typedListener = new StyledTextListener(listener); - addListener(LineGetBackground, typedListener); + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + if (userLineBackground == false) { + removeLineBackgroundListener(defaultLineStyler); + defaultLineStyler.setLineBackground(0, logicalContent.getLineCount(), null); + userLineBackground = true; + } + StyledTextListener typedListener = new StyledTextListener(listener); + addListener(LineGetBackground, typedListener); } /** - * Adds a line style listener. A LineGetStyle event is sent by the widget to + * Adds a line style listener. A LineGetStyle event is sent by the widget to * determine the styles for a line. *

* @@ -1774,20 +1784,20 @@ * */ public void addLineStyleListener(LineStyleListener listener) { - checkWidget(); - if (listener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (userLineStyle == false) { - removeLineStyleListener(defaultLineStyler); - defaultLineStyler.setStyleRange(null); - userLineStyle = true; - } - StyledTextListener typedListener = new StyledTextListener(listener); - addListener(LineGetStyle, typedListener); + checkWidget(); + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + if (userLineStyle == false) { + removeLineStyleListener(defaultLineStyler); + defaultLineStyler.setStyleRange(null); + userLineStyle = true; + } + StyledTextListener typedListener = new StyledTextListener(listener); + addListener(LineGetStyle, typedListener); } -/** - * Adds a modify listener. A Modify event is sent by the widget when the widget text +/** + * Adds a modify listener. A Modify event is sent by the widget when the widget text * has changed. *

* @@ -1801,15 +1811,15 @@ * */ public void addModifyListener(ModifyListener modifyListener) { - checkWidget(); - if (modifyListener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - TypedListener typedListener = new TypedListener(modifyListener); - addListener(SWT.Modify, typedListener); + checkWidget(); + if (modifyListener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + TypedListener typedListener = new TypedListener(modifyListener); + addListener(SWT.Modify, typedListener); } -/** - * Adds a selection listener. A Selection event is sent by the widget when the +/** + * Adds a selection listener. A Selection event is sent by the widget when the * selection has changed. *

* @@ -1823,17 +1833,17 @@ * */ public void addSelectionListener(SelectionListener listener) { - checkWidget(); - if (listener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - TypedListener typedListener = new TypedListener(listener); - addListener(SWT.Selection, typedListener); -} -/** - * Adds a verify key listener. A VerifyKey event is sent by the widget when a key - * is pressed. The widget ignores the key press if the listener sets the doit field - * of the event to false. + checkWidget(); + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + TypedListener typedListener = new TypedListener(listener); + addListener(SWT.Selection, typedListener); +} +/** + * Adds a verify key listener. A VerifyKey event is sent by the widget when a key + * is pressed. The widget ignores the key press if the listener sets the doit field + * of the event to false. *

* * @param listener the listener @@ -1846,17 +1856,17 @@ * */ public void addVerifyKeyListener(VerifyKeyListener listener) { - checkWidget(); - if (listener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - StyledTextListener typedListener = new StyledTextListener(listener); - addListener(VerifyKey, typedListener); -} -/** - * Adds a verify listener. A Verify event is sent by the widget when the widget text - * is about to change. The listener can set the event text and the doit field to - * change the text that is set in the widget or to force the widget to ignore the + checkWidget(); + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + StyledTextListener typedListener = new StyledTextListener(listener); + addListener(VerifyKey, typedListener); +} +/** + * Adds a verify listener. A Verify event is sent by the widget when the widget text + * is about to change. The listener can set the event text and the doit field to + * change the text that is set in the widget or to force the widget to ignore the * text change. *

* @@ -1870,14 +1880,14 @@ * */ public void addVerifyListener(VerifyListener verifyListener) { - checkWidget(); - if (verifyListener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - TypedListener typedListener = new TypedListener(verifyListener); - addListener(SWT.Verify, typedListener); + checkWidget(); + if (verifyListener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + TypedListener typedListener = new TypedListener(verifyListener); + addListener(SWT.Verify, typedListener); } -/** +/** * Appends a string to the text at the end of the widget. *

* @@ -1892,36 +1902,36 @@ * */ public void append(String string) { - checkWidget(); - if (string == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - int lastChar = Math.max(getCharCount(), 0); - replaceTextRange(lastChar, 0, string); + checkWidget(); + if (string == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + int lastChar = Math.max(getCharCount(), 0); + replaceTextRange(lastChar, 0, string); } /** * Calculates the width of the widest visible line. */ void calculateContentWidth() { - if (lineHeight != 0) { - lineCache = getLineCache(content); - lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); - } + if (lineHeight != 0) { + lineCache = getLineCache(content); + lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); + } } /** * Calculates the scroll bars */ void calculateScrollBars() { - ScrollBar horizontalBar = getHorizontalBar(); - ScrollBar verticalBar = getVerticalBar(); - - setScrollBars(); - if (verticalBar != null) { - verticalBar.setIncrement(getVerticalIncrement()); - } - if (horizontalBar != null) { - horizontalBar.setIncrement(getHorizontalIncrement()); - } + ScrollBar horizontalBar = getHorizontalBar(); + ScrollBar verticalBar = getVerticalBar(); + + setScrollBars(); + if (verticalBar != null) { + verticalBar.setIncrement(getVerticalIncrement()); + } + if (horizontalBar != null) { + horizontalBar.setIncrement(getHorizontalIncrement()); + } } /** * Calculates the top index based on the current vertical scroll offset. @@ -1930,97 +1940,97 @@ * The top index starts at 0. */ void calculateTopIndex() { - int oldTopIndex = topIndex; - int verticalIncrement = getVerticalIncrement(); - int clientAreaHeight = getClientArea().height; - - if (verticalIncrement == 0) { - return; - } - topIndex = Compatibility.ceil(verticalScrollOffset, verticalIncrement); - // Set top index to partially visible top line if no line is fully - // visible but at least some of the widget client area is visible. - // Fixes bug 15088. - if (topIndex > 0) { - if (clientAreaHeight > 0) { - int bottomPixel = verticalScrollOffset + clientAreaHeight; - int fullLineTopPixel = topIndex * verticalIncrement; - int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; - // set top index to partially visible line if no line fully fits in - // client area or if space is available but not used (the latter should - // never happen because we use claimBottomFreeSpace) - if (fullLineVisibleHeight < verticalIncrement) { - topIndex--; - } - } - else - if (topIndex >= content.getLineCount()) { - topIndex = content.getLineCount() - 1; - } - } - if (topIndex != oldTopIndex) { - topOffset = content.getOffsetAtLine(topIndex); - lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); - setHorizontalScrollBar(); - } + int oldTopIndex = topIndex; + int verticalIncrement = getVerticalIncrement(); + int clientAreaHeight = getClientArea().height; + + if (verticalIncrement == 0) { + return; + } + topIndex = Compatibility.ceil(verticalScrollOffset, verticalIncrement); + // Set top index to partially visible top line if no line is fully + // visible but at least some of the widget client area is visible. + // Fixes bug 15088. + if (topIndex > 0) { + if (clientAreaHeight > 0) { + int bottomPixel = verticalScrollOffset + clientAreaHeight; + int fullLineTopPixel = topIndex * verticalIncrement; + int fullLineVisibleHeight = bottomPixel - fullLineTopPixel; + // set top index to partially visible line if no line fully fits in + // client area or if space is available but not used (the latter should + // never happen because we use claimBottomFreeSpace) + if (fullLineVisibleHeight < verticalIncrement) { + topIndex--; + } + } + else + if (topIndex >= content.getLineCount()) { + topIndex = content.getLineCount() - 1; + } + } + if (topIndex != oldTopIndex) { + topOffset = content.getOffsetAtLine(topIndex); + lineCache.calculate(topIndex, getPartialBottomIndex() - topIndex + 1); + setHorizontalScrollBar(); + } } /** * Hides the scroll bars if widget is created in single line mode. */ static int checkStyle(int style) { - if ((style & SWT.SINGLE) != 0) { - style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); - } - return style; + if ((style & SWT.SINGLE) != 0) { + style &= ~(SWT.H_SCROLL | SWT.V_SCROLL); + } + 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() { - int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - getClientArea().height); - - if (newVerticalOffset < verticalScrollOffset) { - // Scroll up so that empty lines below last text line are used. - // Fixes 1GEYJM0 - setVerticalScrollOffset(newVerticalOffset, true); - } + int newVerticalOffset = Math.max(0, content.getLineCount() * lineHeight - getClientArea().height); + + if (newVerticalOffset < verticalScrollOffset) { + // Scroll up so that empty lines below last text line are used. + // Fixes 1GEYJM0 + setVerticalScrollOffset(newVerticalOffset, true); + } } /** * Scrolls text to the right to use new space made available by a resize. */ void claimRightFreeSpace() { - int newHorizontalOffset = Math.max(0, lineCache.getWidth() - (getClientArea().width - leftMargin - rightMargin)); - - if (newHorizontalOffset < horizontalScrollOffset) { - // item is no longer drawn past the right border of the client area - // align the right end of the item with the right border of the - // client area (window is scrolled right). - scrollHorizontalBar(newHorizontalOffset - horizontalScrollOffset); - } + int newHorizontalOffset = Math.max(0, lineCache.getWidth() - (getClientArea().width - leftMargin - rightMargin)); + + if (newHorizontalOffset < horizontalScrollOffset) { + // item is no longer drawn past the right border of the client area + // align the right end of the item with the right border of the + // client area (window is scrolled right). + scrollHorizontalBar(newHorizontalOffset - horizontalScrollOffset); + } } /** * Clears the widget margin. - * + * * @param gc GC to render on * @param background background color to use for clearing the margin * @param clientArea widget client area dimensions * @param renderHeight height in pixel of the rendered lines */ void clearMargin(GC gc, Color background, Rectangle clientArea, int renderHeight) { - if (renderHeight + topMargin <= 0) { - return; - } - // clear the margin background - gc.setBackground(background); - gc.fillRectangle(0, 0, clientArea.width, topMargin); - gc.fillRectangle(0, 0, leftMargin, renderHeight + topMargin); - gc.fillRectangle( - 0, clientArea.height - bottomMargin, - clientArea.width, bottomMargin); - gc.fillRectangle( - clientArea.width - rightMargin, 0, - rightMargin, renderHeight + topMargin); + if (renderHeight + topMargin <= 0) { + return; + } + // clear the margin background + gc.setBackground(background); + gc.fillRectangle(0, 0, clientArea.width, topMargin); + gc.fillRectangle(0, 0, leftMargin, renderHeight + topMargin); + gc.fillRectangle( + 0, clientArea.height - bottomMargin, + clientArea.width, bottomMargin); + gc.fillRectangle( + clientArea.width - rightMargin, 0, + rightMargin, renderHeight + topMargin); } /** * Removes the widget selection. @@ -2029,24 +2039,24 @@ * @param sendEvent a Selection event is sent when set to true and when the selection is actually reset. */ void clearSelection(boolean sendEvent) { - int selectionStart = selection.x; - int selectionEnd = selection.y; - int length = content.getCharCount(); - - resetSelection(); - // redraw old selection, if any - if (selectionEnd - selectionStart > 0) { - // called internally to remove selection after text is removed - // therefore make sure redraw range is valid. - int redrawStart = Math.min(selectionStart, length); - int redrawEnd = Math.min(selectionEnd, length); - if (redrawEnd - redrawStart > 0) { - internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); - } - if (sendEvent == true) { - sendSelectionEvent(); - } - } + int selectionStart = selection.x; + int selectionEnd = selection.y; + int length = content.getCharCount(); + + resetSelection(); + // redraw old selection, if any + if (selectionEnd - selectionStart > 0) { + // called internally to remove selection after text is removed + // therefore make sure redraw range is valid. + int redrawStart = Math.min(selectionStart, length); + int redrawEnd = Math.min(selectionEnd, length); + if (redrawEnd - redrawStart > 0) { + internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); + } + if (sendEvent == true) { + sendSelectionEvent(); + } + } } /** * Computes the preferred size. @@ -2057,77 +2067,77 @@ * */ public Point computeSize (int wHint, int hHint, boolean changed) { - checkWidget(); - int count, width, height; - boolean singleLine = (getStyle() & SWT.SINGLE) != 0; - - if (singleLine) { - count = 1; - } else { - count = content.getLineCount(); - } - if (wHint != SWT.DEFAULT) { - width = wHint; - } - else { - width = DEFAULT_WIDTH; - } - - if (wordWrap) { - if (((WrappedContent) content).getVisualLineCount() != 0) { - // lines have already been wrapped to a specific width. - // use existing line count. fixes bug 9191 - if (wHint == SWT.DEFAULT) { - width = lineCache.getWidth(); - } else { - ((WrappedContent) content).wrapLines(width); - // caret may be on a different line after a rewrap - setCaretLocation(); - } - if (singleLine == false) { - count = content.getLineCount(); - } - } - else { - if (singleLine == false) { - ((WrappedContent) content).wrapLines(width); - // caret may be on a different line after a rewrap - setCaretLocation(); - count = content.getLineCount(); - } - } - } - else if (wHint == SWT.DEFAULT) { - // Only calculate what can actually be displayed. - // Do this because measuring each text line is a - // time-consuming process. - int visibleCount = Math.min (count, getDisplay().getBounds().height / lineHeight); - lineCache.calculate(0, visibleCount); - width = lineCache.getWidth() + leftMargin + rightMargin; - } - if (hHint != SWT.DEFAULT) { - height = hHint; - } - else { - height = count * lineHeight + topMargin + bottomMargin; - } - // Use default values if no text is defined. - if (width == 0) { - width = DEFAULT_WIDTH; - } - if (height == 0) { - if (singleLine) { - height = lineHeight; - } - else { - height = DEFAULT_HEIGHT; - } - } - Rectangle rect = computeTrim(0, 0, width, height); - return new Point (rect.width, rect.height); + checkWidget(); + int count, width, height; + boolean singleLine = (getStyle() & SWT.SINGLE) != 0; + + if (singleLine) { + count = 1; + } else { + count = content.getLineCount(); + } + if (wHint != SWT.DEFAULT) { + width = wHint; + } + else { + width = DEFAULT_WIDTH; + } + + if (wordWrap) { + if (((WrappedContent) content).getVisualLineCount() != 0) { + // lines have already been wrapped to a specific width. + // use existing line count. fixes bug 9191 + if (wHint == SWT.DEFAULT) { + width = lineCache.getWidth(); + } else { + ((WrappedContent) content).wrapLines(width); + // caret may be on a different line after a rewrap + setCaretLocation(); + } + if (singleLine == false) { + count = content.getLineCount(); + } + } + else { + if (singleLine == false) { + ((WrappedContent) content).wrapLines(width); + // caret may be on a different line after a rewrap + setCaretLocation(); + count = content.getLineCount(); + } + } + } + else if (wHint == SWT.DEFAULT) { + // Only calculate what can actually be displayed. + // Do this because measuring each text line is a + // time-consuming process. + int visibleCount = Math.min (count, getDisplay().getBounds().height / lineHeight); + lineCache.calculate(0, visibleCount); + width = lineCache.getWidth() + leftMargin + rightMargin; + } + if (hHint != SWT.DEFAULT) { + height = hHint; + } + else { + height = count * lineHeight + topMargin + bottomMargin; + } + // Use default values if no text is defined. + if (width == 0) { + width = DEFAULT_WIDTH; + } + if (height == 0) { + if (singleLine) { + height = lineHeight; + } + else { + height = DEFAULT_HEIGHT; + } + } + Rectangle rect = computeTrim(0, 0, width, height); + return new Point (rect.width, rect.height); } /** - * Copies the selected text to the clipboard. The text will be put in the + * Copies the selected text to the clipboard. The text will be put in the * clipboard in plain text format and RTF format. *

* @@ -2137,135 +2147,135 @@ * */ public void copy() { - checkWidget(); - int length = selection.y - selection.x; - if (length > 0) { - try { - setClipboardContent(selection.x, length); - } - catch (SWTError error) { - // Copy to clipboard failed. This happens when another application - // is accessing the clipboard while we copy. Ignore the error. - // Fixes 1GDQAVN - // Rethrow all other errors. Fixes bug 17578. - if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { - throw error; - } - } - } + checkWidget(); + int length = selection.y - selection.x; + if (length > 0) { + try { + setClipboardContent(selection.x, length); + } + catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + } + } } /** - * Returns a string that uses only the line delimiter specified by the + * Returns a string that uses only the line delimiter specified by the * StyledTextContent implementation. * Returns only the first line if the widget has the SWT.SINGLE style. *

* - * @param text the text that may have line delimiters that don't - * match the model line delimiter. Possible line delimiters - * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") - * @return the converted text that only uses the line delimiter - * specified by the model. Returns only the first line if the widget - * has the SWT.SINGLE style. + * @param text the text that may have line delimiters that don't + * match the model line delimiter. Possible line delimiters + * are CR ('\r'), LF ('\n'), CR/LF ("\r\n") + * @return the converted text that only uses the line delimiter + * specified by the model. Returns only the first line if the widget + * has the SWT.SINGLE style. */ String getModelDelimitedText(String text) { - StringBuffer convertedText; - String delimiter = getLineDelimiter(); - int length = text.length(); - int crIndex = 0; - int lfIndex = 0; - int i = 0; - - if (length == 0) { - return text; - } - convertedText = new StringBuffer(length); - while (i < length) { - if (crIndex != -1) { - crIndex = text.indexOf(SWT.CR, i); - } - if (lfIndex != -1) { - lfIndex = text.indexOf(SWT.LF, i); - } - if (lfIndex == -1 && crIndex == -1) { // no more line breaks? - break; - } - else // CR occurs before LF or no LF present? - if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { - convertedText.append(text.substring(i, crIndex)); - if (lfIndex == crIndex + 1) { // CR/LF combination? - i = lfIndex + 1; - } - else { - i = crIndex + 1; - } - } - else { // LF occurs before CR! - convertedText.append(text.substring(i, lfIndex)); - i = lfIndex + 1; - } - if (isSingleLine()) { - break; - } - convertedText.append(delimiter); - } - // copy remaining text if any and if not in single line mode or no - // text copied thus far (because there only is one line) - if (i < length && (isSingleLine() == false || convertedText.length() == 0)) { - convertedText.append(text.substring(i)); - } - return convertedText.toString(); + StringBuffer convertedText; + String delimiter = getLineDelimiter(); + int length = text.length(); + int crIndex = 0; + int lfIndex = 0; + int i = 0; + + if (length == 0) { + return text; + } + convertedText = new StringBuffer(length); + while (i < length) { + if (crIndex != -1) { + crIndex = text.indexOf(SWT.CR, i); + } + if (lfIndex != -1) { + lfIndex = text.indexOf(SWT.LF, i); + } + if (lfIndex == -1 && crIndex == -1) { // no more line breaks? + break; + } + else // CR occurs before LF or no LF present? + if ((crIndex < lfIndex && crIndex != -1) || lfIndex == -1) { + convertedText.append(text.substring(i, crIndex)); + if (lfIndex == crIndex + 1) { // CR/LF combination? + i = lfIndex + 1; + } + else { + i = crIndex + 1; + } + } + else { // LF occurs before CR! + convertedText.append(text.substring(i, lfIndex)); + i = lfIndex + 1; + } + if (isSingleLine()) { + break; + } + convertedText.append(delimiter); + } + // copy remaining text if any and if not in single line mode or no + // text copied thus far (because there only is one line) + if (i < length && (isSingleLine() == false || convertedText.length() == 0)) { + convertedText.append(text.substring(i)); + } + return convertedText.toString(); } /** * Creates default key bindings. */ void createKeyBindings() { - // Navigation - setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); - setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); - setKeyBinding(SWT.HOME, ST.LINE_START); - setKeyBinding(SWT.END, ST.LINE_END); - setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS); - setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT); - setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); - setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); - setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS); - setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT); - setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); - setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); - setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); - // Selection - setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); - setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); - setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); - setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); - setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); - setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT); - setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); - setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); - setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); - setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); - setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); - setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); - setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); - - // Modification - // Cut, Copy, Paste - setKeyBinding('X' | SWT.MOD1, ST.CUT); - setKeyBinding('C' | SWT.MOD1, ST.COPY); - setKeyBinding('V' | SWT.MOD1, ST.PASTE); - // Cut, Copy, Paste Wordstar style - setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); - setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); - setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); - setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); - - setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); - setKeyBinding(SWT.DEL, ST.DELETE_NEXT); - - // Miscellaneous - setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); + // Navigation + setKeyBinding(SWT.ARROW_UP, ST.LINE_UP); + setKeyBinding(SWT.ARROW_DOWN, ST.LINE_DOWN); + setKeyBinding(SWT.HOME, ST.LINE_START); + setKeyBinding(SWT.END, ST.LINE_END); + setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS); + setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT); + setKeyBinding(SWT.PAGE_UP, ST.PAGE_UP); + setKeyBinding(SWT.PAGE_DOWN, ST.PAGE_DOWN); + setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS); + setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT); + setKeyBinding(SWT.HOME | SWT.MOD1, ST.TEXT_START); + setKeyBinding(SWT.END | SWT.MOD1, ST.TEXT_END); + setKeyBinding(SWT.PAGE_UP | SWT.MOD1, ST.WINDOW_START); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1, ST.WINDOW_END); + // Selection + setKeyBinding(SWT.ARROW_UP | SWT.MOD2, ST.SELECT_LINE_UP); + setKeyBinding(SWT.ARROW_DOWN | SWT.MOD2, ST.SELECT_LINE_DOWN); + setKeyBinding(SWT.HOME | SWT.MOD2, ST.SELECT_LINE_START); + setKeyBinding(SWT.END | SWT.MOD2, ST.SELECT_LINE_END); + setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS); + setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT); + setKeyBinding(SWT.PAGE_UP | SWT.MOD2, ST.SELECT_PAGE_UP); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD2, ST.SELECT_PAGE_DOWN); + setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS); + setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT); + setKeyBinding(SWT.HOME | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_START); + setKeyBinding(SWT.END | SWT.MOD1 | SWT.MOD2, ST.SELECT_TEXT_END); + setKeyBinding(SWT.PAGE_UP | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_START); + setKeyBinding(SWT.PAGE_DOWN | SWT.MOD1 | SWT.MOD2, ST.SELECT_WINDOW_END); + + // Modification + // Cut, Copy, Paste + setKeyBinding('X' | SWT.MOD1, ST.CUT); + setKeyBinding('C' | SWT.MOD1, ST.COPY); + setKeyBinding('V' | SWT.MOD1, ST.PASTE); + // Cut, Copy, Paste Wordstar style + setKeyBinding(SWT.DEL | SWT.MOD2, ST.CUT); + setKeyBinding(SWT.INSERT | SWT.MOD1, ST.COPY); + setKeyBinding(SWT.INSERT | SWT.MOD2, ST.PASTE); + setKeyBinding(SWT.BS | SWT.MOD2, ST.DELETE_PREVIOUS); + + setKeyBinding(SWT.BS, ST.DELETE_PREVIOUS); + setKeyBinding(SWT.DEL, ST.DELETE_NEXT); + + // Miscellaneous + setKeyBinding(SWT.INSERT, ST.TOGGLE_OVERWRITE); } /** * Create the bitmaps to use for the caret in bidi mode. This @@ -2273,37 +2283,37 @@ * font changes (the caret bitmap height needs to match font height). */ void createCaretBitmaps() { - int caretWidth = BIDI_CARET_WIDTH; - - Display display = getDisplay(); - if (caretPalette == null) { - caretPalette = new PaletteData(new RGB[] {new RGB (0,0,0), new RGB (255,255,255)}); - } - if (leftCaretBitmap != null) { - leftCaretBitmap.dispose(); - } - ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette); - leftCaretBitmap = new Image(display, imageData); - GC gc = new GC (leftCaretBitmap); - gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); - gc.drawLine(0,0,0,lineHeight); - gc.drawLine(0,0,caretWidth-1,0); - gc.drawLine(0,1,1,1); - gc.dispose(); - - if (rightCaretBitmap != null) { - rightCaretBitmap.dispose(); - } - rightCaretBitmap = new Image(display, imageData); - gc = new GC (rightCaretBitmap); - gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); - gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); - gc.drawLine(0,0,caretWidth-1,0); - gc.drawLine(caretWidth-1,1,1,1); - gc.dispose(); + int caretWidth = BIDI_CARET_WIDTH; + + Display display = getDisplay(); + if (caretPalette == null) { + caretPalette = new PaletteData(new RGB[] {new RGB (0,0,0), new RGB (255,255,255)}); + } + if (leftCaretBitmap != null) { + leftCaretBitmap.dispose(); + } + ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette); + leftCaretBitmap = new Image(display, imageData); + GC gc = new GC (leftCaretBitmap); + gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); + gc.drawLine(0,0,0,lineHeight); + gc.drawLine(0,0,caretWidth-1,0); + gc.drawLine(0,1,1,1); + gc.dispose(); + + if (rightCaretBitmap != null) { + rightCaretBitmap.dispose(); + } + rightCaretBitmap = new Image(display, imageData); + gc = new GC (rightCaretBitmap); + gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); + gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight); + gc.drawLine(0,0,caretWidth-1,0); + gc.drawLine(caretWidth-1,1,1,1); + gc.dispose(); } /** - * Moves the selected text to the clipboard. The text will be put in the + * Moves the selected text to the clipboard. The text will be put in the * clipboard in plain text format and RTF format. *

* @@ -2313,564 +2323,564 @@ * */ public void cut(){ - checkWidget(); - int length = selection.y - selection.x; - - if (length > 0) { - try { - setClipboardContent(selection.x, length); - } - catch (SWTError error) { - // Copy to clipboard failed. This happens when another application - // is accessing the clipboard while we copy. Ignore the error. - // Fixes 1GDQAVN - // Rethrow all other errors. Fixes bug 17578. - if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { - throw error; - } - // Abort cut operation if copy to clipboard fails. - // Fixes bug 21030. - return; - } - doDelete(); - } + checkWidget(); + int length = selection.y - selection.x; + + if (length > 0) { + try { + setClipboardContent(selection.x, length); + } + catch (SWTError error) { + // Copy to clipboard failed. This happens when another application + // is accessing the clipboard while we copy. Ignore the error. + // Fixes 1GDQAVN + // Rethrow all other errors. Fixes bug 17578. + if (error.code != DND.ERROR_CANNOT_SET_CLIPBOARD) { + throw error; + } + // Abort cut operation if copy to clipboard fails. + // Fixes bug 21030. + return; + } + doDelete(); + } } -/** +/** * A mouse move event has occurred. See if we should start autoscrolling. If - * the move position is outside of the client area, initiate autoscrolling. + * the move position is outside of the client area, initiate autoscrolling. * Otherwise, we've moved back into the widget so end autoscrolling. */ void doAutoScroll(Event event) { - Rectangle area = getClientArea(); - - if (event.y > area.height) { - doAutoScroll(SWT.DOWN); - } - else - if (event.y < 0) { - doAutoScroll(SWT.UP); - } - else - if (event.x < leftMargin && wordWrap == false) { - doAutoScroll(SWT.LEFT); - } - else - if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) { - doAutoScroll(SWT.RIGHT); - } - else { - endAutoScroll(); - } + Rectangle area = getClientArea(); + + if (event.y > area.height) { + doAutoScroll(SWT.DOWN); + } + else + if (event.y < 0) { + doAutoScroll(SWT.UP); + } + else + if (event.x < leftMargin && wordWrap == false) { + doAutoScroll(SWT.LEFT); + } + else + if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) { + doAutoScroll(SWT.RIGHT); + } + else { + endAutoScroll(); + } } -/** +/** * Initiates autoscrolling. *

* * @param direction SWT.UP, SWT.DOWN, SWT.RIGHT, SWT.LEFT */ void doAutoScroll(int direction) { - Runnable timer = null; - final int TIMER_INTERVAL = 5; - - // If we're already autoscrolling in the given direction do nothing - if (autoScrollDirection == direction) { - return; - } - - final Display display = getDisplay(); - // Set a timer that will simulate the user pressing and holding - // down a cursor key (i.e., arrowUp, arrowDown). - if (direction == SWT.UP) { - timer = new Runnable() { - public void run() { - if (autoScrollDirection == SWT.UP) { - doSelectionLineUp(); - display.timerExec(TIMER_INTERVAL, this); - } - } - }; - } else if (direction == SWT.DOWN) { - timer = new Runnable() { - public void run() { - if (autoScrollDirection == SWT.DOWN) { - doSelectionLineDown(); - display.timerExec(TIMER_INTERVAL, this); - } - } - }; - } else if (direction == SWT.RIGHT) { - timer = new Runnable() { - public void run() { - if (autoScrollDirection == SWT.RIGHT) { - doColumnRight(); - setMouseWordSelectionAnchor(); - doSelection(SWT.RIGHT); - display.timerExec(TIMER_INTERVAL, this); - } - } - }; - } else if (direction == SWT.LEFT) { - timer = new Runnable() { - public void run() { - if (autoScrollDirection == SWT.LEFT) { - doColumnLeft(); - setMouseWordSelectionAnchor(); - doSelection(SWT.LEFT); - display.timerExec(TIMER_INTERVAL, this); - } - } - }; - } - if (timer != null) { - autoScrollDirection = direction; - display.timerExec(TIMER_INTERVAL, timer); - } + Runnable timer = null; + final int TIMER_INTERVAL = 5; + + // If we're already autoscrolling in the given direction do nothing + if (autoScrollDirection == direction) { + return; + } + + final Display display = getDisplay(); + // Set a timer that will simulate the user pressing and holding + // down a cursor key (i.e., arrowUp, arrowDown). + if (direction == SWT.UP) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.UP) { + doSelectionLineUp(); + display.timerExec(TIMER_INTERVAL, this); + } + } + }; + } else if (direction == SWT.DOWN) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.DOWN) { + doSelectionLineDown(); + display.timerExec(TIMER_INTERVAL, this); + } + } + }; + } else if (direction == SWT.RIGHT) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.RIGHT) { + doColumnRight(); + setMouseWordSelectionAnchor(); + doSelection(SWT.RIGHT); + display.timerExec(TIMER_INTERVAL, this); + } + } + }; + } else if (direction == SWT.LEFT) { + timer = new Runnable() { + public void run() { + if (autoScrollDirection == SWT.LEFT) { + doColumnLeft(); + setMouseWordSelectionAnchor(); + doSelection(SWT.LEFT); + display.timerExec(TIMER_INTERVAL, this); + } + } + }; + } + if (timer != null) { + autoScrollDirection = direction; + display.timerExec(TIMER_INTERVAL, timer); + } } /** * Deletes the previous character. Delete the selected text if any. * Move the caret in front of the deleted text. */ void doBackspace() { - Event event = new Event(); - event.text = ""; - if (selection.x != selection.y) { - event.start = selection.x; - event.end = selection.y; - sendKeyEvent(event); - } - else - if (caretOffset > 0) { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - - if (caretOffset == lineOffset) { - lineOffset = content.getOffsetAtLine(line - 1); - event.start = lineOffset + content.getLine(line - 1).length(); - event.end = caretOffset; - } - else { - event.start = caretOffset - 1; - event.end = caretOffset; - } - sendKeyEvent(event); - } + Event event = new Event(); + event.text = ""; + if (selection.x != selection.y) { + event.start = selection.x; + event.end = selection.y; + sendKeyEvent(event); + } + else + if (caretOffset > 0) { + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + + if (caretOffset == lineOffset) { + lineOffset = content.getOffsetAtLine(line - 1); + event.start = lineOffset + content.getLine(line - 1).length(); + event.end = caretOffset; + } + else { + event.start = caretOffset - 1; + event.end = caretOffset; + } + sendKeyEvent(event); + } } /** * 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 doColumnLeft() { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = caretOffset - lineOffset; - - if (isBidi()) { - String lineText = content.getLine(line); - int lineLength = lineText.length(); - GC gc = getGC(); - StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); - - if (horizontalScrollOffset > 0 || offsetInLine > 0) { - if (offsetInLine < lineLength && bidi.isRightToLeft(offsetInLine)) { - // advance caret logically if in R2L segment (move visually left) - caretOffset++; - doSelection(SWT.RIGHT); - if (caretOffset - lineOffset == lineLength) { - // if the line end is reached in a R2L segment, make the - // caret position (visual left border) visible before - // jumping to segment start - showCaret(); - } - // end of R2L segment reached (visual left side)? - if (bidi.isRightToLeft(caretOffset - lineOffset) == false) { - if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { - // make beginning of R2L segment visible before going - // left, to L2R segment important if R2L segment ends - // at visual left in order to scroll all the way to the - // left. Fixes 1GKM3XS - showCaret(); - } - // go to beginning of R2L segment (visually end of next L2R - // segment)/beginning of line - caretOffset--; - while (caretOffset - lineOffset > 0 && - bidi.isRightToLeft(caretOffset - lineOffset)) { - caretOffset--; - } - } - } - else - if (offsetInLine == lineLength && - bidi.getTextPosition(lineLength) != XINSET) { - // at logical line end in R2L segment but there's more text (a - // L2R segment) go to end of R2L segment (visually left of next - // L2R segment)/end of line - caretOffset--; - while (caretOffset - lineOffset > 0 && - bidi.isRightToLeft(caretOffset - lineOffset)) { - caretOffset--; - } - } - else - if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { - // decrease caret logically if in L2R segment (move visually left) - caretOffset--; - doSelection(SWT.LEFT); - // end of L2R segment reached (visual left side of preceeding R2L - // segment)? - if (caretOffset - lineOffset > 0 && - bidi.isRightToLeft(caretOffset - lineOffset - 1)) { - // go to beginning of R2L segment (visually start of next L2R - // segment)/beginning of line - caretOffset--; - while (caretOffset - lineOffset > 0 && - bidi.isRightToLeft(caretOffset - lineOffset - 1)) { - caretOffset--; - } - } - } - // if new caret position is to the left of the client area - if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { - // scroll to the caret position - showCaret(); - } - else { - // otherwise just update caret position without scrolling it into view - setBidiCaretLocation(null); - setBidiKeyboardLanguage(); - } - // Beginning of line reached (auto scroll finished) but not scrolled - // completely to the left? Fixes 1GKM193 - if (caretOffset - lineOffset == 0 && horizontalScrollOffset > 0 && - horizontalScrollOffset <= XINSET) { - scrollHorizontalBar(-horizontalScrollOffset); - } - } - gc.dispose(); - } - else - if (offsetInLine > 0) { - caretOffset--; - showCaret(); - } + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = caretOffset - lineOffset; + + if (isBidi()) { + String lineText = content.getLine(line); + int lineLength = lineText.length(); + GC gc = getGC(); + StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); + + if (horizontalScrollOffset > 0 || offsetInLine > 0) { + if (offsetInLine < lineLength && bidi.isRightToLeft(offsetInLine)) { + // advance caret logically if in R2L segment (move visually left) + caretOffset++; + doSelection(SWT.RIGHT); + if (caretOffset - lineOffset == lineLength) { + // if the line end is reached in a R2L segment, make the + // caret position (visual left border) visible before + // jumping to segment start + showCaret(); + } + // end of R2L segment reached (visual left side)? + if (bidi.isRightToLeft(caretOffset - lineOffset) == false) { + if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { + // make beginning of R2L segment visible before going + // left, to L2R segment important if R2L segment ends + // at visual left in order to scroll all the way to the + // left. Fixes 1GKM3XS + showCaret(); + } + // go to beginning of R2L segment (visually end of next L2R + // segment)/beginning of line + caretOffset--; + while (caretOffset - lineOffset > 0 && + bidi.isRightToLeft(caretOffset - lineOffset)) { + caretOffset--; + } + } + } + else + if (offsetInLine == lineLength && + bidi.getTextPosition(lineLength) != XINSET) { + // at logical line end in R2L segment but there's more text (a + // L2R segment) go to end of R2L segment (visually left of next + // L2R segment)/end of line + caretOffset--; + while (caretOffset - lineOffset > 0 && + bidi.isRightToLeft(caretOffset - lineOffset)) { + caretOffset--; + } + } + else + if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { + // decrease caret logically if in L2R segment (move visually left) + caretOffset--; + doSelection(SWT.LEFT); + // end of L2R segment reached (visual left side of preceeding R2L + // segment)? + if (caretOffset - lineOffset > 0 && + bidi.isRightToLeft(caretOffset - lineOffset - 1)) { + // go to beginning of R2L segment (visually start of next L2R + // segment)/beginning of line + caretOffset--; + while (caretOffset - lineOffset > 0 && + bidi.isRightToLeft(caretOffset - lineOffset - 1)) { + caretOffset--; + } + } + } + // if new caret position is to the left of the client area + if (bidi.getTextPosition(caretOffset - lineOffset) < horizontalScrollOffset) { + // scroll to the caret position + showCaret(); + } + else { + // otherwise just update caret position without scrolling it into view + setBidiCaretLocation(null); + setBidiKeyboardLanguage(); + } + // Beginning of line reached (auto scroll finished) but not scrolled + // completely to the left? Fixes 1GKM193 + if (caretOffset - lineOffset == 0 && horizontalScrollOffset > 0 && + horizontalScrollOffset <= XINSET) { + scrollHorizontalBar(-horizontalScrollOffset); + } + } + gc.dispose(); + } + else + if (offsetInLine > 0) { + caretOffset--; + showCaret(); + } } /** * Moves the caret one character to the right. Do not go to the next line. - * When in a bidi locale and at a R2L character the caret is moved to the - * end of the R2L segment (visually left) and then one character to the + * 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 doColumnRight() { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = caretOffset - lineOffset; - String lineText = content.getLine(line); - int lineLength = lineText.length(); - - if (isBidi()) { - GC gc = getGC(); - StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); - if (bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || - offsetInLine < lineLength) { - if (bidi.isRightToLeft(offsetInLine) == false && - offsetInLine < lineLength) { - // advance caret logically if in L2R segment (move visually right) - caretOffset++; - doSelection(SWT.RIGHT); - // end of L2R segment reached (visual right side)? - if (bidi.isRightToLeft(caretOffset - lineOffset)) { - // go to end of R2L segment (visually left of next R2L segment)/ - // end of line - caretOffset++; - while (caretOffset < lineOffset + lineLength && - bidi.isRightToLeft(caretOffset - lineOffset)) { - caretOffset++; - } - } - } - else - if (offsetInLine > 0 && - (bidi.isRightToLeft(offsetInLine) || - bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || - offsetInLine < lineLength)) { - // advance caret visually if in R2L segment or logically at line end - // but right end of line is not fully visible yet - caretOffset--; - doSelection(SWT.LEFT); - offsetInLine = caretOffset - lineOffset; - // end of R2L segment reached (visual right side)? - if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { - // go to end of R2L segment (visually left of next L2R segment)/ - // end of line - caretOffset++; - while (caretOffset < lineOffset + lineLength && - bidi.isRightToLeft(caretOffset - lineOffset)) { - caretOffset++; - } - } - } - else - if (offsetInLine == 0 && bidi.getTextPosition(0) != bidi.getTextWidth()) { - // at logical line start in R2L segment but there's more text (a L2R - // segment) go to end of R2L segment (visually left of next L2R - // segment)/end of line - caretOffset++; - while (caretOffset < lineOffset + lineLength && - bidi.isRightToLeft(caretOffset - lineOffset - 1)) { - caretOffset++; - } - } - offsetInLine = caretOffset - lineOffset; - // if new caret position is to the right of the client area - if (bidi.getTextPosition(offsetInLine) >= horizontalScrollOffset) { - // scroll to the caret position - showCaret(); - } - else { - // otherwise just update caret position without scrolling it into view - setBidiCaretLocation(null); - setBidiKeyboardLanguage(); - } - if (offsetInLine > 0 && offsetInLine < lineLength - 1) { - int clientAreaEnd = horizontalScrollOffset + getClientArea().width; - boolean directionChange = bidi.isRightToLeft(offsetInLine - 1) == false && bidi.isRightToLeft(offsetInLine); - int textWidth = bidi.getTextWidth() + leftMargin; - // between L2R and R2L segment and second character of R2L segment is - // left of right border and logical line end is left of right border - // but visual line end is not left of right border - if (directionChange && - bidi.isRightToLeft(offsetInLine + 1) && - bidi.getTextPosition(offsetInLine + 1) + leftMargin < clientAreaEnd && - bidi.getTextPosition(lineLength) + leftMargin < clientAreaEnd && textWidth > clientAreaEnd) { - // make visual line end visible - scrollHorizontalBar(textWidth - clientAreaEnd); - } - } - } - gc.dispose(); - } - else - if (offsetInLine < lineLength) { - caretOffset++; - showCaret(); - } + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = caretOffset - lineOffset; + String lineText = content.getLine(line); + int lineLength = lineText.length(); + + if (isBidi()) { + GC gc = getGC(); + StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); + if (bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || + offsetInLine < lineLength) { + if (bidi.isRightToLeft(offsetInLine) == false && + offsetInLine < lineLength) { + // advance caret logically if in L2R segment (move visually right) + caretOffset++; + doSelection(SWT.RIGHT); + // end of L2R segment reached (visual right side)? + if (bidi.isRightToLeft(caretOffset - lineOffset)) { + // go to end of R2L segment (visually left of next R2L segment)/ + // end of line + caretOffset++; + while (caretOffset < lineOffset + lineLength && + bidi.isRightToLeft(caretOffset - lineOffset)) { + caretOffset++; + } + } + } + else + if (offsetInLine > 0 && + (bidi.isRightToLeft(offsetInLine) || + bidi.getTextWidth() + leftMargin > horizontalScrollOffset + getClientArea().width || + offsetInLine < lineLength)) { + // advance caret visually if in R2L segment or logically at line end + // but right end of line is not fully visible yet + caretOffset--; + doSelection(SWT.LEFT); + offsetInLine = caretOffset - lineOffset; + // end of R2L segment reached (visual right side)? + if (offsetInLine > 0 && bidi.isRightToLeft(offsetInLine) == false) { + // go to end of R2L segment (visually left of next L2R segment)/ + // end of line + caretOffset++; + while (caretOffset < lineOffset + lineLength && + bidi.isRightToLeft(caretOffset - lineOffset)) { + caretOffset++; + } + } + } + else + if (offsetInLine == 0 && bidi.getTextPosition(0) != bidi.getTextWidth()) { + // at logical line start in R2L segment but there's more text (a L2R + // segment) go to end of R2L segment (visually left of next L2R + // segment)/end of line + caretOffset++; + while (caretOffset < lineOffset + lineLength && + bidi.isRightToLeft(caretOffset - lineOffset - 1)) { + caretOffset++; + } + } + offsetInLine = caretOffset - lineOffset; + // if new caret position is to the right of the client area + if (bidi.getTextPosition(offsetInLine) >= horizontalScrollOffset) { + // scroll to the caret position + showCaret(); + } + else { + // otherwise just update caret position without scrolling it into view + setBidiCaretLocation(null); + setBidiKeyboardLanguage(); + } + if (offsetInLine > 0 && offsetInLine < lineLength - 1) { + int clientAreaEnd = horizontalScrollOffset + getClientArea().width; + boolean directionChange = bidi.isRightToLeft(offsetInLine - 1) == false && bidi.isRightToLeft(offsetInLine); + int textWidth = bidi.getTextWidth() + leftMargin; + // between L2R and R2L segment and second character of R2L segment is + // left of right border and logical line end is left of right border + // but visual line end is not left of right border + if (directionChange && + bidi.isRightToLeft(offsetInLine + 1) && + bidi.getTextPosition(offsetInLine + 1) + leftMargin < clientAreaEnd && + bidi.getTextPosition(lineLength) + leftMargin < clientAreaEnd && textWidth > clientAreaEnd) { + // make visual line end visible + scrollHorizontalBar(textWidth - clientAreaEnd); + } + } + } + gc.dispose(); + } + else + if (offsetInLine < lineLength) { + caretOffset++; + showCaret(); + } } /** - * 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. - * 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. *

* * @param key the character typed by the user */ void doContent(char key) { - Event event; - - if (textLimit > 0 && - content.getCharCount() - (selection.y - selection.x) >= textLimit) { - return; - } - event = new Event(); - event.start = selection.x; - event.end = selection.y; - // replace a CR line break with the widget line break - // CR does not make sense on Windows since most (all?) applications - // don't recognize CR as a line break. - if (key == SWT.CR || key == SWT.LF) { - if (isSingleLine() == false) { - event.text = getLineDelimiter(); - } - } - // no selection and overwrite mode is on and the typed key is not a - // tab character (tabs are always inserted without overwriting)? - else - if (selection.x == selection.y && overwrite == true && key != TAB) { - int lineIndex = content.getLineAtOffset(event.end); - int lineOffset = content.getOffsetAtLine(lineIndex); - String line = content.getLine(lineIndex); - // replace character at caret offset if the caret is not at the - // end of the line - if (event.end < lineOffset + line.length()) { - event.end++; - } - event.text = new String(new char[] {key}); - } - else { - event.text = new String(new char[] {key}); - } - if (event.text != null) { - sendKeyEvent(event); - } + Event event; + + if (textLimit > 0 && + content.getCharCount() - (selection.y - selection.x) >= textLimit) { + return; + } + event = new Event(); + event.start = selection.x; + event.end = selection.y; + // replace a CR line break with the widget line break + // CR does not make sense on Windows since most (all?) applications + // don't recognize CR as a line break. + if (key == SWT.CR || key == SWT.LF) { + if (isSingleLine() == false) { + event.text = getLineDelimiter(); + } + } + // no selection and overwrite mode is on and the typed key is not a + // tab character (tabs are always inserted without overwriting)? + else + if (selection.x == selection.y && overwrite == true && key != TAB) { + int lineIndex = content.getLineAtOffset(event.end); + int lineOffset = content.getOffsetAtLine(lineIndex); + String line = content.getLine(lineIndex); + // replace character at caret offset if the caret is not at the + // end of the line + if (event.end < lineOffset + line.length()) { + event.end++; + } + event.text = new String(new char[] {key}); + } + else { + event.text = new String(new char[] {key}); + } + if (event.text != null) { + sendKeyEvent(event); + } } /** * Moves the caret after the last character of the widget content. */ void doContentEnd() { - // place caret at end of first line if receiver is in single - // line mode. fixes 4820. - if (isSingleLine()) { - doLineEnd(); - } - else { - int length = content.getCharCount(); - if (caretOffset < length) { - caretOffset = length; - showCaret(); - } - } + // place caret at end of first line if receiver is in single + // line mode. fixes 4820. + if (isSingleLine()) { + doLineEnd(); + } + else { + int length = content.getCharCount(); + if (caretOffset < length) { + caretOffset = length; + showCaret(); + } + } } /** * Moves the caret in front of the first character of the widget content. */ void doContentStart() { - if (caretOffset > 0) { - caretOffset = 0; - showCaret(); - } + if (caretOffset > 0) { + caretOffset = 0; + showCaret(); + } } /** * Moves the caret to the start of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. *

* * @see #doSelectionCursorPrevious */ void doCursorPrevious() { - if (selection.y - selection.x > 0) { - int caretLine; - - caretOffset = selection.x; - caretLine = getCaretLine(); - showCaret(caretLine); - } - else { - doSelectionCursorPrevious(); - } + if (selection.y - selection.x > 0) { + int caretLine; + + caretOffset = selection.x; + caretLine = getCaretLine(); + showCaret(caretLine); + } + else { + doSelectionCursorPrevious(); + } } /** * Moves the caret to the end of the selection if a selection exists. - * Otherwise, if no selection exists move the cursor according to the + * Otherwise, if no selection exists move the cursor according to the * cursor selection rules. *

* * @see #doSelectionCursorNext */ void doCursorNext() { - if (selection.y - selection.x > 0) { - int caretLine; + if (selection.y - selection.x > 0) { + int caretLine; - caretOffset = selection.y; - caretLine = getCaretLine(); - showCaret(caretLine); - } - else { - doSelectionCursorNext(); - } + caretOffset = selection.y; + caretLine = getCaretLine(); + showCaret(caretLine); + } + else { + doSelectionCursorNext(); + } } /** * Deletes the next character. Delete the selected text if any. */ void doDelete() { - Event event = new Event(); - - event.text = ""; - if (selection.x != selection.y) { - event.start = selection.x; - event.end = selection.y; - sendKeyEvent(event); - } - else - if (caretOffset < content.getCharCount()) { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - int lineLength = content.getLine(line).length(); - - if (caretOffset == lineOffset + lineLength) { - event.start = caretOffset; - event.end = content.getOffsetAtLine(line + 1); - } - else { - event.start = caretOffset; - event.end = caretOffset + 1; - } - sendKeyEvent(event); - } + Event event = new Event(); + + event.text = ""; + if (selection.x != selection.y) { + event.start = selection.x; + event.end = selection.y; + sendKeyEvent(event); + } + else + if (caretOffset < content.getCharCount()) { + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + int lineLength = content.getLine(line).length(); + + if (caretOffset == lineOffset + lineLength) { + event.start = caretOffset; + event.end = content.getOffsetAtLine(line + 1); + } + else { + event.start = caretOffset; + event.end = caretOffset + 1; + } + sendKeyEvent(event); + } } /** - * 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. - * + * * @return index of the new line relative to the first line in the document */ int doLineDown() { - if (isSingleLine()) { - return 0; - } - // allow line down action only if receiver is not in single line mode. - // fixes 4820. - int caretLine = getCaretLine(); - if (caretLine < content.getLineCount() - 1) { - caretLine++; - if (isBidi()) { - caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); - } - else { - caretOffset = getOffsetAtMouseLocation(columnX, caretLine); - } - } - return caretLine; + if (isSingleLine()) { + return 0; + } + // allow line down action only if receiver is not in single line mode. + // fixes 4820. + int caretLine = getCaretLine(); + if (caretLine < content.getLineCount() - 1) { + caretLine++; + if (isBidi()) { + caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); + } + else { + caretOffset = getOffsetAtMouseLocation(columnX, caretLine); + } + } + return caretLine; } /** * Moves the caret to the end of the line. */ void doLineEnd() { - int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); - int lineLength = content.getLine(caretLine).length(); - int lineEndOffset = lineOffset + lineLength; - - if (caretOffset < lineEndOffset) { - caretOffset = lineEndOffset; - showCaret(); - } + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int lineLength = content.getLine(caretLine).length(); + int lineEndOffset = lineOffset + lineLength; + + if (caretOffset < lineEndOffset) { + caretOffset = lineEndOffset; + showCaret(); + } } /** * Moves the caret to the beginning of the line. */ void doLineStart() { - int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); - - if (caretOffset > lineOffset) { - caretOffset = lineOffset; - showCaret(caretLine); - } + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + + if (caretOffset > lineOffset) { + caretOffset = lineOffset; + showCaret(caretLine); + } } /** - * Moves the caret one line up and to the same character offset relative - * to the beginning of the line. Move the caret to the end of the new line + * Moves the caret one line up and to the same character offset relative + * to the beginning of the line. Move the caret to the end of the new line * if the new line is shorter than the character offset. - * + * * @return index of the new line relative to the first line in the document */ int doLineUp() { - int caretLine = getCaretLine(); + int caretLine = getCaretLine(); - if (caretLine > 0) { - caretLine--; - if (isBidi()) { - caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); - } - else { - caretOffset = getOffsetAtMouseLocation(columnX, caretLine); - } - } - return caretLine; + if (caretLine > 0) { + caretLine--; + if (isBidi()) { + caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); + } + else { + caretOffset = getOffsetAtMouseLocation(columnX, caretLine); + } + } + return caretLine; } /** * Moves the caret to the specified location. @@ -2879,370 +2889,370 @@ * @param x x location of the new caret position * @param y y location of the new caret position * @param select the location change is a selection operation. - * include the line delimiter in the selection + * include the line delimiter in the selection */ void doMouseLocationChange(int x, int y, boolean select) { - int line = (y + verticalScrollOffset) / lineHeight; - int lineCount = content.getLineCount(); - int newCaretOffset; - int newCaretLine; - - if (line > lineCount - 1) { - line = lineCount - 1; - } - // allow caret to be placed below first line only if receiver is - // not in single line mode. fixes 4820. - if (line < 0 || (isSingleLine() && line > 0)) { - return; - } - if (isBidi()) { - newCaretOffset = getBidiOffsetAtMouseLocation(x, line); - } - else { - newCaretOffset = getOffsetAtMouseLocation(x, line); - } - if (mouseDoubleClick) { - // double click word select the previous/next word. fixes bug 15610 - newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); - } - newCaretLine = content.getLineAtOffset(newCaretOffset); - // Is the mouse within the left client area border or on - // a different line? If not the autoscroll selection - // could be incorrectly reset. Fixes 1GKM3XS - if (y >= 0 && y < getClientArea().height && - (x >= 0 || newCaretLine != content.getLineAtOffset(caretOffset))) { - if (newCaretOffset != caretOffset) { - caretOffset = newCaretOffset; - if (select) { - doMouseSelection(); - } - showCaret(); - } - } - if (select == false) { - clearSelection(true); - } + int line = (y + verticalScrollOffset) / lineHeight; + int lineCount = content.getLineCount(); + int newCaretOffset; + int newCaretLine; + + if (line > lineCount - 1) { + line = lineCount - 1; + } + // allow caret to be placed below first line only if receiver is + // not in single line mode. fixes 4820. + if (line < 0 || (isSingleLine() && line > 0)) { + return; + } + if (isBidi()) { + newCaretOffset = getBidiOffsetAtMouseLocation(x, line); + } + else { + newCaretOffset = getOffsetAtMouseLocation(x, line); + } + if (mouseDoubleClick) { + // double click word select the previous/next word. fixes bug 15610 + newCaretOffset = doMouseWordSelect(x, newCaretOffset, line); + } + newCaretLine = content.getLineAtOffset(newCaretOffset); + // Is the mouse within the left client area border or on + // a different line? If not the autoscroll selection + // could be incorrectly reset. Fixes 1GKM3XS + if (y >= 0 && y < getClientArea().height && + (x >= 0 || newCaretLine != content.getLineAtOffset(caretOffset))) { + if (newCaretOffset != caretOffset) { + caretOffset = newCaretOffset; + if (select) { + doMouseSelection(); + } + showCaret(); + } + } + if (select == false) { + clearSelection(true); + } } /** * Updates the selection based on the caret position */ void doMouseSelection() { - if (caretOffset <= selection.x || - (caretOffset > selection.x && - caretOffset < selection.y && selectionAnchor == selection.x)) { - doSelection(SWT.LEFT); - } - else { - doSelection(SWT.RIGHT); - } + if (caretOffset <= selection.x || + (caretOffset > selection.x && + caretOffset < selection.y && selectionAnchor == selection.x)) { + doSelection(SWT.LEFT); + } + else { + doSelection(SWT.RIGHT); + } } /** - * Returns the offset of the word at the specified offset. - * If the current selection extends from high index to low index - * (i.e., right to left, or caret is at left border of selecton on + * Returns the offset of the word at the specified offset. + * If the current selection extends from high index to low index + * (i.e., right to left, or caret is at left border of selecton on * non-bidi platforms) the start offset of the word preceeding the - * selection is returned. If the current selection extends from - * low index to high index the end offset of the word following + * selection is returned. If the current selection extends from + * low index to high index the end offset of the word following * the selection is returned. - * + * * @param x mouse x location * @param newCaretOffset caret offset of the mouse cursor location * @param line line index of the mouse cursor location */ int doMouseWordSelect(int x, int newCaretOffset, int line) { - int wordOffset; + int wordOffset; - // flip selection anchor based on word selection direction from - // base double click. Always do this here (and don't rely on doAutoScroll) - // because auto scroll only does not cover all possible mouse selections - // (e.g., mouse x < 0 && mouse y > caret line y) - if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) { - selectionAnchor = doubleClickSelection.y; - } - else - if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) { - selectionAnchor = doubleClickSelection.x; - } - if (x >= 0 && x < getClientArea().width) { - // find the previous/next word - if (caretOffset == selection.x) { - wordOffset = getWordStart(newCaretOffset); - } - else { - wordOffset = getWordEndNoSpaces(newCaretOffset); - } - // mouse word select only on same line mouse cursor is on - if (content.getLineAtOffset(wordOffset) == line) { - newCaretOffset = wordOffset; - } - } - return newCaretOffset; + // flip selection anchor based on word selection direction from + // base double click. Always do this here (and don't rely on doAutoScroll) + // because auto scroll only does not cover all possible mouse selections + // (e.g., mouse x < 0 && mouse y > caret line y) + if (newCaretOffset < selectionAnchor && selectionAnchor == selection.x) { + selectionAnchor = doubleClickSelection.y; + } + else + if (newCaretOffset > selectionAnchor && selectionAnchor == selection.y) { + selectionAnchor = doubleClickSelection.x; + } + if (x >= 0 && x < getClientArea().width) { + // find the previous/next word + if (caretOffset == selection.x) { + wordOffset = getWordStart(newCaretOffset); + } + else { + wordOffset = getWordEndNoSpaces(newCaretOffset); + } + // mouse word select only on same line mouse cursor is on + if (content.getLineAtOffset(wordOffset) == line) { + newCaretOffset = wordOffset; + } + } + return newCaretOffset; } /** * Scrolls one page down so that the last line (truncated or whole) * of the current page becomes the fully visible top line. - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the end - * of the text where a full page scroll is not possible. In this case + * The caret is 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. *

* * @param select whether or not to select the page */ void doPageDown(boolean select) { - int lineCount = content.getLineCount(); - int oldColumnX = columnX; - int caretLine; - - // do nothing if in single line mode. fixes 5673 - if (isSingleLine()) { - return; - } - caretLine = getCaretLine(); - if (caretLine < lineCount - 1) { - int verticalMaximum = lineCount * getVerticalIncrement(); - int pageSize = getClientArea().height; - int scrollLines = Math.min(lineCount - caretLine - 1, getLineCountWhole()); - int scrollOffset; - - // ensure that scrollLines never gets negative and at leat one - // line is scrolled. fixes bug 5602. - scrollLines = Math.max(1, scrollLines); - caretLine += scrollLines; - if (isBidi()) { - caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); - } - else { - caretOffset = getOffsetAtMouseLocation(columnX, caretLine); - } - if (select) { - doSelection(SWT.RIGHT); - } - // scroll one page down or to the bottom - scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); - if (scrollOffset + pageSize > verticalMaximum) { - scrollOffset = verticalMaximum - pageSize; - } - if (scrollOffset > verticalScrollOffset) { - setVerticalScrollOffset(scrollOffset, true); - } - } - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - // save the original horizontal caret position - columnX = oldColumnX; + int lineCount = content.getLineCount(); + int oldColumnX = columnX; + int caretLine; + + // do nothing if in single line mode. fixes 5673 + if (isSingleLine()) { + return; + } + caretLine = getCaretLine(); + if (caretLine < lineCount - 1) { + int verticalMaximum = lineCount * getVerticalIncrement(); + int pageSize = getClientArea().height; + int scrollLines = Math.min(lineCount - caretLine - 1, getLineCountWhole()); + int scrollOffset; + + // ensure that scrollLines never gets negative and at leat one + // line is scrolled. fixes bug 5602. + scrollLines = Math.max(1, scrollLines); + caretLine += scrollLines; + if (isBidi()) { + caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); + } + else { + caretOffset = getOffsetAtMouseLocation(columnX, caretLine); + } + if (select) { + doSelection(SWT.RIGHT); + } + // scroll one page down or to the bottom + scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement(); + if (scrollOffset + pageSize > verticalMaximum) { + scrollOffset = verticalMaximum - pageSize; + } + if (scrollOffset > verticalScrollOffset) { + setVerticalScrollOffset(scrollOffset, true); + } + } + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + // save the original horizontal caret position + columnX = oldColumnX; } /** * Moves the cursor to the end of the last fully visible line. */ void doPageEnd() { - // go to end of line if in single line mode. fixes 5673 - if (isSingleLine()) { - doLineEnd(); - } - else { - int line = getBottomIndex(); - int bottomCaretOffset = content.getOffsetAtLine(line) + content.getLine(line).length(); - - if (caretOffset < bottomCaretOffset) { - caretOffset = bottomCaretOffset; - showCaret(); - } - } + // go to end of line if in single line mode. fixes 5673 + if (isSingleLine()) { + doLineEnd(); + } + else { + int line = getBottomIndex(); + int bottomCaretOffset = content.getOffsetAtLine(line) + content.getLine(line).length(); + + if (caretOffset < bottomCaretOffset) { + caretOffset = bottomCaretOffset; + showCaret(); + } + } } /** * Moves the cursor to the beginning of the first fully visible line. */ void doPageStart() { - int topCaretOffset = content.getOffsetAtLine(topIndex); - - if (caretOffset > topCaretOffset) { - caretOffset = topCaretOffset; - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(topIndex); - } + int topCaretOffset = content.getOffsetAtLine(topIndex); + + if (caretOffset > topCaretOffset) { + caretOffset = topCaretOffset; + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(topIndex); + } } /** * Scrolls one page up so that the first line (truncated or whole) * of the current page becomes the fully visible last line. - * The caret is scrolled the same number of lines so that its location - * relative to the top line remains the same. The exception is the beginning + * The caret is scrolled the same number of lines so that its location + * relative to the top line remains the same. The exception is the beginning * of the text where a full page scroll is not possible. In this case the * caret is moved in front of the first character. */ void doPageUp() { - int oldColumnX = columnX; - int caretLine = getCaretLine(); - - if (caretLine > 0) { - int scrollLines = Math.max(1, Math.min(caretLine, getLineCountWhole())); - int scrollOffset; - - caretLine -= scrollLines; - if (isBidi()) { - caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); - } - else { - caretOffset = getOffsetAtMouseLocation(columnX, caretLine); - } - // scroll one page up or to the top - scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); - if (scrollOffset < verticalScrollOffset) { - setVerticalScrollOffset(scrollOffset, true); - } - } - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - // save the original horizontal caret position - columnX = oldColumnX; + int oldColumnX = columnX; + int caretLine = getCaretLine(); + + if (caretLine > 0) { + int scrollLines = Math.max(1, Math.min(caretLine, getLineCountWhole())); + int scrollOffset; + + caretLine -= scrollLines; + if (isBidi()) { + caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine); + } + else { + caretOffset = getOffsetAtMouseLocation(columnX, caretLine); + } + // scroll one page up or to the top + scrollOffset = Math.max(0, verticalScrollOffset - scrollLines * getVerticalIncrement()); + if (scrollOffset < verticalScrollOffset) { + setVerticalScrollOffset(scrollOffset, true); + } + } + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + // save the original horizontal caret position + columnX = oldColumnX; } /** * Updates the selection to extend to the current caret position. */ void doSelection(int direction) { - int redrawStart = -1; - int redrawEnd = -1; - - if (selectionAnchor == -1) { - selectionAnchor = selection.x; - } - if (direction == SWT.LEFT) { - if (caretOffset < selection.x) { - // grow selection - redrawEnd = selection.x; - redrawStart = selection.x = caretOffset; - // check if selection has reversed direction - if (selection.y != selectionAnchor) { - redrawEnd = selection.y; - selection.y = selectionAnchor; - } - } - else // test whether selection actually changed. Fixes 1G71EO1 - if (selectionAnchor == selection.x && caretOffset < selection.y) { - // caret moved towards selection anchor (left side of selection). - // shrink selection - redrawEnd = selection.y; - redrawStart = selection.y = caretOffset; - } - } - else { - if (caretOffset > selection.y) { - // grow selection - redrawStart = selection.y; - redrawEnd = selection.y = caretOffset; - // check if selection has reversed direction - if (selection.x != selectionAnchor) { - redrawStart = selection.x; - selection.x = selectionAnchor; - } - } - else // test whether selection actually changed. Fixes 1G71EO1 - if (selectionAnchor == selection.y && caretOffset > selection.x) { - // caret moved towards selection anchor (right side of selection). - // shrink selection - redrawStart = selection.x; - redrawEnd = selection.x = caretOffset; - } - } - if (redrawStart != -1 && redrawEnd != -1) { - internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); - sendSelectionEvent(); - } + int redrawStart = -1; + int redrawEnd = -1; + + if (selectionAnchor == -1) { + selectionAnchor = selection.x; + } + if (direction == SWT.LEFT) { + if (caretOffset < selection.x) { + // grow selection + redrawEnd = selection.x; + redrawStart = selection.x = caretOffset; + // check if selection has reversed direction + if (selection.y != selectionAnchor) { + redrawEnd = selection.y; + selection.y = selectionAnchor; + } + } + else // test whether selection actually changed. Fixes 1G71EO1 + if (selectionAnchor == selection.x && caretOffset < selection.y) { + // caret moved towards selection anchor (left side of selection). + // shrink selection + redrawEnd = selection.y; + redrawStart = selection.y = caretOffset; + } + } + else { + if (caretOffset > selection.y) { + // grow selection + redrawStart = selection.y; + redrawEnd = selection.y = caretOffset; + // check if selection has reversed direction + if (selection.x != selectionAnchor) { + redrawStart = selection.x; + selection.x = selectionAnchor; + } + } + else // test whether selection actually changed. Fixes 1G71EO1 + if (selectionAnchor == selection.y && caretOffset > selection.x) { + // caret moved towards selection anchor (right side of selection). + // shrink selection + redrawStart = selection.x; + redrawEnd = selection.x = caretOffset; + } + } + if (redrawStart != -1 && redrawEnd != -1) { + internalRedrawRange(redrawStart, redrawEnd - redrawStart, true); + sendSelectionEvent(); + } } /** - * Moves the caret to the next character or to the beginning of the + * Moves the caret to the next character or to the beginning of the * next line if the cursor is at the end of a line. */ void doSelectionCursorNext() { - int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - - if (offsetInLine < content.getLine(caretLine).length()) { - // Remember the last direction. Always update lastCaretDirection, - // even though it's not used in non-bidi mode in order to avoid - // extra methods. - lastCaretDirection = ST.COLUMN_NEXT; - caretOffset++; - showCaret(); - } - else - if (caretLine < content.getLineCount() - 1 && isSingleLine() == false) { - // only go to next line if not in single line mode. fixes 5673 - caretLine++; - caretOffset = content.getOffsetAtLine(caretLine); - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - } + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + + if (offsetInLine < content.getLine(caretLine).length()) { + // Remember the last direction. Always update lastCaretDirection, + // even though it's not used in non-bidi mode in order to avoid + // extra methods. + lastCaretDirection = ST.COLUMN_NEXT; + caretOffset++; + showCaret(); + } + else + if (caretLine < content.getLineCount() - 1 && isSingleLine() == false) { + // only go to next line if not in single line mode. fixes 5673 + caretLine++; + caretOffset = content.getOffsetAtLine(caretLine); + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + } } /** - * Moves the caret to the previous character or to the end of the previous + * Moves the caret to the previous character or to the end of the previous * line if the cursor is at the beginning of a line. */ void doSelectionCursorPrevious() { - int caretLine = getCaretLine(); - int lineOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineOffset; - - if (offsetInLine > 0) { - // Remember the last direction. Always update lastCaretDirection, - // even though it's not used in non-bidi mode in order to avoid - // extra methods. - lastCaretDirection = ST.COLUMN_PREVIOUS; - caretOffset--; - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - } - else - if (caretLine > 0) { - caretLine--; - lineOffset = content.getOffsetAtLine(caretLine); - caretOffset = lineOffset + content.getLine(caretLine).length(); - showCaret(); - } + int caretLine = getCaretLine(); + int lineOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineOffset; + + if (offsetInLine > 0) { + // Remember the last direction. Always update lastCaretDirection, + // even though it's not used in non-bidi mode in order to avoid + // extra methods. + lastCaretDirection = ST.COLUMN_PREVIOUS; + caretOffset--; + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + } + else + if (caretLine > 0) { + caretLine--; + lineOffset = content.getOffsetAtLine(caretLine); + caretOffset = lineOffset + content.getLine(caretLine).length(); + showCaret(); + } } /** - * Moves the caret one line down and to the same character offset relative - * to the beginning of the line. Moves the caret to the end of the new line + * 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 * direction. */ void doSelectionLineDown() { - int oldColumnX = columnX; - int caretLine; - - if (isSingleLine()) { - return; - } - caretLine = getCaretLine(); - if (caretLine == content.getLineCount() - 1) { - caretOffset = content.getCharCount(); - } - else { - caretLine = doLineDown(); - } - setMouseWordSelectionAnchor(); - // select first and then scroll to reduce flash when key - // repeat scrolls lots of lines - doSelection(SWT.RIGHT); - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - // save the original horizontal caret position - columnX = oldColumnX; + int oldColumnX = columnX; + int caretLine; + + if (isSingleLine()) { + return; + } + caretLine = getCaretLine(); + if (caretLine == content.getLineCount() - 1) { + caretOffset = content.getCharCount(); + } + else { + caretLine = doLineDown(); + } + setMouseWordSelectionAnchor(); + // select first and then scroll to reduce flash when key + // repeat scrolls lots of lines + doSelection(SWT.RIGHT); + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + // save the original horizontal caret position + columnX = oldColumnX; } /** - * Moves the caret one line up and to the same character offset relative - * to the beginning of the line. Moves the caret to the end of the new line + * 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. @@ -3251,54 +3261,54 @@ * direction. */ void doSelectionLineUp() { - int oldColumnX = columnX; - int caretLine = getCaretLine(); - - if (caretLine == 0) { - caretOffset = 0; - } - else { - caretLine = doLineUp(); - } - setMouseWordSelectionAnchor(); - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - doSelection(SWT.LEFT); - // save the original horizontal caret position - columnX = oldColumnX; + int oldColumnX = columnX; + int caretLine = getCaretLine(); + + if (caretLine == 0) { + caretOffset = 0; + } + else { + caretLine = doLineUp(); + } + setMouseWordSelectionAnchor(); + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + doSelection(SWT.LEFT); + // save the original horizontal caret position + columnX = oldColumnX; } /** * Moves the caret to the end of the next word . */ void doSelectionWordNext() { - int newCaretOffset = getWordEnd(caretOffset); - - // don't change caret position if in single line mode and the cursor - // would be on a different line. fixes 5673 - if (isSingleLine() == false || - content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) { - lastCaretDirection = ST.COLUMN_NEXT; - caretOffset = newCaretOffset; - showCaret(); - } + int newCaretOffset = getWordEnd(caretOffset); + + // don't change caret position if in single line mode and the cursor + // would be on a different line. fixes 5673 + if (isSingleLine() == false || + content.getLineAtOffset(caretOffset) == content.getLineAtOffset(newCaretOffset)) { + lastCaretDirection = ST.COLUMN_NEXT; + caretOffset = newCaretOffset; + showCaret(); + } } /** * Moves the caret to the start of the previous word. */ void doSelectionWordPrevious() { - int caretLine; - - lastCaretDirection = ST.COLUMN_PREVIOUS; - caretOffset = getWordStart(caretOffset); - caretLine = content.getLineAtOffset(caretOffset); - // word previous always comes from bottom line. when - // wrapping lines, stay on bottom line when on line boundary - if (wordWrap && caretLine < content.getLineCount() - 1 && - caretOffset == content.getOffsetAtLine(caretLine + 1)) { - caretLine++; - } - showCaret(caretLine); + int caretLine; + + lastCaretDirection = ST.COLUMN_PREVIOUS; + caretOffset = getWordStart(caretOffset); + caretLine = content.getLineAtOffset(caretOffset); + // word previous always comes from bottom line. when + // wrapping lines, stay on bottom line when on line boundary + if (wordWrap && caretLine < content.getLineCount() - 1 && + caretOffset == content.getOffsetAtLine(caretLine + 1)) { + caretLine++; + } + showCaret(caretLine); } /** * Moves the caret to the end of the next word. @@ -3306,16 +3316,16 @@ * and remove the selection. */ void doWordNext() { - if (selection.y - selection.x > 0) { - int caretLine; - - caretOffset = selection.y; - caretLine = getCaretLine(); - showCaret(caretLine); - } - else { - doSelectionWordNext(); - } + if (selection.y - selection.x > 0) { + int caretLine; + + caretOffset = selection.y; + caretLine = getCaretLine(); + showCaret(caretLine); + } + else { + doSelectionWordNext(); + } } /** * Moves the caret to the start of the previous word. @@ -3323,20 +3333,20 @@ * and remove the selection. */ void doWordPrevious() { - if (selection.y - selection.x > 0) { - int caretLine; - - caretOffset = selection.x; - caretLine = getCaretLine(); - showCaret(caretLine); - } - else { - doSelectionWordPrevious(); - } + if (selection.y - selection.x > 0) { + int caretLine; + + caretOffset = selection.x; + caretLine = getCaretLine(); + showCaret(caretLine); + } + else { + doSelectionWordPrevious(); + } } /** * Draws the specified rectangle. - * Draw directly without invalidating the affected area when clearBackground is + * Draw directly without invalidating the affected area when clearBackground is * false. *

* @@ -3344,53 +3354,53 @@ * @param y the y position * @param width the width * @param height the height - * @param clearBackground true=clear the background by invalidating the requested - * redraw area, false=draw the foreground directly without invalidating the - * redraw area. + * @param clearBackground true=clear the background by invalidating the requested + * redraw area, false=draw the foreground directly without invalidating the + * redraw area. */ void draw(int x, int y, int width, int height, boolean clearBackground) { - if (clearBackground) { - redraw(x + leftMargin, y + topMargin, width, height, true); - } - else { - int startLine = (y + verticalScrollOffset) / lineHeight; - int endY = y + height; - int paintYFromTopLine = (startLine - topIndex) * lineHeight; - int topLineOffset = (topIndex * lineHeight - verticalScrollOffset); - int paintY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling - int lineCount = content.getLineCount(); - Color background = getBackground(); - Color foreground = getForeground(); - GC gc = getGC(); - - if (isSingleLine()) { - lineCount = 1; - if (startLine > 1) { - startLine = 1; - } - } - for (int i = startLine; paintY < endY && i < lineCount; i++, paintY += lineHeight) { - String line = content.getLine(i); - renderer.drawLine(line, i, paintY, gc, background, foreground, clearBackground); - } - gc.dispose(); - } + if (clearBackground) { + redraw(x + leftMargin, y + topMargin, width, height, true); + } + else { + int startLine = (y + verticalScrollOffset) / lineHeight; + int endY = y + height; + int paintYFromTopLine = (startLine - topIndex) * lineHeight; + int topLineOffset = (topIndex * lineHeight - verticalScrollOffset); + int paintY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling + int lineCount = content.getLineCount(); + Color background = getBackground(); + Color foreground = getForeground(); + GC gc = getGC(); + + if (isSingleLine()) { + lineCount = 1; + if (startLine > 1) { + startLine = 1; + } + } + for (int i = startLine; paintY < endY && i < lineCount; i++, paintY += lineHeight) { + String line = content.getLine(i); + renderer.drawLine(line, i, paintY, gc, background, foreground, clearBackground); + } + gc.dispose(); + } } -/** +/** * Ends the autoscroll process. */ void endAutoScroll() { - autoScrollDirection = SWT.NULL; + autoScrollDirection = SWT.NULL; } /** * @see org.eclipse.swt.widgets.Control#getBackground */ public Color getBackground() { - checkWidget(); - if (background == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); - } - return background; + checkWidget(); + if (background == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND); + } + return background; } /** * Gets the BIDI coloring mode. When true the BIDI text display @@ -3407,70 +3417,70 @@ *

*/ public boolean getBidiColoring() { - checkWidget(); - return bidiColoring; + checkWidget(); + return bidiColoring; } /** * Returns the offset at the specified x location in the specified line. - * Also sets the caret direction so that the caret is placed correctly + * Also sets the caret direction so that the caret is placed correctly * depending on whether the mouse location is in a R2L or L2R segment. *

* - * @param x x location of the mouse location - * @param line line the mouse location is in + * @param x x location of the mouse location + * @param line line the mouse location is in * @return the offset at the specified x location in the specified line, - * relative to the beginning of the document + * relative to the beginning of the document */ int getBidiOffsetAtMouseLocation(int x, int line) { - String lineText = content.getLine(line); - int lineOffset = content.getOffsetAtLine(line); - GC gc = getGC(); - StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); - int[] values; - int offsetInLine; - x += horizontalScrollOffset; - values = bidi.getCaretOffsetAndDirectionAtX(x - leftMargin); - offsetInLine = values[0]; - lastCaretDirection = values[1]; - gc.dispose(); - - return lineOffset + offsetInLine; + String lineText = content.getLine(line); + int lineOffset = content.getOffsetAtLine(line); + GC gc = getGC(); + StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); + int[] values; + int offsetInLine; + x += horizontalScrollOffset; + values = bidi.getCaretOffsetAndDirectionAtX(x - leftMargin); + offsetInLine = values[0]; + lastCaretDirection = values[1]; + gc.dispose(); + + return lineOffset + offsetInLine; } /** - * Returns the x position of the character at the specified offset + * Returns the x position of the character at the specified offset * relative to the first character in the line. *

* * @param text text to be measured. * @param endOffset offset of the character * @param bidi the bidi object to use for measuring text in bidi - * locales. - * @return x position of the character at the specified offset. - * 0 if the length is outside the specified text. + * locales. + * @return x position of the character at the specified offset. + * 0 if the length is outside the specified text. */ int getBidiTextPosition(String text, int endOffset, StyledTextBidi bidi) { - if (endOffset > text.length()) { - return 0; - } - // Use lastCaretDirection in order to get same results as during - // caret positioning (setBidiCaretLocation). Fixes 1GKU4C5. - return bidi.getTextPosition(endOffset, lastCaretDirection); + if (endOffset > text.length()) { + return 0; + } + // Use lastCaretDirection in order to get same results as during + // caret positioning (setBidiCaretLocation). Fixes 1GKU4C5. + return bidi.getTextPosition(endOffset, lastCaretDirection); } -/** +/** * Returns the index of the last fully visible line. *

* * @return index of the last fully visible line. */ int getBottomIndex() { - int lineCount = 1; - - if (lineHeight != 0) { - // calculate the number of lines that are fully visible - int partialTopLineHeight = topIndex * lineHeight - verticalScrollOffset; - lineCount = (getClientArea().height - partialTopLineHeight) / lineHeight; - } - return Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); + int lineCount = 1; + + if (lineHeight != 0) { + // calculate the number of lines that are fully visible + int partialTopLineHeight = topIndex * lineHeight - verticalScrollOffset; + lineCount = (getClientArea().height - partialTopLineHeight) / lineHeight; + } + return Math.min(content.getLineCount() - 1, topIndex + Math.max(0, lineCount - 1)); } /** * Returns the caret position relative to the start of the text. @@ -3483,53 +3493,53 @@ * */ public int getCaretOffset() { - checkWidget(); - - return caretOffset; + checkWidget(); + + return caretOffset; } /** * Returns the caret offset at the given x location in the line. * The caret offset is the offset of the character where the caret will be - * placed when a mouse click occurs. The caret offset will be the offset of - * the character after the clicked one if the mouse click occurs at the second + * placed when a mouse click occurs. The caret offset will be the offset of + * the character after the clicked one if the mouse click occurs at the second * half of a character. - * Doesn't properly handle ligatures and other context dependent characters - * unless the current locale is a bidi locale. + * Doesn't properly handle ligatures and other context dependent characters + * unless the current locale is a bidi locale. * Ligatures are handled properly as long as they don't occur at lineXOffset. *

* * @param line text of the line to calculate the offset in - * @param lineOffset offset of the first character in the line. - * 0 based from the beginning of the document. + * @param lineOffset offset of the first character in the line. + * 0 based from the beginning of the document. * @param lineXOffset x location in the line * @return caret offset at the x location relative to the start of the line. */ int getCaretOffsetAtX(String line, int lineOffset, int lineXOffset) { - int offset = 0; - GC gc = getGC(); - StyleRange[] styles = null; - StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); - - lineXOffset += horizontalScrollOffset; - if (event != null) { - styles = renderer.filterLineStyles(event.styles); - } - int low = -1; - int high = line.length(); - while (high - low > 1) { - offset = (high + low) / 2; - int x = renderer.getTextPosition(line, lineOffset, offset, styles, gc) + leftMargin; - int charWidth = renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc) + leftMargin - x; - if (lineXOffset <= x + charWidth / 2) { - high = offset; - } - else { - low = offset; - } - } - offset = high; - gc.dispose(); - return offset; + int offset = 0; + GC gc = getGC(); + StyleRange[] styles = null; + StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); + + lineXOffset += horizontalScrollOffset; + if (event != null) { + styles = renderer.filterLineStyles(event.styles); + } + int low = -1; + int high = line.length(); + while (high - low > 1) { + offset = (high + low) / 2; + int x = renderer.getTextPosition(line, lineOffset, offset, styles, gc) + leftMargin; + int charWidth = renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc) + leftMargin - x; + if (lineXOffset <= x + charWidth / 2) { + high = offset; + } + else { + low = offset; + } + } + offset = high; + gc.dispose(); + return offset; } /** * Returns the caret width. @@ -3538,16 +3548,16 @@ * @return the caret width, 0 if caret is null. */ int getCaretWidth() { - Caret caret = getCaret(); - if (caret == null) return 0; - return caret.getSize().x; + Caret caret = getCaret(); + if (caret == null) return 0; + return caret.getSize().x; } /** * Returns the content implementation that is used for text storage * or null if no user defined content implementation has been set. *

* - * @return content implementation that is used for text storage or null + * @return content implementation that is used for text storage or null * if no user defined content implementation has been set. * @exception SWTException

*/ public StyledTextContent getContent() { - checkWidget(); - - return logicalContent; + checkWidget(); + + return logicalContent; } -/** +/** * Returns whether the widget implements double click mouse behavior. *

* @@ -3571,8 +3581,8 @@ * */ public boolean getDoubleClickEnabled() { - checkWidget(); - return doubleClickEnabled; + checkWidget(); + return doubleClickEnabled; } /** * Returns whether the widget content can be edited. @@ -3585,20 +3595,20 @@ * */ public boolean getEditable() { - checkWidget(); - return editable; + checkWidget(); + return editable; } /** * @see org.eclipse.swt.widgets.Control#getForeground */ public Color getForeground() { - checkWidget(); - if (foreground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); - } - return foreground; + checkWidget(); + if (foreground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND); + } + return foreground; } -/** +/** * Return a GC to use for rendering and update the cached font style to * represent the current style. *

@@ -3606,23 +3616,23 @@ * @return GC. */ GC getGC() { - renderer.setCurrentFontStyle(SWT.NORMAL); - return new GC(this); + renderer.setCurrentFontStyle(SWT.NORMAL); + return new GC(this); } -/** +/** * Returns the horizontal scroll increment. *

* * @return horizontal scroll increment. */ int getHorizontalIncrement() { - GC gc = getGC(); - int increment = gc.getFontMetrics().getAverageCharWidth(); - - gc.dispose(); - return increment; + GC gc = getGC(); + int increment = gc.getFontMetrics().getAverageCharWidth(); + + gc.dispose(); + return increment; } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. *

* @@ -3633,11 +3643,11 @@ *

  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * */ -public int getHorizontalIndex() { - checkWidget(); - return horizontalScrollOffset / getHorizontalIncrement(); +public int getHorizontalIndex() { + checkWidget(); + return horizontalScrollOffset / getHorizontalIncrement(); } -/** +/** * Returns the horizontal scroll offset relative to the start of the line. *

    * @@ -3648,39 +3658,39 @@ *

  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * */ -public int getHorizontalPixel() { - checkWidget(); - return horizontalScrollOffset; +public int getHorizontalPixel() { + checkWidget(); + return horizontalScrollOffset; } -/** +/** * Returns the action assigned to the key. * Returns SWT.NULL if there is no action associated with the key. *

    * - * @param key a key code defined in SWT.java or a character. - * Optionally ORd with a state mask. Preferred state masks are one or more of - * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform + * @param key a key code defined in SWT.java or a character. + * Optionally ORd with a state mask. Preferred state masks are one or more of + * SWT.MOD1, SWT.MOD2, SWT.MOD3, since these masks account for modifier platform * differences. However, there may be cases where using the specific state masks * (i.e., SWT.CTRL, SWT.SHIFT, SWT.ALT, SWT.COMMAND) makes sense. - * @return one of the predefined actions defined in ST.java or SWT.NULL - * if there is no action associated with the key. + * @return one of the predefined actions defined in ST.java or SWT.NULL + * if there is no action associated with the key. * @exception SWTException

    */ public int getKeyBinding(int key) { - checkWidget(); - Integer action = (Integer) keyActionMap.get(new Integer(key)); - int intAction; - - if (action == null) { - intAction = SWT.NULL; - } - else { - intAction = action.intValue(); - } - return intAction; + checkWidget(); + Integer action = (Integer) keyActionMap.get(new Integer(key)); + int intAction; + + if (action == null) { + intAction = SWT.NULL; + } + else { + intAction = action.intValue(); + } + return intAction; } /** * Gets the number of characters. @@ -3693,12 +3703,12 @@ * */ public int getCharCount() { - checkWidget(); - return content.getCharCount(); + checkWidget(); + return content.getCharCount(); } /** * Returns the background color of the line at the given index. - * Returns null if a LineBackgroundListener has been set or if no background + * 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. @@ -3714,30 +3724,30 @@ * */ public Color getLineBackground(int index) { - checkWidget(); - Color lineBackground = null; - - if (index < 0 || index > logicalContent.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - if (userLineBackground == false) { - lineBackground = defaultLineStyler.getLineBackground(index); - } - return lineBackground; + checkWidget(); + Color lineBackground = null; + + if (index < 0 || index > logicalContent.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + if (userLineBackground == false) { + lineBackground = defaultLineStyler.getLineBackground(index); + } + return lineBackground; } /** - * Returns the line background data for the given line or null if + * 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. + * of the content. * @param line line to get line background data for * @return line background data for the given line. */ StyledTextEvent getLineBackgroundData(int lineOffset, String line) { - return sendLineEvent(LineGetBackground, lineOffset, line); + return sendLineEvent(LineGetBackground, lineOffset, line); } -/** +/** * Gets the number of text lines. *

    * @@ -3748,27 +3758,27 @@ * */ public int getLineCount() { - checkWidget(); - return getLineAtOffset(getCharCount()) + 1; + checkWidget(); + return getLineAtOffset(getCharCount()) + 1; } /** - * 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 - * client area. + * @return number of lines that can be completely displayed in the widget + * client area. */ int getLineCountWhole() { - int lineCount; - - if (lineHeight != 0) { - lineCount = getClientArea().height / lineHeight; - } - else { - lineCount = 1; - } - return lineCount; + int lineCount; + + if (lineHeight != 0) { + lineCount = getClientArea().height / lineHeight; + } + else { + lineCount = 1; + } + return lineCount; } /** * Returns the line at the specified offset in the text. @@ -3776,24 +3786,24 @@ * returns the line of the insert location. *

    * - * @param offset offset relative to the start of the content. - * 0 <= offset <= getCharCount() + * @param offset offset relative to the start of the content. + * 0 <= offset <= getCharCount() * @return line at the specified offset in the text * @exception SWTException

    * @exception IllegalArgumentException */ public int getLineAtOffset(int offset) { - checkWidget(); - - if (offset < 0 || offset > getCharCount()) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return logicalContent.getLineAtOffset(offset); + checkWidget(); + + if (offset < 0 || offset > getCharCount()) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return logicalContent.getLineAtOffset(offset); } /** * Returns the line delimiter used for entering new lines by key down @@ -3808,43 +3818,43 @@ * */ public String getLineDelimiter() { - checkWidget(); - return content.getLineDelimiter(); + checkWidget(); + return content.getLineDelimiter(); } /** - * 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. - * 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. *

    * * @param lineOffset offset of the line. This may be the offset of - * a visual line if the widget is in word wrap mode. - * @param line line text. This may be the text of a visualline if - * the widget is in word wrap mode. - * @return StyledTextEvent that can be used to request line data - * for the given line. + * a visual line if the widget is in word wrap mode. + * @param line line text. This may be the text of a visualline if + * the widget is in word wrap mode. + * @return StyledTextEvent that can be used to request line data + * for the given line. */ StyledTextEvent sendLineEvent(int eventType, int lineOffset, String line) { - StyledTextEvent event = null; - - if (isListening(eventType)) { - event = new StyledTextEvent(logicalContent); - if (wordWrap) { - // if word wrap is on, the line offset and text may be visual (wrapped) - int lineIndex = logicalContent.getLineAtOffset(lineOffset); - - event.detail = logicalContent.getOffsetAtLine(lineIndex); - event.text = logicalContent.getLine(lineIndex); - } - else { - event.detail = lineOffset; - event.text = line; - } - notifyListeners(eventType, event); - } - return event; + StyledTextEvent event = null; + + if (isListening(eventType)) { + event = new StyledTextEvent(logicalContent); + if (wordWrap) { + // if word wrap is on, the line offset and text may be visual (wrapped) + int lineIndex = logicalContent.getLineAtOffset(lineOffset); + + event.detail = logicalContent.getOffsetAtLine(lineIndex); + event.text = logicalContent.getLine(lineIndex); + } + else { + event.detail = lineOffset; + event.text = line; + } + notifyListeners(eventType, event); + } + return event; } /** * Returns the line height. @@ -3857,108 +3867,108 @@ * */ public int getLineHeight() { - checkWidget(); - return lineHeight; + checkWidget(); + return lineHeight; } /** * Returns a LineCache implementation. Depending on whether or not - * word wrap is on this may be a line wrapping or line width + * word wrap is on this may be a line wrapping or line width * calculating implementaiton. *

    - * + * * @param content StyledTextContent to create the LineCache on. * @return a LineCache implementation */ LineCache getLineCache(StyledTextContent content) { LineCache lineCache; - - if (wordWrap) { - lineCache = new WordWrapCache(this, (WrappedContent) content); - } - else { - lineCache = new ContentWidthCache(this, content.getLineCount()); - } - return lineCache; + + if (wordWrap) { + lineCache = new WordWrapCache(this, (WrappedContent) content); + } + else { + lineCache = new ContentWidthCache(this, content.getLineCount()); + } + return lineCache; } /** - * Returns the line style data for the given line or null if there is - * none. If there is a LineStyleListener but it does not set any styles, - * the StyledTextEvent.styles field will be initialized to an empty + * Returns the line style data for the given line or null if there is + * none. If there is a LineStyleListener but it does not set any styles, + * the StyledTextEvent.styles field will be initialized to an empty * array. *

    - * - * @param lineOffset offset of the line start relative to the start of - * the content. + * + * @param lineOffset offset of the line start relative to the start of + * the content. * @param line line to get line styles for - * @return line style data for the given line. Styles may start before - * line start and end after line end + * @return line style data for the given line. Styles may start before + * line start and end after line end */ StyledTextEvent getLineStyleData(int lineOffset, String line) { - return sendLineEvent(LineGetStyle, lineOffset, line); + return sendLineEvent(LineGetStyle, lineOffset, line); } /** - * Returns the x, y location of the upper left corner of the character - * bounding box at the specified offset in the text. The point is + * Returns the x, y location of the upper left corner of the character + * bounding box at the specified offset in the text. The point is * relative to the upper left corner of the widget client area. *

    * - * @param offset offset relative to the start of the content. - * 0 <= offset <= getCharCount() - * @return x, y location of the upper left corner of the character - * bounding box at the specified offset in the text. + * @param offset offset relative to the start of the content. + * 0 <= offset <= getCharCount() + * @return x, y location of the upper left corner of the character + * bounding box at the specified offset in the text. * @exception SWTException

    * @exception IllegalArgumentException */ public Point getLocationAtOffset(int offset) { - checkWidget(); - if (offset < 0 || offset > getCharCount()) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - int line = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(line); - String lineContent = content.getLine(line); - int x = getXAtOffset(lineContent, line, offset - lineOffset); - int y = line * lineHeight - verticalScrollOffset; - - return new Point(x, y); + checkWidget(); + if (offset < 0 || offset > getCharCount()) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + int line = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(line); + String lineContent = content.getLine(line); + int x = getXAtOffset(lineContent, line, offset - lineOffset); + int y = line * lineHeight - verticalScrollOffset; + + return new Point(x, y); } /** * Returns the character offset of the first character of the given line. *

    * - * @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 + * @param lineIndex index of the line, 0 based relative to the first + * line in the content. 0 <= lineIndex < getLineCount(), except + * lineIndex may always be 0 * @return offset offset of the first character of the line, relative to - * the beginning of the document. The first character of the document is - * at offset 0. - * When there are not any lines, getOffsetAtLine(0) is a valid call that - * answers 0. + * the beginning of the document. The first character of the document is + * at offset 0. + * When there are not any lines, getOffsetAtLine(0) is a valid call that + * answers 0. * @exception SWTException

    * @exception IllegalArgumentException * @since 2.0 */ public int getOffsetAtLine(int lineIndex) { - checkWidget(); - - if (lineIndex < 0 || - (lineIndex > 0 && lineIndex >= logicalContent.getLineCount())) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return logicalContent.getOffsetAtLine(lineIndex); + checkWidget(); + + if (lineIndex < 0 || + (lineIndex > 0 && lineIndex >= logicalContent.getLineCount())) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return logicalContent.getOffsetAtLine(lineIndex); } /** - * Returns the offset of the character at the given location relative + * Returns the offset of the character at the given location relative * to the first character in the document. * The return value reflects the character offset that the caret will * be placed at if a mouse click occurred at the specified location. @@ -3966,10 +3976,10 @@ * the returned offset will be behind the character. *

    * - * @param point the origin of character bounding box relative to - * the origin of the widget client area. - * @return offset of the character at the given location relative - * to the first character in the document. + * @param point the origin of character bounding box relative to + * the origin of the widget client area. + * @return offset of the character at the given location relative + * to the first character in the document. * @exception SWTException

    */ public int getOffsetAtLocation(Point point) { - checkWidget(); - int line; - int lineOffset; - int offsetInLine; - String lineText; - - if (point == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - // is y above first line or is x before first column? - if (point.y + verticalScrollOffset < 0 || point.x + horizontalScrollOffset < 0) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - line = (getTopPixel() + point.y) / lineHeight; - // does the referenced line exist? - if (line >= content.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - lineText = content.getLine(line); - lineOffset = content.getOffsetAtLine(line); - offsetInLine = getOffsetAtX(lineText, lineOffset, point.x); - // is the x position within the line? - if (offsetInLine == -1) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - return lineOffset + offsetInLine; + checkWidget(); + int line; + int lineOffset; + int offsetInLine; + String lineText; + + if (point == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + // is y above first line or is x before first column? + if (point.y + verticalScrollOffset < 0 || point.x + horizontalScrollOffset < 0) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + line = (getTopPixel() + point.y) / lineHeight; + // does the referenced line exist? + if (line >= content.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + lineText = content.getLine(line); + lineOffset = content.getOffsetAtLine(line); + offsetInLine = getOffsetAtX(lineText, lineOffset, point.x); + // is the x position within the line? + if (offsetInLine == -1) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + return lineOffset + offsetInLine; } /** * Returns the offset at the specified x location in the specified line. *

    * - * @param x x location of the mouse location - * @param line line the mouse location is in + * @param x x location of the mouse location + * @param line line the mouse location is in * @return the offset at the specified x location in the specified line, - * relative to the beginning of the document + * relative to the beginning of the document */ int getOffsetAtMouseLocation(int x, int line) { - String lineText = content.getLine(line); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = getCaretOffsetAtX(lineText, lineOffset, x); - return lineOffset + offsetInLine; + String lineText = content.getLine(line); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = getCaretOffsetAtX(lineText, lineOffset, x); + return lineOffset + offsetInLine; } /** * Returns the offset of the character at the given x location in the line. *

    * * @param line text of the line to calculate the offset in - * @param lineOffset offset of the first character in the line. - * 0 based from the beginning of the document. + * @param lineOffset offset of the first character in the line. + * 0 based from the beginning of the document. * @param lineXOffset x location in the line - * @return offset of the character at the x location relative to the start - * of the line. -1 if the x location is past the end if the line. + * @return offset of the character at the x location relative to the start + * of the line. -1 if the x location is past the end if the line. */ int getOffsetAtX(String line, int lineOffset, int lineXOffset) { - GC gc = getGC(); - int offset; - - lineXOffset += (horizontalScrollOffset - leftMargin); - if (isBidi()) { - StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); - offset = bidi.getOffsetAtX(lineXOffset); - } - else { - StyleRange[] styles = null; - StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); - - if (event != null) { - styles = renderer.filterLineStyles(event.styles); - } - int low = -1; - int high = line.length(); - while (high - low > 1) { - offset = (high + low) / 2; - // Restrict right/high search boundary only if x is within searched text segment. - // Fixes 1GL4ZVE. - if (lineXOffset < renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc)) { - high = offset; - } - else - if (high == line.length() && high - offset == 1) { - // requested x location is past end of line - high = -1; - } - else { - low = offset; - } - } - offset = high; - } - gc.dispose(); - return offset; + GC gc = getGC(); + int offset; + + lineXOffset += (horizontalScrollOffset - leftMargin); + if (isBidi()) { + StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc); + offset = bidi.getOffsetAtX(lineXOffset); + } + else { + StyleRange[] styles = null; + StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); + + if (event != null) { + styles = renderer.filterLineStyles(event.styles); + } + int low = -1; + int high = line.length(); + while (high - low > 1) { + offset = (high + low) / 2; + // Restrict right/high search boundary only if x is within searched text segment. + // Fixes 1GL4ZVE. + if (lineXOffset < renderer.getTextPosition(line, lineOffset, offset + 1, styles, gc)) { + high = offset; + } + else + if (high == line.length() && high - offset == 1) { + // requested x location is past end of line + high = -1; + } + else { + low = offset; + } + } + offset = high; + } + gc.dispose(); + return offset; } -/** +/** * Returns the index of the last partially visible line. * * @return index of the last partially visible line. */ int getPartialBottomIndex() { - int partialLineCount = Compatibility.ceil(getClientArea().height, lineHeight); - return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; + int partialLineCount = Compatibility.ceil(getClientArea().height, lineHeight); + return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1; } /** - * Returns the content in the specified range using the platform line + * Returns the content in the specified range using the platform line * delimiter to separate lines. *

    * * @param writer the TextWriter to write line text into - * @return the content in the specified range using the platform line - * delimiter to separate lines as written by the specified TextWriter. + * @return the content in the specified range using the platform line + * delimiter to separate lines as written by the specified TextWriter. */ String getPlatformDelimitedText(TextWriter writer) { - int end = writer.getStart() + writer.getCharCount(); - int startLine = logicalContent.getLineAtOffset(writer.getStart()); - int endLine = logicalContent.getLineAtOffset(end); - String endLineText = logicalContent.getLine(endLine); - int endLineOffset = logicalContent.getOffsetAtLine(endLine); - - for (int i = startLine; i <= endLine; i++) { - writer.writeLine(logicalContent.getLine(i), logicalContent.getOffsetAtLine(i)); - if (i < endLine) { - writer.writeLineDelimiter(PlatformLineDelimiter); - } - } - if (end > endLineOffset + endLineText.length()) { - writer.writeLineDelimiter(PlatformLineDelimiter); - } - writer.close(); - return writer.toString(); + int end = writer.getStart() + writer.getCharCount(); + int startLine = logicalContent.getLineAtOffset(writer.getStart()); + int endLine = logicalContent.getLineAtOffset(end); + String endLineText = logicalContent.getLine(endLine); + int endLineOffset = logicalContent.getOffsetAtLine(endLine); + + for (int i = startLine; i <= endLine; i++) { + writer.writeLine(logicalContent.getLine(i), logicalContent.getOffsetAtLine(i)); + if (i < endLine) { + writer.writeLineDelimiter(PlatformLineDelimiter); + } + } + if (end > endLineOffset + endLineText.length()) { + writer.writeLineDelimiter(PlatformLineDelimiter); + } + writer.close(); + return writer.toString(); } /** * Returns the selection. *

    * 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 *

    * - * @return start and end of the selection, x is the offset of the first - * selected character, y is the offset after the last selected character. - * The selection values returned are visual (i.e., x will always always be - * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right - * (LtoR), compare the caretOffset to the start and end of the selection + * @return start and end of the selection, x is the offset of the first + * selected character, y is the offset after the last selected character. + * The selection values returned are visual (i.e., x will always always be + * <= y). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection * (e.g., caretOffset == start of selection implies that the selection is RtoL). * @see #getSelectionRange * @exception SWTException

    */ public Point getSelection() { - checkWidget(); - return new Point(selection.x, selection.y); + checkWidget(); + return new Point(selection.x, selection.y); } /** * Returns the selection. *

    * - * @return start and length of the selection, x is the offset of the - * first selected character, relative to the first character of the - * widget content. y is the length of the selection. - * The selection values returned are visual (i.e., length will always always be - * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right - * (LtoR), compare the caretOffset to the start and end of the selection + * @return start and length of the selection, x is the offset of the + * first selected character, relative to the first character of the + * widget content. y is the length of the selection. + * The selection values returned are visual (i.e., length will always always be + * positive). To determine if a selection is right-to-left (RtoL) vs. left-to-right + * (LtoR), compare the caretOffset to the start and end of the selection * (e.g., caretOffset == start of selection implies that the selection is RtoL). * @exception SWTException

    */ public Point getSelectionRange() { - checkWidget(); - return new Point(selection.x, selection.y - selection.x); + checkWidget(); + return new Point(selection.x, selection.y - selection.x); } /** * Returns the receiver's selection background color. @@ -4165,11 +4175,11 @@ * @since 2.1 */ public Color getSelectionBackground() { - checkWidget(); - if (selectionBackground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); - } - return selectionBackground; + checkWidget(); + if (selectionBackground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION); + } + return selectionBackground; } /** * Gets the number of selected characters. @@ -4182,8 +4192,8 @@ * */ public int getSelectionCount() { - checkWidget(); - return getSelectionRange().y; + checkWidget(); + return getSelectionRange().y; } /** * Returns the receiver's selection foreground color. @@ -4197,11 +4207,11 @@ * @since 2.1 */ public Color getSelectionForeground() { - checkWidget(); - if (selectionForeground == null) { - return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); - } - return selectionForeground; + checkWidget(); + if (selectionForeground == null) { + return getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT); + } + return selectionForeground; } /** * Returns the selected text. @@ -4214,129 +4224,129 @@ * */ public String getSelectionText() { - checkWidget(); - return content.getTextRange(selection.x, selection.y - selection.x); + checkWidget(); + return content.getTextRange(selection.x, selection.y - selection.x); } /** - * 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. - * 0 based from the beginning of the document. + * @param lineOffset offset of the first character in the line. + * 0 based from the beginning of the document. * @param line text of the line to specify bidi segments for * @return text segments that should be treated as if they had a - * different direction than the surrounding text. Only the start - * index of a segment is specified, relative to the start of the - * line. Always starts with 0 and ends with the line length. - * @exception IllegalArgumentException

    */ public StyleRange [] getStyleRanges() { - checkWidget(); - StyleRange styles[]; - - if (userLineStyle == false) { - styles = defaultLineStyler.getStyleRanges(); - } - else { - styles = new StyleRange[0]; - } - return styles; + checkWidget(); + StyleRange styles[]; + + if (userLineStyle == false) { + styles = defaultLineStyler.getStyleRanges(); + } + else { + styles = new StyleRange[0]; + } + return styles; } /** * Returns a StyledTextBidi object for the specified line. *

    - * - * @param lineText the line that the StyledTextBidi object should - * work on. - * @param lineOffset offset of the beginning of the line, relative - * to the beginning of the document + * + * @param lineText the line that the StyledTextBidi object should + * work on. + * @param lineOffset offset of the beginning of the line, relative + * to the beginning of the document * @param gc GC to use when creating a new StyledTextBidi object. * @return a StyledTextBidi object for the specified line. */ StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc) { - return getStyledTextBidi(lineText, lineOffset, gc, null); + return getStyledTextBidi(lineText, lineOffset, gc, null); } /** * Returns a StyledTextBidi object for the specified line. *

    - * - * @param lineText the line that the StyledTextBidi object should - * work on. - * @param lineOffset offset of the beginning of the line, relative - * to the beginning of the document + * + * @param lineText the line that the StyledTextBidi object should + * work on. + * @param lineOffset offset of the beginning of the line, relative + * to the beginning of the document * @param gc GC to use when creating a new StyledTextBidi object. - * @param styles StyleRanges to use when creating a new StyledTextBidi - * object. + * @param styles StyleRanges to use when creating a new StyledTextBidi + * object. * @return a StyledTextBidi object for the specified line. */ StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc, StyleRange[] styles) { - return renderer.getStyledTextBidi(lineText, lineOffset, gc, styles); -} + return renderer.getStyledTextBidi(lineText, lineOffset, gc, styles); +} /** * Returns the tab width measured in characters. * @@ -4420,8 +4430,8 @@ * */ public int getTabs() { - checkWidget(); - return tabLength; + checkWidget(); + return tabLength; } /** * Returns a copy of the widget content. @@ -4434,15 +4444,15 @@ * */ public String getText() { - checkWidget(); - return content.getTextRange(0, getCharCount()); -} + checkWidget(); + return content.getTextRange(0, getCharCount()); +} /** * Returns the widget content between the two offsets. *

    * * @param start offset of the first character in the returned String - * @param end offset of the last character in the returned String + * @param end offset of the last character in the returned String * @return widget content starting at start and ending at end * @see #getTextRange(int,int) * @exception SWTException

    * @exception IllegalArgumentException */ public String getText(int start, int end) { - checkWidget(); - int contentLength = getCharCount(); - - if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getTextRange(start, end - start + 1); + checkWidget(); + int contentLength = getCharCount(); + + if (start < 0 || start >= contentLength || end < 0 || end >= contentLength || start > end) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getTextRange(start, end - start + 1); } /** * Returns the widget content starting at start for length characters. *

    * * @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 SWTException

    * @exception IllegalArgumentException */ public String getTextRange(int start, int length) { - checkWidget(); - int contentLength = getCharCount(); - int end = start + length; - - if (start > end || start < 0 || end > contentLength) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - return content.getTextRange(start, length); + checkWidget(); + int contentLength = getCharCount(); + int end = start + length; + + if (start > end || start < 0 || end > contentLength) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + return content.getTextRange(start, length); } /** - * Gets the text limit. The text limit specifies the amount of text that the user + * Gets the text limit. The text limit specifies the amount of text that the user * can type into the widget. *

    * @@ -4498,51 +4508,51 @@ * */ public int getTextLimit() { - checkWidget(); - - return textLimit; + checkWidget(); + + return textLimit; } /** - * Returns the x position of the character at the specified offset + * Returns the x position of the character at the specified offset * relative to the first character in the line. * Expands tabs to tab stops using the widget tab width. *

    * * @param line line to be measured. - * @param lineIndex index of the line relative to the first kine of the - * document - * @param length number of characters to measure. Tabs are counted - * as one character in this parameter. + * @param lineIndex index of the line relative to the first kine of the + * document + * @param length number of characters to measure. Tabs are counted + * as one character in this parameter. * @param gc GC to use for measuring text - * @return x position of the character at the specified offset - * with tabs expanded to tab stops. 0 if the length is outside the - * specified text. + * @return x position of the character at the specified offset + * with tabs expanded to tab stops. 0 if the length is outside the + * specified text. */ int getTextPosition(String line, int lineIndex, int length, GC gc) { - int lineOffset = content.getOffsetAtLine(lineIndex); - int lineLength = line.length(); - int width; - if (lineLength == 0 || length > lineLength) { - return 0; - } - if (isBidi()) { - StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc, null); - width = getBidiTextPosition(line, length, bidi); - } - else { - StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); - StyleRange[] styles = null; - if (event != null) { - styles = renderer.filterLineStyles(event.styles); - } - width = renderer.getTextPosition(line, lineOffset, length, styles, gc); - } - return width; + int lineOffset = content.getOffsetAtLine(lineIndex); + int lineLength = line.length(); + int width; + if (lineLength == 0 || length > lineLength) { + return 0; + } + if (isBidi()) { + StyledTextBidi bidi = getStyledTextBidi(line, lineOffset, gc, null); + width = getBidiTextPosition(line, length, bidi); + } + else { + StyledTextEvent event = renderer.getLineStyleData(lineOffset, line); + StyleRange[] styles = null; + if (event != null) { + styles = renderer.filterLineStyles(event.styles); + } + width = renderer.getTextPosition(line, lineOffset, length, styles, gc); + } + return width; } /** * Gets the top index. The top index is the index of the fully visible line that - * is currently at the top of the widget or the topmost partially visible line if - * no line is fully visible. + * 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. *

    * @@ -4553,20 +4563,20 @@ * */ public int getTopIndex() { - checkWidget(); - int logicalTopIndex = topIndex; - - if (wordWrap) { - int visualLineOffset = content.getOffsetAtLine(topIndex); - logicalTopIndex = logicalContent.getLineAtOffset(visualLineOffset); - } - return logicalTopIndex; + checkWidget(); + int logicalTopIndex = topIndex; + + if (wordWrap) { + int visualLineOffset = content.getOffsetAtLine(topIndex); + logicalTopIndex = logicalContent.getLineAtOffset(visualLineOffset); + } + return logicalTopIndex; } /** - * Gets the top pixel. The top pixel is the pixel position of the line that is - * currently at the top of the widget.The text widget can be scrolled by pixels - * by dragging the scroll thumb so that a partial line may be displayed at the top - * the widget. The top pixel changes when the widget is scrolled. The top pixel + * Gets the top pixel. The top pixel is the pixel position of the line that is + * currently at the top of the widget.The text widget can be scrolled by pixels + * by dragging the scroll thumb so that a partial line may be displayed at the top + * the widget. The top pixel changes when the widget is scrolled. The top pixel * does not include the widget trimming. *

    * @@ -4577,39 +4587,39 @@ * */ public int getTopPixel() { - checkWidget(); - return verticalScrollOffset; + checkWidget(); + return verticalScrollOffset; } -/** +/** * Returns the vertical scroll increment. *

    * * @return vertical scroll increment. */ int getVerticalIncrement() { - return lineHeight; + return lineHeight; } /** * Returns the index of the line the caret is on. - * When in word wrap mode and at the end of one wrapped line/ + * When in word wrap mode and at the end of one wrapped line/ * beginning of the continuing wrapped line the caret offset * is not sufficient to determine the caret line. - * + * * @return the index of the line the caret is on. */ int getCaretLine() { - int caretLine = content.getLineAtOffset(caretOffset); - int leftColumnX = 0; - - if (isBidi()) { - leftColumnX = XINSET; - } - if (wordWrap && columnX <= leftColumnX && - caretLine < content.getLineCount() - 1 && - caretOffset == content.getOffsetAtLine(caretLine + 1)) { - caretLine++; - } - return caretLine; + int caretLine = content.getLineAtOffset(caretOffset); + int leftColumnX = 0; + + if (isBidi()) { + leftColumnX = XINSET; + } + if (wordWrap && columnX <= leftColumnX && + caretLine < content.getLineCount() - 1 && + caretOffset == content.getOffsetAtLine(caretLine + 1)) { + caretLine++; + } + return caretLine; } /** * Returns the offset of the character after the word at the specified @@ -4623,42 +4633,42 @@ *

    *

    * Space characters ' ' (ASCII 20) are special as they are treated as - * part of the word leading up to the space character. Line breaks are + * part of the word leading up to the space character. Line breaks are * treated as one word. *

    */ int getWordEnd(int offset) { - int line = logicalContent.getLineAtOffset(offset); - int lineOffset = logicalContent.getOffsetAtLine(line); - String lineText = logicalContent.getLine(line); - int lineLength = lineText.length(); - - if (offset >= getCharCount()) { - return offset; - } - if (offset == lineOffset + lineLength) { - line++; - offset = logicalContent.getOffsetAtLine(line); - } - else { - offset -= lineOffset; - char ch = lineText.charAt(offset); - boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); - while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit) { - offset++; - ch = lineText.charAt(offset); - } - // skip over trailing whitespace - while (offset < lineLength - 1 && Compatibility.isSpaceChar(ch)) { - offset++; - ch = lineText.charAt(offset); - } - if (offset == lineLength - 1 && (Compatibility.isLetterOrDigit(ch) == letterOrDigit || Compatibility.isSpaceChar(ch))) { - offset++; - } - offset += lineOffset; - } - return offset; + int line = logicalContent.getLineAtOffset(offset); + int lineOffset = logicalContent.getOffsetAtLine(line); + String lineText = logicalContent.getLine(line); + int lineLength = lineText.length(); + + if (offset >= getCharCount()) { + return offset; + } + if (offset == lineOffset + lineLength) { + line++; + offset = logicalContent.getOffsetAtLine(line); + } + else { + offset -= lineOffset; + char ch = lineText.charAt(offset); + boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); + while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit) { + offset++; + ch = lineText.charAt(offset); + } + // skip over trailing whitespace + while (offset < lineLength - 1 && Compatibility.isSpaceChar(ch)) { + offset++; + ch = lineText.charAt(offset); + } + if (offset == lineLength - 1 && (Compatibility.isLetterOrDigit(ch) == letterOrDigit || Compatibility.isSpaceChar(ch))) { + offset++; + } + offset += lineOffset; + } + return offset; } /** * Returns the offset of the character after the word at the specified @@ -4671,38 +4681,38 @@ * *

    *

    - * Spaces are ignored and do not represent a word. Line breaks are treated + * Spaces are ignored and do not represent a word. Line breaks are treated * as one word. *

    */ int getWordEndNoSpaces(int offset) { - int line = logicalContent.getLineAtOffset(offset); - int lineOffset = logicalContent.getOffsetAtLine(line); - String lineText = logicalContent.getLine(line); - int lineLength = lineText.length(); - - if (offset >= getCharCount()) { - return offset; - } - if (offset == lineOffset + lineLength) { - line++; - offset = logicalContent.getOffsetAtLine(line); - } - else { - offset -= lineOffset; - char ch = lineText.charAt(offset); - boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); - - while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { - offset++; - ch = lineText.charAt(offset); - } - if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { - offset++; - } - offset += lineOffset; - } - return offset; + int line = logicalContent.getLineAtOffset(offset); + int lineOffset = logicalContent.getOffsetAtLine(line); + String lineText = logicalContent.getLine(line); + int lineLength = lineText.length(); + + if (offset >= getCharCount()) { + return offset; + } + if (offset == lineOffset + lineLength) { + line++; + offset = logicalContent.getOffsetAtLine(line); + } + else { + offset -= lineOffset; + char ch = lineText.charAt(offset); + boolean letterOrDigit = Compatibility.isLetterOrDigit(ch); + + while (offset < lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { + offset++; + ch = lineText.charAt(offset); + } + if (offset == lineLength - 1 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { + offset++; + } + offset += lineOffset; + } + return offset; } /** * Returns the start offset of the word at the specified offset. @@ -4715,44 +4725,44 @@ *

    *

    * Space characters ' ' (ASCII 20) are special as they are treated as - * part of the word leading up to the space character. Line breaks are treated + * part of the word leading up to the space character. Line breaks are treated * as one word. *

    */ int getWordStart(int offset) { - int line = logicalContent.getLineAtOffset(offset); - int lineOffset = logicalContent.getOffsetAtLine(line); - String lineText = logicalContent.getLine(line); - - if (offset <= 0) { - return offset; - } - if (offset == lineOffset) { - line--; - lineText = logicalContent.getLine(line); - offset = logicalContent.getOffsetAtLine(line) + lineText.length(); - } - else { - char ch; - boolean letterOrDigit; - - offset -= lineOffset; - // skip over trailing whitespace - do { - offset--; - ch = lineText.charAt(offset); - } while (offset > 0 && Compatibility.isSpaceChar(ch)); - letterOrDigit = Compatibility.isLetterOrDigit(ch); - while (offset > 0 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { - offset--; - ch = lineText.charAt(offset); - } - if (offset > 0 || Compatibility.isLetterOrDigit(ch) != letterOrDigit) { - offset++; - } - offset += lineOffset; - } - return offset; + int line = logicalContent.getLineAtOffset(offset); + int lineOffset = logicalContent.getOffsetAtLine(line); + String lineText = logicalContent.getLine(line); + + if (offset <= 0) { + return offset; + } + if (offset == lineOffset) { + line--; + lineText = logicalContent.getLine(line); + offset = logicalContent.getOffsetAtLine(line) + lineText.length(); + } + else { + char ch; + boolean letterOrDigit; + + offset -= lineOffset; + // skip over trailing whitespace + do { + offset--; + ch = lineText.charAt(offset); + } while (offset > 0 && Compatibility.isSpaceChar(ch)); + letterOrDigit = Compatibility.isLetterOrDigit(ch); + while (offset > 0 && Compatibility.isLetterOrDigit(ch) == letterOrDigit && Compatibility.isSpaceChar(ch) == false) { + offset--; + ch = lineText.charAt(offset); + } + if (offset > 0 || Compatibility.isLetterOrDigit(ch) != letterOrDigit) { + offset++; + } + offset += lineOffset; + } + return offset; } /** * Returns whether the widget wraps lines. @@ -4762,10 +4772,10 @@ * @since 2.0 */ public boolean getWordWrap() { - checkWidget(); - return wordWrap; + checkWidget(); + return wordWrap; } -/** +/** * Returns the x location of the character at the give offset in the line. * NOTE: Does not return correct values for true italic fonts (vs. slanted fonts). *

    @@ -4773,24 +4783,24 @@ * @return x location of the character at the given offset in the line. */ int getXAtOffset(String line, int lineIndex, int lineOffset) { - int x; - if (lineOffset == 0 && isBidi() == false) { - x = leftMargin; - } - else { - GC gc = getGC(); - x = getTextPosition(line, lineIndex, Math.min(line.length(), lineOffset), gc) + leftMargin; - gc.dispose(); - if (lineOffset > line.length()) { - // offset is not on the line. return an x location one character - // after the line to indicate the line delimiter. - x += lineEndSpaceWidth; - } - } - return x - horizontalScrollOffset; + int x; + if (lineOffset == 0 && isBidi() == false) { + x = leftMargin; + } + else { + GC gc = getGC(); + x = getTextPosition(line, lineIndex, Math.min(line.length(), lineOffset), gc) + leftMargin; + gc.dispose(); + if (lineOffset > line.length()) { + // offset is not on the line. return an x location one character + // after the line to indicate the line delimiter. + x += lineEndSpaceWidth; + } + } + return x - horizontalScrollOffset; } -/** - * Inserts a string. The old selection is replaced with the new text. +/** + * Inserts a string. The old selection is replaced with the new text. *

    * * @param string the string @@ -4804,30 +4814,30 @@ * */ public void insert(String string) { - checkWidget(); - if (string == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - Point sel = getSelectionRange(); - replaceTextRange(sel.x, sel.y, string); + checkWidget(); + if (string == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + Point sel = getSelectionRange(); + replaceTextRange(sel.x, sel.y, string); } /** * Creates content change listeners and set the default content model. */ void installDefaultContent() { - textChangeListener = new TextChangeListener() { - public void textChanging(TextChangingEvent event) { - handleTextChanging(event); - } - public void textChanged(TextChangedEvent event) { - handleTextChanged(event); - } - public void textSet(TextChangedEvent event) { - handleTextSet(event); - } - }; - logicalContent = content = new DefaultContent(); - content.addTextChangeListener(textChangeListener); + textChangeListener = new TextChangeListener() { + public void textChanging(TextChangingEvent event) { + handleTextChanging(event); + } + public void textChanged(TextChangedEvent event) { + handleTextChanged(event); + } + public void textSet(TextChangedEvent event) { + handleTextSet(event); + } + }; + logicalContent = content = new DefaultContent(); + content.addTextChangeListener(textChangeListener); } /** * Creates a default line style listener. @@ -4838,159 +4848,159 @@ * @see #addLineStyleListener */ void installDefaultLineStyler() { - defaultLineStyler = new DefaultLineStyler(logicalContent); - StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); - if (userLineStyle == false) { - addListener(LineGetStyle, typedListener); - } - if (userLineBackground == false) { - addListener(LineGetBackground, typedListener); - } + defaultLineStyler = new DefaultLineStyler(logicalContent); + StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); + if (userLineStyle == false) { + addListener(LineGetStyle, typedListener); + } + if (userLineBackground == false) { + addListener(LineGetBackground, typedListener); + } } -/** +/** * Adds event listeners */ void installListeners() { - ScrollBar verticalBar = getVerticalBar(); - ScrollBar horizontalBar = getHorizontalBar(); - - addListener(SWT.Dispose, new Listener() { - public void handleEvent(Event event) { - handleDispose(); - } - }); - addListener(SWT.KeyDown, new Listener() { - public void handleEvent(Event event) { - handleKeyDown(event); - } - }); - addListener(SWT.MouseDown, new Listener() { - public void handleEvent(Event event) { - handleMouseDown(event); - } - }); - addListener(SWT.MouseUp, new Listener() { - public void handleEvent(Event event) { - handleMouseUp(event); - } - }); - addListener(SWT.MouseDoubleClick, new Listener() { - public void handleEvent(Event event) { - handleMouseDoubleClick(event); - } - }); - addListener(SWT.MouseMove, new Listener() { - public void handleEvent(Event event) { - handleMouseMove(event); - } - }); - addListener(SWT.Paint, new Listener() { - public void handleEvent(Event event) { - handlePaint(event); - } - }); - addListener(SWT.Resize, new Listener() { - public void handleEvent(Event event) { - handleResize(event); - } - }); - addListener(SWT.Traverse, new Listener() { - public void handleEvent(Event event) { - handleTraverse(event); - } - }); - if (verticalBar != null) { - verticalBar.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - handleVerticalScroll(event); - } - }); - } - if (horizontalBar != null) { - horizontalBar.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - handleHorizontalScroll(event); - } - }); - } + ScrollBar verticalBar = getVerticalBar(); + ScrollBar horizontalBar = getHorizontalBar(); + + addListener(SWT.Dispose, new Listener() { + public void handleEvent(Event event) { + handleDispose(); + } + }); + addListener(SWT.KeyDown, new Listener() { + public void handleEvent(Event event) { + handleKeyDown(event); + } + }); + addListener(SWT.MouseDown, new Listener() { + public void handleEvent(Event event) { + handleMouseDown(event); + } + }); + addListener(SWT.MouseUp, new Listener() { + public void handleEvent(Event event) { + handleMouseUp(event); + } + }); + addListener(SWT.MouseDoubleClick, new Listener() { + public void handleEvent(Event event) { + handleMouseDoubleClick(event); + } + }); + addListener(SWT.MouseMove, new Listener() { + public void handleEvent(Event event) { + handleMouseMove(event); + } + }); + addListener(SWT.Paint, new Listener() { + public void handleEvent(Event event) { + handlePaint(event); + } + }); + addListener(SWT.Resize, new Listener() { + public void handleEvent(Event event) { + handleResize(event); + } + }); + addListener(SWT.Traverse, new Listener() { + public void handleEvent(Event event) { + handleTraverse(event); + } + }); + if (verticalBar != null) { + verticalBar.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + handleVerticalScroll(event); + } + }); + } + if (horizontalBar != null) { + horizontalBar.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + handleHorizontalScroll(event); + } + }); + } } StyledTextContent internalGetContent() { - return content; + return content; } int internalGetHorizontalPixel() { - return horizontalScrollOffset; + return horizontalScrollOffset; } LineCache internalGetLineCache() { - return lineCache; + return lineCache; } Point internalGetSelection() { - return selection; + return selection; } boolean internalGetWordWrap() { - return wordWrap; + return wordWrap; } /** * Used by WordWrapCache to bypass StyledText.redraw which does * an unwanted cache reset. */ void internalRedraw() { - super.redraw(); + super.redraw(); } -/** +/** * Redraws the specified text range. *

    * * @param start offset of the first character to redraw * @param length number of characters to redraw - * @param clearBackground true if the background should be cleared as - * part of the redraw operation. If true, the entire redraw range will + * @param clearBackground true if the background should be cleared as + * part of the redraw operation. If true, the entire redraw range will * be cleared before anything is redrawn. If the redraw range includes - * the last character of a line (i.e., the entire line is redrawn) the - * line is cleared all the way to the right border of the widget. - * The redraw operation will be faster and smoother if clearBackground is - * set to false. Whether or not the flag can be set to false depends on - * the type of change that has taken place. If font styles or background - * colors for the redraw range have changed, clearBackground should be - * set to true. If only foreground colors have changed for the redraw - * range, clearBackground can be set to false. + * the last character of a line (i.e., the entire line is redrawn) the + * line is cleared all the way to the right border of the widget. + * The redraw operation will be faster and smoother if clearBackground is + * set to false. Whether or not the flag can be set to false depends on + * the type of change that has taken place. If font styles or background + * colors for the redraw range have changed, clearBackground should be + * set to true. If only foreground colors have changed for the redraw + * range, clearBackground can be set to false. */ void internalRedrawRange(int start, int length, boolean clearBackground) { - int end = start + length; - int firstLine = content.getLineAtOffset(start); - int lastLine = content.getLineAtOffset(end); - int offsetInFirstLine; - int partialBottomIndex = getPartialBottomIndex(); - int partialTopIndex = verticalScrollOffset / lineHeight; - // do nothing if redraw range is completely invisible - if (firstLine > partialBottomIndex || lastLine < partialTopIndex) { - return; - } - // only redraw visible lines - if (partialTopIndex > firstLine) { - firstLine = partialTopIndex; - offsetInFirstLine = 0; - } - else { - offsetInFirstLine = start - content.getOffsetAtLine(firstLine); - } - if (partialBottomIndex + 1 < lastLine) { - lastLine = partialBottomIndex + 1; // + 1 to redraw whole bottom line, including line break - end = content.getOffsetAtLine(lastLine); - } - // redraw first and last lines - if (isBidi()) { - redrawBidiLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); - } - else { - redrawLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); - } - // redraw entire center lines if redraw range includes more than two lines - if (lastLine - firstLine > 1) { - Rectangle clientArea = getClientArea(); - int redrawStopY = lastLine * lineHeight - verticalScrollOffset; - int redrawY = (firstLine + 1) * lineHeight - verticalScrollOffset; - draw(0, redrawY, clientArea.width, redrawStopY - redrawY, clearBackground); - } + int end = start + length; + int firstLine = content.getLineAtOffset(start); + int lastLine = content.getLineAtOffset(end); + int offsetInFirstLine; + int partialBottomIndex = getPartialBottomIndex(); + int partialTopIndex = verticalScrollOffset / lineHeight; + // do nothing if redraw range is completely invisible + if (firstLine > partialBottomIndex || lastLine < partialTopIndex) { + return; + } + // only redraw visible lines + if (partialTopIndex > firstLine) { + firstLine = partialTopIndex; + offsetInFirstLine = 0; + } + else { + offsetInFirstLine = start - content.getOffsetAtLine(firstLine); + } + if (partialBottomIndex + 1 < lastLine) { + lastLine = partialBottomIndex + 1; // + 1 to redraw whole bottom line, including line break + end = content.getOffsetAtLine(lastLine); + } + // redraw first and last lines + if (isBidi()) { + redrawBidiLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); + } + else { + redrawLines(firstLine, offsetInFirstLine, lastLine, end, clearBackground); + } + // redraw entire center lines if redraw range includes more than two lines + if (lastLine - firstLine > 1) { + Rectangle clientArea = getClientArea(); + int redrawStopY = lastLine * lineHeight - verticalScrollOffset; + int redrawY = (firstLine + 1) * lineHeight - verticalScrollOffset; + draw(0, redrawY, clientArea.width, redrawStopY - redrawY, clearBackground); + } } /** * Returns the widget text with style information encoded using RTF format @@ -5003,41 +5013,41 @@ * */ String getRtf(){ - checkWidget(); - RTFWriter rtfWriter = new RTFWriter(0, getCharCount()); - return getPlatformDelimitedText(rtfWriter); + checkWidget(); + RTFWriter rtfWriter = new RTFWriter(0, getCharCount()); + return getPlatformDelimitedText(rtfWriter); } -/** +/** * Frees resources. */ void handleDispose() { - clipboard.dispose(); - ibeamCursor.dispose(); - if (renderer != null) { - renderer.dispose(); - renderer = null; - } - if (content != null) { - content.removeTextChangeListener(textChangeListener); - } - if (leftCaretBitmap != null) { - leftCaretBitmap.dispose(); - leftCaretBitmap = null; - } - if (rightCaretBitmap != null) { - rightCaretBitmap.dispose(); - rightCaretBitmap = null; - } - if (isBidi()) { - StyledTextBidi.removeLanguageListener(this); - } + clipboard.dispose(); + ibeamCursor.dispose(); + if (renderer != null) { + renderer.dispose(); + renderer = null; + } + if (content != null) { + content.removeTextChangeListener(textChangeListener); + } + if (leftCaretBitmap != null) { + leftCaretBitmap.dispose(); + leftCaretBitmap = null; + } + if (rightCaretBitmap != null) { + rightCaretBitmap.dispose(); + rightCaretBitmap = null; + } + if (isBidi()) { + StyledTextBidi.removeLanguageListener(this); + } } -/** +/** * Scrolls the widget horizontally. */ void handleHorizontalScroll(Event event) { - int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; - scrollHorizontal(scrollPixel); + int scrollPixel = getHorizontalBar().getSelection() - horizontalScrollOffset; + scrollHorizontal(scrollPixel); } /** * If an action has been registered for the key stroke execute the action. @@ -5047,56 +5057,56 @@ * @param event keyboard event */ void handleKey(Event event) { - int action; - - if (event.keyCode != 0) { - // special key pressed (e.g., F1) - action = getKeyBinding(event.keyCode | event.stateMask); - } - else { - // character key pressed - action = getKeyBinding(event.character | event.stateMask); - if (action == SWT.NULL) { - // see if we have a control character - if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) { - // get the character from the CTRL+char sequence, the control - // key subtracts 64 from the value of the key that it modifies - int c = event.character + 64; - action = getKeyBinding(c | event.stateMask); - } - } - } - if (action == SWT.NULL) { - boolean ignore = false; - - if (isCarbon) { - // Ignore acclerator key combinations (we do not want to - // insert a character in the text in this instance). Do not - // ignore COMMAND+ALT combinations since that key sequence - // produces characters on the mac. - ignore = (event.stateMask ^ SWT.COMMAND) == 0 || - (event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0; - } else { - // Ignore acclerator key combinations (we do not want to - // insert a character in the text in this instance). Don't - // ignore CTRL+ALT combinations since that is the Alt Gr - // key on some keyboards. See bug 20953. - ignore = (event.stateMask ^ SWT.ALT) == 0 || - (event.stateMask ^ SWT.CTRL) == 0 || - (event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 || - (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; - } - // -ignore anything below SPACE except for line delimiter keys and tab. - // -ignore DEL - if (!ignore && event.character > 31 && event.character != SWT.DEL || - event.character == SWT.CR || event.character == SWT.LF || - event.character == TAB) { - doContent(event.character); - } - } - else { - invokeAction(action); - } + int action; + + if (event.keyCode != 0) { + // special key pressed (e.g., F1) + action = getKeyBinding(event.keyCode | event.stateMask); + } + else { + // character key pressed + action = getKeyBinding(event.character | event.stateMask); + if (action == SWT.NULL) { + // see if we have a control character + if ((event.stateMask & SWT.CTRL) != 0 && (event.character >= 0) && event.character <= 31) { + // get the character from the CTRL+char sequence, the control + // key subtracts 64 from the value of the key that it modifies + int c = event.character + 64; + action = getKeyBinding(c | event.stateMask); + } + } + } + if (action == SWT.NULL) { + boolean ignore = false; + + if (isCarbon) { + // Ignore acclerator key combinations (we do not want to + // insert a character in the text in this instance). Do not + // ignore COMMAND+ALT combinations since that key sequence + // produces characters on the mac. + ignore = (event.stateMask ^ SWT.COMMAND) == 0 || + (event.stateMask ^ (SWT.COMMAND | SWT.SHIFT)) == 0; + } else { + // Ignore acclerator key combinations (we do not want to + // insert a character in the text in this instance). Don't + // ignore CTRL+ALT combinations since that is the Alt Gr + // key on some keyboards. See bug 20953. + ignore = (event.stateMask ^ SWT.ALT) == 0 || + (event.stateMask ^ SWT.CTRL) == 0 || + (event.stateMask ^ (SWT.ALT | SWT.SHIFT)) == 0 || + (event.stateMask ^ (SWT.CTRL | SWT.SHIFT)) == 0; + } + // -ignore anything below SPACE except for line delimiter keys and tab. + // -ignore DEL + if (!ignore && event.character > 31 && event.character != SWT.DEL || + event.character == SWT.CR || event.character == SWT.LF || + event.character == TAB) { + doContent(event.character); + } + } + else { + invokeAction(action); + } } /** * If a VerifyKey listener exists, verify that the key that was entered @@ -5106,66 +5116,71 @@ * @param event keyboard event */ void handleKeyDown(Event event) { - Event verifyEvent = new Event(); - - verifyEvent.character = event.character; - verifyEvent.keyCode = event.keyCode; - verifyEvent.stateMask = event.stateMask; - verifyEvent.doit = true; - notifyListeners(VerifyKey, verifyEvent); - if (verifyEvent.doit == true) { - handleKey(event); - } + Event verifyEvent = new Event(); + + verifyEvent.character = event.character; + verifyEvent.keyCode = event.keyCode; + verifyEvent.stateMask = event.stateMask; + verifyEvent.doit = true; + notifyListeners(VerifyKey, verifyEvent); + if (verifyEvent.doit == true) { + handleKey(event); + } } /** - * Updates the caret location and selection if mouse button 1 has been + * Updates the caret location and selection if mouse button 1 has been * pressed. */ void handleMouseDoubleClick(Event event) { - if (event.button != 1 || doubleClickEnabled == false) { - return; - } - event.y -= topMargin; - mouseDoubleClick = true; - caretOffset = getWordStart(caretOffset); - resetSelection(); - caretOffset = getWordEndNoSpaces(caretOffset); - showCaret(); - doMouseSelection(); - doubleClickSelection = new Point(selection.x, selection.y); + if (event.button != 1 || doubleClickEnabled == false) { + return; + } + event.y -= topMargin; + mouseDoubleClick = true; + caretOffset = getWordStart(caretOffset); + resetSelection(); + caretOffset = getWordEndNoSpaces(caretOffset); + showCaret(); + doMouseSelection(); + doubleClickSelection = new Point(selection.x, selection.y); } -/** - * Updates the caret location and selection if mouse button 1 has been +/** + * Updates the caret location and selection if mouse button 1 has been * pressed. */ void handleMouseDown(Event event) { - boolean select = (event.stateMask & SWT.MOD2) != 0; - - if (event.button != 1) { - return; - } - mouseDoubleClick = false; - event.y -= topMargin; - doMouseLocationChange(event.x, event.y, select); + boolean select = (event.stateMask & SWT.MOD2) != 0; + + if ((event.button == 1) || (event.button == 3)) { + if ((event.button == 3) && (isMouseOverSelection(event.x, event.y))) { + // we have a right click over a selection, so don't alter the selection + return; + } + mouseDoubleClick = false; + event.y -= topMargin; + doMouseLocationChange(event.x, event.y, select); + } } -/** - * 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) { - if ((event.stateMask & SWT.BUTTON1) == 0) { - return; - } - event.y -= topMargin; - doMouseLocationChange(event.x, event.y, true); - doAutoScroll(event); + if ((event.stateMask & SWT.BUTTON1) != 0) { + event.y -= topMargin; + doMouseLocationChange(event.x, event.y, true); + doAutoScroll(event); + } else if (event.stateMask == 0) { + // changes the mouse pointer based on whether or not it is over a selection + internalSetCursor(event.x, event.y); + } } -/** +/** * Autoscrolling ends when the mouse button is released. */ void handleMouseUp(Event event) { - event.y -= topMargin; - endAutoScroll(); + event.y -= topMargin; + endAutoScroll(); } /** * Renders the invalidated area specified in the paint event. @@ -5174,204 +5189,204 @@ * @param event paint event */ void handlePaint(Event event) { - int startLine = Math.max(0, (event.y - topMargin + verticalScrollOffset) / lineHeight); - int paintYFromTopLine = (startLine - topIndex) * lineHeight; - int topLineOffset = topIndex * lineHeight - verticalScrollOffset; - int startY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling and top margin - int renderHeight = event.y + event.height - startY; - Rectangle clientArea = getClientArea(); - - // Check if there is work to do. clientArea.width should never be 0 - // if we receive a paint event but we never want to try and create - // an Image with 0 width. - if (clientArea.width == 0 || event.height == 0) { - return; - } - performPaint(event.gc, startLine, startY, renderHeight); -} + int startLine = Math.max(0, (event.y - topMargin + verticalScrollOffset) / lineHeight); + int paintYFromTopLine = (startLine - topIndex) * lineHeight; + int topLineOffset = topIndex * lineHeight - verticalScrollOffset; + int startY = paintYFromTopLine + topLineOffset + topMargin; // adjust y position for pixel based scrolling and top margin + int renderHeight = event.y + event.height - startY; + Rectangle clientArea = getClientArea(); + + // Check if there is work to do. clientArea.width should never be 0 + // if we receive a paint event but we never want to try and create + // an Image with 0 width. + if (clientArea.width == 0 || event.height == 0) { + return; + } + performPaint(event.gc, startLine, startY, renderHeight); +} /** - * Recalculates the scroll bars. Rewraps all lines when in word + * Recalculates the scroll bars. Rewraps all lines when in word * wrap mode. *

    * * @param event resize event */ void handleResize(Event event) { - int oldHeight = clientAreaHeight; - int oldWidth = clientAreaWidth; - - clientAreaHeight = getClientArea().height; - clientAreaWidth = getClientArea().width; - if (wordWrap) { - if (oldWidth != clientAreaWidth) { - wordWrapResize(oldWidth); - } - } - else - if (clientAreaHeight > oldHeight) { - int lineCount = content.getLineCount(); - int oldBottomIndex = topIndex + oldHeight / lineHeight; - int newItemCount = Compatibility.ceil(clientAreaHeight - oldHeight, lineHeight); - - oldBottomIndex = Math.min(oldBottomIndex, lineCount); - newItemCount = Math.min(newItemCount, lineCount - oldBottomIndex); - lineCache.calculate(oldBottomIndex, newItemCount); - } - setScrollBars(); - claimBottomFreeSpace(); - claimRightFreeSpace(); - if (oldHeight != clientAreaHeight) { - calculateTopIndex(); - } + int oldHeight = clientAreaHeight; + int oldWidth = clientAreaWidth; + + clientAreaHeight = getClientArea().height; + clientAreaWidth = getClientArea().width; + if (wordWrap) { + if (oldWidth != clientAreaWidth) { + wordWrapResize(oldWidth); + } + } + else + if (clientAreaHeight > oldHeight) { + int lineCount = content.getLineCount(); + int oldBottomIndex = topIndex + oldHeight / lineHeight; + int newItemCount = Compatibility.ceil(clientAreaHeight - oldHeight, lineHeight); + + oldBottomIndex = Math.min(oldBottomIndex, lineCount); + newItemCount = Math.min(newItemCount, lineCount - oldBottomIndex); + lineCache.calculate(oldBottomIndex, newItemCount); + } + setScrollBars(); + claimBottomFreeSpace(); + claimRightFreeSpace(); + if (oldHeight != clientAreaHeight) { + calculateTopIndex(); + } } /** - * Updates the caret position and selection and the scroll bars to reflect + * Updates the caret position and selection and the scroll bars to reflect * the content change. *

    */ void handleTextChanged(TextChangedEvent event) { - lineCache.textChanged(lastTextChangeStart, - lastTextChangeNewLineCount, - lastTextChangeReplaceLineCount, - lastTextChangeNewCharCount, - lastTextChangeReplaceCharCount); - setScrollBars(); - // update selection/caret location after styles have been changed. - // otherwise any text measuring could be incorrect - // - // also, this needs to be done after all scrolling. Otherwise, - // selection redraw would be flushed during scroll which is wrong. - // in some cases new text would be drawn in scroll source area even - // though the intent is to scroll it. - // fixes 1GB93QT - updateSelection( - lastTextChangeStart, - lastTextChangeReplaceCharCount, - lastTextChangeNewCharCount); - - if (lastTextChangeReplaceLineCount > 0) { - // Only check for unused space when lines are deleted. - // Fixes 1GFL4LY - // Scroll up so that empty lines below last text line are used. - // Fixes 1GEYJM0 - claimBottomFreeSpace(); - } - if (lastTextChangeReplaceCharCount > 0) { - // fixes bug 8273 - claimRightFreeSpace(); - } - // do direct drawing if the text change is confined to a single line. - // optimization and fixes bug 13999. see also handleTextChanging. - if (lastTextChangeNewLineCount == 0 && lastTextChangeReplaceLineCount == 0) { - int startLine = content.getLineAtOffset(lastTextChangeStart); - int startY = startLine * lineHeight - verticalScrollOffset + topMargin; - - GC gc = getGC(); - Caret caret = getCaret(); - boolean caretVisible = false; - - if (caret != null) { - caretVisible = caret.getVisible(); - caret.setVisible(false); - } - performPaint(gc, startLine, startY, lineHeight); - if (caret != null) { - caret.setVisible(caretVisible); - } - gc.dispose(); - } + lineCache.textChanged(lastTextChangeStart, + lastTextChangeNewLineCount, + lastTextChangeReplaceLineCount, + lastTextChangeNewCharCount, + lastTextChangeReplaceCharCount); + setScrollBars(); + // update selection/caret location after styles have been changed. + // otherwise any text measuring could be incorrect + // + // also, this needs to be done after all scrolling. Otherwise, + // selection redraw would be flushed during scroll which is wrong. + // in some cases new text would be drawn in scroll source area even + // though the intent is to scroll it. + // fixes 1GB93QT + updateSelection( + lastTextChangeStart, + lastTextChangeReplaceCharCount, + lastTextChangeNewCharCount); + + if (lastTextChangeReplaceLineCount > 0) { + // Only check for unused space when lines are deleted. + // Fixes 1GFL4LY + // Scroll up so that empty lines below last text line are used. + // Fixes 1GEYJM0 + claimBottomFreeSpace(); + } + if (lastTextChangeReplaceCharCount > 0) { + // fixes bug 8273 + claimRightFreeSpace(); + } + // do direct drawing if the text change is confined to a single line. + // optimization and fixes bug 13999. see also handleTextChanging. + if (lastTextChangeNewLineCount == 0 && lastTextChangeReplaceLineCount == 0) { + int startLine = content.getLineAtOffset(lastTextChangeStart); + int startY = startLine * lineHeight - verticalScrollOffset + topMargin; + + GC gc = getGC(); + Caret caret = getCaret(); + boolean caretVisible = false; + + if (caret != null) { + caretVisible = caret.getVisible(); + caret.setVisible(false); + } + performPaint(gc, startLine, startY, lineHeight); + if (caret != null) { + caret.setVisible(caretVisible); + } + gc.dispose(); + } } /** * Updates the screen to reflect a pending content change. *

    * * @param event.start the start offset of the change - * @param event.newText text that is going to be inserted or empty String - * if no text will be inserted + * @param event.newText text that is going to be inserted or empty String + * if no text will be inserted * @param event.replaceCharCount length of text that is going to be replaced * @param event.newCharCount length of text that is going to be inserted * @param event.replaceLineCount number of lines that are going to be replaced * @param event.newLineCount number of new lines that are going to be inserted */ void handleTextChanging(TextChangingEvent event) { - int firstLine; - int textChangeY; - boolean isMultiLineChange = event.replaceLineCount > 0 || event.newLineCount > 0; - - if (event.replaceCharCount < 0) { - event.start += event.replaceCharCount; - event.replaceCharCount *= -1; - } - lastTextChangeStart = event.start; - lastTextChangeNewLineCount = event.newLineCount; - lastTextChangeNewCharCount = event.newCharCount; - lastTextChangeReplaceLineCount = event.replaceLineCount; - lastTextChangeReplaceCharCount = event.replaceCharCount; - firstLine = content.getLineAtOffset(event.start); - textChangeY = firstLine * lineHeight - verticalScrollOffset + topMargin; - if (isMultiLineChange) { - redrawMultiLineChange(textChangeY, event.newLineCount, event.replaceLineCount); - } - // notify default line styler about text change - if (defaultLineStyler != null) { - defaultLineStyler.textChanging(event); - } - - // Update the caret offset if it is greater than the length of the content. - // This is necessary since style range API may be called between the - // handleTextChanging and handleTextChanged events and this API sets the - // caretOffset. - int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; - if (caretOffset > newEndOfText) caretOffset = newEndOfText; + int firstLine; + int textChangeY; + boolean isMultiLineChange = event.replaceLineCount > 0 || event.newLineCount > 0; + + if (event.replaceCharCount < 0) { + event.start += event.replaceCharCount; + event.replaceCharCount *= -1; + } + lastTextChangeStart = event.start; + lastTextChangeNewLineCount = event.newLineCount; + lastTextChangeNewCharCount = event.newCharCount; + lastTextChangeReplaceLineCount = event.replaceLineCount; + lastTextChangeReplaceCharCount = event.replaceCharCount; + firstLine = content.getLineAtOffset(event.start); + textChangeY = firstLine * lineHeight - verticalScrollOffset + topMargin; + if (isMultiLineChange) { + redrawMultiLineChange(textChangeY, event.newLineCount, event.replaceLineCount); + } + // notify default line styler about text change + if (defaultLineStyler != null) { + defaultLineStyler.textChanging(event); + } + + // Update the caret offset if it is greater than the length of the content. + // This is necessary since style range API may be called between the + // handleTextChanging and handleTextChanged events and this API sets the + // caretOffset. + int newEndOfText = content.getCharCount() - event.replaceCharCount + event.newCharCount; + if (caretOffset > newEndOfText) caretOffset = newEndOfText; } /** - * Called when the widget content is set programatically, overwriting - * the old content. Resets the caret position, selection and scroll offsets. + * Called when the widget content is set programatically, overwriting + * the old content. Resets the caret position, selection and scroll offsets. * Recalculates the content width and scroll bars. Redraws the widget. *

    * - * @param event text change event. + * @param event text change event. */ void handleTextSet(TextChangedEvent event) { - reset(); + 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 */ void handleTraverse(Event event) { - int style = getStyle(); - boolean ignoreTab = (style & SWT.MULTI) != 0 && !editable || isSingleLine(); - - if ((event.detail == SWT.TRAVERSE_TAB_NEXT || - event.detail == SWT.TRAVERSE_RETURN) && ignoreTab) { - event.doit = true; - } + int style = getStyle(); + boolean ignoreTab = (style & SWT.MULTI) != 0 && !editable || isSingleLine(); + + if ((event.detail == SWT.TRAVERSE_TAB_NEXT || + event.detail == SWT.TRAVERSE_RETURN) && ignoreTab) { + event.doit = true; + } } -/** +/** * Scrolls the widget vertically. */ void handleVerticalScroll(Event event) { - setVerticalScrollOffset(getVerticalBar().getSelection(), false); + setVerticalScrollOffset(getVerticalBar().getSelection(), false); } -/** +/** * Initializes the fonts used to render font styles. * Presently only regular and bold fonts are supported. */ void initializeRenderer() { - if (renderer != null) { - renderer.dispose(); - } - renderer = new DisplayRenderer( - getDisplay(), getFont(), isBidi(), leftMargin, this, tabLength); - lineHeight = renderer.getLineHeight(); - lineEndSpaceWidth = renderer.getLineEndSpaceWidth(); + if (renderer != null) { + renderer.dispose(); + } + renderer = new DisplayRenderer( + getDisplay(), getFont(), isBidi(), leftMargin, this, tabLength); + lineHeight = renderer.getLineHeight(); + lineEndSpaceWidth = renderer.getLineEndSpaceWidth(); } /** * Executes the action. @@ -5380,178 +5395,178 @@ * @param action one of the actions defined in ST.java */ public void invokeAction(int action) { - int oldColumnX; - int caretLine; - - checkWidget(); - switch (action) { - // Navigation - case ST.LINE_UP: - caretLine = doLineUp(); - oldColumnX = columnX; - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - // save the original horizontal caret position - columnX = oldColumnX; - clearSelection(true); - break; - case ST.LINE_DOWN: - caretLine = doLineDown(); - oldColumnX = columnX; - // explicitly go to the calculated caret line. may be different - // from content.getLineAtOffset(caretOffset) when in word wrap mode - showCaret(caretLine); - // save the original horizontal caret position - columnX = oldColumnX; - clearSelection(true); - break; - case ST.LINE_START: - doLineStart(); - clearSelection(true); - break; - case ST.LINE_END: - doLineEnd(); - clearSelection(true); - break; - case ST.COLUMN_PREVIOUS: - doCursorPrevious(); - clearSelection(true); - break; - case ST.COLUMN_NEXT: - doCursorNext(); - clearSelection(true); - break; - case ST.PAGE_UP: - doPageUp(); - clearSelection(true); - break; - case ST.PAGE_DOWN: - doPageDown(false); - clearSelection(true); - break; - case ST.WORD_PREVIOUS: - doWordPrevious(); - clearSelection(true); - break; - case ST.WORD_NEXT: - doWordNext(); - clearSelection(true); - break; - case ST.TEXT_START: - doContentStart(); - clearSelection(true); - break; - case ST.TEXT_END: - doContentEnd(); - clearSelection(true); - break; - case ST.WINDOW_START: - doPageStart(); - clearSelection(true); - break; - case ST.WINDOW_END: - doPageEnd(); - clearSelection(true); - break; - // Selection - case ST.SELECT_LINE_UP: - doSelectionLineUp(); - break; - case ST.SELECT_LINE_DOWN: - doSelectionLineDown(); - break; - case ST.SELECT_LINE_START: - doLineStart(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_LINE_END: - doLineEnd(); - doSelection(SWT.RIGHT); - break; - case ST.SELECT_COLUMN_PREVIOUS: - doSelectionCursorPrevious(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_COLUMN_NEXT: - doSelectionCursorNext(); - doSelection(SWT.RIGHT); - break; - case ST.SELECT_PAGE_UP: - doPageUp(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_PAGE_DOWN: - doPageDown(true); - break; - case ST.SELECT_WORD_PREVIOUS: - doSelectionWordPrevious(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_WORD_NEXT: - doSelectionWordNext(); - doSelection(SWT.RIGHT); - break; - case ST.SELECT_TEXT_START: - doContentStart(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_TEXT_END: - doContentEnd(); - doSelection(SWT.RIGHT); - break; - case ST.SELECT_WINDOW_START: - doPageStart(); - doSelection(SWT.LEFT); - break; - case ST.SELECT_WINDOW_END: - doPageEnd(); - doSelection(SWT.RIGHT); - break; - // Modification - case ST.CUT: - cut(); - break; - case ST.COPY: - copy(); - break; - case ST.PASTE: - paste(); - break; - case ST.DELETE_PREVIOUS: - doBackspace(); - break; - case ST.DELETE_NEXT: - doDelete(); - break; - // Miscellaneous - case ST.TOGGLE_OVERWRITE: - overwrite = !overwrite; // toggle insert/overwrite mode - break; - } + int oldColumnX; + int caretLine; + + checkWidget(); + switch (action) { + // Navigation + case ST.LINE_UP: + caretLine = doLineUp(); + oldColumnX = columnX; + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + // save the original horizontal caret position + columnX = oldColumnX; + clearSelection(true); + break; + case ST.LINE_DOWN: + caretLine = doLineDown(); + oldColumnX = columnX; + // explicitly go to the calculated caret line. may be different + // from content.getLineAtOffset(caretOffset) when in word wrap mode + showCaret(caretLine); + // save the original horizontal caret position + columnX = oldColumnX; + clearSelection(true); + break; + case ST.LINE_START: + doLineStart(); + clearSelection(true); + break; + case ST.LINE_END: + doLineEnd(); + clearSelection(true); + break; + case ST.COLUMN_PREVIOUS: + doCursorPrevious(); + clearSelection(true); + break; + case ST.COLUMN_NEXT: + doCursorNext(); + clearSelection(true); + break; + case ST.PAGE_UP: + doPageUp(); + clearSelection(true); + break; + case ST.PAGE_DOWN: + doPageDown(false); + clearSelection(true); + break; + case ST.WORD_PREVIOUS: + doWordPrevious(); + clearSelection(true); + break; + case ST.WORD_NEXT: + doWordNext(); + clearSelection(true); + break; + case ST.TEXT_START: + doContentStart(); + clearSelection(true); + break; + case ST.TEXT_END: + doContentEnd(); + clearSelection(true); + break; + case ST.WINDOW_START: + doPageStart(); + clearSelection(true); + break; + case ST.WINDOW_END: + doPageEnd(); + clearSelection(true); + break; + // Selection + case ST.SELECT_LINE_UP: + doSelectionLineUp(); + break; + case ST.SELECT_LINE_DOWN: + doSelectionLineDown(); + break; + case ST.SELECT_LINE_START: + doLineStart(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_LINE_END: + doLineEnd(); + doSelection(SWT.RIGHT); + break; + case ST.SELECT_COLUMN_PREVIOUS: + doSelectionCursorPrevious(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_COLUMN_NEXT: + doSelectionCursorNext(); + doSelection(SWT.RIGHT); + break; + case ST.SELECT_PAGE_UP: + doPageUp(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_PAGE_DOWN: + doPageDown(true); + break; + case ST.SELECT_WORD_PREVIOUS: + doSelectionWordPrevious(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_WORD_NEXT: + doSelectionWordNext(); + doSelection(SWT.RIGHT); + break; + case ST.SELECT_TEXT_START: + doContentStart(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_TEXT_END: + doContentEnd(); + doSelection(SWT.RIGHT); + break; + case ST.SELECT_WINDOW_START: + doPageStart(); + doSelection(SWT.LEFT); + break; + case ST.SELECT_WINDOW_END: + doPageEnd(); + doSelection(SWT.RIGHT); + break; + // Modification + case ST.CUT: + cut(); + break; + case ST.COPY: + copy(); + break; + case ST.PASTE: + paste(); + break; + case ST.DELETE_PREVIOUS: + doBackspace(); + break; + case ST.DELETE_NEXT: + doDelete(); + break; + // Miscellaneous + case ST.TOGGLE_OVERWRITE: + overwrite = !overwrite; // toggle insert/overwrite mode + break; + } } /** * Temporary until SWT provides this */ boolean isBidi() { - return isBidi; + return isBidi; } /** * Returns whether the given offset is inside a multi byte line delimiter. - * Example: + * Example: * "Line1\r\n" isLineDelimiter(5) == false but isLineDelimiter(6) == true - * + * * @return true if the given offset is inside a multi byte line delimiter. * false if the given offset is before or after a line delimiter. */ boolean isLineDelimiter(int offset) { - int line = content.getLineAtOffset(offset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = offset - lineOffset; - // offsetInLine will be greater than line length if the line - // delimiter is longer than one character and the offset is set - // in between parts of the line delimiter. - return offsetInLine > content.getLine(line).length(); + int line = content.getLineAtOffset(offset); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = offset - lineOffset; + // offsetInLine will be greater than line length if the line + // delimiter is longer than one character and the offset is set + // in between parts of the line delimiter. + return offsetInLine > content.getLine(line).length(); } /** * Returns whether or not the given lines are visible. @@ -5561,190 +5576,243 @@ * false if none of the lines is visible */ boolean isAreaVisible(int firstLine, int lastLine) { - int partialBottomIndex = getPartialBottomIndex(); - int partialTopIndex = verticalScrollOffset / lineHeight; - boolean notVisible = firstLine > partialBottomIndex || lastLine < partialTopIndex; - return !notVisible; + int partialBottomIndex = getPartialBottomIndex(); + int partialTopIndex = verticalScrollOffset / lineHeight; + boolean notVisible = firstLine > partialBottomIndex || lastLine < partialTopIndex; + return !notVisible; +} +/** + * Tests whether the mouse pointer is over a selection. + * + * @param x mouse x position in client coordinates + * @param y mouse y position in client coordinates + */ +private boolean isMouseOverSelection(int x, int y) { + if (selectionAnchor == -1) { + // no selection + return false; + } else { + // there is a selection + int mouseLineIndex = (y + verticalScrollOffset) / lineHeight; + int mouseCharOffset; + int selLineIndexX; + int selLineIndexY; + int selLineOffset; + String lineContent = null; + + selLineIndexX = content.getLineAtOffset(selection.x); + selLineIndexY = content.getLineAtOffset(selection.y); + + if ((mouseLineIndex < selLineIndexX) || (mouseLineIndex > selLineIndexY)) { + // mouse is before the first or after the last line of the selection + return false; + } + + if (mouseLineIndex == selLineIndexX) { + // the mouse is on the first line of the selection + selLineOffset = content.getOffsetAtLine(selLineIndexX); + lineContent = content.getLine(selLineIndexX); + if (x < getXAtOffset(lineContent, selLineIndexX, selection.x - selLineOffset)) { + // mouse is before the start of the selection + return false; + } + } + + if (mouseLineIndex == selLineIndexY) { + // the mouse is on the last line of the selection + selLineOffset = content.getOffsetAtLine(selLineIndexY); + if (selLineIndexY != selLineIndexX) { + lineContent = content.getLine(selLineIndexY); + } + if (x > getXAtOffset(lineContent, selLineIndexY, selection.y - selLineOffset)) { + // mouse is after the end of the selection + return false; + } + } + + // mouse is over the selection + return true; + } } /** - * Returns whether or not the given styles will necessitate a redraw for the given start line. - * A redraw is necessary when font style changes after the start of a style will take place. + * Returns whether or not the given styles will necessitate a redraw for the given start line. + * A redraw is necessary when font style changes after the start of a style will take place. * This method assumes ranges is in order and non-overlapping. *

    * * @return true if a redraw of the given line is necessary, false otherwise */ boolean isRedrawFirstLine(StyleRange[] ranges, int firstLine, int firstLineOffset) { - int lineEnd = firstLineOffset + content.getLine(firstLine).length(); - for (int i=0; i * * @return true if a redraw of the last line is necessary, false otherwise */ boolean isRedrawLastLine(StyleRange[] ranges, int lastLine, int lastLineOffset) { - for (int i = ranges.length - 1; i >= 0; i--) { - StyleRange range = ranges[i]; - int rangeEnd = range.start + range.length; - // does style range end on the last line? - if (rangeEnd >= lastLineOffset) { - if (isStyleChanging(range, Math.max(range.start, lastLineOffset), rangeEnd)) return true; - } else { - break; - } - } - return false; + for (int i = ranges.length - 1; i >= 0; i--) { + StyleRange range = ranges[i]; + int rangeEnd = range.start + range.length; + // does style range end on the last line? + if (rangeEnd >= lastLineOffset) { + if (isStyleChanging(range, Math.max(range.start, lastLineOffset), rangeEnd)) return true; + } else { + break; + } + } + return false; } /** * Returns whether the widget can have only one line. *

    * - * @return true if widget can have only one line, false if widget can have - * multiple lines + * @return true if widget can have only one line, false if widget can have + * multiple lines */ boolean isSingleLine() { - return (getStyle() & SWT.SINGLE) != 0; + return (getStyle() & SWT.SINGLE) != 0; } -/** - * Returns whether the font style in the given style range is changing +/** + * Returns whether the font style in the given style range is changing * from SWT.NORMAL to SWT.BOLD or vice versa. *

    * * @param range StyleRange to compare current font style with. - * @param start offset of the first font style to compare + * @param start offset of the first font style to compare * @param end offset behind the last font style to compare * @return true if the font style is changing in the given style range, - * false if the font style is not changing in the given style range. + * false if the font style is not changing in the given style range. * @exception SWTException

    */ boolean isStyleChanging(StyleRange range, int start, int end) { - checkWidget(); - StyleRange[] styles = defaultLineStyler.getStyleRangesFor(start, end - start); - - if (styles == null) { - return (range.fontStyle != SWT.NORMAL); - } - for (int i = 0; i < styles.length; i++) { - StyleRange newStyle = styles[i]; - if (newStyle.fontStyle != range.fontStyle) { - return true; - } - } - return false; + checkWidget(); + StyleRange[] styles = defaultLineStyler.getStyleRangesFor(start, end - start); + + if (styles == null) { + return (range.fontStyle != SWT.NORMAL); + } + for (int i = 0; i < styles.length; i++) { + StyleRange newStyle = styles[i]; + if (newStyle.fontStyle != range.fontStyle) { + return true; + } + } + return false; } /** - * Sends the specified verify event, replace/insert text as defined by + * 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. + * * @param updateCaret whether or not he caret should be set behind - * the new text + * the new text */ void modifyContent(Event event, boolean updateCaret) { - event.doit = true; - notifyListeners(SWT.Verify, event); - if (event.doit) { - StyledTextEvent styledTextEvent = null; - int replacedLength = event.end - event.start; - boolean isCharacterRemove = replacedLength == 1 && event.text.length() == 0; - boolean isBackspace = event.start < caretOffset; - boolean isDirectionBoundary = false; - - if (updateCaret && isBidi() && isCharacterRemove) { - // set the keyboard language to the language of the deleted character. - // determine direction boundary so that caret location can be updated - // properly. - int line = content.getLineAtOffset(caretOffset); - int lineStartOffset = content.getOffsetAtLine(line); - int offsetInLine = caretOffset - lineStartOffset; - String lineText = content.getLine(line); - GC gc = getGC(); - StyledTextBidi bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); - if (isBackspace) { - if (offsetInLine > 0) { - // the line start/end does not represent a direction boundary - // even if the previous/next line has a different direction. - isDirectionBoundary = - offsetInLine < lineText.length() && - (bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || - bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); - bidi.setKeyboardLanguage(offsetInLine - 1); - } - } - else { - if (offsetInLine < lineText.length()) { - // the line start/end does not represent a direction boundary - // even if the previous/next line has a different direction. - isDirectionBoundary = - offsetInLine > 0 && - (bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || - bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); - bidi.setKeyboardLanguage(offsetInLine); - } - } - gc.dispose(); - } - if (isListening(ExtendedModify)) { - styledTextEvent = new StyledTextEvent(logicalContent); - styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); - styledTextEvent.text = content.getTextRange(event.start, replacedLength); - } - content.replaceTextRange(event.start, replacedLength, event.text); - // set the caret position prior to sending the modify event. - // fixes 1GBB8NJ - if (updateCaret) { - // always update the caret location. fixes 1G8FODP - internalSetSelection(event.start + event.text.length(), 0, true); - if (isBidi()) { - // Update the caret direction so that the caret moves to the - // typed/deleted character. Fixes 1GJLQ16. - if (isCharacterRemove) { - updateBidiDirection(isBackspace, isDirectionBoundary); - } - else { - lastCaretDirection = ST.COLUMN_NEXT; - } - showBidiCaret(); - } - else { - showCaret(); - } - } - notifyListeners(SWT.Modify, event); - if (isListening(ExtendedModify)) { - notifyListeners(ExtendedModify, styledTextEvent); - } - } -} -/** - * Replaces the selection with the clipboard text or insert the text at - * the current caret offset if there is no selection. + event.doit = true; + notifyListeners(SWT.Verify, event); + if (event.doit) { + StyledTextEvent styledTextEvent = null; + int replacedLength = event.end - event.start; + boolean isCharacterRemove = replacedLength == 1 && event.text.length() == 0; + boolean isBackspace = event.start < caretOffset; + boolean isDirectionBoundary = false; + + if (updateCaret && isBidi() && isCharacterRemove) { + // set the keyboard language to the language of the deleted character. + // determine direction boundary so that caret location can be updated + // properly. + int line = content.getLineAtOffset(caretOffset); + int lineStartOffset = content.getOffsetAtLine(line); + int offsetInLine = caretOffset - lineStartOffset; + String lineText = content.getLine(line); + GC gc = getGC(); + StyledTextBidi bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); + if (isBackspace) { + if (offsetInLine > 0) { + // the line start/end does not represent a direction boundary + // even if the previous/next line has a different direction. + isDirectionBoundary = + offsetInLine < lineText.length() && + (bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || + bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); + bidi.setKeyboardLanguage(offsetInLine - 1); + } + } + else { + if (offsetInLine < lineText.length()) { + // the line start/end does not represent a direction boundary + // even if the previous/next line has a different direction. + isDirectionBoundary = + offsetInLine > 0 && + (bidi.isRightToLeft(offsetInLine) != bidi.isRightToLeft(offsetInLine - 1) || + bidi.isLocalNumber(offsetInLine) != bidi.isLocalNumber(offsetInLine - 1)); + bidi.setKeyboardLanguage(offsetInLine); + } + } + gc.dispose(); + } + if (isListening(ExtendedModify)) { + styledTextEvent = new StyledTextEvent(logicalContent); + styledTextEvent.start = event.start; + styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.text = content.getTextRange(event.start, replacedLength); + } + content.replaceTextRange(event.start, replacedLength, event.text); + // set the caret position prior to sending the modify event. + // fixes 1GBB8NJ + if (updateCaret) { + // always update the caret location. fixes 1G8FODP + internalSetSelection(event.start + event.text.length(), 0, true); + if (isBidi()) { + // Update the caret direction so that the caret moves to the + // typed/deleted character. Fixes 1GJLQ16. + if (isCharacterRemove) { + updateBidiDirection(isBackspace, isDirectionBoundary); + } + else { + lastCaretDirection = ST.COLUMN_NEXT; + } + showBidiCaret(); + } + else { + showCaret(); + } + } + notifyListeners(SWT.Modify, event); + if (isListening(ExtendedModify)) { + notifyListeners(ExtendedModify, styledTextEvent); + } + } +} +/** + * Replaces the selection with the clipboard text or insert the text at + * the current caret offset if there is no selection. * If the widget has the SWT.SINGLE style and the clipboard text contains - * more than one line, only the first line without line delimiters is + * more than one line, only the first line without line delimiters is * inserted in the widget. *

    * @@ -5754,73 +5822,73 @@ * */ public void paste(){ - checkWidget(); - TextTransfer transfer = TextTransfer.getInstance(); - String text; - text = (String) clipboard.getContents(transfer); - if (text != null && text.length() > 0) { - Event event = new Event(); - event.start = selection.x; - event.end = selection.y; - event.text = getModelDelimitedText(text); - sendKeyEvent(event); - } + checkWidget(); + TextTransfer transfer = TextTransfer.getInstance(); + String text; + text = (String) clipboard.getContents(transfer); + if (text != null && text.length() > 0) { + Event event = new Event(); + event.start = selection.x; + event.end = selection.y; + event.text = getModelDelimitedText(text); + sendKeyEvent(event); + } } /** * Render the specified area. Broken out as its own method to support * direct drawing. *

    * - * @param gc GC to render on + * @param gc GC to render on * @param startLine first line to render * @param startY y pixel location to start rendering at * @param renderHeight renderHeight widget area that needs to be filled with lines */ -void performPaint(GC gc,int startLine,int startY, int renderHeight) { - Rectangle clientArea = getClientArea(); - Color background = getBackground(); - - // Check if there is work to do. We never want to try and create - // an Image with 0 width or 0 height. - if (clientArea.width == 0) { - return; - } - if (renderHeight > 0) { - // renderHeight will be negative when only top margin needs redrawing - Color foreground = getForeground(); - int lineCount = content.getLineCount(); - int paintY = 0; - - if (isSingleLine()) { - lineCount = 1; - if (startLine > 1) { - startLine = 1; - } - } - Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight); - GC lineGC = new GC(lineBuffer); - - lineGC.setFont(getFont()); - renderer.setCurrentFontStyle(SWT.NORMAL); - lineGC.setForeground(foreground); - lineGC.setBackground(background); - - for (int i = startLine; paintY < renderHeight && i < lineCount; i++, paintY += lineHeight) { - String line = content.getLine(i); - renderer.drawLine(line, i, paintY, lineGC, background, foreground, true); - } - if (paintY < renderHeight) { - lineGC.setBackground(background); - lineGC.setForeground(background); - lineGC.fillRectangle(0, paintY, clientArea.width, renderHeight - paintY); - } - gc.drawImage(lineBuffer, 0, startY); - lineGC.dispose(); - lineBuffer.dispose(); - } - clearMargin(gc, background, clientArea, renderHeight); +void performPaint(GC gc,int startLine,int startY, int renderHeight) { + Rectangle clientArea = getClientArea(); + Color background = getBackground(); + + // Check if there is work to do. We never want to try and create + // an Image with 0 width or 0 height. + if (clientArea.width == 0) { + return; + } + if (renderHeight > 0) { + // renderHeight will be negative when only top margin needs redrawing + Color foreground = getForeground(); + int lineCount = content.getLineCount(); + int paintY = 0; + + if (isSingleLine()) { + lineCount = 1; + if (startLine > 1) { + startLine = 1; + } + } + Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight); + GC lineGC = new GC(lineBuffer); + + lineGC.setFont(getFont()); + renderer.setCurrentFontStyle(SWT.NORMAL); + lineGC.setForeground(foreground); + lineGC.setBackground(background); + + for (int i = startLine; paintY < renderHeight && i < lineCount; i++, paintY += lineHeight) { + String line = content.getLine(i); + renderer.drawLine(line, i, paintY, lineGC, background, foreground, true); + } + if (paintY < renderHeight) { + lineGC.setBackground(background); + lineGC.setForeground(background); + lineGC.fillRectangle(0, paintY, clientArea.width, renderHeight - paintY); + } + gc.drawImage(lineBuffer, 0, startY); + lineGC.dispose(); + lineBuffer.dispose(); + } + clearMargin(gc, background, clientArea, renderHeight); } -/** +/** * Prints the widget's text to the default printer. * * @exception SWTException

    */ public void print() { - checkWidget(); - Printer printer = new Printer(); - StyledTextPrintOptions options = new StyledTextPrintOptions(); - - options.printTextForeground = true; - options.printTextBackground = true; - options.printTextFontStyle = true; - options.printLineBackground = true; - new Printing(this, printer, options).run(); - printer.dispose(); + checkWidget(); + Printer printer = new Printer(); + StyledTextPrintOptions options = new StyledTextPrintOptions(); + + options.printTextForeground = true; + options.printTextBackground = true; + options.printTextFontStyle = true; + options.printLineBackground = true; + new Printing(this, printer, options).run(); + printer.dispose(); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. *

    * The runnable may be run in a non-UI thread. *

    - * + * * @param printer the printer to print to * @exception SWTException */ public Runnable print(Printer printer) { - StyledTextPrintOptions options = new StyledTextPrintOptions(); + StyledTextPrintOptions options = new StyledTextPrintOptions(); - checkWidget(); - options.printTextForeground = true; - options.printTextBackground = true; - options.printTextFontStyle = true; - options.printLineBackground = true; - if (printer == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - return print(printer, options); + checkWidget(); + options.printTextForeground = true; + options.printTextBackground = true; + options.printTextFontStyle = true; + options.printLineBackground = true; + if (printer == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + return print(printer, options); } -/** +/** * Returns a runnable that will print the widget's text * to the specified printer. *

    * The runnable may be run in a non-UI thread. *

    - * + * * @param printer the printer to print to * @param options print options to use during printing * @exception SWTException */ public void removeExtendedModifyListener(ExtendedModifyListener extendedModifyListener) { - checkWidget(); - if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeListener(ExtendedModify, extendedModifyListener); + checkWidget(); + if (extendedModifyListener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(ExtendedModify, extendedModifyListener); } /** * Removes the specified line background listener. @@ -6251,15 +6319,15 @@ * */ public void removeLineBackgroundListener(LineBackgroundListener listener) { - checkWidget(); - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeListener(LineGetBackground, listener); - // use default line styler if last user line styler was removed. - if (isListening(LineGetBackground) == false && userLineBackground) { - StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); - addListener(LineGetBackground, typedListener); - userLineBackground = false; - } + checkWidget(); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(LineGetBackground, listener); + // use default line styler if last user line styler was removed. + if (isListening(LineGetBackground) == false && userLineBackground) { + StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); + addListener(LineGetBackground, typedListener); + userLineBackground = false; + } } /** * Removes the specified line style listener. @@ -6275,17 +6343,17 @@ * */ public void removeLineStyleListener(LineStyleListener listener) { - checkWidget(); - if (listener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - removeListener(LineGetStyle, listener); - // use default line styler if last user line styler was removed. Fixes 1G7B1X2 - if (isListening(LineGetStyle) == false && userLineStyle) { - StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); - addListener(LineGetStyle, typedListener); - userLineStyle = false; - } + checkWidget(); + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + removeListener(LineGetStyle, listener); + // use default line styler if last user line styler was removed. Fixes 1G7B1X2 + if (isListening(LineGetStyle) == false && userLineStyle) { + StyledTextListener typedListener = new StyledTextListener(defaultLineStyler); + addListener(LineGetStyle, typedListener); + userLineStyle = false; + } } /** * Removes the specified modify listener. @@ -6301,11 +6369,11 @@ * */ public void removeModifyListener(ModifyListener modifyListener) { - checkWidget(); - if (modifyListener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - removeListener(SWT.Modify, modifyListener); + checkWidget(); + if (modifyListener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + removeListener(SWT.Modify, modifyListener); } /** * Removes the specified selection listener. @@ -6321,11 +6389,11 @@ * */ public void removeSelectionListener(SelectionListener listener) { - checkWidget(); - if (listener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - removeListener(SWT.Selection, listener); + checkWidget(); + if (listener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + removeListener(SWT.Selection, listener); } /** * Removes the specified verify listener. @@ -6341,11 +6409,11 @@ * */ public void removeVerifyListener(VerifyListener verifyListener) { - checkWidget(); - if (verifyListener == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - removeListener(SWT.Verify, verifyListener); + checkWidget(); + if (verifyListener == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + removeListener(SWT.Verify, verifyListener); } /** * Removes the specified key verify listener. @@ -6361,22 +6429,22 @@ * */ public void removeVerifyKeyListener(VerifyKeyListener listener) { - if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - removeListener(VerifyKey, listener); + if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + removeListener(VerifyKey, listener); } -/** +/** * Replaces the styles in the given range with new styles. This method * effectively deletes the styles in the given range and then adds the - * the new styles. + * the new styles. *

    - * 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. *

    * * @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 SWTException * @exception IllegalArgumentException * @since 2.0 */ public void replaceStyleRanges(int start, int length, StyleRange[] ranges) { - checkWidget(); - if (userLineStyle) { - return; - } - if (ranges == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (ranges.length == 0) { - setStyleRange(new StyleRange(start, length, null, null)); - return; - } - int end = start + length; - if (start > end || start < 0 || end > getCharCount()) { - SWT.error(SWT.ERROR_INVALID_RANGE); - } - - int firstLine = content.getLineAtOffset(start); - int lastLine = content.getLineAtOffset(end); - - // if the area is not visible, there is no need to redraw - boolean redrawLines = isAreaVisible(firstLine, lastLine); - - if (!redrawLines) { - defaultLineStyler.replaceStyleRanges(start, length, ranges); - lineCache.reset(firstLine, lastLine - firstLine + 1, true); - } else { - boolean redrawFirstLine = false; - boolean redrawLastLine = false; - // the first and last line needs to be redrawn completely if the - // font style is changing from SWT.NORMAL to something else or - // vice versa. fixes 1G7M5WE. - int firstLineOffset = content.getOffsetAtLine(firstLine); - if (isBidi()) { - redrawFirstLine = true; - redrawLastLine = true; - } else { - int firstLineEnd = firstLineOffset + content.getLine(firstLine).length(); - redrawFirstLine = isRedrawFirstLine(ranges, firstLine, firstLineOffset); - // check if any bold styles will be cleared - StyleRange clearRange = new StyleRange(firstLineOffset, firstLineEnd - firstLineOffset, null, null); - redrawFirstLine = redrawFirstLine || isRedrawFirstLine(new StyleRange[] {clearRange}, firstLine, firstLineOffset); - if (lastLine != firstLine) { - int lastLineOffset = content.getOffsetAtLine(lastLine); - int lastLineEnd = lastLineOffset + content.getLine(lastLine).length(); - redrawLastLine = isRedrawLastLine(ranges, lastLine, lastLineOffset); - // check if any bold styles will be cleared - clearRange = new StyleRange(lastLineOffset, lastLineEnd - lastLineOffset, null, null); - redrawLastLine = redrawLastLine || isRedrawLastLine(new StyleRange[] {clearRange}, lastLine, lastLineOffset); - } - } - defaultLineStyler.replaceStyleRanges(start, length, ranges); - // reset all lines affected by the style change but let the redraw - // recalculate only those that are visible. - lineCache.reset(firstLine, lastLine - firstLine + 1, true); - internalRedrawRange(start, length, true); - if (redrawFirstLine) { - redrawLine(firstLine, start - firstLineOffset); - } - if (redrawLastLine) { - redrawLine(lastLine, 0); - } - } - - // make sure that the caret is positioned correctly. - // caret location may change if font style changes. - // fixes 1G8FODP - setCaretLocation(); + checkWidget(); + if (userLineStyle) { + return; + } + if (ranges == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + if (ranges.length == 0) { + setStyleRange(new StyleRange(start, length, null, null)); + return; + } + int end = start + length; + if (start > end || start < 0 || end > getCharCount()) { + SWT.error(SWT.ERROR_INVALID_RANGE); + } + + int firstLine = content.getLineAtOffset(start); + int lastLine = content.getLineAtOffset(end); + + // if the area is not visible, there is no need to redraw + boolean redrawLines = isAreaVisible(firstLine, lastLine); + + if (!redrawLines) { + defaultLineStyler.replaceStyleRanges(start, length, ranges); + lineCache.reset(firstLine, lastLine - firstLine + 1, true); + } else { + boolean redrawFirstLine = false; + boolean redrawLastLine = false; + // the first and last line needs to be redrawn completely if the + // font style is changing from SWT.NORMAL to something else or + // vice versa. fixes 1G7M5WE. + int firstLineOffset = content.getOffsetAtLine(firstLine); + if (isBidi()) { + redrawFirstLine = true; + redrawLastLine = true; + } else { + int firstLineEnd = firstLineOffset + content.getLine(firstLine).length(); + redrawFirstLine = isRedrawFirstLine(ranges, firstLine, firstLineOffset); + // check if any bold styles will be cleared + StyleRange clearRange = new StyleRange(firstLineOffset, firstLineEnd - firstLineOffset, null, null); + redrawFirstLine = redrawFirstLine || isRedrawFirstLine(new StyleRange[] {clearRange}, firstLine, firstLineOffset); + if (lastLine != firstLine) { + int lastLineOffset = content.getOffsetAtLine(lastLine); + int lastLineEnd = lastLineOffset + content.getLine(lastLine).length(); + redrawLastLine = isRedrawLastLine(ranges, lastLine, lastLineOffset); + // check if any bold styles will be cleared + clearRange = new StyleRange(lastLineOffset, lastLineEnd - lastLineOffset, null, null); + redrawLastLine = redrawLastLine || isRedrawLastLine(new StyleRange[] {clearRange}, lastLine, lastLineOffset); + } + } + defaultLineStyler.replaceStyleRanges(start, length, ranges); + // reset all lines affected by the style change but let the redraw + // recalculate only those that are visible. + lineCache.reset(firstLine, lastLine - firstLine + 1, true); + internalRedrawRange(start, length, true); + if (redrawFirstLine) { + redrawLine(firstLine, start - firstLineOffset); + } + if (redrawLastLine) { + redrawLine(lastLine, 0); + } + } + + // make sure that the caret is positioned correctly. + // caret location may change if font style changes. + // fixes 1G8FODP + setCaretLocation(); } /** * Replaces the given text range with new text. - * If the widget has the SWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text - * that was set. Note that only a single line of text should be set when + * If the widget has the SWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text + * that was set. Note that only a single line of text should be set when * the SWT.SINGLE style is used. *

    * NOTE: During the replace operation the current selection is * changed as follows: - *

    */ public void selectAll() { - checkWidget(); - setSelection(new Point(0, Math.max(getCharCount(),0))); + checkWidget(); + setSelection(new Point(0, Math.max(getCharCount(),0))); } /** * Replaces/inserts text as defined by the event. *

    * - * @param event the text change event. - *

    + * @param event the text change event. + * */ void sendKeyEvent(Event event) { - if (editable == false) { - return; - } - modifyContent(event, true); + if (editable == false) { + return; + } + modifyContent(event, true); } /** * Sends the specified selection event. */ void sendSelectionEvent() { - Event event = new Event(); - event.x = selection.x; - event.y = selection.y; - notifyListeners(SWT.Selection, event); + Event event = new Event(); + event.x = selection.x; + event.y = selection.y; + notifyListeners(SWT.Selection, event); } /** * Sets whether the widget wraps lines. @@ -6665,59 +6735,59 @@ * @since 2.0 */ public void setWordWrap(boolean wrap) { - checkWidget(); - - if (wrap != wordWrap) { - ScrollBar horizontalBar = getHorizontalBar(); - - wordWrap = wrap; - if (wordWrap) { - logicalContent = content; - content = new WrappedContent(renderer, logicalContent); - } - else { - content = logicalContent; - } - calculateContentWidth(); - horizontalScrollOffset = 0; - if (horizontalBar != null) { - horizontalBar.setVisible(!wordWrap); - } - setScrollBars(); - setCaretLocation(); - super.redraw(); - } + checkWidget(); + + if (wrap != wordWrap) { + ScrollBar horizontalBar = getHorizontalBar(); + + wordWrap = wrap; + if (wordWrap) { + logicalContent = content; + content = new WrappedContent(renderer, logicalContent); + } + else { + content = logicalContent; + } + calculateContentWidth(); + horizontalScrollOffset = 0; + if (horizontalBar != null) { + horizontalBar.setVisible(!wordWrap); + } + setScrollBars(); + setCaretLocation(); + super.redraw(); + } } /** * Sets the caret location and scrolls the caret offset into view. */ void showBidiCaret() { - int line = content.getLineAtOffset(caretOffset); - int lineOffset = content.getOffsetAtLine(line); - int offsetInLine = caretOffset - lineOffset; - String lineText = content.getLine(line); - int xAtOffset = 0; - boolean scrolled = false; - GC gc = getGC(); - StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); - // getXAtOffset, inlined for better performance - xAtOffset = getBidiTextPosition(lineText, offsetInLine, bidi) + leftMargin; - if (offsetInLine > lineText.length()) { - // offset is not on the line. return an x location one character - // after the line to indicate the line delimiter. - xAtOffset += lineEndSpaceWidth; - } - xAtOffset -= horizontalScrollOffset; - // - scrolled = showLocation(xAtOffset, line); - if (scrolled == false) { - setBidiCaretLocation(bidi); - } - gc.dispose(); + int line = content.getLineAtOffset(caretOffset); + int lineOffset = content.getOffsetAtLine(line); + int offsetInLine = caretOffset - lineOffset; + String lineText = content.getLine(line); + int xAtOffset = 0; + boolean scrolled = false; + GC gc = getGC(); + StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc); + // getXAtOffset, inlined for better performance + xAtOffset = getBidiTextPosition(lineText, offsetInLine, bidi) + leftMargin; + if (offsetInLine > lineText.length()) { + // offset is not on the line. return an x location one character + // after the line to indicate the line delimiter. + xAtOffset += lineEndSpaceWidth; + } + xAtOffset -= horizontalScrollOffset; + // + scrolled = showLocation(xAtOffset, line); + if (scrolled == false) { + setBidiCaretLocation(bidi); + } + gc.dispose(); } /** * Sets the receiver's caret. Set the caret's height and location. - * + * *

    * @param caret the new caret for the receiver * @@ -6727,100 +6797,100 @@ * */ public void setCaret(Caret caret) { - checkWidget (); - super.setCaret(caret); - if (caret != null) { - if (isBidi() == false) { - caret.setSize(caret.getSize().x, lineHeight); - } - setCaretLocation(); - if (isBidi()) { - setBidiKeyboardLanguage(); - } - } + checkWidget (); + super.setCaret(caret); + if (caret != null) { + if (isBidi() == false) { + caret.setSize(caret.getSize().x, lineHeight); + } + setCaretLocation(); + if (isBidi()) { + setBidiKeyboardLanguage(); + } + } } /** * @see org.eclipse.swt.widgets.Control#setBackground */ public void setBackground(Color color) { - checkWidget(); - super.setBackground(color); - background = color; - redraw(); + checkWidget(); + super.setBackground(color); + background = color; + redraw(); } /** * Set the caret to indicate the current typing direction. */ void setBidiCaretDirection() { - Caret caret = getCaret(); - int direction = StyledTextBidi.getKeyboardLanguageDirection(); - - if (caret == null || direction == caretDirection) { - return; - } - caretDirection = direction; - if (direction == SWT.DEFAULT) { - caret.setImage(null); - caret.setSize(caret.getSize().x, lineHeight); - } - else - if (caretDirection == SWT.LEFT) { - caret.setImage(leftCaretBitmap); - } - else - if (caretDirection == SWT.RIGHT) { - caret.setImage(rightCaretBitmap); - } + Caret caret = getCaret(); + int direction = StyledTextBidi.getKeyboardLanguageDirection(); + + if (caret == null || direction == caretDirection) { + return; + } + caretDirection = direction; + if (direction == SWT.DEFAULT) { + caret.setImage(null); + caret.setSize(caret.getSize().x, lineHeight); + } + else + if (caretDirection == SWT.LEFT) { + caret.setImage(leftCaretBitmap); + } + else + if (caretDirection == SWT.RIGHT) { + caret.setImage(rightCaretBitmap); + } } /** * Moves the Caret to the current caret offset. *

    - * + * * @param bidi StyledTextBidi object to use for measuring. - * May be left null in which case a new object will be created. + * May be left null in which case a new object will be created. */ void setBidiCaretLocation(StyledTextBidi bidi) { - int caretLine = getCaretLine(); - - setBidiCaretLocation(bidi, caretLine); + int caretLine = getCaretLine(); + + setBidiCaretLocation(bidi, caretLine); } /** * Moves the Caret to the current caret offset. *

    - * + * * @param bidi StyledTextBidi object to use for measuring. - * May be left null in which case a new object will be created. + * May be left null in which case a new object will be created. * @param caretLine line the caret should be placed on. Relative to - * first line in document + * first line in document */ void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) { - Caret caret = getCaret(); - String lineText = content.getLine(caretLine); - int lineStartOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineStartOffset; - GC gc = null; - - if (bidi == null) { - gc = getGC(); - bidi = getStyledTextBidi(lineText, lineStartOffset, gc); - } - if (lastCaretDirection == SWT.NULL) { - columnX = bidi.getTextPosition(offsetInLine) + leftMargin - horizontalScrollOffset; - } else { - columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset; - } - if (StyledTextBidi.getKeyboardLanguageDirection() == SWT.RIGHT) { - columnX -= (getCaretWidth() - 1); - } - if (caret != null) { - setBidiCaretDirection(); - caret.setLocation( - columnX, - caretLine * lineHeight - verticalScrollOffset + topMargin); - } - if (gc != null) { - gc.dispose(); - } + Caret caret = getCaret(); + String lineText = content.getLine(caretLine); + int lineStartOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineStartOffset; + GC gc = null; + + if (bidi == null) { + gc = getGC(); + bidi = getStyledTextBidi(lineText, lineStartOffset, gc); + } + if (lastCaretDirection == SWT.NULL) { + columnX = bidi.getTextPosition(offsetInLine) + leftMargin - horizontalScrollOffset; + } else { + columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset; + } + if (StyledTextBidi.getKeyboardLanguageDirection() == SWT.RIGHT) { + columnX -= (getCaretWidth() - 1); + } + if (caret != null) { + setBidiCaretDirection(); + caret.setLocation( + columnX, + caretLine * lineHeight - verticalScrollOffset + topMargin); + } + if (gc != null) { + gc.dispose(); + } } /** * Sets the BIDI coloring mode. When true the BIDI text display @@ -6837,87 +6907,87 @@ *

    */ public void setBidiColoring(boolean mode) { - checkWidget(); - bidiColoring = mode; + checkWidget(); + bidiColoring = mode; } /** - * Switches the keyboard language according to the current editing + * Switches the keyboard language according to the current editing * position and cursor direction. */ void setBidiKeyboardLanguage() { - int caretLine = getCaretLine(); - int lineStartOffset = content.getOffsetAtLine(caretLine); - int offsetInLine = caretOffset - lineStartOffset; - String lineText = content.getLine(caretLine); - GC gc = getGC(); - StyledTextBidi bidi; - int lineLength = lineText.length(); - - // Don't supply the bold styles/font since we don't want to measure anything - bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); - if (offsetInLine == 0) { - bidi.setKeyboardLanguage(offsetInLine); - } - else - if (offsetInLine >= lineLength) { - offsetInLine = Math.min(offsetInLine, lineLength - 1); - bidi.setKeyboardLanguage(offsetInLine); - } - else - if (lastCaretDirection == ST.COLUMN_NEXT) { - // continue with previous character type - bidi.setKeyboardLanguage(offsetInLine - 1); - } - else { - bidi.setKeyboardLanguage(offsetInLine); - } - gc.dispose(); + int caretLine = getCaretLine(); + int lineStartOffset = content.getOffsetAtLine(caretLine); + int offsetInLine = caretOffset - lineStartOffset; + String lineText = content.getLine(caretLine); + GC gc = getGC(); + StyledTextBidi bidi; + int lineLength = lineText.length(); + + // Don't supply the bold styles/font since we don't want to measure anything + bidi = new StyledTextBidi(gc, lineText, getBidiSegments(lineStartOffset, lineText)); + if (offsetInLine == 0) { + bidi.setKeyboardLanguage(offsetInLine); + } + else + if (offsetInLine >= lineLength) { + offsetInLine = Math.min(offsetInLine, lineLength - 1); + bidi.setKeyboardLanguage(offsetInLine); + } + else + if (lastCaretDirection == ST.COLUMN_NEXT) { + // continue with previous character type + bidi.setKeyboardLanguage(offsetInLine - 1); + } + else { + bidi.setKeyboardLanguage(offsetInLine); + } + gc.dispose(); } /** * Moves the Caret to the current caret offset. *

    - * + * * @param newCaretX the new x location of the caret. - * passed in for better performance when it has already been - * calculated outside this method. - * @param line index of the line the caret is on. Relative to - * the first line in the document. + * passed in for better performance when it has already been + * calculated outside this method. + * @param line index of the line the caret is on. Relative to + * the first line in the document. */ void setCaretLocation(int newCaretX, int line) { - if (isBidi()) { - setBidiCaretLocation(null, line); - } - else { - Caret caret = getCaret(); - - columnX = newCaretX; - if (caret != null) { - caret.setLocation( - newCaretX, - line * lineHeight - verticalScrollOffset + topMargin); - } - } + if (isBidi()) { + setBidiCaretLocation(null, line); + } + else { + Caret caret = getCaret(); + + columnX = newCaretX; + if (caret != null) { + caret.setLocation( + newCaretX, + line * lineHeight - verticalScrollOffset + topMargin); + } + } } /** * Moves the Caret to the current caret offset. */ void setCaretLocation() { - if (isBidi()) { - setBidiCaretLocation(null); - } - else { - Caret caret = getCaret(); - int caretLine = getCaretLine(); - int lineStartOffset = content.getOffsetAtLine(caretLine); - - columnX = getXAtOffset( - content.getLine(caretLine), caretLine, caretOffset - lineStartOffset); - if (caret != null) { - caret.setLocation( - columnX, - caretLine * lineHeight - verticalScrollOffset + topMargin); - } - } + if (isBidi()) { + setBidiCaretLocation(null); + } + else { + Caret caret = getCaret(); + int caretLine = getCaretLine(); + int lineStartOffset = content.getOffsetAtLine(caretLine); + + columnX = getXAtOffset( + content.getLine(caretLine), caretLine, caretOffset - lineStartOffset); + if (caret != null) { + caret.setLocation( + columnX, + caretLine * lineHeight - verticalScrollOffset + topMargin); + } + } } /** * Sets the caret offset. @@ -6928,40 +6998,40 @@ *

  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * * @exception IllegalArgumentException */ public void setCaretOffset(int offset) { - checkWidget(); - int length = getCharCount(); - - if (length > 0 && offset != caretOffset) { - if (offset < 0) { - caretOffset = 0; - } - else - if (offset > length) { - caretOffset = length; - } - else { - if (isLineDelimiter(offset)) { - // offset is inside a multi byte line delimiter. This is an - // illegal operation and an exception is thrown. Fixes 1GDKK3R - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - caretOffset = offset; - } - // clear the selection if the caret is moved. - // don't notify listeners about the selection change. - clearSelection(false); - } - // always update the caret location. fixes 1G8FODP - setCaretLocation(); - if (isBidi()) { - setBidiKeyboardLanguage(); - } -} + checkWidget(); + int length = getCharCount(); + + if (length > 0 && offset != caretOffset) { + if (offset < 0) { + caretOffset = 0; + } + else + if (offset > length) { + caretOffset = length; + } + else { + if (isLineDelimiter(offset)) { + // offset is inside a multi byte line delimiter. This is an + // illegal operation and an exception is thrown. Fixes 1GDKK3R + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + caretOffset = offset; + } + // clear the selection if the caret is moved. + // don't notify listeners about the selection change. + clearSelection(false); + } + // always update the caret location. fixes 1G8FODP + setCaretLocation(); + if (isBidi()) { + setBidiKeyboardLanguage(); + } +} /** * Copies the specified text range to the clipboard. The text will be placed * in the clipboard in plain text format and RTF format. @@ -6969,21 +7039,21 @@ * * @param start start index of the text * @param length length of text to place in clipboard - * + * * @exception SWTError, see Clipboard.setContents * @see org.eclipse.swt.dnd.Clipboard.setContents */ void setClipboardContent(int start, int length) throws SWTError { - RTFTransfer rtfTransfer = RTFTransfer.getInstance(); - TextTransfer plainTextTransfer = TextTransfer.getInstance(); - RTFWriter rtfWriter = new RTFWriter(start, length); - TextWriter plainTextWriter = new TextWriter(start, length); - String rtfText = getPlatformDelimitedText(rtfWriter); - String plainText = getPlatformDelimitedText(plainTextWriter); - - clipboard.setContents( - new String[]{rtfText, plainText}, - new Transfer[]{rtfTransfer, plainTextTransfer}); + RTFTransfer rtfTransfer = RTFTransfer.getInstance(); + TextTransfer plainTextTransfer = TextTransfer.getInstance(); + RTFWriter rtfWriter = new RTFWriter(start, length); + TextWriter plainTextWriter = new TextWriter(start, length); + String rtfText = getPlatformDelimitedText(rtfWriter); + String plainText = getPlatformDelimitedText(plainTextWriter); + + clipboard.setContents( + new String[]{rtfText, plainText}, + new Transfer[]{rtfTransfer, plainTextTransfer}); } /** * Sets the content implementation to use for text storage. @@ -6999,66 +7069,67 @@ * */ public void setContent(StyledTextContent newContent) { - checkWidget(); - if (newContent == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (content != null) { - content.removeTextChangeListener(textChangeListener); - } - logicalContent = newContent; - if (wordWrap) { - content = new WrappedContent(renderer, logicalContent); - } - else { - content = logicalContent; - } - content.addTextChangeListener(textChangeListener); - reset(); + checkWidget(); + if (newContent == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + if (content != null) { + content.removeTextChangeListener(textChangeListener); + } + logicalContent = newContent; + if (wordWrap) { + content = new WrappedContent(renderer, logicalContent); + } + else { + content = logicalContent; + } + content.addTextChangeListener(textChangeListener); + reset(); } /** * Sets the receiver's cursor to the cursor specified by the - * argument. Overridden to handle the null case since the + * argument. Overridden to handle the null case since the * StyledText widget uses an ibeam as its default cursor. * * @see org.eclipse.swt.widgets.Control#setCursor */ public void setCursor (Cursor cursor) { - if (cursor == null) { - super.setCursor(ibeamCursor); - } else { - super.setCursor(cursor); - } + if (cursor == null || cursor.equals(ibeamCursor)) { + customCursor = null; + } else { + customCursor = cursor; + } + internalSetCursor(); } -/** +/** * Sets whether the widget implements double click mouse behavior. *

    * * @param enable if true double clicking a word selects the word, if false - * double clicks have the same effect as regular mouse clicks. + * double clicks have the same effect as regular mouse clicks. * @exception SWTException */ public void setDoubleClickEnabled(boolean enable) { - checkWidget(); - doubleClickEnabled = enable; + checkWidget(); + doubleClickEnabled = enable; } /** * Sets whether the widget content can be edited. *

    * - * @param editable if true content can be edited, if false content can not be - * edited + * @param editable if true content can be edited, if false content can not be + * edited * @exception SWTException */ public void setEditable(boolean editable) { - checkWidget(); - this.editable = editable; + checkWidget(); + this.editable = editable; } /** * Sets a new font to render text with. @@ -7074,93 +7145,93 @@ * */ public void setFont(Font font) { - checkWidget(); - int oldLineHeight = lineHeight; - - super.setFont(font); - initializeRenderer(); - // keep the same top line visible. fixes 5815 - if (lineHeight != oldLineHeight) { - setVerticalScrollOffset(verticalScrollOffset * lineHeight / oldLineHeight, true); - claimBottomFreeSpace(); - } - calculateContentWidth(); - calculateScrollBars(); - if (isBidi()) { - caretDirection = SWT.NULL; - createCaretBitmaps(); - setBidiCaretDirection(); - } - else { - Caret caret = getCaret(); - if (caret != null) { - caret.setSize(caret.getSize().x, lineHeight); - } - } - // always set the caret location. Fixes 6685 - setCaretLocation(); - super.redraw(); + checkWidget(); + int oldLineHeight = lineHeight; + + super.setFont(font); + initializeRenderer(); + // keep the same top line visible. fixes 5815 + if (lineHeight != oldLineHeight) { + setVerticalScrollOffset(verticalScrollOffset * lineHeight / oldLineHeight, true); + claimBottomFreeSpace(); + } + calculateContentWidth(); + calculateScrollBars(); + if (isBidi()) { + caretDirection = SWT.NULL; + createCaretBitmaps(); + setBidiCaretDirection(); + } + else { + Caret caret = getCaret(); + if (caret != null) { + caret.setSize(caret.getSize().x, lineHeight); + } + } + // always set the caret location. Fixes 6685 + setCaretLocation(); + super.redraw(); } /** * @see org.eclipse.swt.widgets.Control#setForeground */ public void setForeground(Color color) { - checkWidget(); - super.setForeground(color); - foreground = color; - redraw(); + checkWidget(); + super.setForeground(color); + foreground = color; + redraw(); } -/** +/** * Sets the horizontal scroll offset relative to the start of the line. * Do nothing if there is no text set. *

    - * NOTE: The horizontal index is reset to 0 when new text is set in the + * NOTE: The horizontal index is reset to 0 when new text is set in the * widget. *

    * - * @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. + * @param offset horizontal scroll offset relative to the start + * of the line, measured in character increments starting at 0, if + * equal to 0 the content is not scrolled, if > 0 = the content is scrolled. * @exception SWTException */ public void setHorizontalIndex(int offset) { - checkWidget(); - int clientAreaWidth = getClientArea().width; - if (getCharCount() == 0) { - return; - } - if (offset < 0) { - offset = 0; - } - offset *= getHorizontalIncrement(); - // allow any value if client area width is unknown or 0. - // offset will be checked in resize handler. - // don't use isVisible since width is known even if widget - // is temporarily invisible - if (clientAreaWidth > 0) { - int width = lineCache.getWidth(); - // prevent scrolling if the content fits in the client area. - // align end of longest line with right border of client area - // if offset is out of range. - if (offset > width - clientAreaWidth) { - offset = Math.max(0, width - clientAreaWidth); - } - } - scrollHorizontalBar(offset - horizontalScrollOffset); + checkWidget(); + int clientAreaWidth = getClientArea().width; + if (getCharCount() == 0) { + return; + } + if (offset < 0) { + offset = 0; + } + offset *= getHorizontalIncrement(); + // allow any value if client area width is unknown or 0. + // offset will be checked in resize handler. + // don't use isVisible since width is known even if widget + // is temporarily invisible + if (clientAreaWidth > 0) { + int width = lineCache.getWidth(); + // prevent scrolling if the content fits in the client area. + // align end of longest line with right border of client area + // if offset is out of range. + if (offset > width - clientAreaWidth) { + offset = Math.max(0, width - clientAreaWidth); + } + } + scrollHorizontalBar(offset - horizontalScrollOffset); } -/** +/** * Sets the horizontal pixel offset relative to the start of the line. * Do nothing if there is no text set. *

    - * NOTE: The horizontal pixel offset is reset to 0 when new text + * NOTE: The horizontal pixel offset is reset to 0 when new text * is set in the widget. *

    * - * @param pixel horizontal pixel offset relative to the start - * of the line. + * @param pixel horizontal pixel offset relative to the start + * of the line. * @exception SWTException */ public void setLineBackground(int startLine, int lineCount, Color background) { - checkWidget(); - int partialBottomIndex = getPartialBottomIndex(); - - // this API can not be used if the client is providing the line background - if (userLineBackground) { - return; - } - if (startLine < 0 || startLine + lineCount > logicalContent.getLineCount()) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); - } - defaultLineStyler.setLineBackground(startLine, lineCount, background); - // do nothing if redraw range is completely invisible - if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { - return; - } - // only redraw visible lines - if (startLine < topIndex) { - lineCount -= topIndex - startLine; - startLine = topIndex; - } - if (startLine + lineCount - 1 > partialBottomIndex) { - lineCount = partialBottomIndex - startLine + 1; - } - startLine -= topIndex; - super.redraw( - leftMargin, startLine * lineHeight + topMargin, - getClientArea().width - leftMargin - rightMargin, lineCount * lineHeight, true); + checkWidget(); + int partialBottomIndex = getPartialBottomIndex(); + + // this API can not be used if the client is providing the line background + if (userLineBackground) { + return; + } + if (startLine < 0 || startLine + lineCount > logicalContent.getLineCount()) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + defaultLineStyler.setLineBackground(startLine, lineCount, background); + // do nothing if redraw range is completely invisible + if (startLine > partialBottomIndex || startLine + lineCount - 1 < topIndex) { + return; + } + // only redraw visible lines + if (startLine < topIndex) { + lineCount -= topIndex - startLine; + startLine = topIndex; + } + if (startLine + lineCount - 1 > partialBottomIndex) { + lineCount = partialBottomIndex - startLine + 1; + } + startLine -= topIndex; + super.redraw( + leftMargin, startLine * lineHeight + topMargin, + getClientArea().width - leftMargin - rightMargin, lineCount * lineHeight, true); } /** * Flips selection anchor based on word selection direction. */ void setMouseWordSelectionAnchor() { - if (mouseDoubleClick == false) { - return; - } - if (caretOffset < doubleClickSelection.x) { - selectionAnchor = doubleClickSelection.y; - } - else - if (caretOffset > doubleClickSelection.y) { - selectionAnchor = doubleClickSelection.x; - } + if (mouseDoubleClick == false) { + return; + } + if (caretOffset < doubleClickSelection.x) { + selectionAnchor = doubleClickSelection.y; + } + else + if (caretOffset > doubleClickSelection.y) { + selectionAnchor = doubleClickSelection.x; + } } /** - * Adjusts the maximum and the page size of the scroll bars to + * Adjusts the maximum and the page size of the scroll bars to * reflect content width/length changes. */ void setScrollBars() { - ScrollBar verticalBar = getVerticalBar(); - - if (verticalBar != null) { - Rectangle clientArea = getClientArea(); - final int INACTIVE = 1; - int maximum = content.getLineCount() * getVerticalIncrement(); - - // only set the real values if the scroll bar can be used - // (ie. because the thumb size is less than the scroll maximum) - // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 - if (clientArea.height < maximum) { - verticalBar.setValues( - verticalBar.getSelection(), - verticalBar.getMinimum(), - maximum, - clientArea.height, // thumb size - verticalBar.getIncrement(), - clientArea.height); // page size - } - else - if (verticalBar.getThumb() != INACTIVE || verticalBar.getMaximum() != INACTIVE) { - verticalBar.setValues( - verticalBar.getSelection(), - verticalBar.getMinimum(), - INACTIVE, - INACTIVE, - verticalBar.getIncrement(), - INACTIVE); - } - } - setHorizontalScrollBar(); + ScrollBar verticalBar = getVerticalBar(); + + if (verticalBar != null) { + Rectangle clientArea = getClientArea(); + final int INACTIVE = 1; + int maximum = content.getLineCount() * getVerticalIncrement(); + + // only set the real values if the scroll bar can be used + // (ie. because the thumb size is less than the scroll maximum) + // avoids flashing on Motif, fixes 1G7RE1J and 1G5SE92 + if (clientArea.height < maximum) { + verticalBar.setValues( + verticalBar.getSelection(), + verticalBar.getMinimum(), + maximum, + clientArea.height, // thumb size + verticalBar.getIncrement(), + clientArea.height); // page size + } + else + if (verticalBar.getThumb() != INACTIVE || verticalBar.getMaximum() != INACTIVE) { + verticalBar.setValues( + verticalBar.getSelection(), + verticalBar.getMinimum(), + INACTIVE, + INACTIVE, + verticalBar.getIncrement(), + INACTIVE); + } + } + setHorizontalScrollBar(); } -/** +/** * Sets the selection to the given position and scrolls it into view. Equivalent to setSelection(start,start). *

    * @@ -7351,24 +7422,24 @@ * * @exception IllegalArgumentException

    + * */ public void setSelection(int start) { - // checkWidget test done in setSelectionRange - setSelection(start, start); + // checkWidget test done in setSelectionRange + setSelection(start, start); } -/** +/** * Sets the selection and scrolls it into view. *

    * 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 *

    * * @param point x=selection start offset, y=selection end offset - * The caret will be placed at the selection start when x > y. + * The caret will be placed at the selection start when x > y. * @see #setSelection(int,int) * @exception SWTException */ public void setSelection(Point point) { - checkWidget(); - if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - setSelection(point.x, point.y); + checkWidget(); + if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + setSelection(point.x, point.y); } /** * Sets the receiver's selection background color to the color specified @@ -7394,7 +7465,7 @@ * @param color the new color (or null) * * @exception IllegalArgumentException * @exception SWTException */ public void setTabs(int tabs) { - checkWidget(); - tabLength = tabs; - renderer.setTabLength(tabLength); - if (caretOffset > 0) { - caretOffset = 0; - if (isBidi()) { - showBidiCaret(); - } - else { - showCaret(); - } - clearSelection(false); - } - // reset all line widths when the tab width changes - lineCache.reset(0, content.getLineCount(), false); - redraw(); -} -/** - * Sets the widget content. - * If the widget has the SWT.SINGLE style and "text" contains more than - * one line, only the first line is rendered but the text is stored - * unchanged. A subsequent call to getText will return the same text + checkWidget(); + tabLength = tabs; + renderer.setTabLength(tabLength); + if (caretOffset > 0) { + caretOffset = 0; + if (isBidi()) { + showBidiCaret(); + } + else { + showCaret(); + } + clearSelection(false); + } + // reset all line widths when the tab width changes + lineCache.reset(0, content.getLineCount(), false); + redraw(); +} +/** + * Sets the widget content. + * If the widget has the SWT.SINGLE style and "text" contains more than + * one line, only the first line is rendered but the text is stored + * unchanged. A subsequent call to getText will return the same text * that was set. *

    - * Note: Only a single line of text should be set when the SWT.SINGLE + * Note: Only a single line of text should be set when the SWT.SINGLE * style is used. *

    * - * @param text new widget content. Replaces existing content. Line styles - * that were set using StyledText API are discarded. The - * current selection is also discarded. + * @param text new widget content. Replaces existing content. Line styles + * that were set using StyledText API are discarded. The + * current selection is also discarded. * @exception SWTException */ public void setText(String text) { - checkWidget(); - Event event = new Event(); - - if (text == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - event.start = 0; - event.end = getCharCount(); - event.text = text; - event.doit = true; - notifyListeners(SWT.Verify, event); - if (event.doit) { - StyledTextEvent styledTextEvent = null; - - if (isListening(ExtendedModify)) { - styledTextEvent = new StyledTextEvent(logicalContent); - styledTextEvent.start = event.start; - styledTextEvent.end = event.start + event.text.length(); - styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); - } - content.setText(event.text); - notifyListeners(SWT.Modify, event); - if (styledTextEvent != null) { - notifyListeners(ExtendedModify, styledTextEvent); - } - } + checkWidget(); + Event event = new Event(); + + if (text == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } + event.start = 0; + event.end = getCharCount(); + event.text = text; + event.doit = true; + notifyListeners(SWT.Verify, event); + if (event.doit) { + StyledTextEvent styledTextEvent = null; + + if (isListening(ExtendedModify)) { + styledTextEvent = new StyledTextEvent(logicalContent); + styledTextEvent.start = event.start; + styledTextEvent.end = event.start + event.text.length(); + styledTextEvent.text = content.getTextRange(event.start, event.end - event.start); + } + content.setText(event.text); + notifyListeners(SWT.Modify, event); + if (styledTextEvent != null) { + notifyListeners(ExtendedModify, styledTextEvent); + } + } } /** * Sets the text limit. @@ -7774,50 +7889,50 @@ * */ public void setTextLimit(int limit) { - checkWidget(); - if (limit == 0) { - SWT.error(SWT.ERROR_CANNOT_BE_ZERO); - } - textLimit = limit; + checkWidget(); + if (limit == 0) { + SWT.error(SWT.ERROR_CANNOT_BE_ZERO); + } + textLimit = limit; } /** * Sets the top index. Do nothing if there is no text set. *

    - * 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. *

    * - * @param index new top index. Must be between 0 and - * getLineCount() - fully visible lines per page. If no lines are fully - * visible the maximum value is getLineCount() - 1. An out of range - * index will be adjusted accordingly. + * @param index new top index. Must be between 0 and + * getLineCount() - fully visible lines per page. If no lines are fully + * visible the maximum value is getLineCount() - 1. An out of range + * index will be adjusted accordingly. * @exception SWTException */ public void setTopIndex(int topIndex) { - checkWidget(); - int lineCount = logicalContent.getLineCount(); - int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); - - if (getCharCount() == 0) { - return; - } - if (topIndex < 0) { - topIndex = 0; - } - else - if (topIndex > lineCount - pageSize) { - topIndex = lineCount - pageSize; - } - if (wordWrap) { - int logicalLineOffset = logicalContent.getOffsetAtLine(topIndex); - topIndex = content.getLineAtOffset(logicalLineOffset); - } - setVerticalScrollOffset(topIndex * getVerticalIncrement(), true); + checkWidget(); + int lineCount = logicalContent.getLineCount(); + int pageSize = Math.max(1, Math.min(lineCount, getLineCountWhole())); + + if (getCharCount() == 0) { + return; + } + if (topIndex < 0) { + topIndex = 0; + } + else + if (topIndex > lineCount - pageSize) { + topIndex = lineCount - pageSize; + } + if (wordWrap) { + int logicalLineOffset = logicalContent.getOffsetAtLine(topIndex); + topIndex = content.getLineAtOffset(logicalLineOffset); + } + setVerticalScrollOffset(topIndex * getVerticalIncrement(), true); } /** * Sets the top pixel offset. Do nothing if there is no text set. @@ -7828,9 +7943,9 @@ * Note: The top pixel is reset to 0 when new text is set in the widget. *

    * - * @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. + * @param pixel new top pixel offset. Must be between 0 and + * (getLineCount() - visible lines per page) / getLineHeight()). An out + * of range offset will be adjusted accordingly. * @exception SWTException */ public void showSelection() { - checkWidget(); - boolean selectionFits; - int startOffset, startLine, startX, endOffset, endLine, endX, offsetInLine; - - // is selection from right-to-left? - boolean rightToLeft = caretOffset == selection.x; - - if (rightToLeft) { - startOffset = selection.y; - endOffset = selection.x; - } else { - startOffset = selection.x; - endOffset = selection.y; - } - - // calculate the logical start and end values for the selection - startLine = content.getLineAtOffset(startOffset); - offsetInLine = startOffset - content.getOffsetAtLine(startLine); - startX = getXAtOffset(content.getLine(startLine), startLine, offsetInLine); - endLine = content.getLineAtOffset(endOffset); - offsetInLine = endOffset - content.getOffsetAtLine(endLine); - endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); - - // can the selection be fully displayed within the widget's visible width? - int w = getClientArea().width; - if (rightToLeft) { - selectionFits = startX - endX <= w; - } else { - selectionFits = endX - startX <= w; - } - - if (selectionFits) { - // show as much of the selection as possible by first showing - // the start of the selection - showLocation(startX, startLine); - // endX value could change if showing startX caused a scroll to occur - endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); - showLocation(endX, endLine); - } else { - // just show the end of the selection since the selection start - // will not be visible - showLocation(endX, endLine); - } + checkWidget(); + boolean selectionFits; + int startOffset, startLine, startX, endOffset, endLine, endX, offsetInLine; + + // is selection from right-to-left? + boolean rightToLeft = caretOffset == selection.x; + + if (rightToLeft) { + startOffset = selection.y; + endOffset = selection.x; + } else { + startOffset = selection.x; + endOffset = selection.y; + } + + // calculate the logical start and end values for the selection + startLine = content.getLineAtOffset(startOffset); + offsetInLine = startOffset - content.getOffsetAtLine(startLine); + startX = getXAtOffset(content.getLine(startLine), startLine, offsetInLine); + endLine = content.getLineAtOffset(endOffset); + offsetInLine = endOffset - content.getOffsetAtLine(endLine); + endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); + + // can the selection be fully displayed within the widget's visible width? + int w = getClientArea().width; + if (rightToLeft) { + selectionFits = startX - endX <= w; + } else { + selectionFits = endX - startX <= w; + } + + if (selectionFits) { + // show as much of the selection as possible by first showing + // the start of the selection + showLocation(startX, startLine); + // endX value could change if showing startX caused a scroll to occur + endX = getXAtOffset(content.getLine(endLine), endLine, offsetInLine); + showLocation(endX, endLine); + } else { + // just show the end of the selection since the selection start + // will not be visible + showLocation(endX, endLine); + } } /** - * Updates the caret direction when a delete operation occured based on - * the type of the delete operation (next/previous character) and the + * Updates the caret direction when a delete operation occured based on + * the type of the delete operation (next/previous character) and the * caret location (at a direction boundary or inside a direction segment). * The intent is to place the caret at the visual location where a * character was deleted. *

    - * - * @param isBackspace true=the previous character was deleted, false=the - * character next to the caret location was deleted + * + * @param isBackspace true=the previous character was deleted, false=the + * character next to the caret location was deleted * @param isDirectionBoundary true=the caret is between a R2L and L2R segment, - * false=the caret is within a direction segment + * false=the caret is within a direction segment */ void updateBidiDirection(boolean isBackspace, boolean isDirectionBoundary) { - if (isDirectionBoundary) { - if (isBackspace) { - // Deleted previous character (backspace) at a direction boundary - // Go to direction segment of deleted character - lastCaretDirection = ST.COLUMN_NEXT; - } - else { - // Deleted next character. Go to direction segment of deleted character - lastCaretDirection = ST.COLUMN_PREVIOUS; - } - } - else { - if (isBackspace) { - // Delete previous character inside direction segment (i.e., not at a direction boundary) - lastCaretDirection = ST.COLUMN_PREVIOUS; - } - else { - // Deleted next character. - lastCaretDirection = ST.COLUMN_NEXT; - } - } + if (isDirectionBoundary) { + if (isBackspace) { + // Deleted previous character (backspace) at a direction boundary + // Go to direction segment of deleted character + lastCaretDirection = ST.COLUMN_NEXT; + } + else { + // Deleted next character. Go to direction segment of deleted character + lastCaretDirection = ST.COLUMN_PREVIOUS; + } + } + else { + if (isBackspace) { + // Delete previous character inside direction segment (i.e., not at a direction boundary) + lastCaretDirection = ST.COLUMN_PREVIOUS; + } + else { + // Deleted next character. + lastCaretDirection = ST.COLUMN_NEXT; + } + } } /** * Updates the selection and caret position depending on the text change. - * If the selection intersects with the replaced text, the selection is + * 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. *

    * @@ -8085,86 +8200,86 @@ * @param newLength length of new text */ void updateSelection(int startOffset, int replacedLength, int newLength) { - if (selection.y <= startOffset) { - // selection ends before text change - return; - } - if (selection.x < startOffset) { - // clear selection fragment before text change - internalRedrawRange(selection.x, startOffset - selection.x, true); - } - if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { - // clear selection fragment after text change. - // do this only when the selection is actually affected by the - // change. Selection is only affected if it intersects the change (1GDY217). - int netNewLength = newLength - replacedLength; - int redrawStart = startOffset + newLength; - internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart, true); - } - if (selection.y > startOffset && selection.x < startOffset + replacedLength) { - // selection intersects replaced text. set caret behind text change - internalSetSelection(startOffset + newLength, 0, true); - // always update the caret location. fixes 1G8FODP - setCaretLocation(); - } - else { - // move selection to keep same text selected - internalSetSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); - // always update the caret location. fixes 1G8FODP - setCaretLocation(); - } + if (selection.y <= startOffset) { + // selection ends before text change + return; + } + if (selection.x < startOffset) { + // clear selection fragment before text change + internalRedrawRange(selection.x, startOffset - selection.x, true); + } + if (selection.y > startOffset + replacedLength && selection.x < startOffset + replacedLength) { + // clear selection fragment after text change. + // do this only when the selection is actually affected by the + // change. Selection is only affected if it intersects the change (1GDY217). + int netNewLength = newLength - replacedLength; + int redrawStart = startOffset + newLength; + internalRedrawRange(redrawStart, selection.y + netNewLength - redrawStart, true); + } + if (selection.y > startOffset && selection.x < startOffset + replacedLength) { + // selection intersects replaced text. set caret behind text change + internalSetSelection(startOffset + newLength, 0, true); + // always update the caret location. fixes 1G8FODP + setCaretLocation(); + } + else { + // move selection to keep same text selected + internalSetSelection(selection.x + newLength - replacedLength, selection.y - selection.x, true); + // always update the caret location. fixes 1G8FODP + setCaretLocation(); + } } /** * Rewraps all lines *

    - * - * @param oldClientAreaWidth client area width before resize - * occurred + * + * @param oldClientAreaWidth client area width before resize + * occurred */ void wordWrapResize(int oldClientAreaWidth) { - WrappedContent wrappedContent = (WrappedContent) content; - int newTopIndex; + WrappedContent wrappedContent = (WrappedContent) content; + int newTopIndex; - // all lines are wrapped and no rewrap required if widget has already - // been visible, client area is now wider and visual (wrapped) line - // count equals logical line count. - if (oldClientAreaWidth != 0 && clientAreaWidth > oldClientAreaWidth && - wrappedContent.getLineCount() == logicalContent.getLineCount()) { - return; - } + // all lines are wrapped and no rewrap required if widget has already + // been visible, client area is now wider and visual (wrapped) line + // count equals logical line count. + if (oldClientAreaWidth != 0 && clientAreaWidth > oldClientAreaWidth && + wrappedContent.getLineCount() == logicalContent.getLineCount()) { + return; + } wrappedContent.wrapLines(); - + // adjust the top index so that top line remains the same - newTopIndex = content.getLineAtOffset(topOffset); - // topOffset is the beginning of the top line. therefore it - // needs to be adjusted because in a wrapped line this is also - // the end of the preceeding line. - if (newTopIndex < content.getLineCount() - 1 && - topOffset == content.getOffsetAtLine(newTopIndex + 1)) { - newTopIndex++; - } + newTopIndex = content.getLineAtOffset(topOffset); + // topOffset is the beginning of the top line. therefore it + // needs to be adjusted because in a wrapped line this is also + // the end of the preceeding line. + if (newTopIndex < content.getLineCount() - 1 && + topOffset == content.getOffsetAtLine(newTopIndex + 1)) { + newTopIndex++; + } if (newTopIndex != topIndex) { - ScrollBar verticalBar = getVerticalBar(); - // adjust index and pixel offset manually instead of calling - // setVerticalScrollOffset because the widget does not actually need - // to be scrolled. causes flash otherwise. - verticalScrollOffset += (newTopIndex - topIndex) * getVerticalIncrement(); - // verticalScrollOffset may become negative if first line was - // partially visible and second line was top line. prevent this from - // happening to fix 8503. - if (verticalScrollOffset < 0) { - verticalScrollOffset = 0; - } - topIndex = newTopIndex; - topOffset = content.getOffsetAtLine(topIndex); - if (verticalBar != null) { - verticalBar.setSelection(verticalScrollOffset); - } + ScrollBar verticalBar = getVerticalBar(); + // adjust index and pixel offset manually instead of calling + // setVerticalScrollOffset because the widget does not actually need + // to be scrolled. causes flash otherwise. + verticalScrollOffset += (newTopIndex - topIndex) * getVerticalIncrement(); + // verticalScrollOffset may become negative if first line was + // partially visible and second line was top line. prevent this from + // happening to fix 8503. + if (verticalScrollOffset < 0) { + verticalScrollOffset = 0; + } + topIndex = newTopIndex; + topOffset = content.getOffsetAtLine(topIndex); + if (verticalBar != null) { + verticalBar.setSelection(verticalScrollOffset); + } } - // caret may be on a different line after a rewrap. - // call setCaretLocation after fixing vertical scroll offset. - setCaretLocation(); - // word wrap may have changed on one of the visible lines + // caret may be on a different line after a rewrap. + // call setCaretLocation after fixing vertical scroll offset. + setCaretLocation(); + // word wrap may have changed on one of the visible lines super.redraw(); } }