View | Details | Raw Unified | Return to bug 183164 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/equinox/bidi/internal/tests/STextMethodsTest.java (-11 / +18 lines)
Lines 12-17 Link Here
12
package org.eclipse.equinox.bidi.internal.tests;
12
package org.eclipse.equinox.bidi.internal.tests;
13
13
14
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.*;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
17
/**
18
/**
Lines 34-53 Link Here
34
35
35
	class MyComma extends STextProcessor {
36
	class MyComma extends STextProcessor {
36
37
37
		public String getSeparators(STextEnvironment environment, String text, byte[] dirProps) {
38
		public String getSeparators(STextEnvironment environment, String text, STextDirections dirProps) {
38
			return ","; //$NON-NLS-1$
39
			return ","; //$NON-NLS-1$
39
		}
40
		}
40
41
41
		public boolean skipProcessing(STextEnvironment environment, String text, byte[] dirProps) {
42
		public boolean skipProcessing(STextEnvironment environment, String text, STextDirections dirProps) {
42
			byte dirProp = getDirProp(text, dirProps, 0);
43
			byte dirProp = dirProps.getOrientationAt(0);
43
			if (dirProp == AL)
44
			if (dirProp == AL)
44
				return true;
45
				return true;
45
			return false;
46
			return false;
46
		}
47
		}
47
48
48
		public int getDirection(STextEnvironment environment, String text, byte[] dirProps) {
49
		public int getDirection(STextEnvironment environment, String text, STextDirections dirProps) {
49
			for (int i = 0; i < text.length(); i++) {
50
			for (int i = 0; i < text.length(); i++) {
50
				byte dirProp = getDirProp(text, dirProps, i);
51
				byte dirProp = dirProps.getOrientationAt(i);
51
				if (dirProp == AL)
52
				if (dirProp == AL)
52
					return dirArabic;
53
					return dirArabic;
53
			}
54
			}
Lines 185-199 Link Here
185
		dirArabic = RTL;
186
		dirArabic = RTL;
186
		dirHebrew = LTR;
187
		dirHebrew = LTR;
187
		msg = "TestDirection #1";
188
		msg = "TestDirection #1";
188
		dirA = processor.getDirection(null, toUT16("###"), null);
189
		String text = toUT16("###");
189
		dirH = processor.getDirection(null, toUT16("ABC"), null);
190
		dirA = processor.getDirection(null, text, new STextDirections(text));
191
		text = toUT16("ABC");
192
		dirH = processor.getDirection(null, toUT16("ABC"), new STextDirections(text));
190
		assertTrue(msg, dirA == RTL && dirH == LTR);
193
		assertTrue(msg, dirA == RTL && dirH == LTR);
191
194
192
		dirArabic = RTL;
195
		dirArabic = RTL;
193
		dirHebrew = RTL;
196
		dirHebrew = RTL;
194
		msg = "TestDirection #2";
197
		msg = "TestDirection #2";
195
		dirA = processor.getDirection(null, toUT16("###"), null);
198
		text = toUT16("###");
196
		dirH = processor.getDirection(null, toUT16("ABC"), null);
199
		dirA = processor.getDirection(null, text, new STextDirections(text));
200
		text = toUT16("ABC");
201
		dirH = processor.getDirection(null, text, new STextDirections(text));
197
		assertTrue(msg, dirA == RTL && dirH == RTL);
202
		assertTrue(msg, dirA == RTL && dirH == RTL);
198
203
199
		dirArabic = dirHebrew = LTR;
204
		dirArabic = dirHebrew = LTR;
Lines 212-219 Link Here
212
217
213
		dirArabic = RTL;
218
		dirArabic = RTL;
214
		msg = "TestDirection #10.5";
219
		msg = "TestDirection #10.5";
215
		dirA = processor.getDirection(null, toUT16("###"), null);
220
		text = toUT16("###");
216
		dirH = processor.getDirection(null, toUT16("ABC"), null);
221
		dirA = processor.getDirection(null, text, new STextDirections(text));
222
		text = toUT16("ABC");
223
		dirH = processor.getDirection(null, text, new STextDirections(text));
217
		assertTrue(msg, dirA == RTL && dirH == LTR);
224
		assertTrue(msg, dirA == RTL && dirH == LTR);
218
		STextEnvironment environment = new STextEnvironment(null, true, STextEnvironment.ORIENT_LTR);
225
		STextEnvironment environment = new STextEnvironment(null, true, STextEnvironment.ORIENT_LTR);
219
		data = "ABC,#DEF,HOST,com";
226
		data = "ABC,#DEF,HOST,com";
(-)src/org/eclipse/equinox/bidi/internal/tests/STextNullProcessorTest.java (-1 / +1 lines)
Lines 14-20 Link Here
14
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEngine;
15
15
16
/**
16
/**
17
 * Tests RTL arithmetic
17
 * Tests null processor
18
 */
18
 */
19
public class STextNullProcessorTest extends STextTestBase {
19
public class STextNullProcessorTest extends STextTestBase {
20
20
(-)src/org/eclipse/equinox/bidi/internal/tests/STextSomeMoreTest.java (-6 / +7 lines)
Lines 13-18 Link Here
13
13
14
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEngine;
15
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.STextEnvironment;
16
import org.eclipse.equinox.bidi.custom.STextDirections;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
17
import org.eclipse.equinox.bidi.custom.STextProcessor;
17
18
18
/**
19
/**
Lines 26-40 Link Here
26
27
27
	class Processor1 extends STextProcessor {
28
	class Processor1 extends STextProcessor {
28
29
29
		public int getSpecialsCount(STextEnvironment env, String text, byte[] dirProps) {
30
		public int getSpecialsCount(STextEnvironment env, String text, STextDirections dirProps) {
30
			return 1;
31
			return 1;
31
		}
32
		}
32
33
33
		public int indexOfSpecial(STextEnvironment env, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
34
		public int indexOfSpecial(STextEnvironment env, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
34
			return fromIndex;
35
			return fromIndex;
35
		}
36
		}
36
37
37
		public int processSpecial(STextEnvironment env, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
38
		public int processSpecial(STextEnvironment env, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
38
			int len = text.length();
39
			int len = text.length();
39
			for (int i = len - 1; i >= 0; i--) {
40
			for (int i = len - 1; i >= 0; i--) {
40
				STextProcessor.insertMark(text, dirProps, offsets, i);
41
				STextProcessor.insertMark(text, dirProps, offsets, i);
Lines 46-52 Link Here
46
47
47
	class Processor2 extends STextProcessor {
48
	class Processor2 extends STextProcessor {
48
49
49
		public int getSpecialsCount(STextEnvironment env, String text, byte[] dirProps) {
50
		public int getSpecialsCount(STextEnvironment env, String text, STextDirections dirProps) {
50
			return 1;
51
			return 1;
51
		}
52
		}
52
53
Lines 54-64 Link Here
54
55
55
	class Processor3 extends STextProcessor {
56
	class Processor3 extends STextProcessor {
56
57
57
		public int getSpecialsCount(STextEnvironment env, String text, byte[] dirProps) {
58
		public int getSpecialsCount(STextEnvironment env, String text, STextDirections dirProps) {
58
			return 1;
59
			return 1;
59
		}
60
		}
60
61
61
		public int indexOfSpecial(STextEnvironment env, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
62
		public int indexOfSpecial(STextEnvironment env, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
62
			return fromIndex;
63
			return fromIndex;
63
		}
64
		}
64
	}
65
	}
(-)src/org/eclipse/equinox/bidi/internal/tests/STextTest.java (-4 / +2 lines)
Lines 10-22 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.tests;
11
package org.eclipse.equinox.bidi.internal.tests;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
14
16
public class STextTest extends STextProcessor {
15
public class STextTest extends STextProcessor {
17
16
18
	public String getSeparators(STextEnvironment env, String text, byte[] dirProps) {
17
	public STextTest() {
19
		return "-=.:";
18
		super("-=.:");
20
	}
19
	}
21
22
}
20
}
(-)src/org/eclipse/equinox/bidi/STextEngine.java (-1 / +3 lines)
Lines 10-15 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
11
package org.eclipse.equinox.bidi;
12
12
13
import org.eclipse.equinox.bidi.custom.STextDirections;
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.internal.STextImpl;
15
import org.eclipse.equinox.bidi.internal.STextImpl;
15
16
Lines 295-300 Link Here
295
		return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
296
		return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
296
	}
297
	}
297
298
299
	// TBD why is this method here and not just in the processor? Is it interesting in general?
298
	/**
300
	/**
299
	 * Get the base direction of a structured text. This base direction may depend on
301
	 * Get the base direction of a structured text. This base direction may depend on
300
	 * whether the text contains Arabic or Hebrew words. If the text contains both, 
302
	 * whether the text contains Arabic or Hebrew words. If the text contains both, 
Lines 312-318 Link Here
312
	public static int getCurDirection(STextProcessor processor, STextEnvironment environment, String text) {
314
	public static int getCurDirection(STextProcessor processor, STextEnvironment environment, String text) {
313
		if (processor == null)
315
		if (processor == null)
314
			return DIR_LTR;
316
			return DIR_LTR;
315
		return STextImpl.getCurDirection(processor, environment, text, null);
317
		return processor.getDirection(environment, text, new STextDirections(text));
316
	}
318
	}
317
319
318
}
320
}
(-)src/org/eclipse/equinox/bidi/STextProcessorFactory.java (+4 lines)
Lines 116-119 Link Here
116
	static public STextProcessor getProcessor(String id) {
116
	static public STextProcessor getProcessor(String id) {
117
		return STextTypesCollector.getInstance().getProcessor(id);
117
		return STextTypesCollector.getInstance().getProcessor(id);
118
	}
118
	}
119
120
	static public STextProcessor getMultiProcessor(String id) {
121
		return new STextProcessorMultipass();
122
	}
119
}
123
}
(-)src/org/eclipse/equinox/bidi/STextProcessorMultipass.java (+47 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.internal.STextImpl;
15
16
public class STextProcessorMultipass extends STextProcessor {
17
18
	private int[] state = new int[] {0};
19
20
	public STextProcessorMultipass() {
21
22
	}
23
24
	public String leanToFullText(STextProcessor processor, STextEnvironment environment, String text) {
25
		return STextImpl.leanToFullText(processor, environment, text, state);
26
	}
27
28
	public int[] leanToFullMap(STextProcessor processor, STextEnvironment environment, String text) {
29
		return STextImpl.leanToFullMap(processor, environment, text, state);
30
	}
31
32
	public int[] leanBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
33
		return STextImpl.leanBidiCharOffsets(processor, environment, text, state);
34
	}
35
36
	public String fullToLeanText(STextProcessor processor, STextEnvironment environment, String text) {
37
		return STextImpl.fullToLeanText(processor, environment, text, state);
38
	}
39
40
	public int[] fullToLeanMap(STextProcessor processor, STextEnvironment environment, String text) {
41
		return STextImpl.fullToLeanMap(processor, environment, text, state);
42
	}
43
44
	public int[] fullBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
45
		return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
46
	}
47
}
(-)src/org/eclipse/equinox/bidi/custom/STextDirections.java (+133 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.custom;
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
15
/**
16
 * The class determines bidirectional types of characters in a string.
17
 */
18
public class STextDirections {
19
20
	// In the following lines, B, L, R and AL represent bidi categories
21
	// as defined in the Unicode Bidirectional Algorithm
22
	// ( http://www.unicode.org/reports/tr9/ ).
23
	// B  represents the category Block Separator.
24
	// L  represents the category Left to Right character.
25
	// R  represents the category Right to Left character.
26
	// AL represents the category Arabic Letter.
27
	// AN represents the category Arabic Number.
28
	// EN  represents the category European Number.
29
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
30
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
31
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
32
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
33
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
34
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
35
36
	// TBD consider moving L, R, AL, AN, EN, B into this class from STextImpl
37
	// TBD add methods:
38
	// isRTL	(dirProp == R || dirProp == AL)
39
	// isLTR	(dirProp == L || dirProp == EN)
40
	// isStrong (isRTL() || isLTR() || dirProp == AN) <= excludes unknown, B, WS
41
42
	final protected String text;
43
44
	// 1 byte for each char in text
45
	private byte[] dirProps;
46
47
	// current orientation
48
	private byte baseOrientation = 0; // "0" means "unknown"
49
50
	public STextDirections(String text) {
51
		this.text = text;
52
		dirProps = new byte[text.length()];
53
	}
54
55
	public void setBaseOrientation(byte orientation) {
56
		baseOrientation = orientation;
57
	}
58
59
	public byte getBaseOrientation() {
60
		return baseOrientation;
61
	}
62
63
	private byte getCachedDirectionAt(int index) {
64
		return (byte) (dirProps[index] - 1);
65
	}
66
67
	private boolean hasCachedDirectionAt(int i) {
68
		return (dirProps[i] != 0); // "0" means "unknown"
69
	}
70
71
	/**
72
	 * @param  dirProp bidirectional class of the character. It must be
73
	 *         one of the values which can be returned by
74
	 *         <code>java.lang.Character.getDirectionality</code>.
75
	 */
76
	public void setOrientationAt(int i, byte dirProp) {
77
		dirProps[i] = (byte) (dirProp + 1);
78
	}
79
80
	public int getBaseOrientation(STextEnvironment environment) {
81
		int result;
82
		int orient = environment.getOrientation();
83
		if ((orient & STextEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) { // absolute orientation
84
			result = orient;
85
		} else { // contextual orientation:
86
			result = orient & 1; // initiate to the default orientation minus contextual bit
87
			int len = text.length();
88
			byte dirProp;
89
			for (int i = 0; i < len; i++) {
90
				if (!hasCachedDirectionAt(i)) {
91
					dirProp = Character.getDirectionality(text.charAt(i));
92
					if (dirProp == B) // B char resolves to L or R depending on orientation
93
						continue;
94
					setOrientationAt(i, dirProp);
95
				} else {
96
					dirProp = getCachedDirectionAt(i);
97
				}
98
				if (dirProp == L) { // TBD || == EN ?
99
					result = STextEnvironment.ORIENT_LTR;
100
					break;
101
				}
102
				if (dirProp == R || dirProp == AL) {
103
					result = STextEnvironment.ORIENT_RTL;
104
					break;
105
				}
106
			}
107
			if (result == -1) // return the default orientation minus contextual bit
108
				result = orient & 1;
109
		}
110
		baseOrientation = (byte) result;
111
		return result;
112
	}
113
114
	/**
115
	 * Returns directionality of the character in the original string at
116
	 * the specified index.
117
	 * @param index position of the character in the <i>lean</i> text
118
	 * @return the bidirectional class of the character. It is one of the
119
	 * values which can be returned by {@link Character#getDirectionality(char)}
120
	 */
121
	public byte getOrientationAt(int index) {
122
		if (hasCachedDirectionAt(index))
123
			return getCachedDirectionAt(index);
124
		byte dirProp = Character.getDirectionality(text.charAt(index));
125
		if (dirProp == B) {
126
			byte orient = getBaseOrientation();
127
			dirProp = (orient == STextEnvironment.ORIENT_RTL) ? R : L;
128
		}
129
		setOrientationAt(index, dirProp);
130
		return dirProp;
131
	}
132
133
}
(-)src/org/eclipse/equinox/bidi/custom/STextProcessor.java (-61 / +8 lines)
Lines 132-138 Link Here
132
	 * number of special cases is zero, which means that
132
	 * number of special cases is zero, which means that
133
	 * <code>indexOfSpecial</code> should never be called for them.
133
	 * <code>indexOfSpecial</code> should never be called for them.
134
	 */
134
	 */
135
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
135
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
136
		// This method must be overridden by all subclasses with special cases.
136
		// This method must be overridden by all subclasses with special cases.
137
		throw new IllegalStateException("A processor with specialsCount > 0 must have an indexOfSpecial() method."); //$NON-NLS-1$
137
		throw new IllegalStateException("A processor with specialsCount > 0 must have an indexOfSpecial() method."); //$NON-NLS-1$
138
	}
138
	}
Lines 216-277 Link Here
216
	 * number of special cases is zero, which means that
216
	 * number of special cases is zero, which means that
217
	 * <code>processSpecial</code> should never be called for them.
217
	 * <code>processSpecial</code> should never be called for them.
218
	 */
218
	 */
219
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
219
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
220
		// This method must be overridden by all subclasses with any special case.
220
		// This method must be overridden by all subclasses with any special case.
221
		throw new IllegalStateException("A processor with specialsCount > 0 must have a processSpecial() method."); //$NON-NLS-1$
221
		throw new IllegalStateException("A processor with specialsCount > 0 must have a processSpecial() method."); //$NON-NLS-1$
222
	}
223
224
	/**
225
	 * This method can be called from within {@link #indexOfSpecial} or
226
	 * {@link #processSpecial} in extensions of <code>STextProcessor</code> to retrieve
227
	 * the bidirectional class of characters in the <i>lean</i> text.
228
	 *
229
	 * @param  text is the structured text string received as
230
	 *         parameter to <code>indexOfSpecial</code> or
231
	 *         <code>processSpecial</code>.
232
	 *
233
	 * @param  dirProps is a parameter received by <code>indexOfSpecial</code>
234
	 *         or <code>processSpecial</code>, uniquely to be used as argument
235
	 *         for calls to <code>getDirProp</code> and other methods used
236
	 *         by processors.
237
	 *
238
	 * @param index position of the character in the <i>lean</i> text.
239
	 *         It must be a non-negative number smaller than the length
240
	 *         of the <i>lean</i> text.
241
	 *
242
	 * @return the bidirectional class of the character. It is one of the
243
	 *         values which can be returned by
244
	 *         <code>java.lang.Character.getDirectionality</code>.
245
	 *         However, it is recommended to use <code>getDirProp</code>
246
	 *         rather than <code>java.lang.Character.getDirectionality</code>
247
	 *         since <code>getDirProp</code> manages a cache of character
248
	 *         properties and so can be more efficient than calling the
249
	 *         java.lang.Character method.
250
	 */
251
	public static final byte getDirProp(String text, byte[] dirProps, int index) {
252
		return STextImpl.getDirProp(text, dirProps, index);
253
	}
254
255
	/**
256
	 * This method can be called from within {@link #indexOfSpecial} or
257
	 * {@link #processSpecial} in extensions of <code>STextProcessor</code> to set or
258
	 * override the bidirectional class of characters in the <i>lean</i> text.
259
	 *
260
	 * @param  dirProps is a parameter received by <code>indexOfSpecial</code>
261
	 *         or <code>processSpecial</code>, uniquely to be used as argument
262
	 *         for calls to <code>setDirProp</code> and other methods used
263
	 *         by processors.
264
	 *
265
	 * @param index position of the character in the <i>lean</i> text.
266
	 *         It must be a non-negative number smaller than the length
267
	 *         of the <i>lean</i> text.
268
	 *
269
	 * @param  dirProp bidirectional class of the character. It must be
270
	 *         one of the values which can be returned by
271
	 *         <code>java.lang.Character.getDirectionality</code>.
272
	 */
273
	public static final void setDirProp(byte[] dirProps, int index, byte dirProp) {
274
		STextImpl.setDirProp(dirProps, index, dirProp);
275
	}
222
	}
276
223
277
	/**
224
	/**
Lines 305-311 Link Here
305
	 *         For the benefit of efficiency, it is better to insert
252
	 *         For the benefit of efficiency, it is better to insert
306
	 *         multiple marks in ascending order of the offsets.
253
	 *         multiple marks in ascending order of the offsets.
307
	 */
254
	 */
308
	public static final void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
255
	public static final void insertMark(String text, STextDirections dirProps, int[] offsets, int offset) {
309
		STextImpl.insertMark(text, dirProps, offsets, offset);
256
		STextImpl.insertMark(text, dirProps, offsets, offset);
310
	}
257
	}
311
258
Lines 340-346 Link Here
340
	 *         It must be a non-negative number smaller than the length
287
	 *         It must be a non-negative number smaller than the length
341
	 *         of the <i>lean</i> text.
288
	 *         of the <i>lean</i> text.
342
	 */
289
	 */
343
	public static final void processSeparator(String text, byte[] dirProps, int[] offsets, int separLocation) {
290
	public static final void processSeparator(String text, STextDirections dirProps, int[] offsets, int separLocation) {
344
		STextImpl.processSeparator(text, dirProps, offsets, separLocation);
291
		STextImpl.processSeparator(text, dirProps, offsets, separLocation);
345
	}
292
	}
346
293
Lines 365-371 Link Here
365
	 * @return a string grouping one-character separators which separate
312
	 * @return a string grouping one-character separators which separate
366
	 *         the structured text into tokens.
313
	 *         the structured text into tokens.
367
	 */
314
	 */
368
	public String getSeparators(STextEnvironment environment, String text, byte[] dirProps) {
315
	public String getSeparators(STextEnvironment environment, String text, STextDirections dirProps) {
369
		return separators;
316
		return separators;
370
	}
317
	}
371
318
Lines 394-400 Link Here
394
	 *         The value returned is either
341
	 *         The value returned is either
395
	 *         {@link STextEngine#DIR_LTR DIR_LTR} or {@link STextEngine#DIR_RTL DIR_RTL}.
342
	 *         {@link STextEngine#DIR_LTR DIR_LTR} or {@link STextEngine#DIR_RTL DIR_RTL}.
396
	 */
343
	 */
397
	public int getDirection(STextEnvironment environment, String text, byte[] dirProps) {
344
	public int getDirection(STextEnvironment environment, String text, STextDirections dirProps) {
398
		return STextEngine.DIR_LTR;
345
		return STextEngine.DIR_LTR;
399
	}
346
	}
400
347
Lines 426-432 Link Here
426
	 *         anything which is not identified by a one-character separator.
373
	 *         anything which is not identified by a one-character separator.
427
	 *
374
	 *
428
	 */
375
	 */
429
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
376
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
430
		return 0;
377
		return 0;
431
	}
378
	}
432
379
Lines 455-461 Link Here
455
	 *         text to add directional formatting characters.
402
	 *         text to add directional formatting characters.
456
	 *
403
	 *
457
	 */
404
	 */
458
	public boolean skipProcessing(STextEnvironment environment, String text, byte[] dirProps) {
405
	public boolean skipProcessing(STextEnvironment environment, String text, STextDirections dirProps) {
459
		return false;
406
		return false;
460
	}
407
	}
461
408
(-)src/org/eclipse/equinox/bidi/internal/STextDelims.java (-2 / +3 lines)
Lines 11-16 Link Here
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextDirections;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
16
/**
17
/**
Lines 43-49 Link Here
43
	 *
44
	 *
44
	 *  @see #getDelimiters
45
	 *  @see #getDelimiters
45
	 */
46
	 */
46
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
47
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
47
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
48
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
48
		return text.indexOf(delim, fromIndex);
49
		return text.indexOf(delim, fromIndex);
49
	}
50
	}
Lines 58-64 Link Here
58
	 *  @return the position after the matching end delimiter, or the length
59
	 *  @return the position after the matching end delimiter, or the length
59
	 *          of <code>text</code> if no end delimiter is found.
60
	 *          of <code>text</code> if no end delimiter is found.
60
	 */
61
	 */
61
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
62
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
62
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
63
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
63
		int loc = separLocation + 1;
64
		int loc = separLocation + 1;
64
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
65
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
(-)src/org/eclipse/equinox/bidi/internal/STextDelimsEsc.java (-1 / +2 lines)
Lines 11-16 Link Here
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextDirections;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
16
/**
17
/**
Lines 49-55 Link Here
49
	 *  and skips until after the matching end delimiter,
50
	 *  and skips until after the matching end delimiter,
50
	 *  ignoring possibly escaped end delimiters.
51
	 *  ignoring possibly escaped end delimiters.
51
	 */
52
	 */
52
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
53
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
53
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
54
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
54
		int location = separLocation + 1;
55
		int location = separLocation + 1;
55
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
56
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
(-)src/org/eclipse/equinox/bidi/internal/STextImpl.java (-116 / +33 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
17
/**
18
/**
Lines 25-36 Link Here
25
public class STextImpl {
26
public class STextImpl {
26
27
27
	static final String EMPTY_STRING = ""; //$NON-NLS-1$
28
	static final String EMPTY_STRING = ""; //$NON-NLS-1$
29
30
	// In the following lines, B, L, R and AL represent bidi categories
31
	// as defined in the Unicode Bidirectional Algorithm
32
	// ( http://www.unicode.org/reports/tr9/ ).
33
	// B  represents the category Block Separator.
34
	// L  represents the category Left to Right character.
35
	// R  represents the category Right to Left character.
36
	// AL represents the category Arabic Letter.
37
	// AN represents the category Arabic Number.
38
	// EN  represents the category European Number.
28
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
39
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
29
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
40
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
30
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
41
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
31
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
42
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
32
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
43
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
33
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
44
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
45
34
	static final char LRM = 0x200E;
46
	static final char LRM = 0x200E;
35
	static final char RLM = 0x200F;
47
	static final char RLM = 0x200F;
36
	static final char LRE = 0x202A;
48
	static final char LRE = 0x202A;
Lines 42-48 Link Here
42
	static final int PREFIX_LENGTH = 2;
54
	static final int PREFIX_LENGTH = 2;
43
	static final int SUFFIX_LENGTH = 2;
55
	static final int SUFFIX_LENGTH = 2;
44
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
56
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
45
	static final int DIRPROPS_ADD = 2;
46
	static final int OFFSETS_SHIFT = 3;
57
	static final int OFFSETS_SHIFT = 3;
47
	static final int[] EMPTY_INT_ARRAY = new int[0];
58
	static final int[] EMPTY_INT_ARRAY = new int[0];
48
	static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE);
59
	static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE);
Lines 54-60 Link Here
54
		// nothing to do
65
		// nothing to do
55
	}
66
	}
56
67
57
	static long computeNextLocation(STextProcessor processor, STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] locations, int[] state, int curPos) {
68
	static long computeNextLocation(STextProcessor processor, STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] locations, int[] state, int curPos) {
58
		String separators = processor.getSeparators(environment, text, dirProps);
69
		String separators = processor.getSeparators(environment, text, dirProps);
59
		int separCount = separators.length();
70
		int separCount = separators.length();
60
		int specialsCount = processor.getSpecialsCount(environment, text, dirProps);
71
		int specialsCount = processor.getSpecialsCount(environment, text, dirProps);
Lines 91-197 Link Here
91
			}
102
			}
92
		}
103
		}
93
		return nextLocation + (((long) idxLocation) << 32);
104
		return nextLocation + (((long) idxLocation) << 32);
94
	}
95
96
	static int getCurOrient(STextEnvironment environment, String text, byte[] dirProps) {
97
		int orient = environment.getOrientation();
98
		if ((orient & STextEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) {
99
			// absolute orientation
100
			return orient;
101
		}
102
		// contextual orientation
103
		int len = text.length();
104
		byte dirProp;
105
		for (int i = 0; i < len; i++) {
106
			// In the following lines, B, L, R and AL represent bidi categories
107
			// as defined in the Unicode Bidirectional Algorithm
108
			// ( http://www.unicode.org/reports/tr9/ ).
109
			// B  represents the category Block Separator.
110
			// L  represents the category Left to Right character.
111
			// R  represents the category Right to Left character.
112
			// AL represents the category Arabic Letter.
113
			dirProp = dirProps[i];
114
			if (dirProp == 0) {
115
				dirProp = Character.getDirectionality(text.charAt(i));
116
				if (dirProp == B) // B char resolves to L or R depending on orientation
117
					continue;
118
				dirProps[i] = (byte) (dirProp + DIRPROPS_ADD);
119
			} else {
120
				dirProp -= DIRPROPS_ADD;
121
			}
122
			if (dirProp == L)
123
				return STextEnvironment.ORIENT_LTR;
124
			if (dirProp == R || dirProp == AL)
125
				return STextEnvironment.ORIENT_RTL;
126
		}
127
		// return the default orientation corresponding to the contextual orientation
128
		return orient & 1;
129
	}
130
131
	/**
132
	 *  @see STextEngine#getCurDirection STextEngine.getCurDirection
133
	 */
134
	public static int getCurDirection(STextProcessor processor, STextEnvironment environment, String text, byte[] dirProps) {
135
		return processor.getDirection(environment, text, dirProps);
136
	}
137
138
	/**
139
	 *  @see STextProcessor#getDirProp STextProcessor.getDirProp
140
	 */
141
	public static byte getDirProp(String text, byte[] dirProps, int index) {
142
		byte dirProp = dirProps == null ? 0 : dirProps[index];
143
		if (dirProp == 0) {
144
			// In the following lines, B, L and R represent bidi categories
145
			// as defined in the Unicode Bidirectional Algorithm
146
			// ( http://www.unicode.org/reports/tr9/ ).
147
			// B  represents the category Block Separator.
148
			// L  represents the category Left to Right character.
149
			// R  represents the category Right to Left character.
150
			dirProp = Character.getDirectionality(text.charAt(index));
151
			if (dirProp == B && dirProps != null) {
152
				// the last entry of dirProps contains the current component orientation
153
				byte orient = dirProps[dirProps.length - 1];
154
				if (orient == -1)
155
					return B;
156
				dirProp = orient == STextEnvironment.ORIENT_RTL ? R : L;
157
			}
158
			if (dirProps != null)
159
				dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
160
			return dirProp;
161
		}
162
		return (byte) (dirProp - DIRPROPS_ADD);
163
	}
164
165
	/**
166
	 *  @see STextProcessor#setDirProp STextProcessor.setDirProp
167
	 */
168
	public static void setDirProp(byte[] dirProps, int index, byte dirProp) {
169
		dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
170
	}
105
	}
171
106
172
	/**
107
	/**
173
	 *  @see STextProcessor#processSeparator STextProcessor.processSeparator
108
	 *  @see STextProcessor#processSeparator STextProcessor.processSeparator
174
	 */
109
	 */
175
	public static void processSeparator(String text, byte[] dirProps, int[] offsets, int separLocation) {
110
	public static void processSeparator(String text, STextDirections dirProps, int[] offsets, int separLocation) {
176
		// In this method, L, R, AL, AN and EN represent bidi categories
177
		// as defined in the Unicode Bidirectional Algorithm
178
		// ( http://www.unicode.org/reports/tr9/ ).
179
		// L  represents the category Left to Right character.
180
		// R  represents the category Right to Left character.
181
		// AL represents the category Arabic Letter.
182
		// AN represents the category Arabic Number.
183
		// EN  represents the category European Number.
184
		int len = text.length();
111
		int len = text.length();
185
		// offsets[2] contains the structured text direction
112
		// offsets[2] contains the structured text direction
186
		if (offsets[2] == STextEngine.DIR_RTL) {
113
		if (offsets[2] == STextEngine.DIR_RTL) {
187
			// the structured text base direction is RTL
114
			// the structured text base direction is RTL
188
			for (int i = separLocation - 1; i >= 0; i--) {
115
			for (int i = separLocation - 1; i >= 0; i--) {
189
				byte dirProp = getDirProp(text, dirProps, i);
116
				byte dirProp = dirProps.getOrientationAt(i);
190
				if (dirProp == R || dirProp == AL)
117
				if (dirProp == R || dirProp == AL)
191
					return;
118
					return;
192
				if (dirProp == L) {
119
				if (dirProp == L) {
193
					for (int j = separLocation; j < len; j++) {
120
					for (int j = separLocation; j < len; j++) {
194
						dirProp = getDirProp(text, dirProps, j);
121
						dirProp = dirProps.getOrientationAt(j);
195
						if (dirProp == R || dirProp == AL)
122
						if (dirProp == R || dirProp == AL)
196
							return;
123
							return;
197
						if (dirProp == L || dirProp == EN) {
124
						if (dirProp == L || dirProp == EN) {
Lines 208-219 Link Here
208
		// the structured text base direction is LTR
135
		// the structured text base direction is LTR
209
		boolean doneAN = false;
136
		boolean doneAN = false;
210
		for (int i = separLocation - 1; i >= 0; i--) {
137
		for (int i = separLocation - 1; i >= 0; i--) {
211
			byte dirProp = getDirProp(text, dirProps, i);
138
			byte dirProp = dirProps.getOrientationAt(i);
212
			if (dirProp == L)
139
			if (dirProp == L)
213
				return;
140
				return;
214
			if (dirProp == R || dirProp == AL) {
141
			if (dirProp == R || dirProp == AL) {
215
				for (int j = separLocation; j < len; j++) {
142
				for (int j = separLocation; j < len; j++) {
216
					dirProp = getDirProp(text, dirProps, j);
143
					dirProp = dirProps.getOrientationAt(j);
217
					if (dirProp == L)
144
					if (dirProp == L)
218
						return;
145
						return;
219
					if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
146
					if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
Lines 225-231 Link Here
225
			}
152
			}
226
			if (dirProp == AN && !doneAN) {
153
			if (dirProp == AN && !doneAN) {
227
				for (int j = separLocation; j < len; j++) {
154
				for (int j = separLocation; j < len; j++) {
228
					dirProp = getDirProp(text, dirProps, j);
155
					dirProp = dirProps.getOrientationAt(j);
229
					if (dirProp == L)
156
					if (dirProp == L)
230
						return;
157
						return;
231
					if (dirProp == AL || dirProp == AN || dirProp == R) {
158
					if (dirProp == AL || dirProp == AN || dirProp == R) {
Lines 285-291 Link Here
285
		int len = text.length();
212
		int len = text.length();
286
		if (len == 0)
213
		if (len == 0)
287
			return text;
214
			return text;
288
		byte[] dirProps = new byte[len + 1];
215
		STextDirections dirProps = new STextDirections(text);
289
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
216
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
290
		int prefixLength = offsets[1];
217
		int prefixLength = offsets[1];
291
		int count = offsets[0] - OFFSETS_SHIFT;
218
		int count = offsets[0] - OFFSETS_SHIFT;
Lines 336-342 Link Here
336
		int len = text.length();
263
		int len = text.length();
337
		if (len == 0)
264
		if (len == 0)
338
			return EMPTY_INT_ARRAY;
265
			return EMPTY_INT_ARRAY;
339
		byte[] dirProps = new byte[len + 1];
266
		STextDirections dirProps = new STextDirections(text);
340
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
267
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
341
		int prefixLength = offsets[1];
268
		int prefixLength = offsets[1];
342
		int[] map = new int[len];
269
		int[] map = new int[len];
Lines 359-365 Link Here
359
		int len = text.length();
286
		int len = text.length();
360
		if (len == 0)
287
		if (len == 0)
361
			return EMPTY_INT_ARRAY;
288
			return EMPTY_INT_ARRAY;
362
		byte[] dirProps = new byte[len + 1];
289
		STextDirections dirProps = new STextDirections(text);
363
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
290
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
364
		// offsets[0] contains the number of used entries
291
		// offsets[0] contains the number of used entries
365
		int count = offsets[0] - OFFSETS_SHIFT;
292
		int count = offsets[0] - OFFSETS_SHIFT;
Lines 368-374 Link Here
368
		return result;
295
		return result;
369
	}
296
	}
370
297
371
	static int[] leanToFullCommon(STextProcessor processor, STextEnvironment environment, String text, int[] state, byte[] dirProps) {
298
	static int[] leanToFullCommon(STextProcessor processor, STextEnvironment environment, String text, int[] state, STextDirections dirProps) {
372
		if (environment == null)
299
		if (environment == null)
373
			environment = STextEnvironment.DEFAULT;
300
			environment = STextEnvironment.DEFAULT;
374
		if (state == null) {
301
		if (state == null) {
Lines 376-384 Link Here
376
			state[0] = STextEngine.STATE_INITIAL;
303
			state[0] = STextEngine.STATE_INITIAL;
377
		}
304
		}
378
		int len = text.length();
305
		int len = text.length();
379
		// dirProps: 1 byte for each char in text, + 1 byte = current orientation
306
		int orient = dirProps.getBaseOrientation(environment);
380
		int orient = getCurOrient(environment, text, dirProps);
381
		dirProps[len] = (byte) orient;
382
		int direction = processor.getDirection(environment, text, dirProps);
307
		int direction = processor.getDirection(environment, text, dirProps);
383
		// offsets of marks to add. Entry 0 is the number of used slots;
308
		// offsets of marks to add. Entry 0 is the number of used slots;
384
		//  entry 1 is reserved to pass prefixLength.
309
		//  entry 1 is reserved to pass prefixLength.
Lines 428-435 Link Here
428
			offsets[1] = 0;
353
			offsets[1] = 0;
429
		else {
354
		else {
430
			// recompute orient since it may have changed if contextual
355
			// recompute orient since it may have changed if contextual
431
			orient = getCurOrient(environment, text, dirProps);
356
			orient = dirProps.getBaseOrientation(environment);
432
			dirProps[len] = (byte) orient;
433
			if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN)
357
			if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN)
434
				offsets[1] = 0;
358
				offsets[1] = 0;
435
			else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
359
			else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
Lines 452-458 Link Here
452
			state = new int[1];
376
			state = new int[1];
453
			state[0] = STextEngine.STATE_INITIAL;
377
			state[0] = STextEngine.STATE_INITIAL;
454
		}
378
		}
455
		int dir = processor.getDirection(environment, text, null);
379
		int dir = processor.getDirection(environment, text, new STextDirections(text));
456
		char curMark = MARKS[dir];
380
		char curMark = MARKS[dir];
457
		char curEmbed = EMBEDS[dir];
381
		char curEmbed = EMBEDS[dir];
458
		int i; // used as loop index
382
		int i; // used as loop index
Lines 544-550 Link Here
544
			return EMPTY_INT_ARRAY;
468
			return EMPTY_INT_ARRAY;
545
		String lean = fullToLeanText(processor, environment, full, state);
469
		String lean = fullToLeanText(processor, environment, full, state);
546
		int lenLean = lean.length();
470
		int lenLean = lean.length();
547
		int dir = processor.getDirection(environment, lean, null);
471
		int dir = processor.getDirection(environment, lean, new STextDirections(lean));
548
		char curMark = MARKS[dir];
472
		char curMark = MARKS[dir];
549
		char curEmbed = EMBEDS[dir];
473
		char curEmbed = EMBEDS[dir];
550
		int[] map = new int[lenFull];
474
		int[] map = new int[lenFull];
Lines 581-598 Link Here
581
		offsets[0] = OFFSETS_SHIFT;
505
		offsets[0] = OFFSETS_SHIFT;
582
		int lenLean = lean.length();
506
		int lenLean = lean.length();
583
		int idxLean, idxFull;
507
		int idxLean, idxFull;
508
		STextDirections dirProps = new STextDirections(full);
584
		// lean must be a subset of Full, so we only check on iLean < leanLen
509
		// lean must be a subset of Full, so we only check on iLean < leanLen
585
		for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) {
510
		for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) {
586
			if (full.charAt(idxFull) == lean.charAt(idxLean))
511
			if (full.charAt(idxFull) == lean.charAt(idxLean))
587
				idxLean++;
512
				idxLean++;
588
			else {
513
			else {
589
				offsets = ensureRoomInOffsets(offsets);
514
				offsets = ensureRoomInOffsets(offsets);
590
				insertMark(lean, null, offsets, idxFull);
515
				insertMark(lean, dirProps, offsets, idxFull);
591
			}
516
			}
592
		}
517
		}
593
		for (; idxFull < lenFull; idxFull++) {
518
		for (; idxFull < lenFull; idxFull++) {
594
			offsets = ensureRoomInOffsets(offsets);
519
			offsets = ensureRoomInOffsets(offsets);
595
			insertMark(lean, null, offsets, idxFull);
520
			insertMark(lean, dirProps, offsets, idxFull);
596
		}
521
		}
597
		int[] result = new int[offsets[0] - OFFSETS_SHIFT];
522
		int[] result = new int[offsets[0] - OFFSETS_SHIFT];
598
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length);
523
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length);
Lines 612-618 Link Here
612
	/**
537
	/**
613
	 *  @see STextProcessor#insertMark STextProcessor.insertMark
538
	 *  @see STextProcessor#insertMark STextProcessor.insertMark
614
	 */
539
	 */
615
	public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
540
	public static void insertMark(String text, STextDirections dirProps, int[] offsets, int offset) {
616
		int count = offsets[0];// number of used entries
541
		int count = offsets[0];// number of used entries
617
		int index = count - 1; // index of greatest member <= offset
542
		int index = count - 1; // index of greatest member <= offset
618
		// look up after which member the new offset should be inserted
543
		// look up after which member the new offset should be inserted
Lines 634-650 Link Here
634
		if (dirProps == null || offset < 1)
559
		if (dirProps == null || offset < 1)
635
			return;
560
			return;
636
561
637
		byte dirProp = getDirProp(text, dirProps, offset);
562
		byte dirProp = dirProps.getOrientationAt(offset);
638
		// if the current char is a strong one or a digit, we change the
563
		// if the current char is a strong one or a digit, we change the
639
		//   dirProp of the previous char to account for the inserted mark.
564
		//   dirProp of the previous char to account for the inserted mark.
640
		// In the following lines, L, R, AL, AN and EN represent bidi categories
641
		// as defined in the Unicode Bidirectional Algorithm
642
		// ( http://www.unicode.org/reports/tr9/ ).
643
		// L  represents the category Left to Right character.
644
		// R  represents the category Right to Left character.
645
		// AL represents the category Arabic Letter.
646
		// AN represents the category Arabic Number.
647
		// EN  represents the category European Number.
648
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
565
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
649
			index = offset - 1;
566
			index = offset - 1;
650
		else
567
		else
Lines 652-658 Link Here
652
			index = offset;
569
			index = offset;
653
570
654
		int dir = offsets[2]; // current structured text direction
571
		int dir = offsets[2]; // current structured text direction
655
		setDirProp(dirProps, index, STRONGS[dir]);
572
		dirProps.setOrientationAt(index, STRONGS[dir]);
656
		return;
573
		return;
657
	}
574
	}
658
575
(-)src/org/eclipse/equinox/bidi/internal/STextSingle.java (-3 / +4 lines)
Lines 11-16 Link Here
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextDirections;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
16
/**
17
/**
Lines 40-46 Link Here
40
	 *
41
	 *
41
	 *  @see #getSeparators getSeparators
42
	 *  @see #getSeparators getSeparators
42
	 */
43
	 */
43
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
44
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
44
		return text.indexOf(this.getSeparators(environment, text, dirProps).charAt(0), fromIndex);
45
		return text.indexOf(this.getSeparators(environment, text, dirProps).charAt(0), fromIndex);
45
	}
46
	}
46
47
Lines 50-56 Link Here
50
	 *
51
	 *
51
	 *  @return the length of <code>text</code>.
52
	 *  @return the length of <code>text</code>.
52
	 */
53
	 */
53
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
54
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
54
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
55
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
55
		return text.length();
56
		return text.length();
56
	}
57
	}
Lines 60-66 Link Here
60
	 *
61
	 *
61
	 *  @return 1.
62
	 *  @return 1.
62
	 */
63
	 */
63
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
64
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
64
		return 1;
65
		return 1;
65
	}
66
	}
66
67
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextEmail.java (-4 / +4 lines)
Lines 12-18 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
16
import org.eclipse.equinox.bidi.internal.STextDelimsEsc;
16
import org.eclipse.equinox.bidi.internal.STextDelimsEsc;
17
17
18
/**
18
/**
Lines 38-44 Link Here
38
	 *          </ul>
38
	 *          </ul>
39
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
39
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
40
	 */
40
	 */
41
	public int getDirection(STextEnvironment environment, String text, byte[] dirProps) {
41
	public int getDirection(STextEnvironment environment, String text, STextDirections dirProps) {
42
		String language = environment.getLanguage();
42
		String language = environment.getLanguage();
43
		if (!language.equals("ar")) //$NON-NLS-1$
43
		if (!language.equals("ar")) //$NON-NLS-1$
44
			return STextEngine.DIR_LTR;
44
			return STextEngine.DIR_LTR;
Lines 47-53 Link Here
47
		if (domainStart < 0)
47
		if (domainStart < 0)
48
			domainStart = 0;
48
			domainStart = 0;
49
		for (int i = domainStart; i < text.length(); i++) {
49
		for (int i = domainStart; i < text.length(); i++) {
50
			byte dirProp = STextProcessor.getDirProp(text, dirProps, i);
50
			byte dirProp = dirProps.getOrientationAt(i);
51
			if (dirProp == AL || dirProp == R)
51
			if (dirProp == AL || dirProp == R)
52
				return STextEngine.DIR_RTL;
52
				return STextEngine.DIR_RTL;
53
		}
53
		}
Lines 57-63 Link Here
57
	/**
57
	/**
58
	 *  @return 2 as number of special cases handled by this processor.
58
	 *  @return 2 as number of special cases handled by this processor.
59
	 */
59
	 */
60
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
60
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
61
		return 2;
61
		return 2;
62
	}
62
	}
63
63
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextJava.java (-4 / +5 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.internal.STextActivator;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
17
18
Lines 45-51 Link Here
45
	/**
46
	/**
46
	 *  @return 4 as the number of special cases handled by this processor.
47
	 *  @return 4 as the number of special cases handled by this processor.
47
	 */
48
	 */
48
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
49
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
49
		return 4;
50
		return 4;
50
	}
51
	}
51
52
Lines 58-64 Link Here
58
	     *    <li>comments starting with slash-slash</li>
59
	     *    <li>comments starting with slash-slash</li>
59
	     *  </ol>
60
	     *  </ol>
60
	     */
61
	     */
61
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
62
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
62
		switch (caseNumber) {
63
		switch (caseNumber) {
63
			case 1 : /* space */
64
			case 1 : /* space */
64
				return text.indexOf(' ', fromIndex);
65
				return text.indexOf(' ', fromIndex);
Lines 82-88 Link Here
82
	     *    <li>skip until after a line separator</li>
83
	     *    <li>skip until after a line separator</li>
83
	     *  </ol>
84
	     *  </ol>
84
	 */
85
	 */
85
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
86
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
86
		int location, counter, i;
87
		int location, counter, i;
87
88
88
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
89
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
Lines 90-96 Link Here
90
			case 1 : /* space */
91
			case 1 : /* space */
91
				separLocation++;
92
				separLocation++;
92
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
93
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
93
					STextProcessor.setDirProp(dirProps, separLocation, WS);
94
					dirProps.setOrientationAt(separLocation, WS);
94
					separLocation++;
95
					separLocation++;
95
				}
96
				}
96
				return separLocation;
97
				return separLocation;
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextMath.java (-2 / +3 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
17
/**
18
/**
Lines 40-52 Link Here
40
	 *          </ul>
41
	 *          </ul>
41
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
42
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
42
	 */
43
	 */
43
	public int getDirection(STextEnvironment environment, String text, byte[] dirProps) {
44
	public int getDirection(STextEnvironment environment, String text, STextDirections dirProps) {
44
		String language = environment.getLanguage();
45
		String language = environment.getLanguage();
45
		if (!language.equals("ar")) //$NON-NLS-1$
46
		if (!language.equals("ar")) //$NON-NLS-1$
46
			return STextEngine.DIR_LTR;
47
			return STextEngine.DIR_LTR;
47
		boolean flagAN = false;
48
		boolean flagAN = false;
48
		for (int i = 0; i < text.length(); i++) {
49
		for (int i = 0; i < text.length(); i++) {
49
			byte dirProp = getDirProp(text, dirProps, i);
50
			byte dirProp = dirProps.getOrientationAt(i);
50
			if (dirProp == AL)
51
			if (dirProp == AL)
51
				return STextEngine.DIR_RTL;
52
				return STextEngine.DIR_RTL;
52
			if (dirProp == L || dirProp == R)
53
			if (dirProp == L || dirProp == R)
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextRegex.java (-9 / +10 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
17
/**
18
/**
Lines 68-74 Link Here
68
	 *  
69
	 *  
69
	 *  @return the number of special cases for this processor.
70
	 *  @return the number of special cases for this processor.
70
	 */
71
	 */
71
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
72
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
72
		return maxSpecial;
73
		return maxSpecial;
73
	}
74
	}
74
75
Lines 76-82 Link Here
76
	 *  This method locates occurrences of the syntactic strings and of
77
	 *  This method locates occurrences of the syntactic strings and of
77
	 *  R, AL, EN, AN characters.
78
	 *  R, AL, EN, AN characters.
78
	 */
79
	 */
79
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
80
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
80
		// In this method, L, R, AL, AN and EN represent bidi categories
81
		// In this method, L, R, AL, AN and EN represent bidi categories
81
		// as defined in the Unicode Bidirectional Algorithm
82
		// as defined in the Unicode Bidirectional Algorithm
82
		// ( http://www.unicode.org/reports/tr9/ ).
83
		// ( http://www.unicode.org/reports/tr9/ ).
Lines 112-129 Link Here
112
			fromIndex = 1;
113
			fromIndex = 1;
113
		// look for R, AL, AN, EN which are potentially needing a mark
114
		// look for R, AL, AN, EN which are potentially needing a mark
114
		for (; fromIndex < text.length(); fromIndex++) {
115
		for (; fromIndex < text.length(); fromIndex++) {
115
			dirProp = STextProcessor.getDirProp(text, dirProps, fromIndex);
116
			dirProp = dirProps.getOrientationAt(fromIndex);
116
			// R and AL will always be examined using processSeparator()
117
			// R and AL will always be examined using processSeparator()
117
			if (dirProp == R || dirProp == AL)
118
			if (dirProp == R || dirProp == AL)
118
				return fromIndex;
119
				return fromIndex;
119
120
120
			if (dirProp == EN || dirProp == AN) {
121
			if (dirProp == EN || dirProp == AN) {
121
				// no need for a mark after the first digit in a number
122
				// no need for a mark after the first digit in a number
122
				if (STextProcessor.getDirProp(text, dirProps, fromIndex - 1) == dirProp)
123
				if (dirProps.getOrientationAt(fromIndex - 1) == dirProp)
123
					continue;
124
					continue;
124
125
125
				for (int i = fromIndex - 1; i >= 0; i--) {
126
				for (int i = fromIndex - 1; i >= 0; i--) {
126
					dirProp = STextProcessor.getDirProp(text, dirProps, i);
127
					dirProp = dirProps.getOrientationAt(i);
127
					// after a L char, no need for a mark
128
					// after a L char, no need for a mark
128
					if (dirProp == L)
129
					if (dirProp == L)
129
						continue;
130
						continue;
Lines 144-150 Link Here
144
	/**
145
	/**
145
	 *  This method process the special cases.
146
	 *  This method process the special cases.
146
	 */
147
	 */
147
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
148
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
148
		int location;
149
		int location;
149
150
150
		switch (caseNumber) {
151
		switch (caseNumber) {
Lines 203-209 Link Here
203
					return text.length();
204
					return text.length();
204
				}
205
				}
205
				// set the dirProp for the "E" to L (Left to Right character)
206
				// set the dirProp for the "E" to L (Left to Right character)
206
				STextProcessor.setDirProp(dirProps, location + 1, L);
207
				dirProps.setOrientationAt(location + 1, L);
207
				return location + 2;
208
				return location + 2;
208
			case 18 : /* R, AL, AN, EN */
209
			case 18 : /* R, AL, AN, EN */
209
				STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
210
				STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
Lines 226-237 Link Here
226
	 *          </ul>
227
	 *          </ul>
227
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
228
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
228
	 */
229
	 */
229
	public int getDirection(STextEnvironment environment, String text, byte[] dirProps) {
230
	public int getDirection(STextEnvironment environment, String text, STextDirections dirProps) {
230
		String language = environment.getLanguage();
231
		String language = environment.getLanguage();
231
		if (!language.equals("ar")) //$NON-NLS-1$
232
		if (!language.equals("ar")) //$NON-NLS-1$
232
			return STextEngine.DIR_LTR;
233
			return STextEngine.DIR_LTR;
233
		for (int i = 0; i < text.length(); i++) {
234
		for (int i = 0; i < text.length(); i++) {
234
			byte dirProp = getDirProp(text, dirProps, i);
235
			byte dirProp = dirProps.getOrientationAt(i);
235
			if (dirProp == AL || dirProp == R)
236
			if (dirProp == AL || dirProp == R)
236
				return STextEngine.DIR_RTL;
237
				return STextEngine.DIR_RTL;
237
			if (dirProp == L)
238
			if (dirProp == L)
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextSql.java (-4 / +5 lines)
Lines 12-17 Link Here
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextDirections;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.internal.STextActivator;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
17
18
Lines 45-51 Link Here
45
	/**
46
	/**
46
	 *  @return 5 as the number of special cases handled by this processor.
47
	 *  @return 5 as the number of special cases handled by this processor.
47
	 */
48
	 */
48
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
49
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
49
		return 5;
50
		return 5;
50
	}
51
	}
51
52
Lines 59-65 Link Here
59
	  *    <li>comments starting with hyphen-hyphen</li>
60
	  *    <li>comments starting with hyphen-hyphen</li>
60
	  *  </ol>
61
	  *  </ol>
61
	  */
62
	  */
62
	public int indexOfSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
63
	public int indexOfSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int caseNumber, int fromIndex) {
63
		switch (caseNumber) {
64
		switch (caseNumber) {
64
			case 1 : /* space */
65
			case 1 : /* space */
65
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
66
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
Lines 86-92 Link Here
86
	     *    <li>skip until after a line separator</li>
87
	     *    <li>skip until after a line separator</li>
87
	     *  </ol>
88
	     *  </ol>
88
	 */
89
	 */
89
	public int processSpecial(STextEnvironment environment, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
90
	public int processSpecial(STextEnvironment environment, String text, STextDirections dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
90
		int location;
91
		int location;
91
92
92
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
93
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
Lines 94-100 Link Here
94
			case 1 : /* space */
95
			case 1 : /* space */
95
				separLocation++;
96
				separLocation++;
96
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
97
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
97
					STextProcessor.setDirProp(dirProps, separLocation, WS);
98
					dirProps.setOrientationAt(separLocation, WS);
98
					separLocation++;
99
					separLocation++;
99
				}
100
				}
100
				return separLocation;
101
				return separLocation;
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextXPath.java (-1 / +2 lines)
Lines 11-16 Link Here
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextDirections;
14
import org.eclipse.equinox.bidi.internal.STextDelims;
15
import org.eclipse.equinox.bidi.internal.STextDelims;
15
16
16
/**
17
/**
Lines 25-31 Link Here
25
	/**
26
	/**
26
	 *  @return 2 as the number of special cases handled by this processor.
27
	 *  @return 2 as the number of special cases handled by this processor.
27
	 */
28
	 */
28
	public int getSpecialsCount(STextEnvironment environment, String text, byte[] dirProps) {
29
	public int getSpecialsCount(STextEnvironment environment, String text, STextDirections dirProps) {
29
		return 2;
30
		return 2;
30
	}
31
	}
31
32

Return to bug 183164