Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CCombo.java13
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java2
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java9
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/DisplayRenderer.java3
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PopupList.java18
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/SashForm.java2
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ScrolledComposite.java2
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java579
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java149
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableCursor.java17
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableTree.java12
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ViewForm.java2
12 files changed, 473 insertions, 335 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CCombo.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CCombo.java
index 18fc637809..50b0a55f86 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CCombo.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CCombo.java
@@ -84,6 +84,7 @@ public CCombo (Composite parent, int style) {
int listStyle = SWT.SINGLE | SWT.V_SCROLL;
if ((style & SWT.FLAT) != 0) listStyle |= SWT.FLAT;
+ if ((style & SWT.RIGHT_TO_LEFT) != 0) listStyle |= SWT.RIGHT_TO_LEFT;
list = new List (popup, listStyle);
int arrowStyle = SWT.ARROW | SWT.DOWN;
@@ -134,7 +135,7 @@ public CCombo (Composite parent, int style) {
initAccessible();
}
static int checkStyle (int style) {
- int mask = SWT.BORDER | SWT.READ_ONLY | SWT.FLAT;
+ int mask = SWT.BORDER | SWT.READ_ONLY | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
/**
@@ -341,15 +342,17 @@ void dropDown (boolean drop) {
text.setFocus();
return;
}
+
int index = list.getSelectionIndex ();
if (index != -1) list.setTopIndex (index);
Rectangle listRect = list.getBounds ();
- Point point = getParent().toDisplay (getLocation ());
- Point comboSize = getSize();
+ Display display = getDisplay ();
+ Rectangle rect = display.map (getParent (), null, getBounds ());
+ Point comboSize = getSize ();
int width = Math.max (comboSize.x, listRect.width + 2);
- popup.setBounds (point.x, point.y + comboSize.y, width, listRect.height + 2);
+ popup.setBounds (rect.x, rect.y + comboSize.y, width, listRect.height + 2);
popup.setVisible (true);
- list.setFocus();
+ list.setFocus ();
}
public Control [] getChildren () {
checkWidget();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java
index 9c8cfff482..7b0fdea9b0 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CLabel.java
@@ -120,7 +120,7 @@ public CLabel(Composite parent, int style) {
* Check the style bits to ensure that no invalid styles are applied.
*/
private static int checkStyle (int style) {
- int mask = SWT.SHADOW_IN | SWT.SHADOW_OUT | SWT.SHADOW_NONE;
+ int mask = SWT.SHADOW_IN | SWT.SHADOW_OUT | SWT.SHADOW_NONE | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
style = style & mask;
style |= SWT.NO_FOCUS;
if ((style & (SWT.CENTER | SWT.RIGHT)) == 0) style |= SWT.LEFT;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
index 7ccc95452f..4fcea2fdbe 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java
@@ -237,7 +237,7 @@ public CTabFolder(Composite parent, int style) {
}
private static int checkStyle (int style) {
- int mask = SWT.TOP | SWT.BOTTOM | SWT.FLAT;
+ int mask = SWT.TOP | SWT.BOTTOM | SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
style = style & mask;
// TOP and BOTTOM are mutually exlusive.
// TOP is the default
@@ -509,12 +509,13 @@ void destroyItem (CTabItem item) {
redrawTabArea(-1);
}
private void onKeyDown(Event e) {
- if (e.keyCode == SWT.ARROW_LEFT) {
+ if (e.keyCode != SWT.ARROW_LEFT && e.keyCode != SWT.ARROW_RIGHT) return;
+ int leadKey = (getStyle() & SWT.MIRRORED) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+ if (e.keyCode == leadKey) {
if (selectedIndex > 0) {
setSelection(selectedIndex - 1, true);
}
- }
- if (e.keyCode == SWT.ARROW_RIGHT) {
+ } else {
if (selectedIndex < items.length - 1) {
setSelection(selectedIndex + 1, true);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/DisplayRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/DisplayRenderer.java
index 424413010b..38aeda8c10 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/DisplayRenderer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/DisplayRenderer.java
@@ -76,6 +76,7 @@ protected void drawLineSelectionBackground(String line, int lineOffset, StyleRan
int lineEndSpaceWidth = getLineEndSpaceWidth();
int lineHeight = getLineHeight();
boolean wordWrap = parent.internalGetWordWrap();
+ boolean isRightOriented = (parent.getStyle() & SWT.MIRRORED) != 0;
if (selectionEnd == selectionStart || selectionEnd < 0 || selectionStart > lineLength) {
return;
@@ -129,7 +130,7 @@ protected void drawLineSelectionBackground(String line, int lineOffset, StyleRan
// if the selection extends past this line, render an additional
// whitespace background at the end of the line to represent the
// selected line break
- if (bidi != null && selectionEnd > 0 && bidi.isRightToLeft(selectionEnd - 1)) {
+ if (bidi != null && selectionEnd > 0 && (bidi.isRightToLeft(selectionEnd - 1) || (isRightOriented && bidi.isRightToLeft(selectionEnd - 1) == false))) {
int lineEndX = bidi.getTextWidth();
gc.fillRectangle(lineEndX - horizontalScrollOffset + leftMargin, paintY, lineEndSpaceWidth, lineHeight);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PopupList.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PopupList.java
index e624ca2d71..81e39cd9d2 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PopupList.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/PopupList.java
@@ -31,8 +31,18 @@ public class PopupList {
* Creates a PopupList above the specified shell.
*/
public PopupList(Shell parent) {
-
- shell = new Shell(parent, 0);
+ this (parent, 0);
+}
+/**
+* Creates a PopupList above the specified shell.
+*
+* @param parent a widget which will be the parent of the new instance (cannot be null)
+* @param style the style of widget to construct
+*
+* @since 2.1.2
+*/
+public PopupList(Shell parent, int style) {
+ shell = new Shell(parent, checkStyle(style));
list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);
@@ -70,6 +80,10 @@ public PopupList(Shell parent) {
});
}
+private static int checkStyle (int style) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ return style & mask;
+}
/**
* Gets the widget font.
* <p>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/SashForm.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/SashForm.java
index a017acac2e..3aa8f773ca 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/SashForm.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/SashForm.java
@@ -85,7 +85,7 @@ public SashForm(Composite parent, int style) {
};
}
private static int checkStyle (int style) {
- int mask = SWT.BORDER;
+ int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
public Point computeSize (int wHint, int hHint, boolean changed) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ScrolledComposite.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ScrolledComposite.java
index 9f3cef8c20..70e9d401f5 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ScrolledComposite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ScrolledComposite.java
@@ -173,7 +173,7 @@ public ScrolledComposite(Composite parent, int style) {
}
private static int checkStyle (int style) {
- int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
+ int mask = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
index 80353beea8..03513c4915 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
@@ -140,6 +140,7 @@ public class StyledText extends Canvas {
int lastTextChangeReplaceLineCount; // text changed handler
int lastTextChangeReplaceCharCount;
boolean isBidi;
+ boolean isMirrored;
boolean bidiColoring = false; // apply the BIDI algorithm on text segments of the same color
Image leftCaretBitmap = null;
Image rightCaretBitmap = null;
@@ -1590,7 +1591,8 @@ public StyledText(Composite parent, int style) {
super.setForeground(getForeground());
super.setBackground(getBackground());
Display display = getDisplay();
- isBidi = StyledTextBidi.isBidiPlatform();
+ isMirrored = (getStyle() & SWT.MIRRORED) != 0;
+ isBidi = StyledTextBidi.isBidiPlatform() || isMirrored;
if ((style & SWT.READ_ONLY) != 0) {
setEditable(false);
}
@@ -1612,6 +1614,9 @@ public StyledText(Composite parent, int style) {
}
else {
createCaretBitmaps();
+ if (isMirrored) {
+ BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI);
+ }
new Caret(this, SWT.NULL);
setBidiCaretDirection();
Runnable runnable = new Runnable() {
@@ -2233,32 +2238,49 @@ void createKeyBindings() {
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);
+ if (isMirrored()) {
+ setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_NEXT);
+ setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_PREVIOUS);
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_NEXT);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_PREVIOUS);
+ }
+ else {
+ setKeyBinding(SWT.ARROW_LEFT, ST.COLUMN_PREVIOUS);
+ setKeyBinding(SWT.ARROW_RIGHT, ST.COLUMN_NEXT);
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1, ST.WORD_PREVIOUS);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1, ST.WORD_NEXT);
+ }
+
// 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);
-
+ if (isMirrored()) {
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
+ }
+ else {
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD2, ST.SELECT_COLUMN_PREVIOUS);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD2, ST.SELECT_COLUMN_NEXT);
+ setKeyBinding(SWT.ARROW_LEFT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_PREVIOUS);
+ setKeyBinding(SWT.ARROW_RIGHT | SWT.MOD1 | SWT.MOD2, ST.SELECT_WORD_NEXT);
+ }
+
// Modification
// Cut, Copy, Paste
setKeyBinding('X' | SWT.MOD1, ST.CUT);
@@ -2285,6 +2307,7 @@ void createKeyBindings() {
*/
void createCaretBitmaps() {
int caretWidth = BIDI_CARET_WIDTH;
+ int gcStyle = isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
Display display = getDisplay();
if (caretPalette == null) {
@@ -2295,7 +2318,9 @@ void createCaretBitmaps() {
}
ImageData imageData = new ImageData(caretWidth, lineHeight, 1, caretPalette);
leftCaretBitmap = new Image(display, imageData);
- GC gc = new GC (leftCaretBitmap);
+ // mirror the caret gc because when the bitmap is rendered on the screen it will be
+ // mirrored since the GC for the canvas is mirrored
+ GC gc = new GC (leftCaretBitmap, gcStyle);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(0,0,0,lineHeight);
gc.drawLine(0,0,caretWidth-1,0);
@@ -2306,7 +2331,9 @@ void createCaretBitmaps() {
rightCaretBitmap.dispose();
}
rightCaretBitmap = new Image(display, imageData);
- gc = new GC (rightCaretBitmap);
+ // mirror the caret gc because when the bitmap is rendered on the screen it will be
+ // mirrored since the GC for the canvas is mirrored
+ gc = new GC (rightCaretBitmap, gcStyle);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(caretWidth-1,0,caretWidth-1,lineHeight);
gc.drawLine(0,0,caretWidth-1,0);
@@ -2363,11 +2390,11 @@ void doAutoScroll(Event event) {
}
else
if (event.x < leftMargin && wordWrap == false) {
- doAutoScroll(SWT.LEFT);
+ doAutoScroll(ST.COLUMN_PREVIOUS);
}
else
if (event.x > area.width - leftMargin - rightMargin && wordWrap == false) {
- doAutoScroll(SWT.RIGHT);
+ doAutoScroll(ST.COLUMN_NEXT);
}
else {
endAutoScroll();
@@ -2377,7 +2404,7 @@ void doAutoScroll(Event event) {
* Initiates autoscrolling.
* <p>
*
- * @param direction SWT.UP, SWT.DOWN, SWT.RIGHT, SWT.LEFT
+ * @param direction SWT.UP, SWT.DOWN, SWT.COLUMN_NEXT, SWT.COLUMN_PREVIOUS
*/
void doAutoScroll(int direction) {
Runnable timer = null;
@@ -2409,24 +2436,24 @@ void doAutoScroll(int direction) {
}
}
};
- } else if (direction == SWT.RIGHT) {
+ } else if (direction == ST.COLUMN_NEXT) {
timer = new Runnable() {
public void run() {
- if (autoScrollDirection == SWT.RIGHT) {
- doColumnRight();
+ if (autoScrollDirection == ST.COLUMN_NEXT) {
+ doVisualNext();
setMouseWordSelectionAnchor();
- doSelection(SWT.RIGHT);
+ doMouseSelection();
display.timerExec(TIMER_INTERVAL, this);
}
}
};
- } else if (direction == SWT.LEFT) {
+ } else if (direction == ST.COLUMN_PREVIOUS) {
timer = new Runnable() {
public void run() {
- if (autoScrollDirection == SWT.LEFT) {
- doColumnLeft();
+ if (autoScrollDirection == ST.COLUMN_PREVIOUS) {
+ doVisualPrevious();
setMouseWordSelectionAnchor();
- doSelection(SWT.LEFT);
+ doMouseSelection();
display.timerExec(TIMER_INTERVAL, this);
}
}
@@ -2467,208 +2494,6 @@ void doBackspace() {
}
}
/**
- * Moves the caret one character to the left. Do not go to the previous line.
- * When in a bidi locale and at a R2L character the caret is moved to the
- * beginning of the R2L segment (visually right) and then one character to the
- * left (visually left because it's now in a L2R segment).
- */
-void 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();
- }
-}
-/**
- * Moves the caret one character to the right. Do not go to the next line.
- * When in a bidi locale and at a R2L character the caret is moved to the
- * end of the R2L segment (visually left) and then one character to the
- * right (visually right because it's now in a L2R segment).
- */
-void 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();
- }
-}
-/**
* 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
@@ -2860,7 +2685,9 @@ int doLineDown() {
if (caretLine < content.getLineCount() - 1) {
caretLine++;
if (isBidi()) {
- caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ caretOffset = offsetDirection[0];
+ lastCaretDirection = offsetDirection[1];
}
else {
caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
@@ -2907,7 +2734,9 @@ int doLineUp() {
if (caretLine > 0) {
caretLine--;
if (isBidi()) {
- caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ caretOffset = offsetDirection[0];
+ lastCaretDirection = offsetDirection[1];
}
else {
caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
@@ -2929,6 +2758,7 @@ void doMouseLocationChange(int x, int y, boolean select) {
int lineCount = content.getLineCount();
int newCaretOffset;
int newCaretLine;
+ int newCaretDirection = lastCaretDirection;
if (line > lineCount - 1) {
line = lineCount - 1;
@@ -2939,7 +2769,9 @@ void doMouseLocationChange(int x, int y, boolean select) {
return;
}
if (isBidi()) {
- newCaretOffset = getBidiOffsetAtMouseLocation(x, line);
+ int offsetDirection[] = getBidiOffsetAtMouseLocation(x, line);
+ newCaretOffset = offsetDirection[0];
+ newCaretDirection = offsetDirection[1];
}
else {
newCaretOffset = getOffsetAtMouseLocation(x, line);
@@ -2953,8 +2785,9 @@ void doMouseLocationChange(int x, int y, boolean select) {
// 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))) {
+ (x >= 0 && x < getClientArea().width || newCaretLine != content.getLineAtOffset(caretOffset))) {
if (newCaretOffset != caretOffset) {
+ lastCaretDirection = newCaretDirection;
caretOffset = newCaretOffset;
if (select) {
doMouseSelection();
@@ -2963,6 +2796,7 @@ void doMouseLocationChange(int x, int y, boolean select) {
}
}
if (select == false) {
+ lastCaretDirection = newCaretDirection;
clearSelection(true);
}
}
@@ -2973,10 +2807,10 @@ void doMouseSelection() {
if (caretOffset <= selection.x ||
(caretOffset > selection.x &&
caretOffset < selection.y && selectionAnchor == selection.x)) {
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
}
else {
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
}
}
/**
@@ -3053,13 +2887,15 @@ void doPageDown(boolean select) {
scrollLines = Math.max(1, scrollLines);
caretLine += scrollLines;
if (isBidi()) {
- caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ caretOffset = offsetDirection[0];
+ lastCaretDirection = offsetDirection[1];
}
else {
caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
}
if (select) {
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
}
// scroll one page down or to the bottom
scrollOffset = verticalScrollOffset + scrollLines * getVerticalIncrement();
@@ -3125,7 +2961,9 @@ void doPageUp() {
caretLine -= scrollLines;
if (isBidi()) {
- caretOffset = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ int offsetDirection[] = getBidiOffsetAtMouseLocation(columnX, caretLine);
+ caretOffset = offsetDirection[0];
+ lastCaretDirection = offsetDirection[1];
}
else {
caretOffset = getOffsetAtMouseLocation(columnX, caretLine);
@@ -3152,7 +2990,7 @@ void doSelection(int direction) {
if (selectionAnchor == -1) {
selectionAnchor = selection.x;
}
- if (direction == SWT.LEFT) {
+ if (direction == ST.COLUMN_PREVIOUS) {
if (caretOffset < selection.x) {
// grow selection
redrawEnd = selection.x;
@@ -3281,7 +3119,7 @@ void doSelectionLineDown() {
setMouseWordSelectionAnchor();
// select first and then scroll to reduce flash when key
// repeat scrolls lots of lines
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
// explicitly go to the calculated caret line. may be different
// from content.getLineAtOffset(caretOffset) when in word wrap mode
showCaret(caretLine);
@@ -3316,7 +3154,7 @@ void doSelectionLineUp() {
// explicitly go to the calculated caret line. may be different
// from content.getLineAtOffset(caretOffset) when in word wrap mode
showCaret(caretLine);
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
// save the original horizontal caret position
columnX = oldColumnX;
}
@@ -3401,6 +3239,159 @@ void doSelectionWordPrevious() {
showCaret(caretLine);
}
/**
+ * Moves the caret one character to the left. Do not go to the previous line.
+ * When in a bidi locale and at a R2L character the caret is moved to the
+ * beginning of the R2L segment (visually right) and then one character to the
+ * left (visually left because it's now in a L2R segment).
+ */
+void doVisualPrevious() {
+ int line = content.getLineAtOffset(caretOffset);
+ int lineOffset = content.getOffsetAtLine(line);
+ int offsetInLine = caretOffset - lineOffset;
+
+ if (isBidi()) {
+ // check if caret location is at the visual beginning of the line
+ if (columnX <= XINSET && horizontalScrollOffset == 0) {
+ return;
+ }
+ String lineText = content.getLine(line);
+ int lineLength = lineText.length();
+ GC gc = getGC();
+ StyledTextBidi bidi = getStyledTextBidi(lineText, lineOffset, gc);
+ int visualOffset = -1;
+
+ if (offsetInLine == lineLength) {
+ //logical end of line may not be visual end, setup visualOffset to process as usual
+ visualOffset = bidi.getVisualOffset(offsetInLine - 1);
+ }
+ else
+ if (offsetInLine < lineLength) {
+ visualOffset = bidi.getVisualOffset(offsetInLine);
+ }
+ if (visualOffset != -1) {
+ if (visualOffset > 0) {
+ visualOffset--;
+ offsetInLine = bidi.getLogicalOffset(visualOffset);
+ }
+ else
+ if (visualOffset == 0) {
+ boolean isRightOriented = isMirrored();
+
+ //move to visual line end (i.e., behind L2R character/in front of R2L character at visual 0)
+ if ((isRightOriented && bidi.isRightToLeft(offsetInLine) == false) ||
+ (isRightOriented == false && bidi.isRightToLeft(offsetInLine))) {
+ offsetInLine++;
+ }
+
+ if (offsetInLine > 0 && offsetInLine < lineLength) {
+ if (isRightOriented) {
+ boolean rightToLeftStart = bidi.isRightToLeft(offsetInLine) && bidi.isRightToLeft(offsetInLine - 1) == false;
+ if (rightToLeftStart) {
+ //moving from LtoR segment to RtoL segment
+ lastCaretDirection = ST.COLUMN_NEXT;
+ }
+ }
+ else {
+ boolean leftToRightStart = bidi.isRightToLeft(offsetInLine) == false && bidi.isRightToLeft(offsetInLine - 1);
+ if (bidi.isLatinNumber(offsetInLine) && bidi.isRightToLeftInput(offsetInLine - 1)) {
+ //moving from LtoR segment to latin number
+ lastCaretDirection = ST.COLUMN_PREVIOUS;
+ }
+ else
+ if (leftToRightStart) {
+ //moving from RtoL segment to LtoR segment
+ lastCaretDirection = ST.COLUMN_NEXT;
+ }
+ }
+ }
+ }
+ caretOffset = lineOffset + offsetInLine;
+ showCaret();
+ }
+ if (bidi.getTextPosition(offsetInLine, ST.COLUMN_NEXT) == XINSET) {
+ //scroll to origin if caret is at origin
+ 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
+ * right (visually right because it's now in a L2R segment).
+ */
+void doVisualNext() {
+ 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);
+ // Fixes bug 39032
+ int lineEndPixel = Math.max(bidi.getTextWidth(), XINSET);
+
+ // check if caret location is at the visual end of the line (can't use
+ // caret location here since it's location is dependent on current keyboard
+ // language direction)
+ if (bidi.getTextPosition(offsetInLine, lastCaretDirection) == lineEndPixel) {
+ gc.dispose();
+ return;
+ }
+ int visualOffset = -1;
+ if (offsetInLine == lineLength) {
+ //logical end of line may not be visual end, setup visualOffset to process as usual
+ visualOffset = bidi.getVisualOffset(offsetInLine - 1);
+ }
+ else
+ if (offsetInLine < lineLength) {
+ visualOffset = bidi.getVisualOffset(offsetInLine);
+ }
+ if (visualOffset != -1) {
+ visualOffset++;
+ offsetInLine = bidi.getLogicalOffset(visualOffset);
+ if (offsetInLine > 0 && offsetInLine < lineLength) {
+ boolean isRightOriented = isMirrored();
+ if (isRightOriented) {
+ boolean leftToRightStart = bidi.isRightToLeft(offsetInLine) == false && bidi.isRightToLeft(offsetInLine - 1);
+ if (leftToRightStart) {
+ //moving from RtoL segment to LtoR segment
+ lastCaretDirection = ST.COLUMN_PREVIOUS;
+ }
+ }
+ else {
+ boolean rightToLeftStart = bidi.isRightToLeft(offsetInLine) && bidi.isRightToLeft(offsetInLine - 1) == false;
+ if (bidi.isRightToLeftInput(offsetInLine) && bidi.isLatinNumber(offsetInLine - 1)) {
+ //moving from latin number to RtoL segment
+ lastCaretDirection = ST.COLUMN_NEXT;
+ }
+ else
+ if (rightToLeftStart) {
+ //moving from LtoR segment to RtoL segment
+ lastCaretDirection = ST.COLUMN_PREVIOUS;
+ }
+ }
+ }
+ caretOffset = lineOffset + offsetInLine;
+ showCaret();
+ }
+ gc.dispose();
+ }
+ else
+ if (offsetInLine < lineLength) {
+ caretOffset++;
+ showCaret();
+ }
+}
+/**
* Moves the caret to the end of the next word.
* If a selection exists, move the caret to the end of the selection
* and remove the selection.
@@ -3511,30 +3502,28 @@ public boolean getBidiColoring() {
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
- * depending on whether the mouse location is in a R2L or L2R segment.
+ * Returns the offset and caret direction at the specified x location
+ * in the specified line.
+ * The returned caret direction needs to be set in order to place the
+ * caret correctly based on whether the mouse location is in a R2L
+ * or L2R segment.
* <p>
*
* @param x x location of the mouse location
* @param line line the mouse location is in
- * @return the offset at the specified x location in the specified line,
- * relative to the beginning of the document
+ * @return int array, first element is the offset at the specified x
+ * location in the specified line, relative to the beginning of the
+ * document. second element is the caret direction.
*/
-int getBidiOffsetAtMouseLocation(int x, int line) {
+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();
+ int[] values = bidi.getCaretOffsetAndDirectionAtX(x + horizontalScrollOffset - leftMargin);
- return lineOffset + offsetInLine;
+ gc.dispose();
+ return new int[] {lineOffset + values[0], values[1]};
}
/**
* Returns the x position of the character at the specified offset
@@ -5561,50 +5550,50 @@ public void invokeAction(int action) {
break;
case ST.SELECT_LINE_START:
doLineStart();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_LINE_END:
doLineEnd();
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
break;
case ST.SELECT_COLUMN_PREVIOUS:
doSelectionCursorPrevious();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_COLUMN_NEXT:
doSelectionCursorNext();
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
break;
case ST.SELECT_PAGE_UP:
doSelectionPageUp();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_PAGE_DOWN:
doSelectionPageDown();
break;
case ST.SELECT_WORD_PREVIOUS:
doSelectionWordPrevious();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_WORD_NEXT:
doSelectionWordNext();
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
break;
case ST.SELECT_TEXT_START:
doContentStart();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_TEXT_END:
doContentEnd();
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
break;
case ST.SELECT_WINDOW_START:
doPageStart();
- doSelection(SWT.LEFT);
+ doSelection(ST.COLUMN_PREVIOUS);
break;
case ST.SELECT_WINDOW_END:
doPageEnd();
- doSelection(SWT.RIGHT);
+ doSelection(ST.COLUMN_NEXT);
break;
// Modification
case ST.CUT:
@@ -5658,6 +5647,16 @@ boolean isLineDelimiter(int offset) {
return offsetInLine > content.getLine(line).length();
}
/**
+ * Returns whether the widget is mirrored (right oriented/right to left
+ * writing order).
+ *
+ * @return isMirrored true=the widget is right oriented, false=the widget
+ * is left oriented
+ */
+boolean isMirrored() {
+ return isMirrored;
+}
+/**
* Returns whether or not the given lines are visible.
* <p>
*
@@ -5894,6 +5893,7 @@ void performPaint(GC gc,int startLine,int startY, int renderHeight) {
Color foreground = getForeground();
int lineCount = content.getLineCount();
int paintY = 0;
+ int gcStyle = isMirrored() ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
if (isSingleLine()) {
lineCount = 1;
@@ -5902,7 +5902,7 @@ void performPaint(GC gc,int startLine,int startY, int renderHeight) {
}
}
Image lineBuffer = new Image(getDisplay(), clientArea.width, renderHeight);
- GC lineGC = new GC(lineBuffer);
+ GC lineGC = new GC(lineBuffer, gcStyle);
lineGC.setFont(getFont());
renderer.setCurrentFontStyle(SWT.NORMAL);
@@ -6056,7 +6056,12 @@ public void redraw() {
* @see Control#update
*/
public void redraw(int x, int y, int width, int height, boolean all) {
- super.redraw(x, y, width, height, all);
+ if (isBidi()) {
+ // workaround for bug 4776
+ super.redraw(x, y, width + 1, height, all);
+ } else {
+ super.redraw(x, y, width, height, all);
+ }
if (height > 0) {
int lineCount = content.getLineCount();
int startLine = (getTopPixel() + y) / lineHeight;
@@ -6092,9 +6097,9 @@ void redrawBidiLines(int firstLine, int offsetInFirstLine, int lastLine, int end
String line = content.getLine(firstLine);
GC gc = getGC();
StyledTextBidi bidi = getStyledTextBidi(line, firstLineOffset, gc);
-
+
bidi.redrawRange(
- this, offsetInFirstLine,
+ this, offsetInFirstLine,
Math.min(line.length(), endOffset) - offsetInFirstLine,
leftMargin - horizontalScrollOffset, redrawY + topMargin, lineHeight);
// redraw line break marker (either space or full client area width)
@@ -6903,6 +6908,7 @@ void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) {
int lineStartOffset = content.getOffsetAtLine(caretLine);
int offsetInLine = caretOffset - lineStartOffset;
GC gc = null;
+ boolean isRightOriented = isMirrored();
if (bidi == null) {
gc = getGC();
@@ -6913,7 +6919,10 @@ void setBidiCaretLocation(StyledTextBidi bidi, int caretLine) {
} else {
columnX = bidi.getTextPosition(offsetInLine, lastCaretDirection) + leftMargin - horizontalScrollOffset;
}
- if (StyledTextBidi.getKeyboardLanguageDirection() == SWT.RIGHT) {
+ // take the width of the caret into account
+ int keyboardDirection = StyledTextBidi.getKeyboardLanguageDirection();
+ if ((keyboardDirection == SWT.RIGHT && isRightOriented == false) ||
+ (keyboardDirection == SWT.LEFT && isRightOriented)){
columnX -= (getCaretWidth() - 1);
}
if (caret != null) {
@@ -7407,6 +7416,42 @@ void setMouseWordSelectionAnchor() {
}
}
/**
+ * Sets the widget orientation (writing order). Text will be right aligned
+ * for right to left writing order.
+ * <p>
+ *
+ * @param newOrientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ */
+void setOrientation(int orientation) {
+ if ((orientation & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)) == 0) {
+ return;
+ }
+ if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && (orientation & SWT.LEFT_TO_RIGHT) != 0) {
+ return;
+ }
+ if ((orientation & SWT.RIGHT_TO_LEFT) != 0 && isMirrored()) {
+ return;
+ }
+ if ((orientation & SWT.LEFT_TO_RIGHT) != 0 && isMirrored() == false) {
+ return;
+ }
+ if (StyledTextBidi.setOrientation(this, orientation) == false) {
+ return;
+ }
+ isMirrored = (orientation & SWT.RIGHT_TO_LEFT) != 0;
+ isBidi = StyledTextBidi.isBidiPlatform() || isMirrored();
+ initializeRenderer();
+ if (isBidi()) {
+ caretDirection = SWT.NULL;
+ createCaretBitmaps();
+ setBidiCaretDirection();
+ }
+ setCaretLocation();
+ keyActionMap.clear();
+ createKeyBindings();
+ super.redraw();
+}
+/**
* Adjusts the maximum and the page size of the scroll bars to
* reflect content width/length changes.
*/
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java
index c443b65772..e097698ded 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextBidi.java
@@ -31,6 +31,7 @@ class StyledTextBidi {
private int[] dx; // distance between character cells. in visual order. renderPositions[iV + 1] = renderPositions[iV] + dx[iV]
private byte[] classBuffer; // the character types in logical order, see BidiUtil for the possible types
private char[] glyphBuffer; // the glyphs in visual order as they will be rendered on screen.
+ private boolean isRightOriented;// writing orientation
/**
* This class describes a text segment of a single direction, either
@@ -106,6 +107,7 @@ class StyledTextBidi {
*/
public StyledTextBidi(GC gc, int tabWidth, String text, StyleRange[] ranges, Font boldFont, int[] offsets) {
int length = text.length();
+ isRightOriented = (gc.getStyle() & SWT.MIRRORED) != 0;
this.gc = gc;
bidiSegments = offsets;
@@ -155,6 +157,7 @@ public StyledTextBidi(GC gc, int tabWidth, String text, StyleRange[] ranges, Fon
*/
public StyledTextBidi(GC gc, String text, int[] offsets) {
int length = text.length();
+ isRightOriented = (gc.getStyle() & SWT.MIRRORED) != 0;
this.gc = gc;
bidiSegments = offsets;
order = new int[length];
@@ -381,8 +384,6 @@ void fillBackground(int logicalStart, int length, int xOffset, int yOffset, int
*/
int[] getCaretOffsetAndDirectionAtX(int x) {
int lineLength = getTextLength();
- int offset;
- int direction;
if (lineLength == 0) {
return new int[] {0, 0};
@@ -395,9 +396,16 @@ int[] getCaretOffsetAndDirectionAtX(int x) {
int visualOffset = getVisualOffsetAtX(x);
// figure out if the character was clicked on the right or left
int halfway = renderPositions[visualOffset] + dx[visualOffset] / 2;
- boolean visualLeft = (x <= halfway);
- offset = getLogicalOffset(visualOffset);
+ boolean visualLeft;
+ int offset = getLogicalOffset(visualOffset);
+ int direction;
+ if (isRightOriented) {
+ visualLeft = (x > halfway);
+ }
+ else {
+ visualLeft = (x <= halfway);
+ }
if (isRightToLeft(offset)) {
if (visualLeft) {
if (isLigated(gc)) {
@@ -413,23 +421,23 @@ int[] getCaretOffsetAndDirectionAtX(int x) {
}
else {
// position the caret as if the caret is to the left
- // of the character at location x and the PREVIOUS key is
- // pressed
- direction = ST.COLUMN_PREVIOUS;
+ // of the character at location x and the PREVIOUS
+ // key is pressed
+ direction = ST.COLUMN_PREVIOUS;
}
}
else {
if (visualLeft) {
- // position the caret as if the caret is to the right
- // of the character at location x and the PREVIOUS key is
- // pressed
- direction = ST.COLUMN_PREVIOUS;
+ // position the caret as if the caret is to the left
+ // of the character at location x and the PREVIOUS
+ // key is pressed
+ direction = ST.COLUMN_PREVIOUS;
}
else {
- // position the caret as if the caret is to the left
+ offset++;
+ // position the caret as if the caret is to the right
// of the character at location x and the NEXT key is
// pressed
- offset++;
direction = ST.COLUMN_NEXT;
}
}
@@ -457,6 +465,7 @@ private Vector getDirectionRuns(int logicalStart, int length) {
int logicalEnd = logicalStart + length - 1;
int segmentLogicalStart = logicalStart;
int segmentLogicalEnd = segmentLogicalStart;
+ int checkSide = isRightOriented ? -1 : 1;
if (logicalEnd < getTextLength()) {
int bidiSegmentIndex = 0;
@@ -481,8 +490,9 @@ private Vector getDirectionRuns(int logicalStart, int length) {
// is no direction change.
// If our segment type is LtoR, the order index for the next character will be one more if there is
// no direction change.
- ((isRightToLeftSegment && (order[segmentLogicalEnd + 1]+ 1 == order[segmentLogicalEnd])) ||
- (isRightToLeftSegment == false && (order[segmentLogicalEnd + 1]- 1 == order[segmentLogicalEnd]))) &&
+ (order[segmentLogicalEnd + 1] == order[segmentLogicalEnd] || // treat ligatures as part of the direction segment
+ (isRightToLeftSegment && (order[segmentLogicalEnd + 1] + checkSide == order[segmentLogicalEnd])) ||
+ (isRightToLeftSegment == false && (order[segmentLogicalEnd + 1] - checkSide == order[segmentLogicalEnd]))) &&
segmentLogicalEnd + 1 < bidiSegmentEnd) {
segmentLogicalEnd++;
}
@@ -555,7 +565,7 @@ int getLigatureStartOffset(int offset) {
* @param visualOffset the visual offset
* @return the logical offset of the character at <code>visualOffset</code>.
*/
-private int getLogicalOffset(int visualOffset) {
+int getLogicalOffset(int visualOffset) {
int logicalOffset = 0;
while (logicalOffset < order.length && order[logicalOffset] != visualOffset) {
@@ -697,26 +707,29 @@ int getTextPosition(int logicalOffset, int direction) {
if (getTextLength() == 0 || logicalOffset < 0) {
return StyledText.XINSET;
}
+
+ boolean isRightToLeft = isRightToLeft(logicalOffset);
// at or past end of line?
if (logicalOffset >= order.length) {
logicalOffset = Math.min(logicalOffset, order.length - 1);
+ isRightToLeft = isRightToLeft(logicalOffset);
int visualOffset = order[logicalOffset];
- if (isRightToLeft(logicalOffset)) {
- caretX = renderPositions[visualOffset];
+ if ((!isRightOriented && !isRightToLeft) || (isRightOriented && isRightToLeft)) {
+ caretX = renderPositions[visualOffset] + dx[visualOffset];
}
else {
- caretX = renderPositions[visualOffset] + dx[visualOffset];
+ caretX = renderPositions[visualOffset];
}
}
else
// at beginning of line?
if (logicalOffset == 0) {
int visualOffset = order[logicalOffset];
- if (isRightToLeft(logicalOffset)) {
- caretX = renderPositions[visualOffset] + dx[visualOffset];
+ if ((!isRightOriented && !isRightToLeft) || (isRightOriented && isRightToLeft)) {
+ caretX = renderPositions[visualOffset];
}
else {
- caretX = renderPositions[visualOffset];
+ caretX = renderPositions[visualOffset] + dx[visualOffset];
}
}
else
@@ -733,14 +746,12 @@ int getTextPosition(int logicalOffset, int direction) {
// do not consider local numbers as R2L here, to determine position,
// because local numbers are navigated L2R and we want the caret to
// be to the right of the number. see 1GK9API
- if (isRightToLeft(logicalOffset - 1)) {
- // moving from RtoL to LtoR
- caretX = renderPositions[visualOffset];
- }
- else {
- // moving from LtoR to RtoL
+ isRightToLeft = isRightToLeft(logicalOffset - 1);
+ if ((!isRightOriented && !isRightToLeft) || (isRightOriented && isRightToLeft)) {
caretX = renderPositions[visualOffset] + dx[visualOffset];
- }
+ } else {
+ caretX = renderPositions[visualOffset];
+ }
}
else
// consider local numbers as R2L in determining direction boundaries.
@@ -752,23 +763,22 @@ int getTextPosition(int logicalOffset, int direction) {
// consider local numbers as R2L here, to determine position, because
// we want to stay in L2R segment and place the cursor to the left of
// first L2R character. see 1GK9API
- if (isRightToLeftInput(logicalOffset - 1)) {
- // moving from LtoR to RtoL
+ isRightToLeft = isRightToLeft(logicalOffset - 1);
+ if ((!isRightOriented && !isRightToLeft) || (isRightOriented && isRightToLeft)) {
+ caretX = renderPositions[visualOffset] + dx[visualOffset];
+ } else {
+ caretX = renderPositions[visualOffset];
+ }
+ }
+ else {
+ int visualOffset = order[logicalOffset];
+ if ((!isRightOriented && !isRightToLeft) || (isRightOriented && isRightToLeft)) {
caretX = renderPositions[visualOffset];
}
else {
- // moving from RtoL to LtoR
caretX = renderPositions[visualOffset] + dx[visualOffset];
}
}
- else
- if (isRightToLeft(logicalOffset)) {
- int visualOffset = order[logicalOffset];
- caretX = renderPositions[visualOffset] + dx[visualOffset];
- }
- else {
- caretX = renderPositions[order[logicalOffset]];
- }
return caretX;
}
/**
@@ -786,6 +796,17 @@ int getTextWidth() {
return width;
}
/**
+ * Returns the visual offset of the character at the specified
+ * logical offset.
+ * <p>
+ *
+ * @param logicalOffset the logical offset
+ * @return the visual offset of the character at <code>logicalOffset</code>.
+ */
+int getVisualOffset(int logicalOffset) {
+ return order[logicalOffset];
+}
+/**
* Returns the visual offset of the character at the specified x
* location.
* <p>
@@ -820,6 +841,23 @@ private int getVisualOffsetAtX(int x) {
return high;
}
/**
+ * Returns if the character at the given offset is a latin number.
+ * <p>
+ *
+ * @param logicalIndex the index of the character
+ * @return
+ * true=the character at the specified index is a latin number
+ * false=the character at the specified index is not a latin number
+ */
+boolean isLatinNumber(int logicalIndex) {
+ boolean isLatinNumber = false;
+
+ if (logicalIndex >= 0 && logicalIndex < classBuffer.length) {
+ isLatinNumber = classBuffer[logicalIndex] == BidiUtil.CLASS_LATINNUMBER;
+ }
+ return isLatinNumber;
+}
+/**
* Returns if the character at the given offset is a local number.
* <p>
*
@@ -968,7 +1006,6 @@ private void prepareFontStyledText(String textline, int logicalStart, int length
*/
void redrawRange(Control parent, int logicalStart, int length, int xOffset, int yOffset, int height) {
Enumeration directionRuns;
-
if (logicalStart < 0 || logicalStart + length > getTextLength()) {
return;
}
@@ -976,8 +1013,22 @@ void redrawRange(Control parent, int logicalStart, int length, int xOffset, int
while (directionRuns.hasMoreElements()) {
DirectionRun run = (DirectionRun) directionRuns.nextElement();
int startX = run.getRenderStartX();
+ int endX = run.getRenderStopX();
+ int runStartOffset = run.getVisualStart();
+ int runEndOffset = run.getVisualEnd();
- parent.redraw(xOffset + startX, yOffset, run.getRenderStopX() - startX, height, true);
+ // expand the redraw area by one character in both directions.
+ // fixes bug 40019
+ if (runStartOffset > 0) {
+ startX = renderPositions[runStartOffset - 1];
+ }
+ else {
+ startX = 0;
+ }
+ if (runEndOffset < renderPositions.length - 1) {
+ endX = renderPositions[runEndOffset + 1] + dx[runEndOffset + 1];
+ }
+ parent.redraw(xOffset + startX, yOffset, endX - startX, height, true);
}
}
/**
@@ -1011,6 +1062,18 @@ void setKeyboardLanguage(int logicalIndex) {
BidiUtil.setKeyboardLanguage(language);
}
/**
+ * Sets the orientation (writing order) of the specified control. Text will
+ * be right aligned for right to left writing order.
+ * <p>
+ *
+ * @param orientation one of SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
+ * @return true if the orientation was changed, false if the orientation
+ * could not be changed
+ */
+static boolean setOrientation(Control control, int orientation) {
+ return BidiUtil.setOrientation(control.handle, orientation);
+}
+/**
* Returns a string representation of the receiver.
* <p>
*
@@ -1059,4 +1122,4 @@ public String toString() {
buf.append("}}");
return buf.toString();
}
-}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableCursor.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableCursor.java
index 8055dc73fb..714a1b80ac 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableCursor.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableCursor.java
@@ -298,12 +298,17 @@ void keyDown(Event event) {
case SWT.ARROW_DOWN :
setRowColumn(row + 1, column, true);
break;
- case SWT.ARROW_LEFT :
- setRowColumn(row, column - 1, true);
- break;
- case SWT.ARROW_RIGHT :
- setRowColumn(row, column + 1, true);
- break;
+ case SWT.ARROW_LEFT :
+ case SWT.ARROW_RIGHT :
+ {
+ int leadKey = (getStyle() & SWT.RIGHT_TO_LEFT) != 0 ? SWT.ARROW_RIGHT : SWT.ARROW_LEFT;
+ if (event.keyCode == leadKey) {
+ setRowColumn(row, column - 1, true);
+ } else {
+ setRowColumn(row, column + 1, true);
+ }
+ break;
+ }
case SWT.HOME :
setRowColumn(0, column, true);
break;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableTree.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableTree.java
index 4c8f74cd0f..f118229914 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableTree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/TableTree.java
@@ -91,7 +91,7 @@ public class TableTree extends Composite {
* @see #getStyle
*/
public TableTree(Composite parent, int style) {
- super(parent, SWT.NONE);
+ super(parent, checkStyle (style));
table = new Table(this, style);
Listener tableListener = new Listener() {
public void handleEvent(Event e) {
@@ -196,7 +196,12 @@ public void addTreeListener(TreeListener listener) {
TypedListener typedListener = new TypedListener (listener);
addListener (SWT.Expand, typedListener);
addListener (SWT.Collapse, typedListener);
-}
+}
+private static int checkStyle (int style) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ style = style & mask;
+ return style;
+}
public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget();
return table.computeSize (wHint, hHint, changed);
@@ -502,7 +507,8 @@ void onKeyDown (Event e) {
TableTreeItem item = selection[0];
int type = 0;
if (e.keyCode == SWT.ARROW_RIGHT || e.keyCode == SWT.ARROW_LEFT) {
- if (e.keyCode == SWT.ARROW_RIGHT) {
+ int trailKey = (getStyle() & SWT.MIRRORED) != 0 ? SWT.ARROW_LEFT : SWT.ARROW_RIGHT;
+ if (e.keyCode == trailKey) {
if (item.getItemCount() == 0) return;
if (item.getExpanded()) {
TableTreeItem newSelection = item.getItems()[0];
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ViewForm.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ViewForm.java
index 6acbd1cb1a..b9583196cb 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ViewForm.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/ViewForm.java
@@ -147,7 +147,7 @@ public ViewForm(Composite parent, int style) {
* @private
*/
private static int checkStyle (int style) {
- int mask = SWT.FLAT;
+ int mask = SWT.FLAT | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask | SWT.NO_REDRAW_RESIZE;
}
public Point computeSize(int wHint, int hHint, boolean changed) {

Back to the top