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

Collapse All | Expand All

(-)src/org/eclipse/equinox/bidi/STextEngine.java (-318 lines)
Lines 1-318 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 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
/**
17
 * For a general introduction to structured text, see
18
 * {@link <a href="package-summary.html"> the package documentation</a>}.
19
 * <p>
20
 * Several common processors are included in <b>STextEngine</b>. For processors 
21
 * supplied by other packages, a processor instance can be obtained using the
22
 * {@link org.eclipse.equinox.bidi.STextProcessorFactory#getProcessor}
23
 * method for the registered processors, or by instantiating a private processor.
24
 * </p><p>
25
 * Most of the methods in this class have a <code>text</code>
26
 * argument which may be just a part of a larger body of text.
27
 * When it is the case that the text is submitted in parts with
28
 * repeated calls, there may be a need to pass information from
29
 * one invocation to the next one. For instance, one invocation
30
 * may detect that a comment or a literal has been started but
31
 * has not been completed. In such cases, a <code>state</code>
32
 * argument must be used.
33
 * </p><p>
34
 * The <code>state</code> argument must be an array of integers
35
 * with at least one element. Only the first element is used by
36
 * the methods of this class.
37
 * </p><p>
38
 * When submitting the initial part of the text, the first element
39
 * of <code>state</code> must contain the value {@link #STATE_INITIAL}
40
 * or any value <= 0.
41
 * </p><p>
42
 * After calling a method with a non-null <code>state</code> argument,
43
 * a value is returned in the first element of <code>state</code>. This
44
 * value should be passed unmodified to the method when calling it again
45
 * with the text which is the continuation of the text submitted in the
46
 * last call.
47
 * </p><p>
48
 * When the text submitted to a method is not a continuation and is not
49
 * expected to have a continuation , e.g. it is processed all by itself,
50
 * the <code>state</code> argument should be specified as <code>null</code>.
51
 * </p><p>
52
 * <b>Code Samples</b>
53
 * </p><p>
54
 * The following code shows how to transform a certain type of structured text
55
 * (directory and file paths) in order to obtain the <i>full</i>
56
 * text corresponding to the given <i>lean</i> text.
57
 * <pre>
58
 *   String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
59
 *   String fullText = STextEngine.leanToFullText(STextEngine.PROC_FILE, null, leanText, null);
60
 *   System.out.println("full text = " + fullText);
61
 * </pre>
62
 * </p><p>
63
 * The following code shows how to transform successive lines of Java
64
 * code in order to obtain the <i>full</i>
65
 * text corresponding to the <i>lean</i> text of each line.
66
 * <pre>
67
 *   int[] state = new int[1];
68
 *   state[0] = STextEngine.STATE_INITIAL;
69
 *   String leanText = "int i = 3; // first Java statement";
70
 *   String fullText = STextEngine.leanToFullText(STextEngine.PROC_JAVA, null, leanText, state);
71
 *   System.out.println("full text = " + fullText);
72
 *   leanText = "i += 4; // next Java statement";
73
 *   fullText = STextEngine.leanToFullText(STextEngine.PROC_JAVA, null, leanText, state);
74
 *   System.out.println("full text = " + fullText);
75
 * </pre>
76
 * </p>
77
 *  @author Matitiahu Allouche
78
 *
79
 */
80
public class STextEngine {
81
82
	/**
83
	 *  Constant specifying that the base direction of a structured text is LTR.
84
	 *  The base direction may depend on whether the GUI is
85
	 *  {@link STextEnvironment#getMirrored mirrored} and may
86
	 *  may be different for Arabic and for Hebrew.
87
	 *  This constant can appear as value returned by the
88
	 *  {@link #getCurDirection getCurDirection} method.
89
	 */
90
	public static final int DIR_LTR = 0;
91
92
	/**
93
	 *  Constant specifying that the base direction of a structured text is RTL.
94
	 *  The base direction may depend on whether the GUI is
95
	 *  {@link STextEnvironment#getMirrored mirrored} and may
96
	 *  may be different for Arabic and for Hebrew.
97
	 *  This constant can appear as value returned by the
98
	 *  {@link #getCurDirection getCurDirection} method.
99
	 */
100
	public static final int DIR_RTL = 1;
101
102
	/**
103
	 *  Constant to use in the first element of the <code>state</code>
104
	 *  argument when calling most methods of this class
105
	 *  to indicate that there is no context of previous lines which
106
	 *  should be initialized before performing the operation.
107
	 */
108
	public static final int STATE_INITIAL = 0;
109
110
	private static final int[] EMPTY_INT_ARRAY = new int[0];
111
112
	/**
113
	 *  Prevent creation of a STextEngine instance
114
	 */
115
	private STextEngine() {
116
		// nothing to do
117
	}
118
119
	/** 
120
	 * Add directional formatting characters to a structured text
121
	 * to ensure correct presentation.
122
	 * 
123
	 * @param  processor the processor applicable to the text. If <code>null</code>, 
124
	 * the method returns unmodified text.
125
	 * 
126
	 * @param  environment a bidi environment. If <code>null</code>, the default environment 
127
	 * is used.
128
	 *  
129
	 * @param text is the structured text string
130
	 *
131
	 * @param  state can be used to specify that the <code>text</code> argument is 
132
	 * the continuation of text submitted in a previous call and/or to receive information 
133
	 * to pass to continuation calls. If all calls to this method are independent from one another,
134
	 * this argument should be specified as <code>null</code>.
135
	 *
136
	 * @return the structured text with directional formatting characters added to ensure 
137
	 * correct presentation.
138
	 */
139
	public static String leanToFullText(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
140
		if (processor == null)
141
			return text;
142
		return STextImpl.leanToFullText(processor, environment, text, state);
143
	}
144
145
	/**
146
	 * Given a <i>lean</i> string, compute the positions of each of its
147
	 * characters within the corresponding <i>full</i> string.
148
	 *
149
	 * @param  processor designates a processor instance. If <code>null</code>, this 
150
	 * method returns an identity map.
151
	 *
152
	 * @param  environment specifies an environment whose characteristics may affect 
153
	 * the processor's behavior. If <code>null</code>, the default environment is used.
154
	 *
155
	 * @param text is the structured text string.
156
	 *
157
	 * @param  state can be used to specify that the <code>text</code> argument is 
158
	 * the continuation of text submitted in a previous call and/or to receive information 
159
	 * to pass to continuation calls. If all calls to this method are independent from one another,
160
	 * this argument should be specified as <code>null</code>.
161
	 *
162
	 * @return an array which specifies offsets of the <code>text</code> characters
163
	 * in the <i>full</i> string
164
	 */
165
	public static int[] leanToFullMap(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
166
		if (processor == null) {
167
			int[] map = new int[text.length()];
168
			for (int i = 0; i < map.length; i++)
169
				map[i] = i;
170
			return map;
171
		}
172
		return STextImpl.leanToFullMap(processor, environment, text, state);
173
	}
174
175
	/**
176
	 * Given a <i>lean</i> string, compute the offsets of characters
177
	 * before which directional formatting characters must be added
178
	 * in order to ensure correct presentation.
179
	 * <p>
180
	 * Only LRMs (for a string with LTR base direction) and RLMs (for
181
	 * a string with RTL base direction) are considered. Leading and
182
	 * trailing LRE, RLE and PDF which might be prefixed or suffixed
183
	 * depending on the {@link STextEnvironment#getOrientation orientation} of the
184
	 * GUI component used for display are not reflected in this method.
185
	 * </p>
186
	 * @param processor designates a processor instance
187
	 *
188
	 * @param  environment specifies an environment whose characteristics may affect 
189
	 * the processor's behavior. If <code>null</code>, the default environment is used.
190
	 *
191
	 * @param text is the structured text string
192
	 *
193
	 * @param  state can be used to specify that the <code>text</code> argument is 
194
	 * the continuation of text submitted in a previous call and/or to receive information 
195
	 * to pass to continuation calls. If all calls to this method are independent from one another,
196
	 * this argument should be specified as <code>null</code>.
197
	 *
198
	 * @return an array of offsets to the characters in the <code>text</code> argument 
199
	 * before which directional marks must be added to ensure correct presentation.
200
	 * The offsets are sorted in ascending order.
201
	 */
202
	public static int[] leanBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
203
		if (processor == null)
204
			return EMPTY_INT_ARRAY;
205
		return STextImpl.leanBidiCharOffsets(processor, environment, text, state);
206
	}
207
208
	/**
209
	 * Remove directional formatting characters which were added to a
210
	 * structured text string to ensure correct presentation.
211
	 *
212
	 * @param  processor designates a processor instance
213
	 *
214
	 * @param  environment specifies an environment whose characteristics may affect 
215
	 * the processor's behavior. If <code>null</code>, the default environment is used.
216
	 *
217
	 * @param text is the structured text string including directional formatting characters.
218
	 *
219
	 * @param  state can be used to specify that the <code>text</code> argument is 
220
	 * the continuation of text submitted in a previous call and/or to receive information 
221
	 * to pass to continuation calls. If all calls to this method are independent from one another,
222
	 * this argument should be specified as <code>null</code>.
223
	 *
224
	 * @return the structured text string without directional formatting characters 
225
	 * which might have been added by processing it with {@link #leanToFullText}.
226
	 *
227
	 */
228
	public static String fullToLeanText(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
229
		if (processor == null)
230
			return text;
231
		return STextImpl.fullToLeanText(processor, environment, text, state);
232
	}
233
234
	/**
235
	 * Given a <i>full</i> string, compute the positions of each of its
236
	 * characters within the corresponding <i>lean</i> string.
237
	 *
238
	 * @param  processor designates a processor instance
239
	 *
240
	 * @param  environment specifies an environment whose characteristics may affect 
241
	 * the processor's behavior. If <code>null</code>, the default environment is used.
242
	 *
243
	 * @param  text is the structured text string including directional formatting characters.
244
	 *
245
	 * @param  state can be used to specify that the <code>text</code> argument is 
246
	 * the continuation of text submitted in a previous call and/or to receive information 
247
	 * to pass to continuation calls. If all calls to this method are independent from one another,
248
	 * this argument should be specified as <code>null</code>.
249
	 *
250
	 * @return an array of integers with one element for each of the characters
251
	 * in the <code>text</code> argument, equal to the offset of the corresponding character 
252
	 * in the <i>lean</i> string. If there is no corresponding character in the <i>lean</i> string 
253
	 * (because the specified character is a directional formatting character added when invoking 
254
	 * {@link #leanToFullText}), the value returned for this character is -1.
255
	 */
256
	public static int[] fullToLeanMap(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
257
		if (processor == null) {
258
			int[] map = new int[text.length()];
259
			for (int i = 0; i < map.length; i++)
260
				map[i] = i;
261
			return map;
262
		}
263
		return STextImpl.fullToLeanMap(processor, environment, text, state);
264
	}
265
266
	/**
267
	 * Given a <i>full</i> string, return the offsets of characters
268
	 * which are directional formatting characters that have been added
269
	 * in order to ensure correct presentation.
270
	 * <p>
271
	 * LRMs (for a string with LTR base direction), RLMs (for a string with RTL base direction) 
272
	 * are considered as well as leading and trailing LRE, RLE and PDF which might be prefixed 
273
	 * or suffixed depending on the {@link STextEnvironment#getOrientation orientation} 
274
	 * of the GUI component used for display.
275
	 * </p>
276
	 * @param  processor designates a processor instance
277
	 *
278
	 * @param  environment specifies an environment whose characteristics may affect 
279
	 * the processor's behavior. If <code>null</code>, the default environment is used.
280
	 *
281
	 * @param  text is the structured text string including directional formatting characters
282
	 *
283
	 * @param  state can be used to specify that the <code>text</code> argument is 
284
	 * the continuation of text submitted in a previous call and/or to receive information 
285
	 * to pass to continuation calls. If all calls to this method are independent from one another,
286
	 * this argument should be specified as <code>null</code>.
287
	 *
288
	 * @return an array of offsets to the characters in the <code>text</code> argument which 
289
	 * are directional formatting characters added to ensure correct presentation. The offsets 
290
	 * are sorted in ascending order.
291
	 */
292
	public static int[] fullBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
293
		if (processor == null)
294
			return EMPTY_INT_ARRAY;
295
		return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
296
	}
297
298
	/**
299
	 * 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, 
301
	 * the first Arabic or Hebrew letter in the text determines which is the governing script.
302
	 *
303
	 * @param  processor designates a processor instance
304
	 *
305
	 * @param  environment specifies an environment whose characteristics may affect 
306
	 * the processor's behavior. If <code>null</code>, the default environment is used.
307
	 *
308
	 * @param  text is the structured text string
309
	 *
310
	 * @return the base direction of the structured text, {@link #DIR_LTR} or {@link #DIR_RTL}
311
	 */
312
	public static int getCurDirection(STextProcessor processor, STextEnvironment environment, String text) {
313
		if (processor == null)
314
			return DIR_LTR;
315
		return processor.getDirection(environment, text);
316
	}
317
318
}
(-)src/org/eclipse/equinox/bidi/STextEnvironment.java (-2 / +2 lines)
Lines 13-20 Link Here
13
import org.eclipse.equinox.bidi.internal.STextActivator;
13
import org.eclipse.equinox.bidi.internal.STextActivator;
14
14
15
/**
15
/**
16
 *  This class describes environment within which structured text strings are 
16
 *  This class describes the environment within which structured text strings 
17
 *  processed. It includes, for example:
17
 *  are processed. It includes:
18
 *  <ul>
18
 *  <ul>
19
 *  <li>locale,</li>
19
 *  <li>locale,</li>
20
 *  <li>desired orientation,</li>
20
 *  <li>desired orientation,</li>
(-)src/org/eclipse/equinox/bidi/STextHandler.java (+316 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 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.*;
14
import org.eclipse.equinox.bidi.internal.STextImpl;
15
16
/**
17
 * For a general introduction to structured text, see
18
 * {@link <a href="package-summary.html"> the package documentation</a>}.
19
 * <p>
20
 * Several common processors are included in 
21
 * {@link org.eclipse.equinox.bidi.STextProcessorFactory}.
22
 * For processors 
23
 * supplied by other packages, a processor instance can be obtained using the
24
 * {@link org.eclipse.equinox.bidi.STextProcessorFactory#getProcessor}
25
 * method for the registered processors, or by instantiating a private processor.
26
 * </p><p>
27
 * Most of the methods in this class have a <code>text</code>
28
 * argument which may be just a part of a larger body of text.
29
 * When it is the case that the text is submitted in parts with
30
 * repeated calls, there may be a need to pass information from
31
 * one invocation to the next one. For instance, one invocation
32
 * may detect that a comment or a literal has been started but
33
 * has not been completed.
34
 * </p><p>
35
 * This information is summarized as one integer, the "<b>state</b>".
36
 * The <b>state</b> can be queried using {@link #getState} after any
37
 * operation, and it can be set before an operation using 
38
 * {@link #setState}.
39
 * </p><p>
40
 * When submitting the initial part of the text, the <b>state</b>
41
 * must contain the value {@link #STATE_INITIAL} or any value <= 0.
42
 * </p><p>
43
 * When calling a method repeatedly, the <b>state</b> is automatically 
44
 * passed from one invocation to the next unless it is reset
45
 * by the caller using {@link #setState}.
46
 * </p><p>
47
 * <b>Code Samples</b>
48
 * </p><p>
49
 * The following code shows how to transform a certain type of structured text
50
 * (directory and file paths) in order to obtain the <i>full</i>
51
 * text corresponding to the given <i>lean</i> text.
52
 * <pre>
53
 *   STextHandler handler = new STextHandler(STextProcessorFactory.PROC_FILE);
54
 *   String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
55
 *   String fullText = handler.leanToFullText(null, leanText);
56
 *   System.out.println("full text = " + fullText);
57
 * </pre>
58
 * </p><p>
59
 * The following code shows how to transform successive lines of Java
60
 * code in order to obtain the <i>full</i>
61
 * text corresponding to the <i>lean</i> text of each line.
62
 * <pre>
63
 *   STextHandler handler = new STextHandler(STextProcessorFactory.PROC_JAVA);
64
*   String leanText = "int i = 3; // first Java statement";
65
 *   String fullText = handler.leanToFullText(null, leanText);
66
 *   System.out.println("full text = " + fullText);
67
 *   leanText = "i += 4; // next Java statement";
68
 *   fullText = handler.leanToFullText(null, leanText);
69
 *   System.out.println("full text = " + fullText);
70
 * </pre>
71
 * </p>
72
 *  @author Matitiahu Allouche
73
 *
74
 */
75
public class STextHandler {
76
77
	/**
78
	 *  Constant specifying that the base direction of a structured text is LTR.
79
	 *  The base direction may depend on whether the GUI is
80
	 *  {@link STextEnvironment#getMirrored mirrored} and may
81
	 *  may be different for Arabic and for Hebrew.
82
	 *  This constant can appear as value returned by the
83
	 *  {@link #getCurDirection getCurDirection} method.
84
	 */
85
	public static final int DIR_LTR = 0;
86
87
	/**
88
	 *  Constant specifying that the base direction of a structured text is RTL.
89
	 *  The base direction may depend on whether the GUI is
90
	 *  {@link STextEnvironment#getMirrored mirrored} and may
91
	 *  may be different for Arabic and for Hebrew.
92
	 *  This constant can appear as value returned by the
93
	 *  {@link #getCurDirection getCurDirection} method.
94
	 */
95
	public static final int DIR_RTL = 1;
96
97
	/**
98
	 *  Constant to use in {@link #setState}
99
	 *  to indicate that there is no context of previous lines
100
	 *  to consider before performing the next operation.
101
	 */
102
	public static final int STATE_INITIAL = 0;
103
104
	private static final int[] EMPTY_INT_ARRAY = new int[0];
105
106
	private STextProcessorData procData;
107
	private int state;
108
109
	/**
110
	 *  Constructor
111
	 *  
112
	 *  @param processor is the processor which will transform the 
113
	 *  submitted text.
114
	 */
115
	public STextHandler(STextProcessor processor) {
116
		procData = new STextProcessorData();
117
		setProcessor(processor);
118
		procData.handler = this;
119
		procData.offsets = new STextOffsets();
120
	}
121
122
	/**
123
	 *  Replace the processor of an existing handler. This operation
124
	 *  resets the state to {@link #STATE_INITIAL}.
125
	 *  
126
	 *  @param processor is the new processor.
127
	 */
128
	public void setProcessor(STextProcessor processor) {
129
		procData.processor = processor;
130
		state = STATE_INITIAL;
131
	}
132
133
	/**
134
	 *  Set the state for the next operation.
135
	 *  
136
	 *  @param state is the new value.
137
	 */
138
	public void setState(int state) {
139
		this.state = state;
140
	}
141
142
	/**
143
	 *  Get the value of the state after the last operation.
144
	 *  
145
	 *  @return the last value of the state.
146
	 */
147
	public int getState() {
148
		return state;
149
	}
150
151
	/** 
152
	 * Add directional formatting characters to a structured text
153
	 * to ensure correct presentation.
154
	 * 
155
	 * @param  environment a bidi environment. If <code>null</code>, the default environment 
156
	 * is used.
157
	 *  
158
	 * @param text is the structured text string
159
	 *
160
	 * @return the structured text with directional formatting characters added to ensure 
161
	 * correct presentation.
162
	 */
163
	public String leanToFullText(STextEnvironment environment, String text) {
164
		if (procData.processor == null)
165
			return text;
166
		procData.environment = environment;
167
		procData.text = text;
168
		return STextImpl.leanToFullText(procData);
169
	}
170
171
	/**
172
	 * Given a <i>lean</i> string, compute the positions of each of its
173
	 * characters within the corresponding <i>full</i> string.
174
	 *
175
	 * @param  environment specifies an environment whose characteristics may affect 
176
	 * the processor's behavior. If <code>null</code>, the default environment is used.
177
	 *
178
	 * @param text is the structured text string.
179
	 *
180
	 * @return an array which specifies offsets of the <code>text</code> characters
181
	 * in the <i>full</i> string
182
	 */
183
	public int[] leanToFullMap(STextEnvironment environment, String text) {
184
		if (procData.processor == null) {
185
			int[] map = new int[text.length()];
186
			for (int i = 0; i < map.length; i++)
187
				map[i] = i;
188
			return map;
189
		}
190
		procData.environment = environment;
191
		procData.text = text;
192
		return STextImpl.leanToFullMap(procData);
193
	}
194
195
	/**
196
	 * Given a <i>lean</i> string, compute the offsets of characters
197
	 * before which directional formatting characters must be added
198
	 * in order to ensure correct presentation.
199
	 * <p>
200
	 * Only LRMs (for a string with LTR base direction) and RLMs (for
201
	 * a string with RTL base direction) are considered. Leading and
202
	 * trailing LRE, RLE and PDF which might be prefixed or suffixed
203
	 * depending on the {@link STextEnvironment#getOrientation orientation} of the
204
	 * GUI component used for display are not reflected in this method.
205
	 * </p>
206
	 * @param  environment specifies an environment whose characteristics may affect 
207
	 * the processor's behavior. If <code>null</code>, the default environment is used.
208
	 *
209
	 * @param text is the structured text string
210
	 *
211
	 * @return an array of offsets to the characters in the <code>text</code> argument 
212
	 * before which directional marks must be added to ensure correct presentation.
213
	 * The offsets are sorted in ascending order.
214
	 */
215
	public int[] leanBidiCharOffsets(STextEnvironment environment, String text) {
216
		if (procData.processor == null)
217
			return EMPTY_INT_ARRAY;
218
		procData.environment = environment;
219
		procData.text = text;
220
		return STextImpl.leanBidiCharOffsets(procData);
221
	}
222
223
	/**
224
	 * Remove directional formatting characters which were added to a
225
	 * structured text string to ensure correct presentation.
226
	 *
227
	 * @param  environment specifies an environment whose characteristics may affect 
228
	 * the processor's behavior. If <code>null</code>, the default environment is used.
229
	 *
230
	 * @param text is the structured text string including directional formatting characters.
231
	 *
232
	 * @return the structured text string without directional formatting characters 
233
	 * which might have been added by processing it with {@link #leanToFullText}.
234
	 *
235
	 */
236
	public String fullToLeanText(STextEnvironment environment, String text) {
237
		if (procData.processor == null)
238
			return text;
239
		procData.environment = environment;
240
		procData.text = text;
241
		return STextImpl.fullToLeanText(procData);
242
	}
243
244
	/**
245
	 * Given a <i>full</i> string, compute the positions of each of its
246
	 * characters within the corresponding <i>lean</i> string.
247
	 *
248
	 * @param  environment specifies an environment whose characteristics may affect 
249
	 * the processor's behavior. If <code>null</code>, the default environment is used.
250
	 *
251
	 * @param  text is the structured text string including directional formatting characters.
252
	 *
253
	 * @return an array of integers with one element for each of the characters
254
	 * in the <code>text</code> argument, equal to the offset of the corresponding character 
255
	 * in the <i>lean</i> string. If there is no corresponding character in the <i>lean</i> string 
256
	 * (because the specified character is a directional formatting character added when invoking 
257
	 * {@link #leanToFullText}), the value returned for this character is -1.
258
	 */
259
	public int[] fullToLeanMap(STextEnvironment environment, String text) {
260
		if (procData.processor == null) {
261
			int[] map = new int[text.length()];
262
			for (int i = 0; i < map.length; i++)
263
				map[i] = i;
264
			return map;
265
		}
266
		procData.environment = environment;
267
		procData.text = text;
268
		return STextImpl.fullToLeanMap(procData);
269
	}
270
271
	/**
272
	 * Given a <i>full</i> string, return the offsets of characters
273
	 * which are directional formatting characters that have been added
274
	 * in order to ensure correct presentation.
275
	 * <p>
276
	 * LRMs (for a string with LTR base direction), RLMs (for a string with RTL base direction) 
277
	 * are considered as well as leading and trailing LRE, RLE and PDF which might be prefixed 
278
	 * or suffixed depending on the {@link STextEnvironment#getOrientation orientation} 
279
	 * of the GUI component used for display.
280
	 * </p>
281
	 * @param  environment specifies an environment whose characteristics may affect 
282
	 * the processor's behavior. If <code>null</code>, the default environment is used.
283
	 *
284
	 * @param  text is the structured text string including directional formatting characters
285
	 *
286
	 * @return an array of offsets to the characters in the <code>text</code> argument which 
287
	 * are directional formatting characters added to ensure correct presentation. The offsets 
288
	 * are sorted in ascending order.
289
	 */
290
	public int[] fullBidiCharOffsets(STextEnvironment environment, String text) {
291
		if (procData.processor == null)
292
			return EMPTY_INT_ARRAY;
293
		procData.environment = environment;
294
		procData.text = text;
295
		return STextImpl.fullBidiCharOffsets(procData);
296
	}
297
298
	/**
299
	 * 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, 
301
	 * the first Arabic or Hebrew letter in the text determines which is the governing script.
302
	 *
303
	 * @param  environment specifies an environment whose characteristics may affect 
304
	 * the processor's behavior. If <code>null</code>, the default environment is used.
305
	 *
306
	 * @param  text is the structured text string
307
	 *
308
	 * @return the base direction of the structured text, {@link #DIR_LTR} or {@link #DIR_RTL}
309
	 */
310
	public int getCurDirection(STextEnvironment environment, String text) {
311
		if (procData.processor == null)
312
			return DIR_LTR;
313
		return procData.processor.getDirection(environment, text);
314
	}
315
316
}
(-)src/org/eclipse/equinox/bidi/STextProcessorFactory.java (-3 / +1 lines)
Lines 14-22 Link Here
14
import org.eclipse.equinox.bidi.internal.STextTypesCollector;
14
import org.eclipse.equinox.bidi.internal.STextTypesCollector;
15
15
16
/**
16
/**
17
 * This class provides access to registered structured text processors.
17
 *  This class provides access to registered structured text processors.
18
 * 
19
 * @noinstantiate This class is not intended to be instantiated by clients.
20
 */
18
 */
21
final public class STextProcessorFactory {
19
final public class STextProcessorFactory {
22
20
(-)src/org/eclipse/equinox/bidi/STextProcessorMultipass.java (-21 / +21 lines)
Lines 11-48 Link Here
11
package org.eclipse.equinox.bidi;
11
package org.eclipse.equinox.bidi;
12
12
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.internal.STextImpl;
15
14
16
// TBD experimental
15
// TBD experimental
17
public class STextProcessorMultipass extends STextProcessor {
16
public class STextProcessorMultipass extends STextProcessor {
18
17
19
	private int[] state = new int[] {0};
18
	//	private int[] state = new int[] {0};
20
19
21
	public STextProcessorMultipass() {
20
	public STextProcessorMultipass() {
22
21
23
	}
22
	}
23
	/*
24
		public String leanToFullText(STextProcessor processor, STextEnvironment environment, String text) {
25
			return STextImpl.leanToFullText(processor, environment, text, state);
26
		}
24
27
25
	public String leanToFullText(STextProcessor processor, STextEnvironment environment, String text) {
28
		public int[] leanToFullMap(STextProcessor processor, STextEnvironment environment, String text) {
26
		return STextImpl.leanToFullText(processor, environment, text, state);
29
			return STextImpl.leanToFullMap(processor, environment, text, state);
27
	}
30
		}
28
31
29
	public int[] leanToFullMap(STextProcessor processor, STextEnvironment environment, String text) {
32
		public int[] leanBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
30
		return STextImpl.leanToFullMap(processor, environment, text, state);
33
			return STextImpl.leanBidiCharOffsets(processor, environment, text, state);
31
	}
34
		}
32
35
33
	public int[] leanBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
36
		public String fullToLeanText(STextProcessor processor, STextEnvironment environment, String text) {
34
		return STextImpl.leanBidiCharOffsets(processor, environment, text, state);
37
			return STextImpl.fullToLeanText(processor, environment, text, state);
35
	}
38
		}
36
37
	public String fullToLeanText(STextProcessor processor, STextEnvironment environment, String text) {
38
		return STextImpl.fullToLeanText(processor, environment, text, state);
39
	}
40
39
41
	public int[] fullToLeanMap(STextProcessor processor, STextEnvironment environment, String text) {
40
		public int[] fullToLeanMap(STextProcessor processor, STextEnvironment environment, String text) {
42
		return STextImpl.fullToLeanMap(processor, environment, text, state);
41
			return STextImpl.fullToLeanMap(processor, environment, text, state);
43
	}
42
		}
44
43
45
	public int[] fullBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
44
		public int[] fullBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text) {
46
		return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
45
			return STextImpl.fullBidiCharOffsets(processor, environment, text, state);
47
	}
46
		}
47
	*/
48
}
48
}
(-)src/org/eclipse/equinox/bidi/STextStringRecord.java (-2 / +2 lines)
Lines 86-92 Link Here
86
	 * @param  processor the processor appropriate to handle the type
86
	 * @param  processor the processor appropriate to handle the type
87
	 *         of structured text present in the first segment.
87
	 *         of structured text present in the first segment.
88
	 *         It may be one of the pre-defined processor instances
88
	 *         It may be one of the pre-defined processor instances
89
	 *         appearing in {@link STextEngine}, or it may be an instance
89
	 *         appearing in {@link STextHandler}, or it may be an instance
90
	 *         created by a plug-in or by the application.
90
	 *         created by a plug-in or by the application.
91
	 *
91
	 *
92
	 * @param  start offset in the string of the starting character of the first
92
	 * @param  start offset in the string of the starting character of the first
Lines 144-150 Link Here
144
	 * @param  processor the processor appropriate to handle the type
144
	 * @param  processor the processor appropriate to handle the type
145
	 *         of structured text present in this segment.
145
	 *         of structured text present in this segment.
146
	 *         It may be one of the pre-defined processor instances
146
	 *         It may be one of the pre-defined processor instances
147
	 *         appearing in {@link STextEngine}, or it may be an instance
147
	 *         appearing in {@link STextHandler}, or it may be an instance
148
	 *         created by a plug-in or by the application.
148
	 *         created by a plug-in or by the application.
149
	 *
149
	 *
150
	 * @param  start offset in the string of the starting character of the
150
	 * @param  start offset in the string of the starting character of the
(-)src/org/eclipse/equinox/bidi/STextUtil.java (-12 / +10 lines)
Lines 16-24 Link Here
16
 *  This class provides a number of convenience functions facilitating the
16
 *  This class provides a number of convenience functions facilitating the
17
 *  processing of structured text.
17
 *  processing of structured text.
18
 *
18
 *
19
 *  @noextend This class is not intended to be subclassed by clients.
20
 *  @noinstantiate This class is not intended to be instantiated by clients.
21
 *
22
 *  @author Matitiahu Allouche
19
 *  @author Matitiahu Allouche
23
 */
20
 */
24
public final class STextUtil {
21
public final class STextUtil {
Lines 61-67 Link Here
61
	 * If necessary, leading and trailing directional markers (LRE, RLE and PDF) can 
58
	 * If necessary, leading and trailing directional markers (LRE, RLE and PDF) can 
62
	 * be added depending on the value of the <code>affix</code> argument.
59
	 * be added depending on the value of the <code>affix</code> argument.
63
	 * </p>
60
	 * </p>
64
	 * @see STextEngine#leanBidiCharOffsets(STextProcessor, STextEnvironment, String, int[])
61
	 * @see STextHandler#leanBidiCharOffsets leanBidiCharOffsets
65
	 * 
62
	 * 
66
	 * @param  text the structured text string
63
	 * @param  text the structured text string
67
	 * @param  offsets an array of offsets to characters in <code>text</code>
64
	 * @param  offsets an array of offsets to characters in <code>text</code>
Lines 69-76 Link Here
69
	 *         The array must be sorted in ascending order without duplicates.
66
	 *         The array must be sorted in ascending order without duplicates.
70
	 *         This argument may be <code>null</code> if there are no marks to add.
67
	 *         This argument may be <code>null</code> if there are no marks to add.
71
	 * @param  direction the base direction of the structured text.
68
	 * @param  direction the base direction of the structured text.
72
	 *         It must be one of the values {@link STextEngine#DIR_LTR}, or
69
	 *         It must be one of the values {@link STextHandler#DIR_LTR}, or
73
	 *         {@link STextEngine#DIR_RTL}.
70
	 *         {@link STextHandler#DIR_RTL}.
74
	 * @param  affix specifies if a prefix and a suffix should be added to
71
	 * @param  affix specifies if a prefix and a suffix should be added to
75
	 *         the result
72
	 *         the result
76
	 * @return a string corresponding to the source <code>text</code> with
73
	 * @return a string corresponding to the source <code>text</code> with
Lines 86-92 Link Here
86
		String curPrefix, curSuffix, full;
83
		String curPrefix, curSuffix, full;
87
		char curMark, c;
84
		char curMark, c;
88
		char[] fullChars;
85
		char[] fullChars;
89
		if (direction == STextEngine.DIR_LTR) {
86
		if (direction == STextHandler.DIR_LTR) {
90
			curMark = LRM;
87
			curMark = LRM;
91
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
88
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
92
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
89
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
Lines 187-194 Link Here
187
			separators = defaultSeparators;
184
			separators = defaultSeparators;
188
185
189
		// make sure that LRE/PDF are added around the string
186
		// make sure that LRE/PDF are added around the string
190
		STextProcessor processor = new STextProcessor(separators);
187
		STextHandler handler = new STextHandler(new STextProcessor(separators));
191
		return STextEngine.leanToFullText(processor, env, str, null);
188
		return handler.leanToFullText(env, str);
192
	}
189
	}
193
190
194
	/**
191
	/**
Lines 212-218 Link Here
212
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
209
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
213
		if (!env.isProcessingNeeded())
210
		if (!env.isProcessingNeeded())
214
			return str;
211
			return str;
215
		return STextEngine.leanToFullText(processor, env, str, null);
212
		STextHandler handler = new STextHandler(processor);
213
		return handler.leanToFullText(env, str);
216
	}
214
	}
217
215
218
	/**
216
	/**
Lines 259-265 Link Here
259
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
257
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
260
		if (!env.isProcessingNeeded())
258
		if (!env.isProcessingNeeded())
261
			return str;
259
			return str;
262
		return STextEngine.fullToLeanText(processor, env, str, null);
260
		STextHandler handler = new STextHandler(processor);
261
		return handler.fullToLeanText(env, str);
263
	}
262
	}
264
265
}
263
}
(-)src/org/eclipse/equinox/bidi/custom/STextCharTypes.java (-12 / +33 lines)
Lines 43-48 Link Here
43
	// current orientation
43
	// current orientation
44
	private int orientation = -1; // "-1" means "unknown"
44
	private int orientation = -1; // "-1" means "unknown"
45
45
46
	/**
47
	 *  Constructor
48
	 *  
49
	 *  @param text is the text whose characters are analyzed.
50
	 */
46
	public STextCharTypes(String text) {
51
	public STextCharTypes(String text) {
47
		this.text = text;
52
		this.text = text;
48
		dirProps = new byte[text.length()];
53
		dirProps = new byte[text.length()];
Lines 57-70 Link Here
57
	}
62
	}
58
63
59
	/**
64
	/**
60
	 * @param  dirProp bidirectional class of the character. It must be
65
	 *  Get the orientation of the component in which the text will
61
	 *         one of the values which can be returned by
66
	 *  be displayed.
62
	 *         <code>java.lang.Character.getDirectionality</code>.
67
	 *  
68
	 *  @param environment
69
	 *  
70
	 *  @return the orientation as either 
71
	 *          {@link STextEnvironment#ORIENT_LTR} or
72
	 *          {@link STextEnvironment#ORIENT_RTL}.
63
	 */
73
	 */
64
	public void setBidiTypeAt(int i, byte dirProp) {
65
		dirProps[i] = (byte) (dirProp + DIRPROPS_ADD);
66
	}
67
68
	public int getOrientation(STextEnvironment environment) {
74
	public int getOrientation(STextEnvironment environment) {
69
		int result;
75
		int result;
70
		int orient = environment.getOrientation();
76
		int orient = environment.getOrientation();
Lines 98-108 Link Here
98
	}
104
	}
99
105
100
	/**
106
	/**
101
	 * Returns directionality of the character in the original string at
107
	 *  Returns directionality of the character in the original string at
102
	 * the specified index.
108
	 *  the specified index.
103
	 * @param index position of the character in the <i>lean</i> text
109
	 *  
104
	 * @return the bidirectional class of the character. It is one of the
110
	 *  @param  index position of the character in the <i>lean</i> text
105
	 * values which can be returned by {@link Character#getDirectionality(char)}
111
	 *  
112
	 *  @return the bidi type of the character. It is one of the
113
	 *          values which can be returned by 
114
	 *          {@link Character#getDirectionality(char)}.
106
	 */
115
	 */
107
	public byte getBidiTypeAt(int index) {
116
	public byte getBidiTypeAt(int index) {
108
		if (hasCachedDirectionAt(index))
117
		if (hasCachedDirectionAt(index))
Lines 115-118 Link Here
115
		return dirProp;
124
		return dirProp;
116
	}
125
	}
117
126
127
	/**
128
	 *  Force a bidi type on a character.
129
	 *  
130
	 *  @param  index is the index of the character whose bidi type is set.
131
	 *   
132
	 *  @param  dirProp bidirectional type of the character. It must be
133
	 *          one of the values which can be returned by
134
	 *          <code>java.lang.Character.getDirectionality</code>.
135
	 */
136
	public void setBidiTypeAt(int index, byte dirProp) {
137
		dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
138
	}
118
}
139
}
(-)src/org/eclipse/equinox/bidi/custom/STextOffsets.java (+109 lines)
Added Link Here
1
package org.eclipse.equinox.bidi.custom;
2
3
public class STextOffsets {
4
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
5
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
6
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
7
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
8
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
9
	static final byte[] STRONGS = {L, R};
10
	static final int OFFSET_SIZE = 20;
11
	int[] offsets = new int[OFFSET_SIZE];
12
	int count; // number of used entries		
13
14
	/**
15
	 *  @return the number of used entries in the offsets array.
16
	 */
17
	public int getCount() {
18
		return count;
19
	}
20
21
	/**
22
	 *  Mark that all entries in the offsets array are unused.
23
	 */
24
	public void resetCount() {
25
		count = 0;
26
	}
27
28
	/**
29
	 *  Get the value of a specified entry in the offsets array.
30
	 *  
31
	 *  @param  index is the index of the entry of interest.
32
	 *  
33
	 *  @return the value of the specified entry.
34
	 */
35
	public int getOffset(int index) {
36
		return offsets[index];
37
	}
38
39
	/**
40
	 *  Insert an offset value in the offset array so that the array 
41
	 *  stays in ascending order.
42
	 *  
43
	 *  @param  procData is a group of data accessible to processors.
44
	 *  
45
	 *  @param  offset is the value to insert.
46
	 */
47
	public void insertOffset(STextProcessorData procData, int offset) {
48
		int index = count - 1; // index of greatest member <= offset
49
		// look up after which member the new offset should be inserted
50
		while (index >= 0) {
51
			int wrkOffset = offsets[index];
52
			if (offset > wrkOffset)
53
				break;
54
			if (offset == wrkOffset)
55
				return; // avoid duplicates
56
			index--;
57
		}
58
		index++; // index now points at where to insert
59
		int length = count - index; // number of members to move up
60
		if (length > 0) // shift right all members greater than offset
61
			System.arraycopy(offsets, index, offsets, index + 1, length);
62
		offsets[index] = offset;
63
		count++; // number of used entries
64
		// if the offset is 0, adding a mark does not change anything
65
		if (offset < 1)
66
			return;
67
		STextCharTypes dirProps = procData.dirProps;
68
		if (dirProps == null)
69
			return;
70
71
		byte dirProp = dirProps.getBidiTypeAt(offset);
72
		// if the current char is a strong one or a digit, we change the
73
		//   dirProp of the previous char to account for the inserted mark.
74
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
75
			index = offset - 1;
76
		else
77
			// if the current char is a neutral, we change its own dirProp
78
			index = offset;
79
80
		dirProps.setBidiTypeAt(index, STRONGS[procData.direction]);
81
		return;
82
83
	}
84
85
	/**
86
	 *  Make sure that there is at least 3 free entries in the offsets array.
87
	 */
88
	public void ensureRoom() {
89
		// make sure there are at least 3 empty slots in offsets
90
		if ((offsets.length - count) < 3) {
91
			int[] newOffsets = new int[offsets.length * 2];
92
			System.arraycopy(offsets, 0, newOffsets, 0, count);
93
			offsets = newOffsets;
94
		}
95
	}
96
97
	/**
98
	 *  Get all and only the used offset entries.
99
	 *  
100
	 *  @return the current used entries of the offsets array.
101
	 */
102
	public int[] getArray() {
103
		if (count == offsets.length)
104
			return offsets;
105
		int[] array = new int[count];
106
		System.arraycopy(offsets, 0, array, 0, count);
107
		return array;
108
	}
109
}
(-)src/org/eclipse/equinox/bidi/custom/STextProcessor.java (-284 / +201 lines)
Lines 10-17 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.custom;
11
package org.eclipse.equinox.bidi.custom;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextHandler;
15
import org.eclipse.equinox.bidi.internal.STextImpl;
15
import org.eclipse.equinox.bidi.internal.STextImpl;
16
16
17
/**
17
/**
Lines 23-32 Link Here
23
 *  <ul>
23
 *  <ul>
24
 *    <li>Processor instances may be accessed simultaneously by
24
 *    <li>Processor instances may be accessed simultaneously by
25
 *        several threads. They should have no instance variables.</li>
25
 *        several threads. They should have no instance variables.</li>
26
 *    <li>All the user methods in {@link STextEngine} implement a logic
26
 *    <li>All the user methods in {@link STextHandler} implement a logic
27
 *        common to all processors, located in {@link STextImpl}.
27
 *        common to all processors, located in {@link STextImpl}.
28
 *        These methods all have a first argument which is a processor
29
 *        instance.
30
 *        The common logic uses processor methods to query the
28
 *        The common logic uses processor methods to query the
31
 *        characteristics of the specific processor:
29
 *        characteristics of the specific processor:
32
 *        <ul>
30
 *        <ul>
Lines 49-63 Link Here
49
 *        method, the common logic will repeatedly invoke the processor's
47
 *        method, the common logic will repeatedly invoke the processor's
50
 *        {@link #indexOfSpecial indexOfSpecial} method to let it signal the
48
 *        {@link #indexOfSpecial indexOfSpecial} method to let it signal the
51
 *        presence of special strings which may further delimit the source text.</li>
49
 *        presence of special strings which may further delimit the source text.</li>
52
 *    <li>When such a special case is signalled by the processor, the common
50
 *    <li>When such a special case is signaled by the processor, the common
53
 *        logic will call the processor's {@link #processSpecial processSpecial}
51
 *        logic will call the processor's {@link #processSpecial processSpecial}
54
 *        method to give it the opportunity to handle it as needed. Typical
52
 *        method to give it the opportunity to handle it as needed. Typical
55
 *        actions that the processor may perform are to add directional marks
53
 *        actions that the processor may perform are to add directional marks
56
 *        inconditionally (by calling {@link #insertMark insertMark} or
54
 *        unconditionally (by calling {@link #insertMark insertMark} or
57
 *        conditionally (by calling {@link #processSeparator processSeparator}).</li>
55
 *        conditionally (by calling {@link #processSeparator processSeparator}).</li>
58
 *  </ul>
56
 *  </ul>
59
 *
57
 *
60
 * @see STextEngine
58
 * @see STextHandler
61
 * @author Matitiahu Allouche
59
 * @author Matitiahu Allouche
62
 */
60
 */
63
public class STextProcessor {
61
public class STextProcessor {
Lines 65-389 Link Here
65
	final private String separators;
63
	final private String separators;
66
64
67
	/**
65
	/**
68
	 * Creates a new instance of the STextProcessor class.
66
	 *  Creates a new instance of the STextProcessor class.
69
	 */
67
	 */
70
	public STextProcessor() {
68
	public STextProcessor() {
71
		separators = ""; //$NON-NLS-1$
69
		separators = ""; //$NON-NLS-1$
72
	}
70
	}
73
71
74
	/**
72
	/**
75
	 * Creates a new instance of the STextProcessor class.
73
	 *  Creates a new instance of the STextProcessor class.
76
	 * @param separators string consisting of characters that split the text into fragments
74
	 *  
75
	 *  @param  separators string consisting of characters that split 
76
	 *          the text into fragments
77
	 */
77
	 */
78
	public STextProcessor(String separators) {
78
	public STextProcessor(String separators) {
79
		this.separators = separators;
79
		this.separators = separators;
80
	}
80
	}
81
81
82
	/**
82
	/**
83
	 * Locate occurrences of special strings within a structured text
83
	 *  Locate occurrences of special strings within a structured text
84
	 * and return their indexes one after the other in successive calls.
84
	 *  and return their indexes one after the other in successive calls.
85
	 * <p>
85
	 *  <p>
86
	 * This method is called repeatedly from the code implementing
86
	 *  This method is called repeatedly from the code implementing
87
	 * {@link STextEngine#leanToFullText} if the number of special cases 
87
	 *  {@link STextHandler#leanToFullText} if the number of special cases 
88
	 * returned by {@link #getSpecialsCount} is greater than zero.
88
	 *  returned by {@link #getSpecialsCount} is greater than zero.
89
	 * </p><p>
89
	 *  </p><p>
90
	 * A processor handling special cases must override this method.
90
	 *  A processor handling special cases must override this method.
91
	 * </p>
91
	 *  </p>
92
	 * @param  environment the current environment, which may affect the behavior of
92
	 *  @param  procData is a group of data accessible by the processor.
93
	 *         the processor. This parameter may be specified as
94
	 *         <code>null</code>, in which case the
95
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
96
	 *         environment should be assumed.
97
	 *
93
	 *
98
	 * @param  text is the structured text string before
94
	 *  @param  caseNumber is the number of the special case to locate.
99
	 *         addition of any directional formatting characters.
95
	 *          This number varies from 1 to the number of special cases
100
	 *
96
	 *          returned by {@link #getSpecialsCount getSpecialsCount}
101
	 * @param  dirProps is a parameter received by <code>indexOfSpecial</code>
97
	 *          for this processor.
102
	 *         uniquely to be used as argument for calls to methods which
98
	 *          The meaning of this number is internal to the class
103
	 *         need it.
99
	 *          implementing <code>indexOfSpecial</code>.
104
	 *
105
	 * @param  offsets is a parameter received by <code>indexOfSpecial</code>
106
	 *         uniquely to be used as argument for calls to methods which
107
	 *         need it.
108
	 *
109
	 * @param  caseNumber number of the special case to locate.
110
	 *         This number varies from 1 to the number of special cases
111
	 *         returned by {@link #getSpecialsCount getSpecialsCount}
112
	 *         for this processor.
113
	 *         The meaning of this number is internal to the class
114
	 *         implementing <code>indexOfSpecial</code>.
115
	 *
100
	 *
116
	 * @param  fromIndex the index within <code>text</code> to start
101
	 *  @param  fromIndex is the index within <code>text</code> to start
117
	 *         the search from.
102
	 *          the search from.
118
	 *
103
	 *
119
	 * @return the position where the start of the special case
104
	 *  @return the position where the start of the special case
120
	 *         corresponding to <code>caseNumber</code> was located.
105
	 *          corresponding to <code>caseNumber</code> was located.
121
	 *         The method must return the first occurrence of whatever
106
	 *          The method must return the first occurrence of whatever
122
	 *         identifies the start of the special case starting from
107
	 *          identifies the start of the special case starting from
123
	 *         <code>fromIndex</code>. The method does not have to check if
108
	 *          <code>fromIndex</code>. The method does not have to check if
124
	 *         this occurrence appears within the scope of another special
109
	 *          this occurrence appears within the scope of another special
125
	 *         case (e.g. a comment starting delimiter within the scope of
110
	 *          case (e.g. a comment starting delimiter within the scope of
126
	 *         a literal or vice-versa).
111
	 *          a literal or vice-versa).
127
	 *         <br>If no occurrence is found, the method must return -1.
112
	 *          <br>If no occurrence is found, the method must return -1.
128
	 *
113
	 *
129
	 * @throws IllegalStateException If not overridden, this method throws an
114
	 * @throws  IllegalStateException If not overridden, this method throws an
130
	 * <code>IllegalStateException</code>. This is appropriate behavior
115
	 *          <code>IllegalStateException</code>. This is appropriate behavior
131
	 * (and does not need to be overridden) for processors whose
116
	 *          (and does not need to be overridden) for processors whose
132
	 * number of special cases is zero, which means that
117
	 *          number of special cases is zero, which means that
133
	 * <code>indexOfSpecial</code> should never be called for them.
118
	 *          <code>indexOfSpecial</code> should never be called for them.
134
	 */
119
	 */
135
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
120
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
136
		// This method must be overridden by all subclasses with special cases.
121
		// 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$
122
		throw new IllegalStateException("A processor with specialsCount > 0 must have an indexOfSpecial() method."); //$NON-NLS-1$
138
	}
123
	}
139
124
140
	/**
125
	/**
141
	 * This method handles special cases specific to this processor.
126
	 *  This method handles special cases specific to this processor.
142
	 * It is called by {@link STextEngine#leanToFullText} when a special case occurrence 
127
	 *  It is called by {@link STextHandler#leanToFullText} when a special case occurrence 
143
	 * is located by {@link #indexOfSpecial}.
128
	 *  is located by {@link #indexOfSpecial}.
144
	 * <p>
129
	 *  <p>
145
	 * If a special processing cannot be completed within a current call to
130
	 *  If a special processing cannot be completed within a current call to
146
	 * <code>processSpecial</code> (for instance, a comment has been started
131
	 *  <code>processSpecial</code> (for instance, a comment has been started
147
	 * in the current line but its end appears in a following line),
132
	 *  in the current line but its end appears in a following line),
148
	 * <code>processSpecial</code> should specify a final state by
133
	 *  <code>processSpecial</code> should specify a final <b>state</b> by
149
	 * putting its value in the first element of the <code>state</code>
134
	 *  calling {@link STextHandler#setState}.
150
	 * parameter.
135
	 *  The meaning of this <b>state</b> is internal to the processor.
151
	 * The meaning of this state is internal to the processor.
136
	 *  On a later call to {@link STextHandler#leanToFullText},
152
	 * On a later call to {@link STextEngine#leanToFullText} specifying that 
137
	 *  <code>processSpecial</code> will be called with that value 
153
	 * state value, <code>processSpecial</code> will be called with that value 
138
	 *  for parameter <code>caseNumber</code> and <code>-1</code> for parameter 
154
	 * for parameter <code>caseNumber</code> and <code>-1</code> for parameter 
139
	 *  <code>separLocation</code> and should perform whatever initializations are required
155
	 * <code>separLocation</code> and should perform whatever initializations are required
140
	 *  depending on the <b>state</b>.
156
	 * depending on the state.
141
	 *  </p><p>
157
	 * </p><p>
142
	 *  A processor handling special cases (with a number of
158
	 * A processor handling special cases (with a number of
143
	 *  special cases greater than zero) must override this method.
159
	 * special cases greater than zero) must override this method.
144
	 *  </p>
160
	 * </p>
145
	 *  @param  procData is a group of data accessible to the processor.
161
	 * @param  environment the current environment, which may affect the behavior of
162
	 *         the processor. This parameter may be specified as
163
	 *         <code>null</code>, in which case the
164
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
165
	 *         environment should be assumed.
166
	 *
167
	 * @param  text is the structured text string before
168
	 *         addition of any directional formatting characters.
169
	 *
170
	 * @param  dirProps is a parameter received by <code>processSpecial</code>
171
	 *         uniquely to be used as argument for calls to methods which
172
	 *         need it.
173
	 *
174
	 * @param  offsets is a parameter received by <code>processSpecial</code>
175
	 *         uniquely to be used as argument for calls to methods which
176
	 *         need it.
177
	 *
178
	 * @param  state is an integer array with at least one element.
179
	 *         If the processor needs to signal the occurrence of a
180
	 *         special case which must be passed to the next call to
181
	 *         <code>leanToFullText</code> (for instance, a comment or a
182
	 *         literal started but not closed in the current
183
	 *         <code>text</code>), it must put a value in the first element
184
	 *         of the <code>state</code> parameter.
185
	 *         This number must be >= 1 and less or equal to the number of special
186
	 *         cases returned by {@link #getSpecialsCount getSpecialsCount}
187
	 *         by this processor.
188
	 *         This number is passed back to the caller
189
	 *         and should be specified as <code>state</code> argument
190
	 *         in the next call to <code>leanToFullText</code> together
191
	 *         with the continuation text.
192
	 *         The meaning of this number is internal to the processor.
193
	 *
146
	 *
194
	 * @param  caseNumber number of the special case to handle.
147
	 *  @param  caseNumber number of the special case to handle.
195
	 *
148
	 *
196
	 * @param  separLocation the position returned by
149
	 *  @param  separLocation the position returned by
197
	 *         {@link #indexOfSpecial indexOfSpecial}. In calls to
150
	 *          {@link #indexOfSpecial indexOfSpecial}. In calls to
198
	 *         {@link STextEngine#leanToFullText leanToFullText} and other
151
	 *          {@link STextHandler#leanToFullText leanToFullText} and other
199
	 *         methods of {@link STextEngine} specifying a  non-null
152
	 *          methods of {@link STextHandler} setting a  non-null
200
	 *         <code>state</code> parameter, <code>processSpecial</code> is
153
	 *          <b>state</b> value, <code>processSpecial</code> is
201
	 *         called when initializing the processing with the value of
154
	 *          called when initializing the processing with the value of
202
	 *         <code>caseNumber</code> equal to the value returned in the
155
	 *          <code>caseNumber</code> equal to the value returned
203
	 *         first element of <code>state</code> and the value of
156
	 *          as <b>state</b> and the value of
204
	 *         <code>separLocation</code> equal to <code>-1</code>.
157
	 *          <code>separLocation</code> equal to <code>-1</code>.
205
	 *
158
	 *
206
	 * @return the position after the scope of the special case ends.
159
	 *  @return the position after the scope of the special case ends.
207
	 *         For instance, the position after the end of a comment,
160
	 *          For instance, the position after the end of a comment,
208
	 *         the position after the end of a literal.
161
	 *          the position after the end of a literal.
209
	 *         <br>A value greater or equal to the length of <code>text</code>
162
	 *          <br>A value greater or equal to the length of <code>text</code>
210
	 *         means that there is no further occurrence of this case in the
163
	 *          means that there is no further occurrence of this case in the
211
	 *         current structured text.
164
	 *          current structured text.
212
	 *
165
	 *
213
	 * @throws IllegalStateException If not overridden, this method throws an
166
	 *  @throws IllegalStateException If not overridden, this method throws an
214
	 * <code>IllegalStateException</code>. This is appropriate behavior
167
	 *          <code>IllegalStateException</code>. This is appropriate behavior
215
	 * (and does not need to be overridden) for processors whose
168
	 *          (and does not need to be overridden) for processors whose
216
	 * number of special cases is zero, which means that
169
	 *          number of special cases is zero, which means that
217
	 * <code>processSpecial</code> should never be called for them.
170
	 *          <code>processSpecial</code> should never be called for them.
218
	 */
171
	 */
219
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
172
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
220
		// This method must be overridden by all subclasses with any special case.
173
		// 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$
174
		throw new IllegalStateException("A processor with specialsCount > 0 must have a processSpecial() method."); //$NON-NLS-1$
222
	}
175
	}
223
176
224
	/**
177
	/**
225
	 * This method can be called from within {@link #indexOfSpecial} or
178
	 *  This method can be called from within {@link #indexOfSpecial} or
226
	 * {@link #processSpecial} in extensions of <code>STextProcessor</code>
179
	 *  {@link #processSpecial} in extensions of <code>STextProcessor</code>
227
	 * to specify that a mark character must be added before the character
180
	 *  to specify that a mark character must be added before the character
228
	 * at the specified position of the <i>lean</i> text when generating the
181
	 *  at the specified position of the <i>lean</i> text when generating the
229
	 * <i>full</i> text. The mark character will be LRM for structured text
182
	 *  <i>full</i> text. The mark character will be LRM for structured text
230
	 * with a LTR base direction, and RLM for structured text with RTL
183
	 *  with a LTR base direction, and RLM for structured text with RTL
231
	 * base direction. The mark character is not added physically by this
184
	 *  base direction. The mark character is not added physically by this
232
	 * method, but its position is noted and will be used when generating
185
	 *  method, but its position is noted and will be used when generating
233
	 * the <i>full</i> text.
186
	 *  the <i>full</i> text.
234
	 *
187
	 *
235
	 * @param  text is the structured text string received as
188
	 *  @param  procData is a group of data accessible to the processor.
236
	 *         parameter to <code>indexOfSpecial</code> or
237
	 *         <code>processSpecial</code>.
238
	 *
189
	 *
239
	 * @param  dirProps is a parameter received by <code>indexOfSpecial</code>
190
	 *  @param  offset position of the character in the <i>lean</i> text.
240
	 *         or <code>processSpecial</code>, uniquely to be used as argument
191
	 *          It must be a non-negative number smaller than the length
241
	 *         for calls to <code>insertMark</code> and other methods used
192
	 *          of the <i>lean</i> text.
242
	 *         by processors.
193
	 *          For the benefit of efficiency, it is better to insert
243
	 *
194
	 *          multiple marks in ascending order of the offsets.
244
	 * @param  offsets is a parameter received by <code>indexOfSpecial</code>
245
	 *         or <code>processSpecial</code>, uniquely to be used as argument
246
	 *         for calls to <code>insertMark</code> and other methods used
247
	 *         by processors.
248
	 *
249
	 * @param  offset position of the character in the <i>lean</i> text.
250
	 *         It must be a non-negative number smaller than the length
251
	 *         of the <i>lean</i> text.
252
	 *         For the benefit of efficiency, it is better to insert
253
	 *         multiple marks in ascending order of the offsets.
254
	 */
195
	 */
255
	public static final void insertMark(String text, STextCharTypes dirProps, int[] offsets, int offset) {
196
	public static final void insertMark(STextProcessorData procData, int offset) {
256
		STextImpl.insertMark(text, dirProps, offsets, offset);
197
		procData.offsets.insertOffset(procData, offset);
257
	}
198
	}
258
199
259
	/**
200
	/**
260
	 * This method can be called from within {@link #indexOfSpecial} or
201
	 *  This method can be called from within {@link #indexOfSpecial} or
261
	 * {@link #processSpecial} in extensions of <code>STextProcessor</code> to add 
202
	 *  {@link #processSpecial} in extensions of <code>STextProcessor</code> to add 
262
	 * a directional mark before a separator if needed for correct display, 
203
	 *  a directional mark before a separator if needed for correct display, 
263
	 * depending on the base direction of the text and on the class of the
204
	 *  depending on the base direction of the text and on the type of the
264
	 * characters in the <i>lean</i> text preceding and following the separator itself.
205
	 *  characters in the <i>lean</i> text preceding and following the separator itself.
265
	 * <p>
206
	 *  <p>
266
	 * The logic implemented in this method considers the text before
207
	 *  The logic implemented in this method considers the text before
267
	 * <code>separLocation</code> and the text following it. If, and only if,
208
	 *  <code>separLocation</code> and the text following it. If, and only if,
268
	 * a directional mark is needed to insure that the two parts of text
209
	 *  a directional mark is needed to insure that the two parts of text
269
	 * will be laid out according to the base direction, a mark will be
210
	 *  will be laid out according to the base direction, a mark will be
270
	 * added when generating the <i>full</i> text.
211
	 *  added when generating the <i>full</i> text.
271
	 * </p>
212
	 *  </p>
272
	 * @param  text is the structured text string received as
213
	 *  @param  procData is a group of data accessible to the processor.
273
	 *         parameter to <code>indexOfSpecial</code> or
274
	 *         <code>processSpecial</code>.
275
	 *
276
	 * @param  dirProps is a parameter received by <code>indexOfSpecial</code>
277
	 *         or <code>processSpecial</code>, uniquely to be used as argument
278
	 *         for calls to <code>processSeparator</code> and other methods used
279
	 *         by processors.
280
	 *
281
	 * @param  offsets is a parameter received by <code>indexOfSpecial</code>
282
	 *         or <code>processSpecial</code>, uniquely to be used as argument
283
	 *         for calls to <code>processSeparator</code> and other methods used
284
	 *         by processors.
285
	 *
214
	 *
286
	 * @param  separLocation offset of the separator in the <i>lean</i> text.
215
	 *  @param  separLocation offset of the separator in the <i>lean</i> text.
287
	 *         It must be a non-negative number smaller than the length
216
	 *          It must be a non-negative number smaller than the length
288
	 *         of the <i>lean</i> text.
217
	 *          of the <i>lean</i> text.
289
	 */
218
	 */
290
	public static final void processSeparator(String text, STextCharTypes dirProps, int[] offsets, int separLocation) {
219
	public static final void processSeparator(STextProcessorData procData, int separLocation) {
291
		STextImpl.processSeparator(text, dirProps, offsets, separLocation);
220
		STextImpl.processSeparator(procData, separLocation);
292
	}
221
	}
293
222
294
	/**
223
	/**
295
	 * Indicate the separators to use for the current processor.
224
	 *  Indicate the separators to use for the current processor.
296
	 * This method is invoked before starting the processing.
225
	 *  This method is invoked before starting the processing.
297
	 * <p>
226
	 *  <p>
298
	 * If no separators are specified, this method returns an empty string.
227
	 *  If no separators are specified, this method returns an empty string.
299
	 * </p>
228
	 *  </p>
300
	 * @param  environment the current environment, which may affect the behavior of
229
	 *  @param  environment the current environment, which may affect the behavior of
301
	 *         the processor. This parameter may be specified as
230
	 *          the processor. This parameter may be specified as
302
	 *         <code>null</code>, in which case the
231
	 *          <code>null</code>, in which case the
303
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
232
	 *          {@link STextEnvironment#DEFAULT DEFAULT}
304
	 *         environment should be assumed.
233
	 *          environment should be assumed.
305
	 *
234
	 *
306
	 * @return a string grouping one-character separators which separate
235
	 *  @return a string grouping one-character separators which separate
307
	 *         the structured text into tokens.
236
	 *          the structured text into tokens.
308
	 */
237
	 */
309
	public String getSeparators(STextEnvironment environment) {
238
	public String getSeparators(STextEnvironment environment) {
310
		return separators;
239
		return separators;
311
	}
240
	}
312
241
313
	/**
242
	/**
314
	 * Indicate the base text direction appropriate for an instance of structured text.
243
	 *  Indicate the base text direction appropriate for an instance of structured text.
315
	 * This method is invoked before starting the processing.
244
	 *  This method is invoked before starting the processing.
316
	 * <p>
245
	 *  <p>
317
	 * If not overridden, this method returns <code>DIR_LTR</code>.
246
	 *  If not overridden, this method returns <code>DIR_LTR</code>.
318
	 * </p>
247
	 *  </p>
319
	 * @param  environment the current environment, which may affect the behavior of
248
	 *  @param  environment the current environment, which may affect the behavior of
320
	 *         the processor. This parameter may be specified as
249
	 *          the processor. This parameter may be specified as
321
	 *         <code>null</code>, in which case the
250
	 *          <code>null</code>, in which case the
322
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
251
	 *          {@link STextEnvironment#DEFAULT DEFAULT}
323
	 *         environment should be assumed.
252
	 *          environment should be assumed.
324
	 *
253
	 *
325
	 * @param  text is the structured text string to process.
254
	 *  @param  text is the structured text string to process.
326
	 *
255
	 *
327
	 * @return the base direction of the structured text. This direction
256
	 *  @return the base direction of the structured text. This direction
328
	 *         may not be the same depending on the environment and on
257
	 *          may not be the same depending on the environment and on
329
	 *         whether the structured text contains Arabic or Hebrew
258
	 *          whether the structured text contains Arabic or Hebrew
330
	 *         letters.<br>
259
	 *          letters.<br>
331
	 *         The value returned is either
260
	 *          The value returned is either
332
	 *         {@link STextEngine#DIR_LTR DIR_LTR} or {@link STextEngine#DIR_RTL DIR_RTL}.
261
	 *          {@link STextHandler#DIR_LTR DIR_LTR} or {@link STextHandler#DIR_RTL DIR_RTL}.
333
	 */
262
	 */
334
	public int getDirection(STextEnvironment environment, String text) {
263
	public int getDirection(STextEnvironment environment, String text) {
335
		return STextEngine.DIR_LTR;
264
		return STextHandler.DIR_LTR;
336
	}
265
	}
337
266
338
	/**
267
	/**
339
	 * Indicate the base text direction appropriate for an instance of structured text.
268
	 *  Indicate the base text direction appropriate for an instance of structured text.
340
	 * This method is invoked before starting the processing.
269
	 *  This method is invoked before starting the processing.
341
	 * <p>
270
	 *  <p>
342
	 * If not overridden, this method returns <code>DIR_LTR</code>.
271
	 *  If not overridden, this method returns <code>DIR_LTR</code>.
343
	 * </p>
272
	 *  </p>
344
	 * @param  environment the current environment, which may affect the behavior of
273
	 *  @param  environment the current environment, which may affect the behavior of
345
	 *         the processor. This parameter may be specified as
274
	 *          the processor. This parameter may be specified as
346
	 *         <code>null</code>, in which case the
275
	 *          <code>null</code>, in which case the
347
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
276
	 *          {@link STextEnvironment#DEFAULT DEFAULT}
348
	 *         environment should be assumed.
277
	 *          environment should be assumed.
349
	 *
278
	 *
350
	 * @param  text is the structured text string to process.
279
	 *  @param  text is the structured text string to process.
351
	 *
280
	 *
352
	 * @param  dirProps is a parameter received uniquely to be used as argument
281
	 *  @param  dirProps is a parameter received uniquely to be used as argument
353
	 *         for calls to <code>getDirProp</code> and other methods used
282
	 *          for calls to {@link STextCharTypes#getBidiTypeAt}
354
	 *         by processors.
283
	 *          and other methods used by processors.
355
	 *
284
	 *
356
	 * @return the base direction of the structured text. This direction
285
	 *  @return the base direction of the structured text. This direction
357
	 *         may not be the same depending on the environment and on
286
	 *          may not be the same depending on the environment and on
358
	 *         whether the structured text contains Arabic or Hebrew
287
	 *          whether the structured text contains Arabic or Hebrew
359
	 *         letters.<br>
288
	 *          letters.<br>
360
	 *         The value returned is either
289
	 *          The value returned is either
361
	 *         {@link STextEngine#DIR_LTR DIR_LTR} or {@link STextEngine#DIR_RTL DIR_RTL}.
290
	 *          {@link STextHandler#DIR_LTR DIR_LTR} or {@link STextHandler#DIR_RTL DIR_RTL}.
362
	 */
291
	 */
363
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
292
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
364
		return STextEngine.DIR_LTR;
293
		return STextHandler.DIR_LTR;
365
	}
294
	}
366
295
367
	/**
296
	/**
368
	 * Indicate the number of special cases handled by the current processor.
297
	 *  Indicate the number of special cases handled by the current processor.
369
	 * This method is invoked before starting the processing.
298
	 *  This method is invoked before starting the processing.
370
	 * If the number returned is zero, {@link #indexOfSpecial} and
299
	 *  If the number returned is zero, {@link #indexOfSpecial} and
371
	 * {@link #processSpecial} will not be invoked.
300
	 *  {@link #processSpecial} will not be invoked.
372
	 * <p>
301
	 *  <p>
373
	 * If not overridden, this method returns <code>zero</code>.
302
	 *  If not overridden, this method returns <code>zero</code>.
374
	 * </p>
303
	 *  </p>
375
	 * @param  environment the current environment, which may affect the behavior of
304
	 *  @param  environment the current environment, which may affect the behavior of
376
	 *         the processor. This parameter may be specified as
305
	 *          the processor. This parameter may be specified as
377
	 *         <code>null</code>, in which case the
306
	 *          <code>null</code>, in which case the
378
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
307
	 *          {@link STextEnvironment#DEFAULT DEFAULT}
379
	 *         environment should be assumed.
308
	 *          environment should be assumed.
380
	 *
309
	 *
381
	 * @return the number of special cases for the associated processor.
310
	 *  @return the number of special cases for the associated processor.
382
	 *         Special cases exist for some types of structured text
311
	 *          Special cases exist for some types of structured text
383
	 *         processors. They are implemented by overriding methods
312
	 *          processors. They are implemented by overriding methods
384
	 *         {@link STextProcessor#indexOfSpecial} and {@link STextProcessor#processSpecial}.
313
	 *          {@link STextProcessor#indexOfSpecial} and {@link STextProcessor#processSpecial}.
385
	 *         Examples of special cases are comments, literals, or
314
	 *          Examples of special cases are comments, literals, or
386
	 *         anything which is not identified by a one-character separator.
315
	 *          anything which is not identified by a one-character separator.
387
	 *
316
	 *
388
	 */
317
	 */
389
	public int getSpecialsCount(STextEnvironment environment) {
318
	public int getSpecialsCount(STextEnvironment environment) {
Lines 391-422 Link Here
391
	}
320
	}
392
321
393
	/**
322
	/**
394
	 * Checks if there is a need for processing structured text.
323
	 *  Checks if there is a need for processing structured text.
395
	 * This method is invoked before starting the processing. If the
324
	 *  This method is invoked before starting the processing. If the
396
	 * processor returns <code>true</code>, no directional formatting
325
	 *  processor returns <code>true</code>, no directional formatting
397
	 * characters are added to the <i>lean</i> text and the processing
326
	 *  characters are added to the <i>lean</i> text and the processing
398
	 * is shortened.
327
	 *  is shortened.
399
	 * <p>
328
	 *  <p>
400
	 * If not overridden, this method returns <code>false</code>.
329
	 *  If not overridden, this method returns <code>false</code>.
401
	 * </p>
330
	 *  </p>
402
	 * @param  environment the current environment, which may affect the behavior of
331
403
	 *         the processor. This parameter may be specified as
332
	 *  @return a flag indicating if there is no need to process the structured
404
	 *         <code>null</code>, in which case the
333
	 *          text to add directional formatting characters.
405
	 *         {@link STextEnvironment#DEFAULT DEFAULT}
406
	 *         environment should be assumed.
407
	 *
408
	 * @param  text is the structured text string to process.
409
	 *
410
	 * @param  dirProps is a parameter received uniquely to be used as argument
411
	 *         for calls to <code>getDirProp</code> and other methods used
412
	 *         by processors.
413
	 *
414
	 * @return a flag indicating if there is no need to process the structured
415
	 *         text to add directional formatting characters.
416
	 *
334
	 *
417
	 */
335
	 */
418
	public boolean skipProcessing(STextEnvironment environment, String text, STextCharTypes dirProps) {
336
	public boolean skipProcessing(STextProcessorData procData) {
419
		return false;
337
		return false;
420
	}
338
	}
421
422
}
339
}
(-)src/org/eclipse/equinox/bidi/custom/STextProcessorData.java (+52 lines)
Added Link Here
1
package org.eclipse.equinox.bidi.custom;
2
3
import org.eclipse.equinox.bidi.STextEnvironment;
4
import org.eclipse.equinox.bidi.STextHandler;
5
6
/**
7
 *  This class regroups core information related to structured text operations.
8
 *  It is convenient to pass information between caller and called method.
9
 *  
10
 *  @author Matitiahu Allouche
11
 *
12
 */
13
public class STextProcessorData {
14
	/**
15
	 *  The handler 
16
	 */
17
	public STextHandler handler;
18
	/**
19
	 *  The processor
20
	 */
21
	public STextProcessor processor;
22
	/**
23
	 *  The environment
24
	 */
25
	public STextEnvironment environment;
26
	/**
27
	 *  The class instance to get and set the bidi type of characters
28
	 */
29
	public STextCharTypes dirProps;
30
	/**
31
	 *  The class instance to manipulate the array of offsets to 
32
	 *  directional control characters
33
	 */
34
	public STextOffsets offsets;
35
	/**
36
	 *  The source text
37
	 */
38
	public String text;
39
	/**
40
	 *  The base direction of the source text
41
	 */
42
	public int direction;
43
	/**
44
	 *  The orientation of the component which is to display the text
45
	 */
46
	public int orientation;
47
	/**
48
	 *  The length of the prefix (LRE, RLE, LRM or RLM) to be prepended 
49
	 *  to the text
50
	 */
51
	public int prefixLength;
52
}
(-)src/org/eclipse/equinox/bidi/custom/package.html (-25 / +29 lines)
Lines 1-25 Link Here
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
<html>
2
<html>
3
<head>
3
<head>
4
<META name="Author" content="Matitiahu Allouche">
4
<META name="Author" content="Matitiahu Allouche">
5
</head>
5
</head>
6
<body bgcolor="white">
6
<body bgcolor="white">
7
7
8
This package provides classes for
8
This package provides classes for
9
developing structured text processors.
9
developing structured text processors.
10
10
11
<ul>
11
<ul>
12
  <li>{@link <a href="STextProcessor.html">STextProcessor</a>}
12
  <li>{@link <a href="STextProcessor.html">STextProcessor</a>}
13
      is a generic processor to be used as superclass for specific
13
      is a generic processor to be used as superclass for specific
14
      processors.</li>
14
      processors.</li>
15
  <li>{@link <a href="STextStringProcessor.html">STextStringProcessor</a>}
15
  <li>{@link <a href="STextProcessorData.html">STextProcessorData</a>}
16
      is a class which allows retrieval of the defined processor types and of the
16
      regroups data which can be used by processors.</li>
17
      corresponding processors.</li>
17
  <li>{@link <a href="STextCharTypes.html">STextStringCharTypes</a>}
18
</ul>
18
      allows getting and setting the bidi class of characters.</li>
19
19
  <li>{@link <a href="STextOffsets.html">STextStringOffsets</a>}
20
This package is to be used together with package
20
      allows manipulation of offsets at which directional control
21
{@link <a href="..\package-summary.html">
21
      characters are inserted.</li>
22
org.eclipse.equinox.bidi</a>}.
22
</ul>
23
23
24
</body>
24
This package is to be used together with package
25
</html>
25
{@link <a href="..\package-summary.html">
26
org.eclipse.equinox.bidi</a>}.
27
28
</body>
29
</html>
(-)src/org/eclipse/equinox/bidi/internal/STextDelims.java (-8 / +7 lines)
Lines 10-18 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextCharTypes;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.custom.STextProcessorData;
16
15
17
/**
16
/**
18
 *  A base processor for structured text composed of text segments separated 
17
 *  A base processor for structured text composed of text segments separated 
Lines 44-52 Link Here
44
	 *
43
	 *
45
	 *  @see #getDelimiters
44
	 *  @see #getDelimiters
46
	 */
45
	 */
47
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
46
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
48
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
47
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
49
		return text.indexOf(delim, fromIndex);
48
		return procData.text.indexOf(delim, fromIndex);
50
	}
49
	}
51
50
52
	/**
51
	/**
Lines 59-71 Link Here
59
	 *  @return the position after the matching end delimiter, or the length
58
	 *  @return the position after the matching end delimiter, or the length
60
	 *          of <code>text</code> if no end delimiter is found.
59
	 *          of <code>text</code> if no end delimiter is found.
61
	 */
60
	 */
62
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
61
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
63
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
62
		STextProcessor.processSeparator(procData, separLocation);
64
		int loc = separLocation + 1;
63
		int loc = separLocation + 1;
65
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
64
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
66
		loc = text.indexOf(delim, loc);
65
		loc = procData.text.indexOf(delim, loc);
67
		if (loc < 0)
66
		if (loc < 0)
68
			return text.length();
67
			return procData.text.length();
69
		return loc + 1;
68
		return loc + 1;
70
	}
69
	}
71
70
(-)src/org/eclipse/equinox/bidi/internal/STextDelimsEsc.java (-4 / +4 lines)
Lines 10-18 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextCharTypes;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
13
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.custom.STextProcessorData;
16
15
17
/**
16
/**
18
 *  A base processor for structured text composed of text segments separated 
17
 *  A base processor for structured text composed of text segments separated 
Lines 50-59 Link Here
50
	 *  and skips until after the matching end delimiter,
49
	 *  and skips until after the matching end delimiter,
51
	 *  ignoring possibly escaped end delimiters.
50
	 *  ignoring possibly escaped end delimiters.
52
	 */
51
	 */
53
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
52
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
54
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
53
		STextProcessor.processSeparator(procData, separLocation);
55
		int location = separLocation + 1;
54
		int location = separLocation + 1;
56
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
55
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
56
		String text = procData.text;
57
		while (true) {
57
		while (true) {
58
			location = text.indexOf(delim, location);
58
			location = text.indexOf(delim, location);
59
			if (location < 0)
59
			if (location < 0)
(-)src/org/eclipse/equinox/bidi/internal/STextImpl.java (-172 / +112 lines)
Lines 10-25 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
11
package org.eclipse.equinox.bidi.internal;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
14
import org.eclipse.equinox.bidi.STextHandler;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.*;
17
16
18
/**
17
/**
19
 *  <code>STextImpl</code> provides the code which implements the API in
18
 *  <code>STextImpl</code> provides the code which implements the API in
20
 *  {@link STextEngine}. All its public methods are shadows of similarly
19
 *  {@link STextHandler}. All its public methods are shadows of similarly
21
 *  signed methods of <code>STextEngine</code>, and their documentation
20
 *  signed methods of <code>STextHandler</code>, and their documentation
22
 *  is by reference to the methods in <code>STextEngine</code>.
21
 *  is by reference to the methods in <code>STextHandler</code>.
23
 *
22
 *
24
 *  @author Matitiahu Allouche
23
 *  @author Matitiahu Allouche
25
 */
24
 */
Lines 50-56 Link Here
50
	static final char PDF = 0x202C;
49
	static final char PDF = 0x202C;
51
	static final char[] MARKS = {LRM, RLM};
50
	static final char[] MARKS = {LRM, RLM};
52
	static final char[] EMBEDS = {LRE, RLE};
51
	static final char[] EMBEDS = {LRE, RLE};
53
	static final byte[] STRONGS = {L, R};
54
	static final int PREFIX_LENGTH = 2;
52
	static final int PREFIX_LENGTH = 2;
55
	static final int SUFFIX_LENGTH = 2;
53
	static final int SUFFIX_LENGTH = 2;
56
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
54
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
Lines 59-74 Link Here
59
	static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE);
57
	static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE);
60
58
61
	/**
59
	/**
62
	 *  Prevent creation of a STextEngine instance
60
	 *  Prevent creation of a STextHandler instance
63
	 */
61
	 */
64
	private STextImpl() {
62
	private STextImpl() {
65
		// nothing to do
63
		// nothing to do
66
	}
64
	}
67
65
68
	static long computeNextLocation(STextProcessor processor, STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] locations, int[] state, int curPos) {
66
	static long computeNextLocation(STextProcessorData procData, int[] locations, int curPos) {
69
		String separators = processor.getSeparators(environment);
67
		STextProcessor processor = procData.processor;
68
		String separators = processor.getSeparators(procData.environment);
70
		int separCount = separators.length();
69
		int separCount = separators.length();
71
		int specialsCount = processor.getSpecialsCount(environment);
70
		int specialsCount = processor.getSpecialsCount(procData.environment);
71
		String text = procData.text;
72
		int len = text.length();
72
		int len = text.length();
73
		int nextLocation = len;
73
		int nextLocation = len;
74
		int idxLocation = 0;
74
		int idxLocation = 0;
Lines 77-84 Link Here
77
		for (int i = 0; i < specialsCount; i++) {
77
		for (int i = 0; i < specialsCount; i++) {
78
			int location = locations[separCount + i];
78
			int location = locations[separCount + i];
79
			if (location < curPos) {
79
			if (location < curPos) {
80
				offsets = ensureRoomInOffsets(offsets);
80
				procData.offsets.ensureRoom();
81
				location = processor.indexOfSpecial(environment, text, dirProps, offsets, i + 1, curPos);
81
				location = processor.indexOfSpecial(procData, i + 1, curPos);
82
				if (location < 0)
82
				if (location < 0)
83
					location = len;
83
					location = len;
84
				locations[separCount + i] = location;
84
				locations[separCount + i] = location;
Lines 107-116 Link Here
107
	/**
107
	/**
108
	 *  @see STextProcessor#processSeparator STextProcessor.processSeparator
108
	 *  @see STextProcessor#processSeparator STextProcessor.processSeparator
109
	 */
109
	 */
110
	public static void processSeparator(String text, STextCharTypes dirProps, int[] offsets, int separLocation) {
110
	public static void processSeparator(STextProcessorData procData, int separLocation) {
111
		String text = procData.text;
111
		int len = text.length();
112
		int len = text.length();
112
		// offsets[2] contains the structured text direction
113
		STextCharTypes dirProps = procData.dirProps;
113
		if (offsets[2] == STextEngine.DIR_RTL) {
114
		STextOffsets offsets = procData.offsets;
115
		if (procData.direction == STextHandler.DIR_RTL) {
114
			// the structured text base direction is RTL
116
			// the structured text base direction is RTL
115
			for (int i = separLocation - 1; i >= 0; i--) {
117
			for (int i = separLocation - 1; i >= 0; i--) {
116
				byte dirProp = dirProps.getBidiTypeAt(i);
118
				byte dirProp = dirProps.getBidiTypeAt(i);
Lines 122-128 Link Here
122
						if (dirProp == R || dirProp == AL)
124
						if (dirProp == R || dirProp == AL)
123
							return;
125
							return;
124
						if (dirProp == L || dirProp == EN) {
126
						if (dirProp == L || dirProp == EN) {
125
							insertMark(text, dirProps, offsets, separLocation);
127
							offsets.insertOffset(procData, separLocation);
126
							return;
128
							return;
127
						}
129
						}
128
					}
130
					}
Lines 144-150 Link Here
144
					if (dirProp == L)
146
					if (dirProp == L)
145
						return;
147
						return;
146
					if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
148
					if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
147
						insertMark(text, dirProps, offsets, separLocation);
149
						offsets.insertOffset(procData, separLocation);
148
						return;
150
						return;
149
					}
151
					}
150
				}
152
				}
Lines 156-162 Link Here
156
					if (dirProp == L)
158
					if (dirProp == L)
157
						return;
159
						return;
158
					if (dirProp == AL || dirProp == AN || dirProp == R) {
160
					if (dirProp == AL || dirProp == AN || dirProp == R) {
159
						insertMark(text, dirProps, offsets, separLocation);
161
						offsets.insertOffset(procData, separLocation);
160
						return;
162
						return;
161
					}
163
					}
162
				}
164
				}
Lines 168-252 Link Here
168
	/**
170
	/**
169
	 *  When the orientation is <code>ORIENT_LTR</code> and the
171
	 *  When the orientation is <code>ORIENT_LTR</code> and the
170
	 *  structured text has a RTL base direction,
172
	 *  structured text has a RTL base direction,
171
	 *  {@link STextEngine#leanToFullText leanToFullText}
173
	 *  {@link STextHandler#leanToFullText leanToFullText}
172
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
174
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
173
	 *  end.
175
	 *  end.
174
	 *  <p>
176
	 *  <p>
175
	 *  When the orientation is <code>ORIENT_RTL</code> and the
177
	 *  When the orientation is <code>ORIENT_RTL</code> and the
176
	 *  structured text has a LTR base direction,
178
	 *  structured text has a LTR base direction,
177
	 *  {@link STextEngine#leanToFullText leanToFullText}
179
	 *  {@link STextHandler#leanToFullText leanToFullText}
178
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
180
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
179
	 *  end.
181
	 *  end.
180
	 *  <p>
182
	 *  <p>
181
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
183
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
182
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
184
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
183
	 *  to a RTL orientation while the structured text has a LTR base
185
	 *  to a RTL orientation while the structured text has a LTR base
184
	 *  direction, {@link STextEngine#leanToFullText leanToFullText}
186
	 *  direction, {@link STextHandler#leanToFullText leanToFullText}
185
	 *  adds LRM at the head of the <i>full</i> text.
187
	 *  adds LRM at the head of the <i>full</i> text.
186
	 *  <p>
188
	 *  <p>
187
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
189
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
188
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
190
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
189
	 *  to a LTR orientation while the structured text has a RTL base
191
	 *  to a LTR orientation while the structured text has a RTL base
190
	 *  direction, {@link STextEngine#leanToFullText leanToFullText}
192
	 *  direction, {@link STextHandler#leanToFullText leanToFullText}
191
	 *  adds RLM at the head of the <i>full</i> text.
193
	 *  adds RLM at the head of the <i>full</i> text.
192
	 *  <p>
194
	 *  <p>
193
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
195
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
194
	 *  structured text has a LTR base direction,
196
	 *  structured text has a LTR base direction,
195
	 *  {@link STextEngine#leanToFullText leanToFullText}
197
	 *  {@link STextHandler#leanToFullText leanToFullText}
196
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
198
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
197
	 *  end.
199
	 *  end.
198
	 *  <p>
200
	 *  <p>
199
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
201
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
200
	 *  structured text has a RTL base direction,
202
	 *  structured text has a RTL base direction,
201
	 *  {@link STextEngine#leanToFullText leanToFullText}
203
	 *  {@link STextHandler#leanToFullText leanToFullText}
202
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
204
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
203
	 *  end.
205
	 *  end.
204
	 *  <p>
206
	 *  <p>
205
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
207
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
206
	 *  {@link STextEngine#leanToFullText leanToFullText} does not add any directional
208
	 *  {@link STextHandler#leanToFullText leanToFullText} does not add any directional
207
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
209
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
208
	 *  <p>
210
	 *  <p>
209
	 *  @see STextEngine#leanToFullText STextEngine.leanToFullText
211
	 *  @see STextHandler#leanToFullText STextHandler.leanToFullText
210
	 */
212
	 */
211
	public static String leanToFullText(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
213
	public static String leanToFullText(STextProcessorData procData) {
214
		String text = procData.text;
212
		int len = text.length();
215
		int len = text.length();
213
		if (len == 0)
216
		if (len == 0)
214
			return text;
217
			return text;
215
		STextCharTypes dirProps = new STextCharTypes(text);
218
		leanToFullCommon(procData);
216
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
219
		STextOffsets offsets = procData.offsets;
217
		int prefixLength = offsets[1];
220
		int count = offsets.getCount();
218
		int count = offsets[0] - OFFSETS_SHIFT;
221
		if (count == 0 && procData.prefixLength == 0)
219
		if (count == 0 && prefixLength == 0)
220
			return text;
222
			return text;
221
		int newLen = len + count;
223
		int newLen = len + count;
222
		if (prefixLength == 1)
224
		if (procData.prefixLength == 1)
223
			newLen++; /* +1 for a mark char */
225
			newLen++; /* +1 for a mark char */
224
		else if (prefixLength == 2)
226
		else if (procData.prefixLength == 2)
225
			newLen += FIXES_LENGTH;
227
			newLen += FIXES_LENGTH;
226
		char[] fullChars = new char[newLen];
228
		char[] fullChars = new char[newLen];
227
		int added = prefixLength;
229
		int added = procData.prefixLength;
228
		// add marks at offsets
230
		// add marks at offsets
229
		int direction = offsets[2];
231
		char curMark = MARKS[procData.direction];
230
		char curMark = MARKS[direction];
232
		for (int i = 0, j = 0; i < len; i++) {
231
		for (int i = 0, j = OFFSETS_SHIFT; i < len; i++) {
232
			char c = text.charAt(i);
233
			char c = text.charAt(i);
233
			// offsets[0] contains the number of used entries
234
			if (j < count && i == offsets.getOffset(j)) {
234
			if (j < offsets[0] && i == offsets[j]) {
235
				fullChars[i + added] = curMark;
235
				fullChars[i + added] = curMark;
236
				added++;
236
				added++;
237
				j++;
237
				j++;
238
			}
238
			}
239
			fullChars[i + added] = c;
239
			fullChars[i + added] = c;
240
		}
240
		}
241
		if (prefixLength > 0) { /* add prefix/suffix ? */
241
		if (procData.prefixLength > 0) { /* add prefix/suffix ? */
242
			if (prefixLength == 1) { /* contextual orientation */
242
			if (procData.prefixLength == 1) { /* contextual orientation */
243
				fullChars[0] = curMark;
243
				fullChars[0] = curMark;
244
			} else {
244
			} else {
245
				// When the orientation is RTL, we need to add EMBED at the
245
				// When the orientation is RTL, we need to add EMBED at the
246
				// start of the text and PDF at its end.
246
				// start of the text and PDF at its end.
247
				// However, because of a bug in Windows' handling of LRE/PDF,
247
				// However, because of a bug in Windows' handling of LRE/PDF,
248
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
248
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
249
				char curEmbed = EMBEDS[direction];
249
				char curEmbed = EMBEDS[procData.direction];
250
				fullChars[0] = curEmbed;
250
				fullChars[0] = curEmbed;
251
				fullChars[1] = curMark;
251
				fullChars[1] = curMark;
252
				fullChars[newLen - 1] = PDF;
252
				fullChars[newLen - 1] = PDF;
Lines 257-276 Link Here
257
	}
257
	}
258
258
259
	/**
259
	/**
260
	 *  @see STextEngine#leanToFullMap STextEngine.leanToFullMap
260
	 *  @see STextHandler#leanToFullMap STextHandler.leanToFullMap
261
	 */
261
	 */
262
	public static int[] leanToFullMap(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
262
	public static int[] leanToFullMap(STextProcessorData procData) {
263
		String text = procData.text;
263
		int len = text.length();
264
		int len = text.length();
264
		if (len == 0)
265
		if (len == 0)
265
			return EMPTY_INT_ARRAY;
266
			return EMPTY_INT_ARRAY;
266
		STextCharTypes dirProps = new STextCharTypes(text);
267
		leanToFullCommon(procData);
267
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
268
		STextOffsets offsets = procData.offsets;
268
		int prefixLength = offsets[1];
269
		int[] map = new int[len];
269
		int[] map = new int[len];
270
		int count = offsets[0]; // number of used entries
270
		int count = procData.offsets.getCount();
271
		int added = prefixLength;
271
		int added = procData.prefixLength;
272
		for (int pos = 0, i = OFFSETS_SHIFT; pos < len; pos++) {
272
		for (int pos = 0, i = 0; pos < len; pos++) {
273
			if (i < count && pos == offsets[i]) {
273
			if (i < count && pos == offsets.getOffset(i)) {
274
				added++;
274
				added++;
275
				i++;
275
				i++;
276
			}
276
			}
Lines 280-317 Link Here
280
	}
280
	}
281
281
282
	/**
282
	/**
283
	 *  @see STextEngine#leanBidiCharOffsets STextEngine.leanBidiCharOffsets
283
	 *  @see STextHandler#leanBidiCharOffsets STextHandler.leanBidiCharOffsets
284
	 */
284
	 */
285
	public static int[] leanBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
285
	public static int[] leanBidiCharOffsets(STextProcessorData procData) {
286
		String text = procData.text;
286
		int len = text.length();
287
		int len = text.length();
287
		if (len == 0)
288
		if (len == 0)
288
			return EMPTY_INT_ARRAY;
289
			return EMPTY_INT_ARRAY;
289
		STextCharTypes dirProps = new STextCharTypes(text);
290
		leanToFullCommon(procData);
290
		int[] offsets = leanToFullCommon(processor, environment, text, state, dirProps);
291
		return procData.offsets.getArray();
291
		// offsets[0] contains the number of used entries
292
		int count = offsets[0] - OFFSETS_SHIFT;
293
		int[] result = new int[count];
294
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, count);
295
		return result;
296
	}
292
	}
297
293
298
	static int[] leanToFullCommon(STextProcessor processor, STextEnvironment environment, String text, int[] state, STextCharTypes dirProps) {
294
	static void leanToFullCommon(STextProcessorData procData) {
299
		if (environment == null)
295
		if (procData.environment == null)
300
			environment = STextEnvironment.DEFAULT;
296
			procData.environment = STextEnvironment.DEFAULT;
301
		if (state == null) {
297
		String text = procData.text;
302
			state = new int[1];
303
			state[0] = STextEngine.STATE_INITIAL;
304
		}
305
		int len = text.length();
298
		int len = text.length();
306
		int orient = dirProps.getOrientation(environment);
299
		STextHandler handler = procData.handler;
307
		int direction = processor.getDirection(environment, text, dirProps);
300
		STextProcessor processor = procData.processor;
308
		// offsets of marks to add. Entry 0 is the number of used slots;
301
		STextEnvironment environment = procData.environment;
309
		//  entry 1 is reserved to pass prefixLength.
302
		STextOffsets offsets = procData.offsets;
310
		//  entry 2 is reserved to pass direction..
303
		STextCharTypes dirProps = procData.dirProps = new STextCharTypes(text);
311
		int[] offsets = new int[20];
304
		procData.orientation = dirProps.getOrientation(environment);
312
		offsets[0] = OFFSETS_SHIFT;
305
		procData.direction = processor.getDirection(environment, text, dirProps);
313
		offsets[2] = direction;
306
		offsets.resetCount();
314
		if (!processor.skipProcessing(environment, text, dirProps)) {
307
		if (!processor.skipProcessing(procData)) {
315
			// initialize locations
308
			// initialize locations
316
			int separCount = processor.getSeparators(environment).length();
309
			int separCount = processor.getSeparators(environment).length();
317
			int[] locations = new int[separCount + processor.getSpecialsCount(environment)];
310
			int[] locations = new int[separCount + processor.getSpecialsCount(environment)];
Lines 320-382 Link Here
320
			}
313
			}
321
			// current position
314
			// current position
322
			int curPos = 0;
315
			int curPos = 0;
323
			if (state[0] > STextEngine.STATE_INITIAL) {
316
			int state = handler.getState();
324
				offsets = ensureRoomInOffsets(offsets);
317
			if (state > STextHandler.STATE_INITIAL) {
325
				int initState = state[0];
318
				offsets.ensureRoom();
326
				state[0] = STextEngine.STATE_INITIAL;
319
				handler.setState(STextHandler.STATE_INITIAL);
327
				curPos = processor.processSpecial(environment, text, dirProps, offsets, state, initState, -1);
320
				curPos = processor.processSpecial(procData, state, -1);
328
			}
321
			}
329
			while (true) {
322
			while (true) {
330
				// location of next token to handle
323
				// location of next token to handle
331
				int nextLocation;
324
				int nextLocation;
332
				// index of next token to handle (if < separCount, this is a separator; otherwise a special case
325
				// index of next token to handle (if < separCount, this is a separator; otherwise a special case
333
				int idxLocation;
326
				int idxLocation;
334
				long res = computeNextLocation(processor, environment, text, dirProps, offsets, locations, state, curPos);
327
				long res = computeNextLocation(procData, locations, curPos);
335
				nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
328
				nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
336
				if (nextLocation >= len)
329
				if (nextLocation >= len)
337
					break;
330
					break;
331
				offsets.ensureRoom();
338
				idxLocation = (int) (res >> 32); /* high word */
332
				idxLocation = (int) (res >> 32); /* high word */
339
				if (idxLocation < separCount) {
333
				if (idxLocation < separCount) {
340
					offsets = ensureRoomInOffsets(offsets);
334
					processSeparator(procData, nextLocation);
341
					processSeparator(text, dirProps, offsets, nextLocation);
342
					curPos = nextLocation + 1;
335
					curPos = nextLocation + 1;
343
				} else {
336
				} else {
344
					offsets = ensureRoomInOffsets(offsets);
345
					idxLocation -= (separCount - 1); // because caseNumber starts from 1
337
					idxLocation -= (separCount - 1); // because caseNumber starts from 1
346
					curPos = processor.processSpecial(environment, text, dirProps, offsets, state, idxLocation, nextLocation);
338
					curPos = processor.processSpecial(procData, idxLocation, nextLocation);
347
				}
339
				}
348
				if (curPos >= len)
340
				if (curPos >= len)
349
					break;
341
					break;
350
			} // end while
342
			} // end while
351
		} // end if (!processor.skipProcessing())
343
		} // end if (!processor.skipProcessing())
352
		if (orient == STextEnvironment.ORIENT_IGNORE)
344
		if (procData.orientation == STextEnvironment.ORIENT_IGNORE)
353
			offsets[1] = 0;
345
			procData.prefixLength = 0;
354
		else {
346
		else {
355
			// recompute orient since it may have changed if contextual
347
			// recompute orient since it may have changed if contextual
356
			orient = dirProps.getOrientation(environment);
348
			procData.orientation = dirProps.getOrientation(environment);
357
			if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN)
349
			if (procData.orientation == procData.direction && procData.orientation != STextEnvironment.ORIENT_UNKNOWN)
358
				offsets[1] = 0;
350
				procData.prefixLength = 0;
359
			else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
351
			else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
360
				offsets[1] = 1;
352
				procData.prefixLength = 1;
361
			else
353
			else
362
				offsets[1] = 2;
354
				procData.prefixLength = 2;
363
		}
355
		}
364
		return offsets;
365
	}
356
	}
366
357
367
	/**
358
	/**
368
	 *  @see STextEngine#fullToLeanText STextEngine.fullToLeanText
359
	 *  @see STextHandler#fullToLeanText STextHandler.fullToLeanText
369
	 */
360
	 */
370
	public static String fullToLeanText(STextProcessor processor, STextEnvironment environment, String text, int[] state) {
361
	public static String fullToLeanText(STextProcessorData procData) {
362
		String text = procData.text;
371
		if (text.length() == 0)
363
		if (text.length() == 0)
372
			return text;
364
			return text;
373
		if (environment == null)
365
		if (procData.environment == null)
374
			environment = STextEnvironment.DEFAULT;
366
			procData.environment = STextEnvironment.DEFAULT;
375
		if (state == null) {
367
		int dir = procData.processor.getDirection(procData.environment, text);
376
			state = new int[1];
377
			state[0] = STextEngine.STATE_INITIAL;
378
		}
379
		int dir = processor.getDirection(environment, text);
380
		char curMark = MARKS[dir];
368
		char curMark = MARKS[dir];
381
		char curEmbed = EMBEDS[dir];
369
		char curEmbed = EMBEDS[dir];
382
		int i; // used as loop index
370
		int i; // used as loop index
Lines 414-420 Link Here
414
				chars[i - cnt] = c;
402
				chars[i - cnt] = c;
415
		}
403
		}
416
		String lean = new String(chars, 0, lenText - cnt);
404
		String lean = new String(chars, 0, lenText - cnt);
417
		String full = leanToFullText(processor, IGNORE_ENVIRONMENT, lean, state);
405
		String full = procData.handler.leanToFullText(IGNORE_ENVIRONMENT, lean);
418
		if (full.equals(text))
406
		if (full.equals(text))
419
			return lean;
407
			return lean;
420
408
Lines 460-474 Link Here
460
	}
448
	}
461
449
462
	/**
450
	/**
463
	 *  @see STextEngine#fullToLeanMap STextEngine.fullToLeanMap
451
	 *  @see STextHandler#fullToLeanMap STextHandler.fullToLeanMap
464
	 */
452
	 */
465
	public static int[] fullToLeanMap(STextProcessor processor, STextEnvironment environment, String full, int[] state) {
453
	public static int[] fullToLeanMap(STextProcessorData procData) {
454
		String full = procData.text;
466
		int lenFull = full.length();
455
		int lenFull = full.length();
467
		if (lenFull == 0)
456
		if (lenFull == 0)
468
			return EMPTY_INT_ARRAY;
457
			return EMPTY_INT_ARRAY;
469
		String lean = fullToLeanText(processor, environment, full, state);
458
		String lean = procData.handler.fullToLeanText(procData.environment, full);
470
		int lenLean = lean.length();
459
		int lenLean = lean.length();
471
		int dir = processor.getDirection(environment, lean);
460
		int dir = procData.processor.getDirection(procData.environment, lean);
472
		char curMark = MARKS[dir];
461
		char curMark = MARKS[dir];
473
		char curEmbed = EMBEDS[dir];
462
		char curEmbed = EMBEDS[dir];
474
		int[] map = new int[lenFull];
463
		int[] map = new int[lenFull];
Lines 494-508 Link Here
494
	}
483
	}
495
484
496
	/**
485
	/**
497
	 *  @see STextEngine#fullBidiCharOffsets STextEngine.fullBidiCharOffsets
486
	 *  @see STextHandler#fullBidiCharOffsets STextHandler.fullBidiCharOffsets
498
	 */
487
	 */
499
	public static int[] fullBidiCharOffsets(STextProcessor processor, STextEnvironment environment, String full, int[] state) {
488
	public static int[] fullBidiCharOffsets(STextProcessorData procData) {
489
		String full = procData.text;
500
		int lenFull = full.length();
490
		int lenFull = full.length();
501
		if (lenFull == 0)
491
		if (lenFull == 0)
502
			return EMPTY_INT_ARRAY;
492
			return EMPTY_INT_ARRAY;
503
		String lean = fullToLeanText(processor, environment, full, state);
493
		String lean = procData.handler.fullToLeanText(procData.environment, full);
504
		int[] offsets = new int[20];
494
		procData.text = full;
505
		offsets[0] = OFFSETS_SHIFT;
495
		procData.dirProps = new STextCharTypes(full);
496
		STextOffsets offsets = procData.offsets;
497
		offsets.resetCount();
506
		int lenLean = lean.length();
498
		int lenLean = lean.length();
507
		int idxLean, idxFull;
499
		int idxLean, idxFull;
508
		// lean must be a subset of Full, so we only check on iLean < leanLen
500
		// lean must be a subset of Full, so we only check on iLean < leanLen
Lines 510-575 Link Here
510
			if (full.charAt(idxFull) == lean.charAt(idxLean))
502
			if (full.charAt(idxFull) == lean.charAt(idxLean))
511
				idxLean++;
503
				idxLean++;
512
			else {
504
			else {
513
				offsets = ensureRoomInOffsets(offsets);
505
				offsets.ensureRoom();
514
				insertMark(lean, null, offsets, idxFull);
506
				offsets.insertOffset(procData, idxFull);
515
			}
507
			}
516
		}
508
		}
517
		for (; idxFull < lenFull; idxFull++) {
509
		for (; idxFull < lenFull; idxFull++) {
518
			offsets = ensureRoomInOffsets(offsets);
510
			offsets.ensureRoom();
519
			insertMark(lean, null, offsets, idxFull);
511
			offsets.insertOffset(procData, idxFull);
520
		}
512
		}
521
		int[] result = new int[offsets[0] - OFFSETS_SHIFT];
513
		return offsets.getArray();
522
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length);
523
		return result;
524
	}
525
526
	static int[] ensureRoomInOffsets(int[] offsets) {
527
		// make sure
528
		if ((offsets.length - offsets[0]) < 3) {
529
			int[] newOffsets = new int[offsets.length * 2];
530
			System.arraycopy(offsets, 0, newOffsets, 0, offsets[0]);
531
			return newOffsets;
532
		}
533
		return offsets;
534
	}
535
536
	/**
537
	 *  @see STextProcessor#insertMark STextProcessor.insertMark
538
	 */
539
	public static void insertMark(String text, STextCharTypes dirProps, int[] offsets, int offset) {
540
		int count = offsets[0];// number of used entries
541
		int index = count - 1; // index of greatest member <= offset
542
		// look up after which member the new offset should be inserted
543
		while (index >= OFFSETS_SHIFT) {
544
			int wrkOffset = offsets[index];
545
			if (offset > wrkOffset)
546
				break;
547
			if (offset == wrkOffset)
548
				return; // avoid duplicates
549
			index--;
550
		}
551
		index++; // index now points at where to insert
552
		int length = count - index; // number of members to move up
553
		if (length > 0) // shift right all members greater than offset
554
			System.arraycopy(offsets, index, offsets, index + 1, length);
555
		offsets[index] = offset;
556
		offsets[0]++; // number of used entries
557
		// if the offset is 0, adding a mark does not change anything
558
		if (dirProps == null || offset < 1)
559
			return;
560
561
		byte dirProp = dirProps.getBidiTypeAt(offset);
562
		// if the current char is a strong one or a digit, we change the
563
		//   dirProp of the previous char to account for the inserted mark.
564
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
565
			index = offset - 1;
566
		else
567
			// if the current char is a neutral, we change its own dirProp
568
			index = offset;
569
570
		int dir = offsets[2]; // current structured text direction
571
		dirProps.setBidiTypeAt(index, STRONGS[dir]);
572
		return;
573
	}
514
	}
574
575
}
515
}
(-)src/org/eclipse/equinox/bidi/internal/STextSingle.java (-7 / +6 lines)
Lines 11-18 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.STextCharTypes;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessorData;
16
16
17
/**
17
/**
18
 *  A base processor for structured text composed of two parts separated by a separator.
18
 *  A base processor for structured text composed of two parts separated by a separator.
Lines 41-48 Link Here
41
	 *
41
	 *
42
	 *  @see #getSeparators getSeparators
42
	 *  @see #getSeparators getSeparators
43
	 */
43
	 */
44
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
44
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
45
		return text.indexOf(this.getSeparators(environment).charAt(0), fromIndex);
45
		return procData.text.indexOf(this.getSeparators(procData.environment).charAt(0), fromIndex);
46
	}
46
	}
47
47
48
	/**
48
	/**
Lines 51-59 Link Here
51
	 *
51
	 *
52
	 *  @return the length of <code>text</code>.
52
	 *  @return the length of <code>text</code>.
53
	 */
53
	 */
54
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
54
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
55
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
55
		STextProcessor.processSeparator(procData, separLocation);
56
		return text.length();
56
		return procData.text.length();
57
	}
57
	}
58
58
59
	/**
59
	/**
Lines 64-68 Link Here
64
	public int getSpecialsCount(STextEnvironment environment) {
64
	public int getSpecialsCount(STextEnvironment environment) {
65
		return 1;
65
		return 1;
66
	}
66
	}
67
68
}
67
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextEmail.java (-7 / +19 lines)
Lines 10-17 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextHandler;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
16
import org.eclipse.equinox.bidi.internal.STextDelimsEsc;
16
import org.eclipse.equinox.bidi.internal.STextDelimsEsc;
17
17
Lines 27-38 Link Here
27
		super("<>.:,;@"); //$NON-NLS-1$
27
		super("<>.:,;@"); //$NON-NLS-1$
28
	}
28
	}
29
29
30
	/**
31
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
32
	 *          conditions are satisfied:
33
	 *          <ul>
34
	 *            <li>The current locale (as expressed by the environment
35
	 *                language) is Arabic.</li>
36
	 *            <li>The domain part of the email address contains
37
	 *                at least one RTL character.</li>
38
	 *          </ul>
39
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
40
	 */
30
	public int getDirection(STextEnvironment environment, String text) {
41
	public int getDirection(STextEnvironment environment, String text) {
31
		return getDirection(environment, text, new STextCharTypes(text));
42
		return getDirection(environment, text, new STextCharTypes(text));
32
	}
43
	}
33
44
34
	/**
45
	/**
35
	 *  @return {@link STextEngine#DIR_RTL DIR_RTL} if the following
46
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
36
	 *          conditions are satisfied:
47
	 *          conditions are satisfied:
37
	 *          <ul>
48
	 *          <ul>
38
	 *            <li>The current locale (as expressed by the environment
49
	 *            <li>The current locale (as expressed by the environment
Lines 40-51 Link Here
40
	 *            <li>The domain part of the email address contains
51
	 *            <li>The domain part of the email address contains
41
	 *                at least one RTL character.</li>
52
	 *                at least one RTL character.</li>
42
	 *          </ul>
53
	 *          </ul>
43
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
54
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
44
	 */
55
	 */
45
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
56
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
57
		if (environment == null)
58
			environment = STextEnvironment.DEFAULT;
46
		String language = environment.getLanguage();
59
		String language = environment.getLanguage();
47
		if (!language.equals("ar")) //$NON-NLS-1$
60
		if (!language.equals("ar")) //$NON-NLS-1$
48
			return STextEngine.DIR_LTR;
61
			return STextHandler.DIR_LTR;
49
		int domainStart;
62
		int domainStart;
50
		domainStart = text.indexOf('@');
63
		domainStart = text.indexOf('@');
51
		if (domainStart < 0)
64
		if (domainStart < 0)
Lines 53-61 Link Here
53
		for (int i = domainStart; i < text.length(); i++) {
66
		for (int i = domainStart; i < text.length(); i++) {
54
			byte dirProp = dirProps.getBidiTypeAt(i);
67
			byte dirProp = dirProps.getBidiTypeAt(i);
55
			if (dirProp == AL || dirProp == R)
68
			if (dirProp == AL || dirProp == R)
56
				return STextEngine.DIR_RTL;
69
				return STextHandler.DIR_RTL;
57
		}
70
		}
58
		return STextEngine.DIR_LTR;
71
		return STextHandler.DIR_LTR;
59
	}
72
	}
60
73
61
	/**
74
	/**
Lines 71-75 Link Here
71
	protected String getDelimiters() {
84
	protected String getDelimiters() {
72
		return "()\"\""; //$NON-NLS-1$
85
		return "()\"\""; //$NON-NLS-1$
73
	}
86
	}
74
75
}
87
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextJava.java (-16 / +16 lines)
Lines 10-19 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
14
import org.eclipse.equinox.bidi.STextHandler;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessorData;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
18
18
19
/**
19
/**
Lines 23-37 Link Here
23
 *  <p>
23
 *  <p>
24
 *  In applications like an editor where parts of the text might be modified
24
 *  In applications like an editor where parts of the text might be modified
25
 *  while other parts are not, the user may want to call
25
 *  while other parts are not, the user may want to call
26
 *  {@link STextEngine#leanToFullText leanToFullText}
26
 *  {@link STextHandler#leanToFullText leanToFullText}
27
 *  separately on each line and save the initial state of each line (this is
27
 *  separately on each line and save the initial <b>state</b> of each line (this is
28
 *  the final state of the previous line which can be retrieved using
28
 *  the final <b>state</b> of the previous line which can be retrieved using
29
 *  the value returned in the first element of the <code>state</code> argument).
29
 *  {@link STextHandler#getState}.
30
 *  If both the content
30
 *  If both the content of a line and its initial
31
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  <b>state</b> have not changed, the user can be sure that
32
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *  the last <i>full</i> text computed for this line has not changed either.
33
 *
34
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
35
 *
33
 *
36
 *  @author Matitiahu Allouche
34
 *  @author Matitiahu Allouche
37
 */
35
 */
Lines 59-65 Link Here
59
	     *    <li>comments starting with slash-slash</li>
57
	     *    <li>comments starting with slash-slash</li>
60
	     *  </ol>
58
	     *  </ol>
61
	     */
59
	     */
62
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
60
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
61
		String text = procData.text;
63
		switch (caseNumber) {
62
		switch (caseNumber) {
64
			case 1 : /* space */
63
			case 1 : /* space */
65
				return text.indexOf(' ', fromIndex);
64
				return text.indexOf(' ', fromIndex);
Lines 83-97 Link Here
83
	     *    <li>skip until after a line separator</li>
82
	     *    <li>skip until after a line separator</li>
84
	     *  </ol>
83
	     *  </ol>
85
	 */
84
	 */
86
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
85
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
87
		int location, counter, i;
86
		int location, counter, i;
88
87
89
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
88
		STextProcessor.processSeparator(procData, separLocation);
89
		String text = procData.text;
90
		switch (caseNumber) {
90
		switch (caseNumber) {
91
			case 1 : /* space */
91
			case 1 : /* space */
92
				separLocation++;
92
				separLocation++;
93
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
93
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
94
					dirProps.setBidiTypeAt(separLocation, WS);
94
					procData.dirProps.setBidiTypeAt(separLocation, WS);
95
					separLocation++;
95
					separLocation++;
96
				}
96
				}
97
				return separLocation;
97
				return separLocation;
Lines 115-126 Link Here
115
					location = separLocation + 2; // skip the opening slash-aster
115
					location = separLocation + 2; // skip the opening slash-aster
116
				location = text.indexOf("*/", location); //$NON-NLS-1$
116
				location = text.indexOf("*/", location); //$NON-NLS-1$
117
				if (location < 0) {
117
				if (location < 0) {
118
					state[0] = caseNumber;
118
					procData.handler.setState(caseNumber);
119
					return text.length();
119
					return text.length();
120
				}
120
				}
121
				// we need to call processSeparator since text may follow the
121
				// we need to call processSeparator since text may follow the
122
				//  end of comment immediately without even a space
122
				//  end of comment immediately without even a space
123
				STextProcessor.processSeparator(text, dirProps, offsets, location);
123
				STextProcessor.processSeparator(procData, location);
124
				return location + 2;
124
				return location + 2;
125
			case 4 : /* slash-slash comment */
125
			case 4 : /* slash-slash comment */
126
				location = text.indexOf(lineSep, separLocation + 2);
126
				location = text.indexOf(lineSep, separLocation + 2);
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextMath.java (-9 / +22 lines)
Lines 10-17 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
14
import org.eclipse.equinox.bidi.STextHandler;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
17
17
Lines 29-40 Link Here
29
		super("+-/*()="); //$NON-NLS-1$
29
		super("+-/*()="); //$NON-NLS-1$
30
	}
30
	}
31
31
32
	/**
33
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
34
	 *          conditions are satisfied:
35
	 *          <ul>
36
	 *            <li>The current locale (as expressed by the environment
37
	 *                language) is Arabic.</li>
38
	 *            <li>The first strong character is an Arabic letter.</li>
39
	 *            <li>If there is no strong character in the text, there is
40
	 *                at least one Arabic-Indic digit in the text.</li>
41
	 *          </ul>
42
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
43
	 */
32
	public int getDirection(STextEnvironment environment, String text) {
44
	public int getDirection(STextEnvironment environment, String text) {
33
		return getDirection(environment, text, new STextCharTypes(text));
45
		return getDirection(environment, text, new STextCharTypes(text));
34
	}
46
	}
35
47
36
	/**
48
	/**
37
	 *  @return {@link STextEngine#DIR_RTL DIR_RTL} if the following
49
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
38
	 *          conditions are satisfied:
50
	 *          conditions are satisfied:
39
	 *          <ul>
51
	 *          <ul>
40
	 *            <li>The current locale (as expressed by the environment
52
	 *            <li>The current locale (as expressed by the environment
Lines 43-67 Link Here
43
	 *            <li>If there is no strong character in the text, there is
55
	 *            <li>If there is no strong character in the text, there is
44
	 *                at least one Arabic-Indic digit in the text.</li>
56
	 *                at least one Arabic-Indic digit in the text.</li>
45
	 *          </ul>
57
	 *          </ul>
46
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
58
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
47
	 */
59
	 */
48
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
60
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
61
		if (environment == null)
62
			environment = STextEnvironment.DEFAULT;
49
		String language = environment.getLanguage();
63
		String language = environment.getLanguage();
50
		if (!language.equals("ar")) //$NON-NLS-1$
64
		if (!language.equals("ar")) //$NON-NLS-1$
51
			return STextEngine.DIR_LTR;
65
			return STextHandler.DIR_LTR;
52
		boolean flagAN = false;
66
		boolean flagAN = false;
53
		for (int i = 0; i < text.length(); i++) {
67
		for (int i = 0; i < text.length(); i++) {
54
			byte dirProp = dirProps.getBidiTypeAt(i);
68
			byte dirProp = dirProps.getBidiTypeAt(i);
55
			if (dirProp == AL)
69
			if (dirProp == AL)
56
				return STextEngine.DIR_RTL;
70
				return STextHandler.DIR_RTL;
57
			if (dirProp == L || dirProp == R)
71
			if (dirProp == L || dirProp == R)
58
				return STextEngine.DIR_LTR;
72
				return STextHandler.DIR_LTR;
59
			if (dirProp == AN)
73
			if (dirProp == AN)
60
				flagAN = true;
74
				flagAN = true;
61
		}
75
		}
62
		if (flagAN)
76
		if (flagAN)
63
			return STextEngine.DIR_RTL;
77
			return STextHandler.DIR_RTL;
64
		return STextEngine.DIR_LTR;
78
		return STextHandler.DIR_LTR;
65
	}
79
	}
66
67
}
80
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextRegex.java (-28 / +41 lines)
Lines 10-19 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
14
import org.eclipse.equinox.bidi.STextHandler;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.*;
17
16
18
/**
17
/**
19
 *  <code>STextRegex</code> is a processor for regular expressions.
18
 *  <code>STextRegex</code> is a processor for regular expressions.
Lines 21-35 Link Here
21
 *  <p>
20
 *  <p>
22
 *  In applications like an editor where parts of the text might be modified
21
 *  In applications like an editor where parts of the text might be modified
23
 *  while other parts are not, the user may want to call
22
 *  while other parts are not, the user may want to call
24
 *  {@link STextEngine#leanToFullText leanToFullText}
23
 *  {@link STextHandler#leanToFullText leanToFullText}
25
 *  separately on each line and save the initial state of each line (this is
24
 *  separately on each line and save the initial <b>state</b> of each line (this is
26
 *  the final state of the previous line which can be retrieved using
25
 *  the final <b>state</b> of the previous line which can be retrieved using
27
 *  the value returned in the first element of the <code>state</code> argument).
26
 *  {@link STextHandler#getState}.
28
 *  If both the content
27
 *  If both the content of a line and its initial 
29
 *  of a line and its initial state have not changed, the user can be sure that
28
 *  <b>state</b> have not changed, the user can be sure that
30
 *  the last <i>full</i> text computed for this line has not changed either.
29
 *  the last <i>full</i> text computed for this line has not changed either.
31
 *
32
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
33
 *
30
 *
34
 *  @author Matitiahu Allouche
31
 *  @author Matitiahu Allouche
35
 */
32
 */
Lines 77-83 Link Here
77
	 *  This method locates occurrences of the syntactic strings and of
74
	 *  This method locates occurrences of the syntactic strings and of
78
	 *  R, AL, EN, AN characters.
75
	 *  R, AL, EN, AN characters.
79
	 */
76
	 */
80
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
77
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
81
		// In this method, L, R, AL, AN and EN represent bidi categories
78
		// In this method, L, R, AL, AN and EN represent bidi categories
82
		// as defined in the Unicode Bidirectional Algorithm
79
		// as defined in the Unicode Bidirectional Algorithm
83
		// ( http://www.unicode.org/reports/tr9/ ).
80
		// ( http://www.unicode.org/reports/tr9/ ).
Lines 87-92 Link Here
87
		// AN represents the category Arabic Number.
84
		// AN represents the category Arabic Number.
88
		// EN  represents the category European Number.
85
		// EN  represents the category European Number.
89
		byte dirProp;
86
		byte dirProp;
87
		String text = procData.text;
90
88
91
		if (caseNumber < numberOfStrings) {
89
		if (caseNumber < numberOfStrings) {
92
			/*  1 *//* comment (?#...) */
90
			/*  1 *//* comment (?#...) */
Lines 111-116 Link Here
111
		// there never is a need for a mark before the first char
109
		// there never is a need for a mark before the first char
112
		if (fromIndex <= 0)
110
		if (fromIndex <= 0)
113
			fromIndex = 1;
111
			fromIndex = 1;
112
		STextCharTypes dirProps = procData.dirProps;
114
		// look for R, AL, AN, EN which are potentially needing a mark
113
		// look for R, AL, AN, EN which are potentially needing a mark
115
		for (; fromIndex < text.length(); fromIndex++) {
114
		for (; fromIndex < text.length(); fromIndex++) {
116
			dirProp = dirProps.getBidiTypeAt(fromIndex);
115
			dirProp = dirProps.getBidiTypeAt(fromIndex);
Lines 145-152 Link Here
145
	/**
144
	/**
146
	 *  This method process the special cases.
145
	 *  This method process the special cases.
147
	 */
146
	 */
148
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
147
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
149
		int location;
148
		int location;
149
		String text = procData.text;
150
150
151
		switch (caseNumber) {
151
		switch (caseNumber) {
152
			case 1 : /* comment (?#...) */
152
			case 1 : /* comment (?#...) */
Lines 154-166 Link Here
154
					// initial state from previous line
154
					// initial state from previous line
155
					location = 0;
155
					location = 0;
156
				} else {
156
				} else {
157
					STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
157
					STextProcessor.processSeparator(procData, separLocation);
158
					// skip the opening "(?#"
158
					// skip the opening "(?#"
159
					location = separLocation + 3;
159
					location = separLocation + 3;
160
				}
160
				}
161
				location = text.indexOf(')', location);
161
				location = text.indexOf(')', location);
162
				if (location < 0) {
162
				if (location < 0) {
163
					state[0] = caseNumber;
163
					procData.handler.setState(caseNumber);
164
					return text.length();
164
					return text.length();
165
				}
165
				}
166
				return location + 1;
166
				return location + 1;
Lines 170-176 Link Here
170
			case 5 : /* conditional named back reference (?(<name>) */
170
			case 5 : /* conditional named back reference (?(<name>) */
171
			case 6 : /* conditional named back reference (?('name') */
171
			case 6 : /* conditional named back reference (?('name') */
172
			case 7 : /* named parentheses reference (?&name) */
172
			case 7 : /* named parentheses reference (?&name) */
173
				STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
173
				STextProcessor.processSeparator(procData, separLocation);
174
				// no need for calling processSeparator() for the following cases
174
				// no need for calling processSeparator() for the following cases
175
				//   since the starting string contains a L char
175
				//   since the starting string contains a L char
176
			case 8 : /* named group (?P<name> */
176
			case 8 : /* named group (?P<name> */
Lines 194-213 Link Here
194
					// initial state from previous line
194
					// initial state from previous line
195
					location = 0;
195
					location = 0;
196
				} else {
196
				} else {
197
					STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
197
					STextProcessor.processSeparator(procData, separLocation);
198
					// skip the opening "\Q"
198
					// skip the opening "\Q"
199
					location = separLocation + 2;
199
					location = separLocation + 2;
200
				}
200
				}
201
				location = text.indexOf("\\E", location); //$NON-NLS-1$
201
				location = text.indexOf("\\E", location); //$NON-NLS-1$
202
				if (location < 0) {
202
				if (location < 0) {
203
					state[0] = caseNumber;
203
					procData.handler.setState(caseNumber);
204
					return text.length();
204
					return text.length();
205
				}
205
				}
206
				// 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)
207
				dirProps.setBidiTypeAt(location + 1, L);
207
				procData.dirProps.setBidiTypeAt(location + 1, L);
208
				return location + 2;
208
				return location + 2;
209
			case 18 : /* R, AL, AN, EN */
209
			case 18 : /* R, AL, AN, EN */
210
				STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
210
				STextProcessor.processSeparator(procData, separLocation);
211
				return separLocation + 1;
211
				return separLocation + 1;
212
212
213
		}
213
		}
Lines 215-226 Link Here
215
		return text.length();
215
		return text.length();
216
	}
216
	}
217
217
218
	/**
219
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
220
	 *          conditions are satisfied:
221
	 *          <ul>
222
	 *            <li>The current locale (as expressed by the environment
223
	 *                language) is Arabic.</li>
224
	 *            <li>The first strong character is an Arabic letter.</li>
225
	 *            <li>If there is no strong character in the text, there is
226
	 *                at least one Arabic-Indic digit in the text.</li>
227
	 *          </ul>
228
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
229
	 */
218
	public int getDirection(STextEnvironment environment, String text) {
230
	public int getDirection(STextEnvironment environment, String text) {
219
		return getDirection(environment, text, new STextCharTypes(text));
231
		return getDirection(environment, text, new STextCharTypes(text));
220
	}
232
	}
221
233
222
	/**
234
	/**
223
	 *  @return {@link STextEngine#DIR_RTL DIR_RTL} if the following
235
	 *  @return {@link STextHandler#DIR_RTL DIR_RTL} if the following
224
	 *          conditions are satisfied:
236
	 *          conditions are satisfied:
225
	 *          <ul>
237
	 *          <ul>
226
	 *            <li>The current locale (as expressed by the environment
238
	 *            <li>The current locale (as expressed by the environment
Lines 229-250 Link Here
229
	 *            <li>If there is no strong character in the text, the
241
	 *            <li>If there is no strong character in the text, the
230
	 *                GUI is mirrored.
242
	 *                GUI is mirrored.
231
	 *          </ul>
243
	 *          </ul>
232
	 *          Otherwise, returns {@link STextEngine#DIR_LTR DIR_LTR}.
244
	 *          Otherwise, returns {@link STextHandler#DIR_LTR DIR_LTR}.
233
	 */
245
	 */
234
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
246
	public int getDirection(STextEnvironment environment, String text, STextCharTypes dirProps) {
247
		if (environment == null)
248
			environment = STextEnvironment.DEFAULT;
235
		String language = environment.getLanguage();
249
		String language = environment.getLanguage();
236
		if (!language.equals("ar")) //$NON-NLS-1$
250
		if (!language.equals("ar")) //$NON-NLS-1$
237
			return STextEngine.DIR_LTR;
251
			return STextHandler.DIR_LTR;
238
		for (int i = 0; i < text.length(); i++) {
252
		for (int i = 0; i < text.length(); i++) {
239
			byte dirProp = dirProps.getBidiTypeAt(i);
253
			byte dirProp = dirProps.getBidiTypeAt(i);
240
			if (dirProp == AL || dirProp == R)
254
			if (dirProp == AL || dirProp == R)
241
				return STextEngine.DIR_RTL;
255
				return STextHandler.DIR_RTL;
242
			if (dirProp == L)
256
			if (dirProp == L)
243
				return STextEngine.DIR_LTR;
257
				return STextHandler.DIR_LTR;
244
		}
258
		}
245
		if (environment.getMirrored())
259
		if (environment.getMirrored())
246
			return STextEngine.DIR_RTL;
260
			return STextHandler.DIR_RTL;
247
		return STextEngine.DIR_LTR;
261
		return STextHandler.DIR_LTR;
248
	}
262
	}
249
250
}
263
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextSql.java (-17 / +17 lines)
Lines 10-19 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
11
package org.eclipse.equinox.bidi.internal.consumable;
12
12
13
import org.eclipse.equinox.bidi.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
13
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextCharTypes;
14
import org.eclipse.equinox.bidi.STextHandler;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
import org.eclipse.equinox.bidi.custom.STextProcessorData;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
17
import org.eclipse.equinox.bidi.internal.STextActivator;
18
18
19
/**
19
/**
Lines 23-37 Link Here
23
 *  <p>
23
 *  <p>
24
 *  In applications like an editor where parts of the text might be modified
24
 *  In applications like an editor where parts of the text might be modified
25
 *  while other parts are not, the user may want to call
25
 *  while other parts are not, the user may want to call
26
 *  {@link STextEngine#leanToFullText leanToFullText}
26
 *  {@link STextHandler#leanToFullText leanToFullText}
27
 *  separately on each line and save the initial state of each line (this is
27
 *  separately on each line and save the initial <b>state</b> of each line (this is
28
 *  the final state of the previous line which can be retrieved from the
28
 *  the final <b>state</b> of the previous line which can be retrieved using
29
 *  value returned in the first element of the <code>state</code> argument).
29
 *  {@link STextHandler#getState}.
30
 *  If both the content
30
 *  If both the content of a line and its initial
31
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  <b>state</b> have not changed, the user can be sure that
32
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *  the last <i>full</i> text computed for this line has not changed either.
33
 *
34
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
35
 *
33
 *
36
 *  @author Matitiahu Allouche
34
 *  @author Matitiahu Allouche
37
 */
35
 */
Lines 60-66 Link Here
60
	  *    <li>comments starting with hyphen-hyphen</li>
58
	  *    <li>comments starting with hyphen-hyphen</li>
61
	  *  </ol>
59
	  *  </ol>
62
	  */
60
	  */
63
	public int indexOfSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int caseNumber, int fromIndex) {
61
	public int indexOfSpecial(STextProcessorData procData, int caseNumber, int fromIndex) {
62
		String text = procData.text;
64
		switch (caseNumber) {
63
		switch (caseNumber) {
65
			case 1 : /* space */
64
			case 1 : /* space */
66
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
65
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
Lines 87-101 Link Here
87
	     *    <li>skip until after a line separator</li>
86
	     *    <li>skip until after a line separator</li>
88
	     *  </ol>
87
	     *  </ol>
89
	 */
88
	 */
90
	public int processSpecial(STextEnvironment environment, String text, STextCharTypes dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
89
	public int processSpecial(STextProcessorData procData, int caseNumber, int separLocation) {
91
		int location;
90
		int location;
91
		String text = procData.text;
92
92
93
		STextProcessor.processSeparator(text, dirProps, offsets, separLocation);
93
		STextProcessor.processSeparator(procData, separLocation);
94
		switch (caseNumber) {
94
		switch (caseNumber) {
95
			case 1 : /* space */
95
			case 1 : /* space */
96
				separLocation++;
96
				separLocation++;
97
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
97
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
98
					dirProps.setBidiTypeAt(separLocation, WS);
98
					procData.dirProps.setBidiTypeAt(separLocation, WS);
99
					separLocation++;
99
					separLocation++;
100
				}
100
				}
101
				return separLocation;
101
				return separLocation;
Lines 104-110 Link Here
104
				while (true) {
104
				while (true) {
105
					location = text.indexOf('\'', location);
105
					location = text.indexOf('\'', location);
106
					if (location < 0) {
106
					if (location < 0) {
107
						state[0] = caseNumber;
107
						procData.handler.setState(caseNumber);
108
						return text.length();
108
						return text.length();
109
					}
109
					}
110
					if ((location + 1) < text.length() && text.charAt(location + 1) == '\'') {
110
					if ((location + 1) < text.length() && text.charAt(location + 1) == '\'') {
Lines 133-144 Link Here
133
					location = separLocation + 2; // skip the opening slash-aster
133
					location = separLocation + 2; // skip the opening slash-aster
134
				location = text.indexOf("*/", location); //$NON-NLS-1$
134
				location = text.indexOf("*/", location); //$NON-NLS-1$
135
				if (location < 0) {
135
				if (location < 0) {
136
					state[0] = caseNumber;
136
					procData.handler.setState(caseNumber);
137
					return text.length();
137
					return text.length();
138
				}
138
				}
139
				// we need to call processSeparator since text may follow the
139
				// we need to call processSeparator since text may follow the
140
				//  end of comment immediately without even a space
140
				//  end of comment immediately without even a space
141
				STextProcessor.processSeparator(text, dirProps, offsets, location);
141
				STextProcessor.processSeparator(procData, location);
142
				return location + 2;
142
				return location + 2;
143
			case 5 : /* hyphen-hyphen comment */
143
			case 5 : /* hyphen-hyphen comment */
144
				location = text.indexOf(lineSep, separLocation + 2);
144
				location = text.indexOf(lineSep, separLocation + 2);
(-)src/org/eclipse/equinox/bidi/package.html (-183 / +191 lines)
Lines 1-183 Link Here
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
<html>
2
<html>
3
<head>
3
<head>
4
<META name="Author" content="Matitiahu Allouche">
4
<META name="Author" content="Matitiahu Allouche">
5
</head>
5
</head>
6
<body bgcolor="white">
6
<body bgcolor="white">
7
7
8
This package provides classes for
8
This package provides classes for
9
processing structured text.
9
processing structured text.
10
<p>
10
<p>
11
There are various types of structured text. Each type should
11
There are various types of structured text. Each type should
12
be handled by a specific <i>processor</i>. A number of standard
12
be handled by a specific <i>processor</i>. A number of standard
13
processors are supplied in the associated package
13
processors are supplied in the associated package
14
{@link <a href="internal\consumable\package-summary.html">
14
{@link <a href="internal\consumable\package-summary.html">
15
org.eclipse.equinox.bidi.internal.consumable</a>}.
15
org.eclipse.equinox.bidi.internal.consumable</a>}.
16
16
17
<h2>Introduction to Structured Text</h2>
17
<h2>Introduction to Structured Text</h2>
18
<p>
18
<p>
19
Bidirectional text offers interesting challenges to presentation systems.
19
Bidirectional text offers interesting challenges to presentation systems.
20
For plain text, the Unicode Bidirectional Algorithm
20
For plain text, the Unicode Bidirectional Algorithm
21
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
21
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
22
generally specifies satisfactorily how to reorder bidirectional text for
22
generally specifies satisfactorily how to reorder bidirectional text for
23
display. This algorithm is implemented in Java's presentation system.
23
display. This algorithm is implemented in Java's presentation system.
24
</p><p>
24
</p><p>
25
However, all bidirectional text is not necessarily plain text. There
25
However, all bidirectional text is not necessarily plain text. There
26
are also instances of text structured to follow a given syntax, which
26
are also instances of text structured to follow a given syntax, which
27
should be reflected in the display order. The general algorithm, which
27
should be reflected in the display order. The general algorithm, which
28
has no awareness of these special cases, often gives incorrect results
28
has no awareness of these special cases, often gives incorrect results
29
when displaying such structured text.
29
when displaying such structured text.
30
</p><p>
30
</p><p>
31
The general idea in handling structured text is to add directional
31
The general idea in handling structured text is to add directional
32
formatting characters at proper locations in the text to supplement the
32
formatting characters at proper locations in the text to supplement the
33
standard algorithm, so that the final result is correctly displayed
33
standard algorithm, so that the final result is correctly displayed
34
using the UBA.
34
using the UBA.
35
</p><p>
35
</p><p>
36
A class which handles structured text is thus essentially a
36
A class which handles structured text is thus essentially a
37
transformation engine which receives text without directional formatting
37
transformation engine which receives text without directional formatting
38
characters as input and produces as output the same text with added
38
characters as input and produces as output the same text with added
39
directional formatting characters, hopefully in the minimum quantity
39
directional formatting characters, hopefully in the minimum quantity
40
which is sufficient to ensure correct display, considering the type of
40
which is sufficient to ensure correct display, considering the type of
41
structured text involved.
41
structured text involved.
42
</p><p>
42
</p><p>
43
In this package, text without directional formatting characters is
43
In this package, text without directional formatting characters is
44
called <b><i>lean</i></b> text while the text with added directional
44
called <b><i>lean</i></b> text while the text with added directional
45
formatting characters is called <b><i>full</i></b> text.
45
formatting characters is called <b><i>full</i></b> text.
46
</p><p>
46
</p><p>
47
The class {@link
47
The class {@link
48
<a href="STextEngine.html"><b>STextEngine</b></a>}
48
<a href="STextHandler.html"><b>STextHandler</b></a>}
49
is the main tool for processing structured text.  It facilitates
49
is the main tool for processing structured text.  It facilitates
50
handling several types of structured text, each type being handled
50
handling several types of structured text, each type being handled
51
by a specific
51
by a specific
52
{@link <a href="custom\STextProcessor.html"><b><i>processor</i></b></a>} :</p>
52
{@link <a href="custom\STextProcessor.html"><b><i>processor</i></b></a>} :</p>
53
<ul>
53
<ul>
54
  <li>property (name=value)</li>
54
  <li>property (name=value)</li>
55
  <li>compound name (xxx_yy_zzzz)</li>
55
  <li>compound name (xxx_yy_zzzz)</li>
56
  <li>comma delimited list</li>
56
  <li>comma delimited list</li>
57
  <li>system(user)</li>
57
  <li>system(user)</li>
58
  <li>directory and file path</li>
58
  <li>directory and file path</li>
59
  <li>e-mail address</li>
59
  <li>e-mail address</li>
60
  <li>URL</li>
60
  <li>URL</li>
61
  <li>regular expression</li>
61
  <li>regular expression</li>
62
  <li>Xpath</li>
62
  <li>Xpath</li>
63
  <li>Java code</li>
63
  <li>Java code</li>
64
  <li>SQL statements</li>
64
  <li>SQL statements</li>
65
  <li>RTL arithmetic expressions</li>
65
  <li>RTL arithmetic expressions</li>
66
</ul>
66
</ul>
67
<p>
67
<p>
68
For each of these types, a static instance is defined in <b>STextEngine</b>.
68
For each of these types, a static instance is defined in
69
These pre-defined instances can be used as argument in the methods of
69
{@link <a href="STextProcessorFactory.html">STextProcessorFactory</a>}.
70
<b>STextEngine</b>.
70
These pre-defined instances can be used as argument when initiating a
71
</p><p>
71
<b>STextHandler</b>.
72
Other classes in this package may be used to
72
</p><p>
73
complement and facilitate the action of
73
Other classes in this package may be used to
74
{@link <a href="STextEngine.html">STextEngine</a>}:
74
complement and facilitate the action of
75
<ul>
75
{@link <a href="STextHandler.html">STextHandler</a>}:
76
  <li>{@link <a href="STextEnvironment.html">STextEnvironment</a>}
76
<ul>
77
      regroups details about the environment</li>.
77
  <li>{@link <a href="STextEnvironment.html">STextEnvironment</a>}
78
  <li>{@link <a href="STextUtil.html">STextUtil</a>}
78
      regroups details about the environment.</li>
79
      provides a number of convenience methods to process some common types of
79
  <li>{@link <a href="STextProcessorFactory.html">STextProcessorFactory</a>}
80
      structured text.  When using methods in this class, there is no need
80
      allows retrieval of the defined processor types and of the
81
      to use other classes of this package.  However, the other classes allow
81
      corresponding processors.</li>
82
      more precise control and possibly better performance.</li>
82
  <li>{@link <a href="STextUtil.html">STextUtil</a>}
83
  <li>{@link <a href="STextStringRecord.html">STextStringRecord</a>}
83
      provides a number of convenience methods to process some common types of
84
      allows to record strings which are structured text with the
84
      structured text.  When using methods in this class, there is no need
85
      type of the appropriate processor,
85
      to use other classes of this package.  However, the other classes allow
86
      so that another module can check if a given string has been recorded
86
      more precise control and possibly better performance.</li>
87
      as a structured text string and run its processor.</li>
87
  <li>{@link <a href="STextStringRecord.html">STextStringRecord</a>}
88
</ul>
88
      allows to record strings which are structured text with the
89
<p>
89
      type of the appropriate processor,
90
{@link <a href="STextEngine.html">STextEngine</a>} and the
90
      so that another module can check if a given string has been recorded
91
other classes mentioned above are intended for users who
91
      as a structured text string and run its processor.</li>
92
need to process structured text for which there already exist
92
</ul>
93
processors.
93
<p>
94
<p>
94
{@link <a href="STextHandler.html">STextHandler</a>} and the
95
Developers who want to develop new processors to support types of structured text
95
other classes mentioned above are intended for users who
96
not currently supported can use the following components of the
96
need to process structured text for which there already exist
97
package {@link <a href="custom\package-summary.html">
97
processors.
98
org.eclipse.equinox.bidi.custom</a>}:
98
<p>
99
<ul>
99
Developers who want to develop new processors to support types of structured text
100
  <li>{@link <a href="custom\STextProcessor.html">STextProcessor</a>}
100
not currently supported can use the following components of the
101
      is a generic processor to be used as superclass for specific
101
package {@link <a href="custom\package-summary.html">
102
      processors.</li>
102
org.eclipse.equinox.bidi.custom</a>}:
103
  <li>{@link <a href="custom\STextStringProcessor.html">STextStringProcessor</a>}
103
<ul>
104
      allows retrieval of the defined processor types and of the
104
  <li>{@link <a href="custom\STextProcessor.html">STextProcessor</a>}
105
      corresponding processors.</li>
105
      is a generic processor to be used as superclass for specific
106
</ul>
106
      processors.</li>
107
<p>
107
  <li>{@link <a href="custom\STextProcessorData.html">STextProcessorData</a>}
108
There are two other packages associated with the current one:
108
      regroups data which can be used by processors.</li>
109
<ul>
109
  <li>{@link <a href="custom\STextCharTypes.html">STextStringCharTypes</a>}
110
  <li>{@link <a href="internal\package-summary.html">
110
      allows getting and setting the bidi class of characters.</li>
111
      org.eclipse.equinox.bidi.internal</a>}</li>
111
  <li>{@link <a href="custom\STextOffsets.html">STextStringOffsets</a>}
112
  <li>{@link <a href="internal\consumable\package-summary.html">
112
      allows manipulation of offsets at which directional control
113
       org.eclipse.equinox.bidi.internal.consumable</a>}</li>
113
      characters are inserted.</li>
114
</ul>
114
</ul>
115
The tools in the first package can serve as example of how to develop
115
<p>
116
processors for currently unsupported types of structured text.<br>
116
There are two other packages associated with the current one:
117
The latter package contains classes for the processors implementing
117
<ul>
118
the currently supported types of structured text.
118
  <li>{@link <a href="internal\package-summary.html">
119
<p>
119
      org.eclipse.equinox.bidi.internal</a>}</li>
120
However, users wishing to process the currently supported types of
120
  <li>{@link <a href="internal\consumable\package-summary.html">
121
structured text typically don't need to interact with these
121
       org.eclipse.equinox.bidi.internal.consumable</a>}</li>
122
two packages.
122
</ul>
123
123
The tools in the first package can serve as example of how to develop
124
<p>&nbsp;</p>
124
processors for currently unsupported types of structured text.<br>
125
125
The latter package contains classes for the processors implementing
126
<h2>Abbreviations used in the documentation of this package</h2>
126
the currently supported types of structured text.
127
127
<p>
128
<dl>
128
However, users wishing to process the currently supported types of
129
<dt><b>UBA</b><dd>Unicode Bidirectional Algorithm
129
structured text typically don't need to interact with these
130
130
two packages.
131
<dt><b>Bidi</b><dd>Bidirectional
131
132
132
<p>&nbsp;</p>
133
<dt><b>GUI</b><dd>Graphical User Interface
133
134
134
<h2>Abbreviations used in the documentation of this package</h2>
135
<dt><b>UI</b><dd>User Interface
135
136
136
<dl>
137
<dt><b>LTR</b><dd>Left to Right
137
<dt><b>UBA</b><dd>Unicode Bidirectional Algorithm
138
138
139
<dt><b>RTL</b><dd>Right to Left
139
<dt><b>Bidi</b><dd>Bidirectional
140
140
141
<dt><b>LRM</b><dd>Left-to-Right Mark
141
<dt><b>GUI</b><dd>Graphical User Interface
142
142
143
<dt><b>RLM</b><dd>Right-to-Left Mark
143
<dt><b>UI</b><dd>User Interface
144
144
145
<dt><b>LRE</b><dd>Left-to-Right Embedding
145
<dt><b>LTR</b><dd>Left to Right
146
146
147
<dt><b>RLE</b><dd>Right-to-Left Embedding
147
<dt><b>RTL</b><dd>Right to Left
148
148
149
<dt><b>PDF</b><dd>Pop Directional Formatting
149
<dt><b>LRM</b><dd>Left-to-Right Mark
150
</dl>
150
151
151
<dt><b>RLM</b><dd>Right-to-Left Mark
152
<p>&nbsp;</p>
152
153
153
<dt><b>LRE</b><dd>Left-to-Right Embedding
154
<h2>Known Limitations</h2>
154
155
155
<dt><b>RLE</b><dd>Right-to-Left Embedding
156
<p>The proposed solution is making extensive usage of LRM, RLM, LRE, RLE
156
157
and PDF directional controls which are invisible but affect the way bidi
157
<dt><b>PDF</b><dd>Pop Directional Formatting
158
text is displayed. The following related key points merit special
158
</dl>
159
attention:</p>
159
160
160
<p>&nbsp;</p>
161
<ul>
161
162
<li>Implementations of the UBA on various platforms (e.g., Windows and
162
<h2>Known Limitations</h2>
163
Linux) are very similar but nevertheless have known differences. Those
163
164
differences are minor and will not have a visible effect in most cases.
164
<p>The proposed solution is making extensive usage of LRM, RLM, LRE, RLE
165
However there might be cases in which the same bidi text on two
165
and PDF directional controls which are invisible but affect the way bidi
166
platforms might look different. These differences will surface in Java
166
text is displayed. The following related key points merit special
167
applications when they use the platform visual components for their UI
167
attention:</p>
168
(e.g., AWT, SWT).</li>
168
169
169
<ul>
170
<li>It is assumed that the presentation engine supports LRE, RLE and
170
<li>Implementations of the UBA on various platforms (e.g., Windows and
171
PDF directional formatting characters.</li>
171
Linux) are very similar but nevertheless have known differences. Those
172
172
differences are minor and will not have a visible effect in most cases.
173
<li>Because some presentation engines are not strictly conformant to the
173
However there might be cases in which the same bidi text on two
174
UBA, the implementation of structured text in this package adds LRM
174
platforms might look different. These differences will surface in Java
175
or RLM characters in association with LRE, RLE or PDF in cases where
175
applications when they use the platform visual components for their UI
176
this would not be needed if the presentation engine was fully conformant
176
(e.g., AWT, SWT).</li>
177
to the UBA. Such added marks will not have harmful effects on
177
178
conformant presentation engines and will help less conformant engines to
178
<li>It is assumed that the presentation engine supports LRE, RLE and
179
achieve the desired presentation.</li>
179
PDF directional formatting characters.</li>
180
</ul>
180
181
181
<li>Because some presentation engines are not strictly conformant to the
182
</body>
182
UBA, the implementation of structured text in this package adds LRM
183
</html>
183
or RLM characters in association with LRE, RLE or PDF in cases where
184
this would not be needed if the presentation engine was fully conformant
185
to the UBA. Such added marks will not have harmful effects on
186
conformant presentation engines and will help less conformant engines to
187
achieve the desired presentation.</li>
188
</ul>
189
190
</body>
191
</html>

Return to bug 183164