Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLina Kemmel2015-05-13 16:24:04 +0000
committerLina Kemmel2015-05-13 16:35:14 +0000
commit4b4619a6b5b2cd61a37c980601ead9593d587b9d (patch)
tree7890f7ca873eafa4be2fc29b258bfaa8a95ebb1a
parent6930fdd35d9cdffd6d05c778fb4b82a2018d7fcb (diff)
downloadeclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.tar.gz
eclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.tar.xz
eclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.zip
Support AUTO (contextual) text direction for Controls
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java14
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java21
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java172
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java28
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java24
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java3
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java2
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandItem.java5
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Group.java22
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java11
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java9
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/List.java83
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java3
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabItem.java12
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java27
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java76
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java8
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolTip.java1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java54
-rw-r--r--tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Control.java23
20 files changed, 496 insertions, 102 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java
index 67476935d1..a6548e58ed 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Item.java
@@ -184,15 +184,23 @@ public void setText (String string) {
checkWidget ();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
text = string;
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
}
boolean updateTextDirection(int textDirection) {
- if (((style & SWT.FLIP_TEXT_DIRECTION) ^ textDirection) != 0) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ state |= HAS_AUTO_DIRECTION;
+ textDirection = (style ^ resolveTextDirection (text)) == 0 ? 0 : SWT.FLIP_TEXT_DIRECTION;
+ } else {
+ state &= ~HAS_AUTO_DIRECTION;
+ }
+ if (((style & SWT.FLIP_TEXT_DIRECTION) ^ textDirection) != 0) {
style ^= SWT.FLIP_TEXT_DIRECTION;
return true;
}
- return false;
+ return textDirection == AUTO_TEXT_DIRECTION;
}
-
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java
index ac082683c6..a76e148442 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java
@@ -297,6 +297,9 @@ void _setText (String text) {
}
TCHAR buffer = new TCHAR (getCodePage (), text, true);
OS.SetWindowText (handle, buffer);
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
}
/**
@@ -1098,6 +1101,24 @@ public void setText (String string) {
_setText (string);
}
+@Override
+boolean updateTextDirection(int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ textDirection = (style & SWT.ARROW) != 0 ? SWT.NONE : resolveTextDirection(text);
+ }
+ if (super.updateTextDirection(textDirection)) {
+// TODO: Keep for now, to follow up
+// int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
+// style &= ~SWT.MIRRORED;
+// style &= ~flags;
+// style |= textDirection & flags;
+// updateOrientation ();
+// checkMirrored ();
+ return true;
+ }
+ return false;
+}
+
void updateImageList () {
if (OS.COMCTL32_MAJOR >= 6) {
if (imageList != null) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
index 1461dee94e..ae098e9283 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java
@@ -339,32 +339,21 @@ public void addVerifyListener (VerifyListener listener) {
void applyEditSegments () {
if (--clearSegmentsCount != 0) return;
- if (!hooks (SWT.Segments) && !filters (SWT.Segments)) return;
+ if (!hooks (SWT.Segments) && !filters (SWT.Segments) && (state & HAS_AUTO_DIRECTION) == 0) return;
long /*int*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT);
int length = OS.GetWindowTextLength (hwndText);
int cp = getCodePage ();
TCHAR buffer = new TCHAR (cp, length + 1);
if (length > 0) OS.GetWindowText (hwndText, buffer, length + 1);
String string = buffer.toString (0, length);
-
- /* Get segments text */
- Event event = new Event ();
- event.text = string;
- event.segments = segments;
- sendEvent (SWT.Segments, event);
+ /* Get segments */
+ segments = null;
+ Event event = getSegments (string);
+ if (event == null || event.segments == null) return;
segments = event.segments;
- if (segments == null) return;
- int nSegments = segments.length;
+ int nSegments = segments.length;
if (nSegments == 0) return;
- length = string == null ? 0 : string.length ();
-
- for (int i = 1; i < nSegments; i++) {
- if (event.segments [i] < event.segments [i - 1] || event.segments [i] > length) {
- error (SWT.ERROR_INVALID_ARGUMENT);
- }
- }
char [] segmentsChars = event.segmentsChars;
-
int/*64*/ limit = (int/*64*/)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit + Math.min (nSegments, LIMIT - limit), 0);
length += nSegments;
@@ -411,6 +400,19 @@ void applyEditSegments () {
start [0] = wcsToMbcsPos (start [0]);
end [0] = wcsToMbcsPos (end [0]);
}
+ if (segmentsChars != null && segmentsChars.length > 0) {
+ /*
+ * In addition to enforcing the required direction by prepending a UCC (LRE
+ * or RLE), also set the direction through a Window style.
+ * This is to ensure correct caret movement, and makes sense even when the
+ * UCC was added by an authentic SegmentListener.
+ */
+ if (segmentsChars[0] == RLE) {
+ super.updateTextDirection(SWT.RIGHT_TO_LEFT);
+ } else if (segmentsChars[0] == LRE) {
+ super.updateTextDirection(SWT.LEFT_TO_RIGHT);
+ }
+ }
OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
ignoreCharacter = oldIgnoreCharacter;
ignoreModify = oldIgnoreModify;
@@ -1057,7 +1059,7 @@ public String getItem (int index) {
checkWidget ();
int length = (int)/*64*/OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, index, 0);
if (length != OS.CB_ERR) {
- if (hooks (SWT.Segments) || filters (SWT.Segments)) return items [index];
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || (state & HAS_AUTO_DIRECTION) != 0) return items [index];
TCHAR buffer = new TCHAR (getCodePage (), length + 1);
int result = (int)/*64*/OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer);
if (result != OS.CB_ERR) return buffer.toString (0, length);
@@ -1122,14 +1124,9 @@ public int getItemHeight () {
public String [] getItems () {
checkWidget ();
String [] result;
- if (hooks (SWT.Segments) || filters (SWT.Segments)) {
- result = new String [items.length];
- System.arraycopy (items, 0, result, 0, items.length);
- } else {
- int count = getItemCount ();
- result = new String [count];
- for (int i=0; i<count; i++) result [i] = getItem (i);
- }
+ int count = getItemCount ();
+ result = new String [count];
+ for (int i=0; i<count; i++) result [i] = getItem (i);
return result;
}
@@ -1204,17 +1201,49 @@ public int getOrientation () {
}
Event getSegments (String string) {
- if (!hooks (SWT.Segments) && !filters (SWT.Segments)) return null;
- Event event = new Event ();
- event.text = string;
- sendEvent (SWT.Segments, event);
- if (event.segments != null) {
- for (int i = 1, segmentCount = event.segments.length, lineLength = string == null ? 0 : string.length(); i < segmentCount; i++) {
- if (event.segments[i] < event.segments[i - 1] || event.segments[i] > lineLength) {
- SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ Event event = null;
+ if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+ event = new Event ();
+ event.text = string;
+ sendEvent (SWT.Segments, event);
+ if (event != null && event.segments != null) {
+ for (int i = 1, segmentCount = event.segments.length, lineLength = string == null ? 0 : string.length(); i < segmentCount; i++) {
+ if (event.segments[i] < event.segments[i - 1] || event.segments[i] > lineLength) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
}
}
}
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ int direction = resolveTextDirection(string);
+ if (direction == SWT.NONE) {
+ /*
+ * Force adding a UCC even when no strong characters are found.
+ * Otherwise, the widget would keep the old direction, which might be
+ * inappropriate for the new text.
+ */
+ direction = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+ }
+ int [] oldSegments = null;
+ char [] oldSegmentsChars = null;
+ if (event == null) {
+ event = new Event ();
+ } else {
+ oldSegments = event.segments;
+ oldSegmentsChars = event.segmentsChars;
+ }
+ int nSegments = oldSegments == null ? 0 : oldSegments.length;
+ event.segments = new int [nSegments + 1];
+ event.segmentsChars = new char [nSegments + 1];
+ if (oldSegments != null) {
+ System.arraycopy(oldSegments, 0, event.segments, 1, nSegments);
+ }
+ if (oldSegmentsChars != null) {
+ System.arraycopy(oldSegmentsChars, 0, event.segmentsChars, 1, nSegments);
+ }
+ event.segments [0] = 0;
+ event.segmentsChars [0] = direction == SWT.RIGHT_TO_LEFT ? RLE : LRE;
+ }
return event;
}
@@ -2427,6 +2456,28 @@ void updateDropDownHeight () {
}
}
+@Override
+boolean updateTextDirection(int textDirection) {
+ state &= ~HAS_AUTO_DIRECTION;
+ if (super.updateTextDirection(textDirection)) {
+ /*
+ * state gets updated in Control#setTextDirection after updateTextDirection
+ * completes, but we need here the state to be up-to-date already, before
+ * clearing / applying segments.
+ */
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ /* To support auto direction we use UCC that are not available in ANSI CP */
+ if (!OS.IsUnicode) return false;
+ state |= HAS_AUTO_DIRECTION;
+ }
+ clearSegments (true);
+ applyEditSegments ();
+ applyListSegments ();
+ return true;
+ }
+ return false;
+}
+
void updateOrientation () {
int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
if ((style & SWT.RIGHT_TO_LEFT) != 0) {
@@ -2560,12 +2611,12 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
switch (msg) {
/* Keyboard messages */
case OS.WM_CHAR:
- processSegments = (hooks (SWT.Segments) || filters (SWT.Segments)) && !ignoreCharacter && OS.GetKeyState (OS.VK_CONTROL) >= 0 && OS.GetKeyState (OS.VK_MENU) >= 0;
+ processSegments = (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) && !ignoreCharacter && OS.GetKeyState (OS.VK_CONTROL) >= 0 && OS.GetKeyState (OS.VK_MENU) >= 0;
result = wmChar (hwnd, wParam, lParam);
break;
case OS.WM_IME_CHAR: result = wmIMEChar (hwnd, wParam, lParam); break;
case OS.WM_KEYDOWN:
- processSegments = wParam == OS.VK_DELETE && (hooks (SWT.Segments) || filters (SWT.Segments));
+ processSegments = wParam == OS.VK_DELETE && (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0));
result = wmKeyDown (hwnd, wParam, lParam);
break;
case OS.WM_KEYUP: result = wmKeyUp (hwnd, wParam, lParam); break;
@@ -2600,16 +2651,16 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
/* Clipboard messages */
case OS.EM_CANUNDO:
- if (hooks (SWT.Segments) || filters (SWT.Segments)) return 0;
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) return 0;
break;
case OS.WM_UNDO:
case OS.EM_UNDO:
- if (hooks (SWT.Segments) || filters (SWT.Segments)) return 0;
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) return 0;
case OS.WM_COPY:
case OS.WM_CLEAR:
case OS.WM_CUT:
case OS.WM_PASTE:
- processSegments = hooks (SWT.Segments) || filters (SWT.Segments);
+ processSegments = hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0);
case OS.WM_SETTEXT:
if (hwnd == hwndText) {
result = wmClipboard (hwnd, msg, wParam, lParam);
@@ -2663,20 +2714,27 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
}
}
}
- if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
code = super.windowProc (hwnd, msg, wParam, lParam);
if (!(code == OS.CB_ERR || code == OS.CB_ERRSPACE)) {
- segments = null;
Event event = getSegments (items [index]);
- if (event != null) segments = event.segments;
+ segments = event != null ? event.segments : null;
+ if (event.segmentsChars != null) {
+ if (event.segmentsChars[0] == RLE) {
+ super.updateTextDirection(SWT.RIGHT_TO_LEFT);
+ } else if (event.segmentsChars[0] == LRE) {
+ super.updateTextDirection(SWT.LEFT_TO_RIGHT);
+ }
+ }
return code;
}
}
+ break;
}
case OS.CB_ADDSTRING:
case OS.CB_INSERTSTRING:
case OS.CB_FINDSTRINGEXACT:
- if (lParam != 0 && (hooks (SWT.Segments) || filters (SWT.Segments))) {
+ if (lParam != 0 && (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0))) {
long /*int*/ code = OS.CB_ERR;
int length = OS.IsUnicode ? OS.wcslen (lParam) : OS.strlen (lParam);
TCHAR buffer = new TCHAR (getCodePage (), length);
@@ -2704,14 +2762,18 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
}
break;
case OS.CB_DELETESTRING: {
- if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
long /*int*/ code = super.windowProc (hwnd, msg, wParam, lParam);
if (code != OS.CB_ERR && code != OS.CB_ERRSPACE) {
int index = (int)/*64*/ wParam;
- String [] newItems = new String [items.length - 1];
- System.arraycopy (items, 0, newItems, 0, index);
- System.arraycopy (items, index + 1, newItems, index, items.length - index - 1);
- items = newItems;
+ if (items.length == 1) {
+ items = new String[0];
+ } else if (items.length > 1) {
+ String [] newItems = new String [items.length - 1];
+ System.arraycopy (items, 0, newItems, 0, index);
+ System.arraycopy (items, index + 1, newItems, index, items.length - index - 1);
+ items = newItems;
+ }
if (!noSelection) {
index = (int)/*64*/OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
if (index == wParam) {
@@ -2725,7 +2787,7 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
break;
}
case OS.CB_RESETCONTENT: {
- if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
if (items.length > 0) items = new String [0];
clearSegments (false);
applyEditSegments ();
@@ -3139,9 +3201,15 @@ LRESULT wmCommandChild (long /*int*/ wParam, long /*int*/ lParam) {
}
OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits1);
OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits2);
- } else if (hooks (SWT.Segments) || filters (SWT.Segments)) {
- clearSegments (true);
- applyEditSegments ();
+ }
+ if (hooks (SWT.Segments) || filters (SWT.Segments) || ((state & HAS_AUTO_DIRECTION) != 0)) {
+ clearSegments(true);
+ /*
+ * Explicit LTR or RTL direction was set, so auto direction
+ * should be deactivated.
+ */
+ state &= ~HAS_AUTO_DIRECTION;
+ applyEditSegments();
}
break;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java
index cf479ba12c..811abd4ca3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java
@@ -1176,20 +1176,24 @@ boolean setTabGroupFocus () {
}
boolean updateTextDirection(int textDirection) {
- if (super.updateTextDirection(textDirection)) {
- /*
- * OS.WS_EX_RTLREADING doesn't propagate to children
- */
- Control[] children = _getChildren ();
- int i = children.length;
- while (i-- > 0) {
- if (children[i] != null && !children[i].isDisposed ()) {
- children[i].updateTextDirection(textDirection);
- }
+ super.updateTextDirection (textDirection);
+ /*
+ * Always continue, communicating the direction to the children since
+ * OS.WS_EX_RTLREADING doesn't propagate to them natively, and since
+ * the direction might need to be handled by each child individually.
+ */
+ Control[] children = _getChildren ();
+ int i = children.length;
+ while (i-- > 0) {
+ if (children[i] != null && !children[i].isDisposed ()) {
+ children[i].updateTextDirection(textDirection);
}
- return true;
}
- return false;
+ /*
+ * Return value indicates whether or not to update derivatives, so in case
+ * of AUTO always return true regardless of the actual update.
+ */
+ return true;
}
String toolTipText (NMTTDISPINFO hdr) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
index 2f50f4bd89..28d08b9d99 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
@@ -3699,8 +3699,11 @@ boolean setTabItemFocus () {
/**
* Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
- * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code> or
- * <code>SWT.RIGHT_TO_LEFT</code>.
+ * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code>,
+ * <code>SWT.RIGHT_TO_LEFT</code>, or a bitwise disjunction
+ * <code>SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT</code>. The latter stands for an
+ * "auto" direction, which implies that a control containing text derives the
+ * direction from the directionality of the first strong bidi character.
* <p>
* <code>setOrientation</code> would override this value with the text direction
* that is consistent with the new orientation.
@@ -3717,6 +3720,8 @@ boolean setTabItemFocus () {
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
* </ul>
*
+ * @see SWT#LEFT_TO_RIGHT
+ * @see SWT#RIGHT_TO_LEFT
* @see SWT#FLIP_TEXT_DIRECTION
*
* @since 3.102
@@ -3725,11 +3730,12 @@ public void setTextDirection(int textDirection) {
checkWidget ();
if (OS.IsWinCE) return;
if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
- int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
- textDirection &= flags;
- if (textDirection == 0 || textDirection == flags) return;
- if (updateTextDirection(textDirection)) {
- OS.InvalidateRect (handle, null, true);
+ textDirection &= (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT);
+ updateTextDirection (textDirection);
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ state |= HAS_AUTO_DIRECTION;
+ } else {
+ state &= ~HAS_AUTO_DIRECTION;
}
}
@@ -4525,7 +4531,8 @@ void updateOrientation () {
}
boolean updateTextDirection (int textDirection) {
- int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+ if (textDirection == 0 || textDirection == AUTO_TEXT_DIRECTION) return false;
+ int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
/*
* OS.WS_EX_RTLREADING means that the text direction is opposite to the
* natural one for the current layout. So text direction would be RTL when
@@ -4545,6 +4552,7 @@ boolean updateTextDirection (int textDirection) {
style &= ~SWT.FLIP_TEXT_DIRECTION;
}
OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+ OS.InvalidateRect (handle, null, true);
return true;
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java
index 04615024d5..5e2a11c204 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Decorations.java
@@ -1366,6 +1366,9 @@ public void setText (String string) {
} else {
OS.SetWindowText (handle, buffer);
}
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
}
public void setVisible (boolean visible) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java
index 461c312b8a..3622ae75a0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java
@@ -571,7 +571,7 @@ boolean updateTextDirection(int textDirection) {
if (super.updateTextDirection(textDirection)) {
for (int i = 0, n = items.length; i < n; i++) {
if (items[i] != null) {
- items[i].updateTextDirection(style & SWT.FLIP_TEXT_DIRECTION);
+ items[i].updateTextDirection(textDirection == AUTO_TEXT_DIRECTION ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION);
}
}
return true;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandItem.java
index 3fd7a823aa..5057c8b810 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandItem.java
@@ -198,7 +198,7 @@ void drawItem (GC gc, long /*int*/ hTheme, RECT clipRect, boolean drawFocus) {
if (text.length () > 0) {
rect.left += ExpandItem.TEXT_INSET;
TCHAR buffer;
- if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+ if (OS.IsUnicode && (style & SWT.FLIP_TEXT_DIRECTION) != 0) {
int bits = OS.GetWindowLong (parent.handle, OS.GWL_EXSTYLE);
if ((bits & OS.WS_EX_LAYOUTRTL) != 0) {
buffer = new TCHAR (parent.getCodePage (), LRE + text, false);
@@ -494,6 +494,9 @@ public void setImage (Image image) {
public void setText (String string) {
super.setText (string);
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
redraw (true);
}
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Group.java
index 509a746b1d..a71997230d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Group.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Group.java
@@ -237,8 +237,8 @@ String fixText (boolean enabled) {
if (!enabled && (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ())) {
string = " " + text + " ";
}
- return (style & SWT.FLIP_TEXT_DIRECTION) == 0 ? string : string != null ? LRE + string : LRE + text;
- } else if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+ return !OS.IsUnicode || (style & SWT.FLIP_TEXT_DIRECTION) == 0 ? string : string != null ? LRE + string : LRE + text;
+ } else if (OS.IsUnicode && (style & SWT.FLIP_TEXT_DIRECTION) != 0) {
return RLE + text;
}
return null;
@@ -399,18 +399,22 @@ public void setText (String string) {
checkWidget ();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
text = string;
- string = fixText (OS.IsWindowEnabled (handle));
- TCHAR buffer = new TCHAR (getCodePage (), string == null ? text : string, true);
- OS.SetWindowText (handle, buffer);
+ if ((state & HAS_AUTO_DIRECTION) == 0 || !updateTextDirection (AUTO_TEXT_DIRECTION)) {
+ string = fixText (OS.IsWindowEnabled (handle));
+ TCHAR buffer = new TCHAR (getCodePage (), string == null ? text : string, true);
+ OS.SetWindowText (handle, buffer);
+ }
}
boolean updateTextDirection(int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ /* resolveTextDirection is called before fixText intentionally */
+ textDirection = resolveTextDirection (text);
+ }
if (super.updateTextDirection(textDirection)) {
String string = fixText (OS.IsWindowEnabled (handle));
- if (string != null) {
- TCHAR buffer = new TCHAR (getCodePage (), string, true);
- OS.SetWindowText (handle, buffer);
- }
+ TCHAR buffer = new TCHAR (getCodePage (), string == null ? text : string, true);
+ OS.SetWindowText (handle, buffer);
return true;
}
return false;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java
index 3edfc3e8bc..4b55c77efa 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java
@@ -411,6 +411,9 @@ public void setText (String string) {
string = Display.withCrLf (string);
TCHAR buffer = new TCHAR (getCodePage (), string, true);
OS.SetWindowText (handle, buffer);
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
/*
* Bug in Windows. For some reason, the HBRUSH that
* is returned from WM_CTRLCOLOR is misaligned when
@@ -424,6 +427,14 @@ public void setText (String string) {
}
}
+@Override
+boolean updateTextDirection(int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ textDirection = (style & SWT.SEPARATOR) != 0 ? SWT.NONE : resolveTextDirection(text);
+ }
+ return super.updateTextDirection(textDirection);
+}
+
int widgetExtStyle () {
int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
if ((style & SWT.BORDER) != 0) return bits | OS.WS_EX_STATICEDGE;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
index 397afd3a06..3f119ca1f8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Link.java
@@ -694,7 +694,11 @@ public void setText (String string) {
checkWidget ();
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
if (string.equals (text)) return;
- text = string;
+ text = string;
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
+
if (OS.COMCTL32_MAJOR >= 6) {
boolean enabled = OS.IsWindowEnabled (handle);
/*
@@ -739,6 +743,9 @@ public void setText (String string) {
}
boolean updateTextDirection(int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ textDirection = resolveTextDirection(text);
+ }
if (super.updateTextDirection(textDirection)) {
int flags = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT;
style &= ~SWT.MIRRORED;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/List.java
index 2fa0eb324b..1764a67ade 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/List.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/List.java
@@ -42,6 +42,7 @@ public class List extends Scrollable {
static final int INSET = 3;
static final long /*int*/ ListProc;
static final TCHAR ListClass = new TCHAR (0, "LISTBOX", true);
+ boolean addedUCC = false; // indicates whether Bidi UCC were added; 'state & HAS_AUTO_DIRECTION' isn't a sufficient indicator
static {
WNDCLASS lpWndClass = new WNDCLASS ();
OS.GetClassInfo (0, ListClass, lpWndClass);
@@ -428,7 +429,7 @@ public String getItem (int index) {
if (length != OS.LB_ERR) {
TCHAR buffer = new TCHAR (getCodePage (), length + 1);
int result = (int)/*64*/OS.SendMessage (handle, OS.LB_GETTEXT, index, buffer);
- if (result != OS.LB_ERR) return buffer.toString (0, length);
+ if (result != OS.LB_ERR) return ((state & HAS_AUTO_DIRECTION) != 0) ? buffer.toString (1, length - 1) : buffer.toString (0, length);
}
int count = (int)/*64*/OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
if (0 <= index && index < count) error (SWT.ERROR_CANNOT_GET_ITEM);
@@ -1548,6 +1549,50 @@ void updateMenuLocation (Event event) {
event.y = pt.y;
}
+@Override
+boolean updateTextDirection (int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ /*
+ * To apply auto direction we use UCC that are not available in ANSI CP
+ * and - most important - will not be supported by TCHAR - even though
+ * they could be supported natively through "wide" (Unicode) versions of
+ * win32 API. Also, if auto is already in effect, there's nothing to do.
+ */
+ if (!OS.IsUnicode || (state & HAS_AUTO_DIRECTION) != 0) return false;
+ state |= HAS_AUTO_DIRECTION;
+ } else {
+ state &= ~HAS_AUTO_DIRECTION;
+ if (!addedUCC /*(state & HAS_AUTO_DIRECTION) == 0*/) {
+ return super.updateTextDirection (textDirection);
+ }
+ }
+ int count = (int)/*64*/OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+ if (count == OS.LB_ERR) return false;
+ int selection = (int)/*64*/OS.SendMessage (handle, OS.LB_GETCURSEL, 0, 0);
+ int cp = getCodePage ();
+ addedUCC = false;
+ while (count-- > 0) {
+ int length = (int)/*64*/OS.SendMessage (handle, OS.LB_GETTEXTLEN, count, 0);
+ if (length == OS.LB_ERR) break;
+ if (length == 0) continue;
+ TCHAR buffer = new TCHAR (cp, length + 1);
+ if (OS.SendMessage (handle, OS.LB_GETTEXT, count, buffer) == OS.LB_ERR) break;
+ if (OS.SendMessage (handle, OS.LB_DELETESTRING, count, 0) == OS.LB_ERR) break;
+ if ((state & HAS_AUTO_DIRECTION) == 0) {
+ /* Should remove UCC */
+ char [] chars = new char [length - 1];
+ System.arraycopy (buffer.chars, 1, chars, 0, length - 1); // buffer.chars as we are always Unicode here
+ buffer = new TCHAR (cp, chars, true);
+ }
+ /* Adding UCC is handled in OS.LB_INSERTSTRING */
+ if (OS.SendMessage (handle, OS.LB_INSERTSTRING, count, buffer) == OS.LB_ERR) break;
+ }
+ if (selection != OS.LB_ERR) {
+ OS.SendMessage (handle, OS.LB_SETCURSEL, selection, 0);
+ }
+ return textDirection == AUTO_TEXT_DIRECTION || super.updateTextDirection (textDirection);
+}
+
int widgetStyle () {
int bits = super.widgetStyle () | OS.LBS_NOTIFY | OS.LBS_NOINTEGRALHEIGHT;
if ((style & SWT.SINGLE) != 0) return bits;
@@ -1566,6 +1611,42 @@ long /*int*/ windowProc () {
return ListProc;
}
+long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /*int*/ lParam) {
+ if (!OS.IsUnicode || handle == 0 || lParam == 0 || (state & HAS_AUTO_DIRECTION) == 0) {
+ return callWindowProc (hwnd, msg, wParam, lParam);
+ }
+ switch (msg) {
+ case OS.LB_ADDSTRING:
+ case OS.LB_INSERTSTRING:
+ case OS.LB_FINDSTRINGEXACT:
+ int length = OS.wcslen (lParam); // we are always Unicode here
+ int cp = getCodePage ();
+ TCHAR buffer = new TCHAR (cp, length);
+ OS.MoveMemory (buffer, lParam, buffer.length () * TCHAR.sizeof);
+ String string = buffer.toString (0, length);
+ int direction = resolveTextDirection (string);
+ if (direction == SWT.NONE) {
+ /*
+ * Force adding a UCC even when no strong characters are found.
+ * Otherwise, the List items would retain the old direction,
+ * which might be inappropriate for the new text.
+ */
+ direction = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+ }
+ string = (direction == SWT.RIGHT_TO_LEFT ? RLE : LRE) + string;
+ buffer = new TCHAR (cp, string, true);
+ long /*int*/ hHeap = OS.GetProcessHeap ();
+ length = buffer.length() * TCHAR.sizeof;
+ long /*int*/ pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, length);
+ OS.MoveMemory (pszText, buffer, length);
+ long /*int*/ code = super.windowProc (hwnd, msg, wParam, pszText);
+ OS.HeapFree (hHeap, 0, pszText);
+ addedUCC = true;
+ return code;
+ }
+ return callWindowProc (hwnd, msg, wParam, lParam);
+}
+
LRESULT WM_CHAR (long /*int*/ wParam, long /*int*/ lParam) {
LRESULT result = super.WM_CHAR (wParam, lParam);
if (result != null) return result;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java
index 39e2c22229..c82a698a8f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabFolder.java
@@ -747,6 +747,9 @@ void setSelection (int index, boolean notify) {
boolean updateTextDirection(int textDirection) {
if (super.updateTextDirection(textDirection)) {
+ if (textDirection != AUTO_TEXT_DIRECTION) {
+ textDirection = style & SWT.FLIP_TEXT_DIRECTION;
+ }
for (int i = 0, n = items.length; i < n && items[i] != null; i++) {
items[i].updateTextDirection (textDirection);
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabItem.java
index 26461c3cd8..54c7f77edf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/TabItem.java
@@ -341,11 +341,19 @@ public void setText (String string) {
int index = parent.indexOf (this);
if (index == -1) return;
super.setText (string);
- _setText (index, string);
+ /*
+ * Need to update direction since it is set via UCC which the new text
+ * overrides
+ */
+ int textDirection = (state & HAS_AUTO_DIRECTION) != 0 ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION;
+ if (!updateTextDirection (textDirection)) {
+ _setText (index, string);
+ }
}
boolean updateTextDirection(int textDirection) {
- if (super.updateTextDirection(textDirection)) {
+ /* AUTO is handled by super */
+ if (super.updateTextDirection(textDirection) && OS.IsUnicode) {
int index = parent.indexOf (this);
if (index != -1) {
if ((textDirection & SWT.RIGHT_TO_LEFT) != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
index f32b253f87..ca0c7bbadd 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java
@@ -5775,6 +5775,21 @@ void updateOrientation () {
}
}
+boolean updateTextDirection(int textDirection) {
+ if (super.updateTextDirection(textDirection)) {
+ if (textDirection == AUTO_TEXT_DIRECTION || (state & HAS_AUTO_DIRECTION) != 0) {
+ for (int i = 0, n = items.length; i < n; i++) {
+ if (items[i] != null) {
+ items[i].updateTextDirection(textDirection == AUTO_TEXT_DIRECTION ? AUTO_TEXT_DIRECTION : style & SWT.FLIP_TEXT_DIRECTION);
+ }
+ }
+ }
+ OS.InvalidateRect (handle, null, true);
+ return true;
+ }
+ return false;
+}
+
int widgetStyle () {
int bits = super.widgetStyle () | OS.LVS_SHAREIMAGELISTS;
if ((style & SWT.HIDE_SELECTION) == 0) bits |= OS.LVS_SHOWSELALWAYS;
@@ -6851,6 +6866,18 @@ LRESULT wmNotifyChild (NMHDR hdr, long /*int*/ wParam, long /*int*/ lParam) {
string = " "; //$NON-NLS-1$
length = 1;
}
+ if (length > 1 && (state & HAS_AUTO_DIRECTION) != 0) {
+ switch (resolveTextDirection(string)) {
+ case SWT.LEFT_TO_RIGHT:
+ string = LRE + string;
+ length++;
+ break;
+ case SWT.RIGHT_TO_LEFT:
+ string = RLE + string;
+ length++;
+ break;
+ }
+ }
char [] buffer = display.tableBuffer;
if (buffer == null || plvfi.cchTextMax > buffer.length) {
buffer = display.tableBuffer = new char [plvfi.cchTextMax];
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java
index a788ce5caf..e43cd53940 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java
@@ -460,6 +460,9 @@ public void append (String string) {
OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
ignoreCharacter = false;
OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
applySegments ();
}
@@ -1555,6 +1558,9 @@ public void insert (String string) {
ignoreCharacter = true;
OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
ignoreCharacter = false;
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
applySegments ();
}
@@ -2263,6 +2269,9 @@ public void setText (String string) {
if (string.length () > limit) string = string.substring (0, limit);
TCHAR buffer = new TCHAR (getCodePage (), string, true);
OS.SetWindowText (handle, buffer);
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection(AUTO_TEXT_DIRECTION);
+ }
applySegments ();
/*
* Bug in Windows. When the widget is multi line
@@ -2325,6 +2334,9 @@ public void setTextChars (char[] text) {
TCHAR buffer = new TCHAR (getCodePage (), text, true);
OS.SetWindowText (handle, buffer);
buffer.clear ();
+ if ((state & HAS_AUTO_DIRECTION) != 0) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
applySegments ();
/*
* Bug in Windows. When the widget is multi line
@@ -2446,6 +2458,36 @@ void updateOrientation (){
fixAlignment ();
}
+@Override
+boolean updateTextDirection(int textDirection) {
+ if (textDirection == AUTO_TEXT_DIRECTION) {
+ int length = OS.GetWindowTextLength (handle);
+ if (length > 0) {
+ TCHAR buffer = new TCHAR (getCodePage (), length + 1);
+ OS.GetWindowText (handle, buffer, length + 1);
+ if (segments != null) {
+ buffer = deprocessText (buffer, 0, -1, false);
+ textDirection = resolveTextDirection(buffer.toString ());
+ } else {
+ textDirection = resolveTextDirection(buffer.toString (0, length));
+ }
+ if (textDirection == SWT.NONE) {
+ /*
+ * Force direction update also when no strong bidi chars are
+ * found.
+ */
+ textDirection = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
+ }
+ }
+ }
+ if (super.updateTextDirection(textDirection)) {
+ clearSegments (true);
+ applySegments ();
+ return true;
+ }
+ return false;
+}
+
String verifyText (String string, int start, int end, Event keyEvent) {
if (ignoreVerify) return string;
Event event = new Event ();
@@ -2563,28 +2605,38 @@ long /*int*/ windowProc () {
}
long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /*int*/ lParam) {
- boolean processSegments = false, redraw = false;
+ boolean processSegments = hooks (SWT.Segments) || filters (SWT.Segments), redraw = false, updateDirection = (state & HAS_AUTO_DIRECTION) != 0;
long /*int*/ code;
- if (hooks (SWT.Segments) || filters (SWT.Segments)) {
+ if (processSegments || updateDirection) {
switch (msg) {
+ case OS.EM_CANUNDO:
+ if (processSegments) return 0;
+ updateDirection = false;
+ break;
case OS.EM_UNDO:
case OS.WM_UNDO:
- case OS.EM_CANUNDO:
- return 0;
- case OS.WM_KEYDOWN:
- processSegments = wParam == OS.VK_DELETE;
+ if (processSegments) return 0;
+ break;
+ case OS.WM_KEYDOWN:
+ if (wParam != OS.VK_DELETE) {
+ processSegments = updateDirection = false;
+ }
break;
case OS.WM_COPY:
processSegments = segments != null;
+ updateDirection = false;
break;
case OS.WM_CHAR:
- processSegments = !ignoreCharacter && OS.GetKeyState (OS.VK_CONTROL) >= 0 && OS.GetKeyState (OS.VK_MENU) >= 0;
+ if (ignoreCharacter || OS.GetKeyState (OS.VK_CONTROL) < 0 || OS.GetKeyState (OS.VK_MENU) < 0) {
+ processSegments = updateDirection = false;
+ }
break;
case OS.WM_PASTE:
case OS.WM_CUT:
case OS.WM_CLEAR:
- processSegments = true;
break;
+ default:
+ processSegments = updateDirection = false;
}
}
if (processSegments) {
@@ -2613,6 +2665,9 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long /
return 1;
}
code = super.windowProc (hwnd, msg, wParam, lParam);
+ if (updateDirection) {
+ updateTextDirection (AUTO_TEXT_DIRECTION);
+ }
if (processSegments) {
applySegments ();
if (redraw) {
@@ -3014,6 +3069,11 @@ LRESULT wmCommandChild (long /*int*/ wParam, long /*int*/ lParam) {
break;
case OS.EN_ALIGN_LTR_EC:
case OS.EN_ALIGN_RTL_EC:
+ /*
+ * Ctrl + Shift to set explicit LTR or RTL text direction was
+ * pressed, so auto direction should no longer be effective.
+ */
+ state &= ~HAS_AUTO_DIRECTION;
int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
if ((bits & OS.WS_EX_RTLREADING) != 0) {
style &= ~SWT.LEFT_TO_RIGHT;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
index 481151f918..6e76e404c6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolItem.java
@@ -788,7 +788,7 @@ void _setText (String string) {
if (string.length () != 0) {
info.fsStyle |= OS.BTNS_SHOWTEXT;
TCHAR buffer;
- if ((style & SWT.FLIP_TEXT_DIRECTION) != 0) {
+ if (OS.IsUnicode && (style & SWT.FLIP_TEXT_DIRECTION) != 0) {
int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
if ((bits & OS.WS_EX_LAYOUTRTL) != 0) {
buffer = new TCHAR (parent.getCodePage (), LRE + string, true);
@@ -838,8 +838,9 @@ public void setText (String string) {
if ((style & SWT.SEPARATOR) != 0) return;
if (string.equals (text)) return;
super.setText (string);
- _setText (string);
-
+ if ((state & HAS_AUTO_DIRECTION) == 0 || !updateTextDirection (AUTO_TEXT_DIRECTION)) {
+ _setText (string);
+ }
/*
* Bug in Windows. For some reason, when the font is set
* before any tool item has text, the tool items resize to
@@ -857,6 +858,7 @@ public void setText (String string) {
}
boolean updateTextDirection(int textDirection) {
+ /* AUTO is handled by super */
if (super.updateTextDirection(textDirection) && text.length() != 0) {
_setText (text);
return true;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolTip.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolTip.java
index ba967b9410..b5440a3ccb 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolTip.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ToolTip.java
@@ -436,6 +436,7 @@ public void setText (String string) {
if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
text = string;
//TODO - update when visible
+ //TODO - support text direction (?)
}
/**
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java
index 66c8b4632e..a844eda79a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java
@@ -92,14 +92,20 @@ public abstract class Widget {
/* Notify of the opportunity to skin this widget */
static final int SKIN_NEEDED = 1<<21;
+ /* Bidi "auto" text direction */
+ static final int HAS_AUTO_DIRECTION = 1<<22;
+
/* Default size for widgets */
static final int DEFAULT_WIDTH = 64;
static final int DEFAULT_HEIGHT = 64;
- /* Bidi UCC to enforce text orientation */
+ /* Bidi UCC to enforce text direction */
static final char LRE = '\u202a';
static final char RLE = '\u202b';
+ /* Bidi flag and for auto text direction */
+ static final int AUTO_TEXT_DIRECTION = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+
/* Check and initialize the Common Controls DLL */
static final int MAJOR = 5, MINOR = 80;
static {
@@ -1033,6 +1039,52 @@ void reskinWidget() {
}
}
+static int resolveTextDirection(String text) {
+ if (text == null) return SWT.NONE;
+ int length = text.length();
+ if (length == 0) return SWT.NONE;
+ char[] rtlProbe = {' ', ' ', '1'};
+ /*
+ * "Wide" version of win32 API can also run even on non-Unicode Windows,
+ * hence need for OS.IsUnicode check here.
+ */
+ char[] ltrProbe = {RLE, 'a', ' '};
+ char[] numberProbe = {'\u05d0', ' ', ' '};
+ GCP_RESULTS result = new GCP_RESULTS();
+ result.lStructSize = GCP_RESULTS.sizeof;
+ int nGlyphs = result.nGlyphs = ltrProbe.length;
+ long /*int*/ hHeap = OS.GetProcessHeap();
+ long /*int*/ lpOrder = result.lpOrder = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, nGlyphs * 4);
+ long /*int*/ hdc = OS.GetDC(0);
+ int[] order = new int[1];
+ int textDirection = SWT.NONE;
+ for (int i = 0; i < length; i++) {
+ char ch = text.charAt(i);
+ rtlProbe[0] = ch;
+ OS.GetCharacterPlacementW(hdc, rtlProbe, rtlProbe.length, 0, result, OS.GCP_REORDER);
+ OS.MoveMemory(order, result.lpOrder, 4);
+ if (order[0] == 2) {
+ textDirection = SWT.RIGHT_TO_LEFT;
+ break;
+ }
+ ltrProbe[2] = ch;
+ OS.GetCharacterPlacementW(hdc, ltrProbe, ltrProbe.length, 0, result, OS.GCP_REORDER);
+ OS.MoveMemory(order, result.lpOrder + 4, 4);
+ if (order[0] == 1) {
+ numberProbe[2] = ch;
+ OS.GetCharacterPlacementW(hdc, numberProbe, numberProbe.length, 0, result, OS.GCP_REORDER);
+ OS.MoveMemory(order, result.lpOrder, 4);
+ if (order[0] == 0) {
+ textDirection = SWT.LEFT_TO_RIGHT;
+ break;
+ }
+ }
+ }
+ OS.ReleaseDC (0, hdc);
+ OS.HeapFree(hHeap, 0, lpOrder);
+ return textDirection;
+}
+
boolean sendDragEvent (int button, int x, int y) {
Event event = new Event ();
event.button = button;
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Control.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Control.java
index 7706698188..14a3e506af 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Control.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Control.java
@@ -436,6 +436,29 @@ public void test_setEnabledZ() {
assertTrue(!control.getEnabled());
}
@Test
+public void test_setTextDirection() {
+ if (!SwtTestUtil.isWindows) {
+ // TODO Fix GTK and Cocoa failure.
+ if (SwtTestUtil.verbose) {
+ System.out
+ .println("Excluded test_setTextDirection(org.eclipse.swt.tests.junit.Test_org_eclipse_swt_widgets_Control).");
+ }
+ return;
+ }
+ final int [] orientations = {SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT};
+ final int [] directions = {SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT};
+ int [] expectedDirections = {SWT.LEFT_TO_RIGHT, SWT.RIGHT_TO_LEFT, SWT.NONE};
+ for (int i = orientations.length; i-- > 0;) {
+ control.setOrientation (orientations [i]);
+ expectedDirections[2] = control.getOrientation ();
+ for (int j = directions.length; j-- > 0;) {
+ control.setTextDirection (directions [j]);
+ assertEquals("orientation: " + orientations [i] + ", text direction: " + directions [j],
+ control.getTextDirection(), expectedDirections [j]);
+ }
+ }
+}
+@Test
public void test_setFocus() {
control.setFocus();
}

Back to the top