diff options
author | Lina Kemmel | 2015-12-03 13:37:13 +0000 |
---|---|---|
committer | Niraj Modi | 2015-12-04 10:34:52 +0000 |
commit | 1b2cca0b6c41113211d8146c1c6ceaaca7d5989c (patch) | |
tree | 51d5a9e1f358891b8f206e23301d01fc469da4ab /bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse | |
parent | 6351a474b1ab7b8c3b9258742a72f9361637458c (diff) | |
download | eclipse.platform.swt-1b2cca0b6c41113211d8146c1c6ceaaca7d5989c.tar.gz eclipse.platform.swt-1b2cca0b6c41113211d8146c1c6ceaaca7d5989c.tar.xz eclipse.platform.swt-1b2cca0b6c41113211d8146c1c6ceaaca7d5989c.zip |
[Bug 467463] [BiDi] Implement contextual base text direction for
StyledText:
(1) Addressed Niraj' comments
(2) Control: updated javadoc to accommodate AUTO direction
(3) Added isAutoDirection to all platforms
(4) win32 TextLayout now returns resolved direction for
back-compatibility reasons.
(5) Class SWT: javadoc for AUTO_TEXT_DIRECTION mentions public API it
can be consumed.
Change-Id: I07ab212d1a8e2bc2b4a54ea6348ee1d97d190ec7
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse')
12 files changed, 118 insertions, 73 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java index 03dee9fc1a..be806db841 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java @@ -1820,7 +1820,7 @@ public int getLevel (int offset) { return allRuns[i - 1].analysis.s.uBidiLevel; } } - return (textDirection & SWT.RIGHT_TO_LEFT) != 0 ? 1 : 0; + return (resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 0 ? 1 : 0; } /** @@ -2439,7 +2439,7 @@ String getSegmentsText() { text.getChars(0, length, oldChars, 0); char[] newChars = new char[length + nSegments]; int charCount = 0, segmentCount = 0; - char defaultSeparator = (textDirection & SWT.RIGHT_TO_LEFT) != 0 ? RTL_MARK : LTR_MARK; + char defaultSeparator = (resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 0 ? RTL_MARK : LTR_MARK; while (charCount < length) { if (segmentCount < nSegments && charCount == segments[segmentCount]) { char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator; @@ -2566,7 +2566,7 @@ public String getText () { */ public int getTextDirection () { checkLayout(); - return textDirection; + return resolveTextDirection(); } /** @@ -2625,7 +2625,7 @@ StyleItem[] itemize () { SCRIPT_STATE scriptState = new SCRIPT_STATE(); final int MAX_ITEM = length + 1; - if ((textDirection & SWT.RIGHT_TO_LEFT) != 0) { + if ((resolveTextDirection() & SWT.RIGHT_TO_LEFT) != 0) { scriptState.uBidiLevel = 1; scriptState.fArabicNumContext = true; } @@ -2762,6 +2762,15 @@ StyleItem[] merge (long /*int*/ items, int itemCount) { } /* + * Resolves text direction. If the nominal direction is LTR or RTL, no + * resolution is needed; if the nominal direction is "auto", have BidiUtil + * resolve it according to the first strong bidi character. + */ +int resolveTextDirection () { + return textDirection == SWT.AUTO_TEXT_DIRECTION ? BidiUtil.resolveTextDirection (text) : textDirection; +} + +/* * Reorder the run */ StyleItem[] reorder (StyleItem[] runs, boolean terminate) { @@ -3214,7 +3223,8 @@ public void setText (String text) { /** * Sets the text direction of the receiver, which must be one - * of <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>. + * of <code>SWT.LEFT_TO_RIGHT</code>, <code>SWT.RIGHT_TO_LEFT</code> + * or <code>SWT.AUTO_TEXT_DIRECTION</code>. * * <p> * <b>Warning</b>: This API is currently only implemented on Windows. @@ -3233,8 +3243,10 @@ public void setTextDirection (int textDirection) { int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; textDirection &= mask; if (textDirection == 0) return; - if ((textDirection & SWT.LEFT_TO_RIGHT) != 0) textDirection = SWT.LEFT_TO_RIGHT; - if (this.textDirection == textDirection) return; + if (textDirection != SWT.AUTO_TEXT_DIRECTION) { + if ((textDirection & SWT.LEFT_TO_RIGHT) != 0) textDirection = SWT.LEFT_TO_RIGHT; + if (this.textDirection == textDirection) return; + } this.textDirection = textDirection; freeRuns(); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java index 7ba1807d4c..9dabebfcdc 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/BidiUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,7 +19,9 @@ import org.eclipse.swt.graphics.GC; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.widgets.*; /* - * Wraps Win32 API used to bidi enable the StyledText widget. + * Wraps Win32 API used to bidi enable widgets. Up to 3.104 was used by + * StyledText widget exclusively. 3.105 release introduced the method + * #resolveTextDirection, which is used by other widgets as well. */ public class BidiUtil { @@ -501,6 +503,66 @@ public static void removeLanguageListener (Control control) { removeLanguageListener(control.handle); } /** + * Determine the base direction for the given text. The direction is derived + * from that of the first strong bidirectional character. In case the text + * doesn't contain any strong characters, the base direction is to be + * derived from a higher-level protocol (e.g. the widget orientation). + * <p> + * + * @param text + * Text base direction should be resolved for. + * @return SWT#LEFT_RIGHT or SWT#RIGHT_TO_LEFT if the text contains strong + * characters and thus the direction can be resolved, SWT#NONE + * otherwise. + * @since 3.105 + */ +public 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 = {'\u202b', '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; + +} +/** * Switch the keyboard language to the specified language type. We do * not distinguish between multiple bidi or multiple non-bidi languages, so * set the keyboard to the first language of the given type. 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 b8385c9674..8273ccaeba 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 @@ -817,7 +817,7 @@ public void removeSelectionListener (SelectionListener listener) { @Override int resolveTextDirection() { - return (style & SWT.ARROW) != 0 ? SWT.NONE : resolveTextDirection(text); + return (style & SWT.ARROW) != 0 ? SWT.NONE : BidiUtil.resolveTextDirection(text); } void selectRadio () { 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 af4e97841a..4d9120f2e7 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 @@ -1235,7 +1235,7 @@ Event getSegments (String string) { } } if ((state & HAS_AUTO_DIRECTION) != 0) { - int direction = resolveTextDirection(string); + int direction = BidiUtil.resolveTextDirection(string); if (direction == SWT.NONE) { /* * Force adding a UCC even when no strong characters are found. 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 a5cf242700..ab8aabb610 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 @@ -3716,10 +3716,7 @@ 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>, - * <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. + * <code>SWT.RIGHT_TO_LEFT</code>, or <code>SWT.AUTO_TEXT_DIRECTION</code>. * <p> * <code>setOrientation</code> would override this value with the text direction * that is consistent with the new orientation. @@ -3738,6 +3735,7 @@ boolean setTabItemFocus () { * * @see SWT#LEFT_TO_RIGHT * @see SWT#RIGHT_TO_LEFT + * @see SWT#AUTO_TEXT_DIRECTION * @see SWT#FLIP_TEXT_DIRECTION * * @since 3.102 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 4ce38746fb..28884de6a2 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 @@ -11,6 +11,7 @@ package org.eclipse.swt.widgets; +import org.eclipse.swt.internal.BidiUtil; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; @@ -377,7 +378,7 @@ void releaseWidget () { @Override int resolveTextDirection () { - return resolveTextDirection (text); + return BidiUtil.resolveTextDirection (text); } @Override 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 970b510a9b..17d91e9806 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 @@ -11,9 +11,10 @@ package org.eclipse.swt.widgets; -import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.BidiUtil; +import org.eclipse.swt.internal.win32.*; /** * Instances of this class represent a non-selectable @@ -300,7 +301,7 @@ void releaseWidget () { @Override int resolveTextDirection() { - return (style & SWT.SEPARATOR) != 0 ? SWT.NONE : resolveTextDirection(text); + return (style & SWT.SEPARATOR) != 0 ? SWT.NONE : BidiUtil.resolveTextDirection (text); } /** 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 1e84e903e3..97cf652bfb 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.swt.widgets; +import org.eclipse.swt.internal.BidiUtil; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; @@ -762,7 +763,7 @@ public void setText (String string) { @Override int resolveTextDirection() { - return resolveTextDirection(text); + return BidiUtil.resolveTextDirection(text); } @Override 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 3f16621bcd..f3c60c26f9 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 @@ -11,10 +11,11 @@ package org.eclipse.swt.widgets; -import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.*; -import org.eclipse.swt.graphics.*; import org.eclipse.swt.events.*; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.BidiUtil; +import org.eclipse.swt.internal.win32.*; /** * Instances of this class represent a selectable user interface @@ -1638,7 +1639,7 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long / TCHAR buffer = new TCHAR (cp, length); OS.MoveMemory (buffer, lParam, buffer.length () * TCHAR.sizeof); String string = buffer.toString (0, length); - int direction = resolveTextDirection (string); + int direction = BidiUtil.resolveTextDirection (string); if (direction == SWT.NONE) { /* * Force adding a UCC even when no strong characters are found. 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 e2dd3c3e5c..66c9e94930 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 @@ -6932,7 +6932,7 @@ LRESULT wmNotifyChild (NMHDR hdr, long /*int*/ wParam, long /*int*/ lParam) { length = 1; } if (length > 1 && (state & HAS_AUTO_DIRECTION) != 0) { - switch (resolveTextDirection(string)) { + switch (BidiUtil.resolveTextDirection(string)) { case SWT.LEFT_TO_RIGHT: string = LRE + string; length++; 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 6ddb901dd1..34137bf398 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 @@ -14,6 +14,7 @@ package org.eclipse.swt.widgets; import org.eclipse.swt.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; +import org.eclipse.swt.internal.BidiUtil; import org.eclipse.swt.internal.win32.*; /** @@ -1747,9 +1748,9 @@ int resolveTextDirection() { OS.GetWindowText (handle, buffer, length + 1); if (segments != null) { buffer = deprocessText (buffer, 0, -1, false); - textDirection = resolveTextDirection(buffer.toString ()); + textDirection = BidiUtil.resolveTextDirection(buffer.toString ()); } else { - textDirection = resolveTextDirection(buffer.toString (0, length)); + textDirection = BidiUtil.resolveTextDirection(buffer.toString (0, length)); } if (textDirection == SWT.NONE) { /* 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 a70f10b242..01ecd025e7 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -699,6 +699,20 @@ boolean hooks (int eventType) { } /** + * Returns <code>true</code> if the widget has auto text direction, + * and <code>false</code> otherwise. + * + * @return <code>true</code> when the widget has auto direction and <code>false</code> otherwise + * + * @see #HAS_AUTO_DIRECTION + * + * @since 3.105 + */ +public boolean isAutoDirection () { + return (state & HAS_AUTO_DIRECTION) != 0; +} + +/** * Returns <code>true</code> if the widget has been disposed, * and <code>false</code> otherwise. * <p> @@ -1039,52 +1053,6 @@ 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; |