diff options
author | Lina Kemmel | 2015-05-13 16:24:04 +0000 |
---|---|---|
committer | Lina Kemmel | 2015-05-13 16:35:14 +0000 |
commit | 4b4619a6b5b2cd61a37c980601ead9593d587b9d (patch) | |
tree | 7890f7ca873eafa4be2fc29b258bfaa8a95ebb1a | |
parent | 6930fdd35d9cdffd6d05c778fb4b82a2018d7fcb (diff) | |
download | eclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.tar.gz eclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.tar.xz eclipse.platform.swt-4b4619a6b5b2cd61a37c980601ead9593d587b9d.zip |
Support AUTO (contextual) text direction for Controls
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(); } |