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

Collapse All | Expand All

(-)src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java (-48 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import org.eclipse.equinox.bidi.internal.complexp.BiDiTypesCollector;
14
15
/**
16
 * @noinstantiate This class is not intended to be instantiated by clients.
17
 */
18
// TBD do we really want to provide individual instances of the text processors?
19
final public class ComplExpFactory implements IBiDiProcessor {
20
21
	/**
22
	 * Factory method to create a new instance of the bi-directional text
23
	 * processor for the specified text type. This method may return <code>null</code> 
24
	 * if it is unable to locate processor for the specified text type. 
25
	 * 
26
	 * @see #PROPERTY
27
	 * @see #UNDERSCORE
28
	 * @see #COMMA_DELIMITED
29
	 * @see #SYSTEM_USER
30
	 * @see #FILE
31
	 * @see #EMAIL
32
	 * @see #URL
33
	 * @see #REGEXP
34
	 * @see #XPATH
35
	 * @see #JAVA
36
	 * @see #SQL
37
	 * @see #RTL_ARITHMETIC
38
	 * 
39
	 * @param type specifies the type of complex expression to process.
40
	 * @return a <code>IComplExpProcessor</code> instance capable of handling 
41
	 * the type of complex expression specified. May return <code>null</code> 
42
	 * if the processor not found. 
43
	 */
44
	public static IComplExpProcessor create(String type) {
45
		return BiDiTypesCollector.getInstance().makeProcessor(type);
46
	}
47
48
}
(-)src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java (-369 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import java.util.Locale;
14
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
15
16
/**
17
 *  This class provides a number of convenience functions facilitating the
18
 *  processing of complex expressions.
19
 *
20
 *  @noextend This class is not intended to be subclassed by clients.
21
 *  @noinstantiate This class is not intended to be instantiated by clients.
22
 *
23
 *  @author Matitiahu Allouche
24
 */
25
final public class ComplExpUtil {
26
27
	/**
28
	 *  Flag specifying that all complex expressions should by default assume
29
	 *  that the GUI is mirrored (globally going from right to left).
30
	 *  The default can be overridden for specific instances of complex
31
	 *  expressions.
32
	 *  @see #assumeMirroredDefault
33
	 *  @see #isMirroredDefault
34
	 */
35
	static boolean mirroredDefault;
36
37
	/**
38
	 *  prevents instantiation
39
	 */
40
	private ComplExpUtil() {
41
		// empty
42
	}
43
44
	/** Specify whether the GUI where the complex expression will be displayed
45
	 *  is mirrored (is laid out from right to left). The value specified in
46
	 *  this method sets a default for all complex expressions to be created
47
	 *  from now on. If no value has been specified ever, the GUI
48
	 *  is assumed not to be mirrored.
49
	 *
50
	 *  @param  mirrored must be specified as <code>false</code> if the GUI
51
	 *          is not mirrored, as <code>true</code> if it is.
52
	 *
53
	 *  @see #isMirroredDefault
54
	 *  @see IComplExpProcessor#assumeMirrored
55
	 */
56
	public static void assumeMirroredDefault(boolean mirrored) {
57
		mirroredDefault = mirrored;
58
	}
59
60
	/** Retrieve the value currently assumed as default for GUI mirroring.
61
	 *
62
	 *  @return the current value assumed by default for GUI mirroring.
63
	 *
64
	 *  @see #assumeMirroredDefault
65
	 */
66
	public static boolean isMirroredDefault() {
67
		return mirroredDefault;
68
	}
69
70
	/** This is a convenience method which can add directional marks in a given
71
	 *  text before the characters specified in the given array of offsets,
72
	 *  and can add a prefix and/or a suffix of directional formatting characters.
73
	 *  This can be used for instance after obtaining offsets by calling
74
	 *  {@link IComplExpProcessor#leanBidiCharOffsets() leanBidiCharOffsets} in order to
75
	 *  produce a <i>full</i> text corresponding to the source text.
76
	 *  The directional formatting characters that will be added at the given
77
	 *  offsets will be LRMs for expressions with LTR base direction and
78
	 *  RLMs for expressions with RTL base direction. Leading and
79
	 *  trailing LRE, RLE and PDF which might be needed as prefix or suffix
80
	 *  depending on the orientation of the GUI component used for display
81
	 *  may be added depending on argument <code>affix</code>.
82
	 *
83
	 *  @param  text is the text of the complex expression.
84
	 *
85
	 *  @param  offsets is an array of offsets to characters in <code>text</code>
86
	 *          before which an LRM or RLM will be inserted.
87
	 *          Members of the array must be non-negative numbers smaller
88
	 *          than the length of <code>text</code>.
89
	 *          The array must be sorted in ascending order without duplicates.
90
	 *          This argument may be null if there are no marks to add.
91
	 *
92
	 *  @param  direction specifies the base direction of the complex expression.
93
	 *          It must be one of the values {@link IComplExpProcessor#DIRECTION_LTR} or
94
	 *          {@link IComplExpProcessor#DIRECTION_RTL}.
95
	 *
96
	 *  @param  affix specifies if a prefix and a suffix should be added to
97
	 *          the result to make sure that the <code>direction</code>
98
	 *          specified as second argument is honored even if the expression
99
	 *          is displayed in a GUI component with a different orientation.
100
	 *
101
	 *  @return a string corresponding to the source <code>text</code> with
102
	 *          directional marks (LRMs or RLMs) added at the specified offsets,
103
	 *          and directional formatting characters (LRE, RLE, PDF) added
104
	 *          as prefix and suffix if so required.
105
	 *
106
	 */
107
	public static String insertMarks(String text, int[] offsets, int direction, boolean affix) {
108
		int textLen = text.length();
109
		if (textLen == 0)
110
			return ""; //$NON-NLS-1$
111
112
		String curPrefix, curSuffix, full;
113
		char curMark, c;
114
		char[] fullChars;
115
		if (direction == IComplExpProcessor.DIRECTION_LTR) {
116
			curMark = LRM;
117
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
118
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
119
		} else {
120
			curMark = RLM;
121
			curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$
122
			curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$
123
		}
124
		// add marks at offsets
125
		if ((offsets != null) && (offsets.length > 0)) {
126
			int offLen = offsets.length;
127
			fullChars = new char[textLen + offLen];
128
			int added = 0;
129
			for (int i = 0, j = 0; i < textLen; i++) {
130
				c = text.charAt(i);
131
				if ((j < offLen) && (i == offsets[j])) {
132
					fullChars[i + added] = curMark;
133
					added++;
134
					j++;
135
				}
136
				fullChars[i + added] = c;
137
			}
138
			full = new String(fullChars);
139
		} else {
140
			full = text;
141
		}
142
		if (affix)
143
			return curPrefix + full + curSuffix;
144
		return full;
145
	}
146
147
	/*************************************************************************/
148
	/*                                                                       */
149
	/*  The following code is provided for compatibility with TextProcessor  */
150
	/*                                                                       */
151
	/*************************************************************************/
152
153
	//  The default set of delimiters to use to segment a string.
154
	private static final String defaultDelimiters = ".:/\\"; //$NON-NLS-1$
155
	// left to right mark
156
	private static final char LRM = '\u200e';
157
	// left to right mark
158
	private static final char RLM = '\u200f';
159
	// left to right embedding
160
	private static final char LRE = '\u202a';
161
	// right to left embedding
162
	private static final char RLE = '\u202b';
163
	// pop directional format
164
	private static final char PDF = '\u202c';
165
	// TBD use bundle properties
166
	private static String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$	private static String
167
	private static boolean flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$
168
	private static String lastLanguage;
169
	private static boolean lastGoodLang;
170
171
	static boolean isProcessingNeeded() {
172
		if (!flagOS)
173
			return false;
174
		// TBD use OSGi service
175
		String lang = Locale.getDefault().getLanguage();
176
		if (lang.equals(lastLanguage))
177
			return lastGoodLang;
178
		lastLanguage = lang;
179
		lastGoodLang = "iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
180
		return lastGoodLang;
181
	}
182
183
	/**
184
	 *  Process the given text and return a string with appropriate
185
	 *  directional formatting characters if the locale is a Bidi locale.
186
	 *  This is equivalent to calling
187
	 *  {@link #process(String, String)} with the default set of
188
	 *  delimiters (dot, colon, slash, backslash).
189
	 *
190
	 *  @param  str the text to be processed
191
	 *
192
	 *  @return the processed string
193
	 *
194
	 */
195
	public static String process(String str) {
196
		return process(str, defaultDelimiters);
197
	}
198
199
	/**
200
	 *  Process a string that has a particular semantic meaning to render
201
	 *  it correctly on Bidi locales. This is done by adding directional
202
	 *  formatting characters so that presentation using the Unicode Bidi
203
	 *  Algorithm will provide the expected result.
204
	 *  The text is segmented according to the provided delimiters.
205
	 *  Each segment has the Unicode Bidi Algorithm applied to it,
206
	 *  but as a whole, the string is oriented left to right.
207
	 *  <p>
208
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
209
	 *  (where capital letters indicate RTL text) should render as
210
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
211
	 *  <p>
212
	 *  NOTE: this method inserts directional formatting characters into the
213
	 *  text. Methods like <code>String.equals(String)</code> and
214
	 *  <code>String.length()</code> called on the resulting string will not
215
	 *  return the same values as would be returned for the original string.</p>
216
	 *
217
	 *  @param  str the text to process. If <code>null</code>, return
218
	 *          the string itself
219
	 *
220
	 *  @param  delimiters delimiters by which the string will be segmented.
221
	 *          If <code>null</code>, the default delimiters are used
222
	 *          (dot, colon, slash, backslash).
223
	 *
224
	 *  @return the processed string
225
	 */
226
	public static String process(String str, String delimiters) {
227
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
228
			return str;
229
230
		// do not process a string that has already been processed.
231
		if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF)
232
			return str;
233
234
		// do not process a string if all the following conditions are true:
235
		//  a) it has no RTL characters
236
		//  b) it starts with a LTR character
237
		//  c) it ends with a LTR character or a digit
238
		boolean isStringBidi = false;
239
		int strLength = str.length();
240
		char c;
241
		for (int i = 0; i < strLength; i++) {
242
			c = str.charAt(i);
243
			if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) {
244
				isStringBidi = true;
245
				break;
246
			}
247
		}
248
		while (!isStringBidi) {
249
			if (!Character.isLetter(str.charAt(0)))
250
				break;
251
			c = str.charAt(strLength - 1);
252
			if (!Character.isDigit(c) && !Character.isLetter(c))
253
				break;
254
			return str;
255
		}
256
257
		if (delimiters == null)
258
			delimiters = defaultDelimiters;
259
260
		IComplExpProcessor processor = new ComplExpBasic(delimiters);
261
		// make sure that LRE/PDF are added around the string
262
		processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN);
263
		return processor.leanToFullText(str);
264
	}
265
266
	/**
267
	 *  Process a string that has a particular semantic meaning to render
268
	 *  it correctly on Bidi locales. This is done by adding directional
269
	 *  formatting characters so that presentation using the Unicode Bidi
270
	 *  Algorithm will provide the expected result..
271
	 *  The text is segmented according to the syntax specified in the
272
	 *  <code>type</code> argument.
273
	 *  Each segment has the Unicode Bidi Algorithm applied to it, but the
274
	 *  order of the segments is governed by the type of the complex expression.
275
	 *  <p>
276
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
277
	 *  (where capital letters indicate RTL text) should render as
278
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
279
	 *  <p>
280
	 *  NOTE: this method inserts directional formatting characters into the
281
	 *  text. Methods like <code>String.equals(String)</code> and
282
	 *  <code>String.length()</code> called on the resulting string will not
283
	 *  return the same values as would be returned for the original string.</p>
284
	 *
285
	 *  @param  str the text to process. If <code>null</code>, return
286
	 *          the string itself
287
	 *
288
	 *  @param  type specifies the type of the complex expression. It must
289
	 *          be one of the values allowed as argument for method
290
	 *          {@link ComplExpFactory#create}.
291
	 *
292
	 *  @return the processed string
293
	 */
294
	public static String processTyped(String str, String type) {
295
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
296
			return str;
297
298
		// do not process a string that has already been processed.
299
		char c = str.charAt(0);
300
		if (((c == LRE) || (c == RLE)) && str.charAt(str.length() - 1) == PDF)
301
			return str;
302
303
		IComplExpProcessor processor = ComplExpFactory.create(type);
304
		if (processor == null) // invalid type
305
			return str;
306
307
		// make sure that LRE/PDF are added around the string
308
		processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN);
309
		return processor.leanToFullText(str);
310
	}
311
312
	/**
313
	 *  Removes directional marker characters in the given string that were inserted
314
	 *  by the {@link #process(String)} or {@link #process(String, String)}
315
	 *  methods.
316
	 *
317
	 *  @param  str string with directional markers to remove
318
	 *
319
	 *  @return string with no directional formatting characters
320
	 *
321
	 */
322
	public static String deprocess(String str) {
323
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
324
			return str;
325
326
		StringBuffer buf = new StringBuffer();
327
		int strLen = str.length();
328
		for (int i = 0; i < strLen; i++) {
329
			char c = str.charAt(i);
330
			switch (c) {
331
				case LRM :
332
					continue;
333
				case LRE :
334
					continue;
335
				case PDF :
336
					continue;
337
				default :
338
					buf.append(c);
339
			}
340
		}
341
		return buf.toString();
342
	}
343
344
	/**
345
	 *  Removes directional marker characters in the given string that were inserted
346
	 *  by the {@link #process(String, String)} method.
347
	 *
348
	 *  @param  str string with directional markers to remove
349
	 *
350
	 *  @param  type type of the complex expression as specified when
351
	 *          calling <code>process(String str, int type)</code>
352
	 *
353
	 *  @return string with no directional formatting characters
354
	 *
355
	 */
356
	public static String deprocess(String str, String type) {
357
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
358
			return str;
359
360
		IComplExpProcessor processor = ComplExpFactory.create(type);
361
		if (processor == null) // invalid type
362
			return str;
363
364
		// make sure that LRE/PDF are added around the string
365
		processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN);
366
		return processor.fullToLeanText(str);
367
	}
368
369
}
(-)src/org/eclipse/equinox/bidi/complexp/CxpEnv.java (+301 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import java.util.Locale;
14
15
/**
16
 *  This class defines certain details of the environment within which
17
 *  complex expressions are processed.
18
 *  <p>
19
 *  All public fields in this class are <code>final</code>, i.e. cannot be
20
 *  changed after creating an instance.
21
 *  <p>
22
 *  A <code>CxpEnv</code> instance can be associated with a <code>CxpHelper</code>
23
 *  instance either when creating the
24
 * {@link CxpHelper#CxpHelper(java.lang.String, CxpEnv) CxpHelper} instance
25
 *  or using the {@link CxpHelper#setEnvironment setEnvironment} method.
26
 *
27
 *  <h2>Code Samples</h2>
28
 *  <p>Example 1 (set all environment parameters)
29
 *  <pre>
30
 *
31
 *    CxpEnv myEnv = new CxpEnv("he_IL", true, CxpEnv.ORIENT_RTL);
32
 *    CxpHelper myHelper = new CxpHelper(IProcessorTypes.FILE, myEnv);
33
 *
34
 *  </pre>
35
 *  <p>Example 2 (change only the orientation)
36
 *  <pre>
37
 *
38
 *    CxpEnv env1 = myHelper.getEnvironment();
39
 *    CxpEnv env2 = new CxpEnv(env1.language, env1.mirrored, CxpEnv.ORIENT_UNKNOWN);
40
 *    myHelper.setEnvironment(env2);
41
 *
42
 *  </pre>
43
 *  <p>
44
 *  This class also provides a number of convenience methods related to the environment.
45
 *  <p>&nbsp;</p>
46
 *  @see CxpHelper#CxpHelper(String, CxpEnv)
47
 *  @see CxpHelper#CxpHelper(ICxpProcessor, CxpEnv)
48
 *  @see CxpHelper#getEnvironment CxpHelper.getEnvironment
49
 *  @see CxpHelper#setEnvironment CxpHelper.setEnvironment
50
 *  @see ICxpProcessor#init ICxpProcessor.init
51
 *  @see ICxpProcessor#init2 ICxpProcessor.init2
52
 *
53
 *  @author Matitiahu Allouche
54
 */
55
public class CxpEnv {
56
57
    /**
58
     *  Constant specifying that the orientation of the GUI component
59
     *  where a complex expression will be displayed is LTR.
60
     *  It can appear as <code>orientation</code> argument for
61
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
62
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
63
     */
64
    public static final int ORIENT_LTR = 0;
65
66
    /**
67
     *  Constant specifying that the orientation of the GUI component
68
     *  where a complex expression will be displayed is RTL.
69
     *  It can appear as <code>orientation</code> argument for
70
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
71
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
72
     */
73
    public static final int ORIENT_RTL = 1;
74
75
    /**
76
     *  Constant specifying that the orientation of the GUI component
77
     *  where a complex expression will be displayed is contextual with
78
     *  a default of LTR (if no strong character appears in the text).
79
     *  It can appear as <code>orientation</code> argument for
80
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
81
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
82
     */
83
    public static final int ORIENT_CONTEXTUAL_LTR = 2;
84
85
    /**
86
     *  Constant specifying that the orientation of the GUI component
87
     *  where a complex expression will be displayed is contextual with
88
     *  a default of RTL (if no strong character appears in the text).
89
     *  It can appear as <code>orientation</code> argument for
90
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
91
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
92
     */
93
    public static final int ORIENT_CONTEXTUAL_RTL = 3;
94
95
    /**
96
     *  Constant specifying that the orientation of the GUI component
97
     *  where a complex expression will be displayed is not known.
98
     *  Directional formatting characters must be added as prefix and
99
     *  suffix whenever a <i>full</i> text is generated using
100
     *  {@link CxpHelper#leanToFullText leanToFullText}.
101
     *  It can appear as <code>orientation</code> argument for
102
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
103
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
104
     */
105
    public static final int ORIENT_UNKNOWN = 4;
106
107
    /**
108
     *  Constant specifying that whatever the orientation of the
109
     *  GUI component where a complex expression will be displayed, no
110
     *  directional formatting characters must be added as prefix or
111
     *  suffix when a <i>full</i> text is generated using
112
     *  {@link CxpHelper#leanToFullText leanToFullText}.
113
     *  It can appear as <code>orientation</code> argument for
114
     *  {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the
115
     *  {@link CxpEnv#orientation} member of <code>CxpEnv</code>.
116
     */
117
    public static final int ORIENT_IGNORE = 5;
118
119
    /**
120
     *  Pre-defined <code>CxpEnv</code> instance with values for a non-mirrored GUI
121
     *  and a Left-to-Right presentation component.<br>
122
     *  The language is set to <code>null</code>, which defaults to the language
123
     *  of the current default locale.
124
     */
125
    public static final CxpEnv DEFAULT = new CxpEnv(null, false, ORIENT_LTR);
126
127
    /**
128
     *  This string is a 2-letters code representing a language as defined by
129
     *  ISO-639. If left as <code>null</code>, it defaults to the language
130
     *  of the current default locale.
131
     */
132
    public final String language;
133
134
    /**
135
     *  Flag specifying that complex expressions processed under this environment
136
     *  should assume that the GUI is mirrored (globally going from right to left).
137
     */
138
    public final boolean mirrored;
139
140
    /** Specify the orientation (a.k.a. base direction) of the GUI
141
     *  component in which the <i>full</i> text of the complex expression will
142
     *  be displayed.<br>
143
     *  The orientation must have one of the values
144
     *  {@link #ORIENT_LTR ORIENT_LTR},
145
     *  {@link #ORIENT_LTR ORIENT_RTL},
146
     *  {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
147
     *  {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
148
     *  {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
149
     *  {@link #ORIENT_IGNORE ORIENT_IGNORE}.
150
      *  <p>
151
     *  When the orientation is <code>ORIENT_LTR</code> and the complex
152
     *  expression has a RTL base direction,
153
     *  {@link CxpHelper#leanToFullText leanToFullText}
154
     *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
155
     *  end.
156
     *  <p>
157
     *  When the orientation is <code>ORIENT_RTL</code> and the complex
158
     *  expression has a LTR base direction,
159
     *  {@link CxpHelper#leanToFullText leanToFullText}
160
     *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
161
     *  end.
162
     *  <p>
163
     *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
164
     *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
165
     *  to a RTL orientation while the complex expression has a LTR base
166
     *  direction, {@link CxpHelper#leanToFullText leanToFullText}
167
     *  adds LRM at the head of the <i>full</i> text.
168
     *  <p>
169
     *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
170
     *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
171
     *  to a LTR orientation while the complex expression has a RTL base
172
     *  direction, {@link CxpHelper#leanToFullText leanToFullText}
173
     *  adds RLM at the head of the <i>full</i> text.
174
     *  <p>
175
     *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
176
     *  expression has a LTR base direction,
177
     *  {@link CxpHelper#leanToFullText leanToFullText}
178
     *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
179
     *  end.
180
     *  <p>
181
     *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
182
     *  expression has a RTL base direction,
183
     *  {@link CxpHelper#leanToFullText leanToFullText}
184
     *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
185
     *  end.
186
     *  <p>
187
     *  When the orientation is <code>ORIENT_IGNORE</code>,
188
     *  {@link CxpHelper#leanToFullText leanToFullText} does not add any directional
189
     *  formatting characters as either prefix or suffix of the <i>full</i> text.
190
     *  <p>
191
     */
192
    public final int orientation;
193
194
    static Locale defLocale;
195
    static String defLanguage;
196
    static boolean defBidi;
197
    boolean bidiFlag;
198
199
    /**
200
     *  Constructor
201
     *
202
     *  @param lang represents the language to be used in this environment.
203
     *          It should be specified as a 2-letters code as defined by
204
     *          ISO-639.<br>
205
     *          If longer than 2 letters, the extra letters are ignored.<br>
206
     *          If set to <code>null</code>, it defaults to the language
207
     *          of the default locale.
208
     *  @see #language
209
     *
210
     *  @param mirrored specifies if the GUI is mirrored.
211
     *  @see #mirrored
212
     *
213
     *  @param orientation specifies the orientation of the component
214
     *          which is to display the complex expression. It must be
215
     *          one of the values
216
     *          {@link #ORIENT_LTR ORIENT_LTR},
217
     *          {@link #ORIENT_LTR ORIENT_RTL},
218
     *          {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
219
     *          {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
220
     *          {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
221
     *          {@link #ORIENT_IGNORE ORIENT_IGNORE}.<br>
222
     *          If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}.
223
     *  @see #orientation
224
     */
225
    public CxpEnv(String lang, boolean mirrored, int orientation) {
226
        if (lang == null) {
227
            language = null;
228
        } else {
229
            if (lang.length() > 2) {
230
                language = lang.substring(0, 2);
231
            } else {
232
                language = lang;
233
            }
234
            bidiFlag = isBidiLanguage(language);
235
        }
236
        this.mirrored = mirrored;
237
        this.orientation = orientation >= ORIENT_LTR && orientation <= ORIENT_IGNORE ? orientation : ORIENT_UNKNOWN;
238
    }
239
240
    /**
241
     *  Check whether the current language uses a
242
     *  bidi script (Arabic, Hebrew, Farsi or Urdu).
243
     *
244
     *  @return <code>true</code> if the current language uses a bidi script.
245
     *          The language may have been set explicitly when creating the
246
     *          <code>CxpEnv</code> instance, or it may have defaulted to
247
     *          the language of the current default locale.
248
     *  @see #CxpEnv CxpEnv
249
     */
250
    public boolean isBidi() {
251
        // TBD use OSGi service
252
        if (defLanguage != null && defLocale.equals(Locale.getDefault()))
253
            return defBidi;
254
255
        if (language == null) {
256
            // TBD use OSGi service
257
            defLocale = Locale.getDefault();
258
            defLanguage = defLocale.getLanguage();
259
            defBidi = isBidiLanguage(defLanguage);
260
            return defBidi;
261
        }
262
263
        return bidiFlag;
264
    }
265
266
    static boolean isBidiLanguage(String lang) {
267
        return "iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
268
    }
269
270
    static String lineSep;
271
272
    /**
273
     *  Retrieve the string which represents a line separator in this environment.
274
     *
275
     *  @return the string which is used as line separator (e.g. CRLF).
276
     */
277
    public static String getLineSep() {
278
        // TBD use bundle properties
279
        if (lineSep == null)
280
            lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
281
        return lineSep;
282
    }
283
284
    static String osName;
285
    static boolean flagOS;
286
287
    /**
288
     *  Check if the current OS is supported by the complex expression packages.
289
     *
290
     *  @return <code>true</code> if the current OS is supported.
291
     */
292
    public static boolean isSupportedOS() {
293
        if (osName == null) {
294
            // TBD use bundle properties
295
            osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
296
            flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$
297
        }
298
        return flagOS;
299
    }
300
301
}
(-)src/org/eclipse/equinox/bidi/complexp/CxpFeatures.java (+188 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
/**
14
 *  This class defines features of a complex expression processor.
15
 *  <p>
16
 *  All public fields in this class are <code>final</code>, i.e. cannot be
17
 *  changed after creating an instance.
18
 *  <p>
19
 *  A <code>CxpFeatures</code> instance can be associated with a
20
 *  <code>CxpHelper</code> instance using
21
 *  the {@link CxpHelper#setFeatures setFeatures} method.
22
 *
23
 *  <h2>Code Samples</h2>
24
 *  <p>Example 1 (set all features)
25
 *  <pre>
26
 *
27
 *    CxpFeatures myFeatures = new CxpFeatures("+-=", 0, -1, -1, false, false);
28
 *    CxpHelper myHelper = new CxpHelper(IProcessorTypes.FILE, myEnv);
29
 *    myHelper.setFeatures(myFeatures);
30
 *
31
 *  </pre>
32
 *  <p>Example 2 (change only the operators)
33
 *  <pre>
34
 *
35
 *    CxpFeatures f1 = myHelper.getFeatures();
36
 *    CxpFeatures f2 = new CxpFeatures("[]|()", f1.specialsCount,
37
 *                                     f1.dirArabic, f1.dirHebrew,
38
 *                                     f1.ignoreArabic, f1.ignoreHebrew);
39
 *    myHelper.setFeatures(f2);
40
 *
41
 *  </pre>
42
 *
43
 *  @see CxpHelper#getFeatures CxpHelper.getFeatures
44
 *  @see CxpHelper#setFeatures CxpHelper.setFeatures
45
 *  @see ICxpProcessor#init ICxpProcessor.init
46
 *  @see ICxpProcessor#init2 ICxpProcessor.init2
47
 *
48
 *  @author Matitiahu Allouche
49
 */
50
public class CxpFeatures {
51
52
    /**
53
     *  Constant specifying that the base direction of a complex expression is LTR.
54
     *  The base direction may depend on whether the GUI is
55
     *  {@link CxpEnv#mirrored mirrored} and may
56
     *  may be different for Arabic and for Hebrew.
57
     *  This constant can appear as <code>dirArabic</code>
58
     *  or <code>dirHebrew</code> argument for
59
     *  {@link CxpFeatures#CxpFeatures CxpFeatures constructor} and as value
60
     *  for the {@link #dirArabic} or {@link #dirHebrew} members of
61
     *  <code>CxpFeatures</code>.
62
     */
63
    public static final int DIR_LTR = 0;
64
65
    /**
66
     *  Constant specifying that the base direction of a complex expression is RTL.
67
     *  The base direction may depend on whether the GUI is
68
     *  {@link CxpEnv#mirrored mirrored} and may
69
     *  may be different for Arabic and for Hebrew.
70
     *  This constant can appear as <code>dirArabic</code>
71
     *  or <code>dirHebrew</code> argument for
72
     *  {@link CxpFeatures#CxpFeatures CxpFeatures constructor} and as value
73
     *  for the {@link #dirArabic} or {@link #dirHebrew} members of
74
     *  <code>CxpFeatures</code>.
75
     */
76
    public static final int DIR_RTL = 1;
77
78
    /**
79
     *  Pre-defined <code>CxpFeatures</code> instance with values for no
80
     *  operators, no special processing, all directions LTR
81
     *  and support for neither Arabic nor Hebrew.<br>
82
     *  Since there are no operators and no special processing, a complex
83
     *  expression processor with such features would do nothing.<br>
84
     *  It is more efficient to do nothing with a
85
     *  {@link CxpHelper#CxpHelper() CxpHelper}
86
     *  instantiated with no arguments.
87
     */
88
    public static final CxpFeatures DEFAULT = new CxpFeatures(null, 0, -1, -1, true, true);
89
90
    /**
91
     *  String grouping one-character operators which
92
     *  separate the text of the complex expression into tokens.
93
     */
94
    public final String operators;
95
96
    /**
97
     *  Number of special cases for the associated processor.
98
     *  Special cases exist for some types of complex expression processors.
99
     *  They are implemented by overriding methods
100
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} and
101
     *  {@link ICxpProcessor#processSpecial processSpecial}.
102
     *  Examples of special cases are comments, literals, or anything which
103
     *  is not identified by a one-character operator.
104
     */
105
    public final int specialsCount;
106
107
    /**
108
     *  Base direction of the complex expression for Arabic.
109
     *  If a complex expression contains both Arabic and
110
     *  Hebrew words, the first Arabic or Hebrew letter in the
111
     *  expression determines which is the governing script).<br>
112
     *  The value of this field must be one of
113
     *  {@link #DIR_LTR} or {@link #DIR_RTL}.
114
     *
115
     *  @see #dirHebrew
116
     */
117
    public final int dirArabic;
118
119
    /**
120
     *  Base direction of the complex expression for Hebrew.
121
     *  If a complex expression contains both Arabic and
122
     *  Hebrew words, the first Arabic or Hebrew letter in the
123
     *  expression determines which is the governing script).<br>
124
     *  The value of this field must be one of
125
     *  {@link #DIR_LTR} or {@link #DIR_RTL}.
126
     *
127
     *  @see #dirArabic
128
     */
129
    public final int dirHebrew;
130
131
    /**
132
     *  Flag indicating that Arabic letters will not be considered for
133
     *  processing complex expressions. If both this flag and
134
     *  {@link #ignoreHebrew} are set to <code>true</code>, the
135
     *  processor will do nothing (but some overhead can be expected).
136
     */
137
    public final boolean ignoreArabic;
138
139
    /**
140
     *  Flag indicating that Hebrew letters will not be considered for
141
     *  processing complex expressions. If both this flag and
142
     *  {@link #ignoreArabic} are set to <code>true</code>, the
143
     *  processor will do nothing (but some overhead can be expected).
144
     */
145
    public final boolean ignoreHebrew;
146
147
    /**
148
     *  Constructor
149
     *
150
     *  @param operators is a string where each character is a delimiter
151
     *          which separates the complex expression into tokens.
152
     *  @see #operators
153
     *
154
     *  @param specialsCount specifies the number of special cases handled
155
     *          by the processor.
156
     *  @see #specialsCount
157
     *
158
     *  @param dirArabic specifies the base direction of the complex expression
159
     *          for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
160
     *          If it is not (for instance if it is a negative value), it
161
     *          defaults to <code>DIR_LTR</code>.
162
     *  @see #dirArabic
163
     *
164
     *  @param dirHebrew specifies the base direction of the complex expression
165
     *          for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
166
     *          If it is not (for instance if it is a negative value), it
167
     *          defaults to <code>DIR_LTR</code>.
168
     *  @see #dirHebrew
169
     *
170
     *  @param ignoreArabic indicates that Arabic letters will not be
171
     *          considered for processing complex expressions.
172
     *  @see #ignoreArabic
173
     *
174
     *  @param ignoreHebrew indicates that Hebrew letters will not be
175
     *          considered for processing complex expressions.
176
     *  @see #ignoreHebrew
177
     */
178
    public CxpFeatures(String operators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) {
179
180
        this.operators = operators == null ? "" : operators; //$NON-NLS-1$
181
        this.specialsCount = specialsCount;
182
        this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR;
183
        this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR;
184
        this.ignoreArabic = ignoreArabic;
185
        this.ignoreHebrew = ignoreHebrew;
186
    }
187
188
}
(-)src/org/eclipse/equinox/bidi/complexp/CxpHelper.java (+570 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import org.eclipse.equinox.bidi.internal.complexp.CxpDoer;
14
15
/**
16
 *  This class acts as a mediator between applications and complex
17
 *  expression processors.
18
 *  The purpose of complex expression processors is to add directional
19
 *  formatting characters to ensure correct display.
20
 *  This class shields applications from the
21
 *  intricacies of complex expression processors.
22
 *  <p>
23
 *  For a general introduction to complex expressions, see
24
 *  {@link <a href="package-summary.html">
25
 *  the package documentation</a>}.
26
 *
27
 *  <h2>Code Sample</h2>
28
 *
29
 *  <p>The following code shows how to instantiate a CxpHelper adapted for a
30
 *  certain type of complex expression (directory and file paths), and how
31
 *  to obtain the <i>full</i> text corresponding to the <i>lean</i> text
32
 *  of such an expression.
33
 *
34
 *  <pre>
35
 *
36
 *    CxpHelper helper = new CxpHelper(IProcessorTypes.FILE);
37
 *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
38
 *    String fullText = helper.leanToFullText(leanText);
39
 *    System.out.println("full text = " + fullText);
40
 *
41
 *  </pre>
42
 *  This class provides a user-oriented API but does not provides
43
 *  an actual implementation. The real work is done by the class
44
 *  {@link CxpDoer}. Users of the API need not be concerned by, and
45
 *  should not depend upon, details of the implementation by
46
 *  <code>CxpDoer</code>.
47
 *
48
 *  @author Matitiahu Allouche
49
 *
50
 */
51
public class CxpHelper {
52
    /**
53
     *  Constant to use as <code>initState</code> argument when calling
54
     *  {@link #leanToFullText(java.lang.String, int) leanToFullText} or
55
     *  {@link #fullToLeanText(java.lang.String, int) fullToLeanText}
56
     *  to indicate that there is no context of previous lines which
57
     *  should be initialized before performing the operation.
58
     */
59
    public static final int STATE_NOTHING_GOING = -1;
60
61
    private static final int[] EMPTY_INT_ARRAY = new int[0];
62
63
    /**
64
     *  Reference to the {@link CxpDoer} instance which accomplishes
65
     *  most of the work. This member should be accessed only by
66
     *  complex expression processors (implementing {@link ICxpProcessor}).
67
     */
68
    public CxpDoer ced;
69
70
    /**
71
     *  Create a <code>CxpHelper</code> instance which does nothing tangible
72
     *  but does it quickly. We will call it a <i>no-op helper</i>.
73
     *  The {@link #CxpHelper() no-op helper} does not modify text submitted to it, and can be
74
     *  used when it is known that no complex expression processing
75
     *  is needed, for instance because no bidi text is expected. With this
76
     *  helper, the cost of invoking the complex expression API is minimal.
77
     */
78
    public CxpHelper() {
79
        // let ced stay null
80
    }
81
82
    /**
83
     *  Create a <code>CxpHelper</code> instance to process expressions
84
     *  of type <code>type</code> with a
85
     *  {@link CxpEnv#DEFAULT DEFAULT} environment.
86
     *
87
     *  @param type represents the type of the complex expression. It must
88
     *          be one of the values in {@link IProcessorTypes}, or a type
89
     *          added in a plug-in extension.
90
     *
91
     *  @throws IllegalArgumentException if the <code>type</code> is not
92
     *          supported.
93
     */
94
    public CxpHelper(String type) {
95
        this(type, null);
96
    }
97
98
    /**
99
     *  Create a <code>CxpHelper</code> instance to process expressions
100
     *  of type <code>type</code> operating under the environment
101
     *  {@link CxpEnv env}.
102
     *
103
     *  @param type represents the type of the complex expression. It must
104
     *          be one of the values in {@link IProcessorTypes}, or a type
105
     *          added in a plug-in extension.
106
     *
107
     *  @param env represents the environment where the complex expression
108
     *          will be displayed. It is better to specify the environment
109
     *          when instantiating a <code>CxpHelper</code> than to specify
110
     *          it later using {@link #setEnvironment setEnvironment}.<br>
111
     *          <code>null</code> can be specified here for a
112
     *          {@link CxpEnv#DEFAULT DEFAULT} environment.
113
     *
114
     *  @throws IllegalArgumentException if the <code>type</code> is not
115
     *          supported.
116
     */
117
    public CxpHelper(String type, CxpEnv env) {
118
        ICxpProcessor proc = StringProcessor.getProcessor(type);
119
        if (proc == null) {
120
            throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
121
        }
122
        ced = new CxpDoer(this, proc, env);
123
    }
124
125
    /**
126
     *  Create a <code>CxpHelper</code> instance to process complex
127
     *  expressions by means of a given processor <code>proc</code>,
128
     *  operating under the environment {@link CxpEnv env}.
129
     *
130
     *  @param proc is a complex expression processor.
131
     *
132
     *  @param env represents the environment where the complex expression
133
     *          will be displayed. It is better to specify the environment
134
     *          when instantiating a <code>CxpHelper</code> than to specify
135
     *          it later using {@link #setEnvironment setEnvironment}.<br>
136
     *          <code>null</code> can be specified here for a
137
     *          {@link CxpEnv#DEFAULT DEFAULT} environment.
138
     */
139
    public CxpHelper(ICxpProcessor proc, CxpEnv env) {
140
        ced = new CxpDoer(this, proc, env);
141
    }
142
143
    /** Add directional formatting characters to a complex expression
144
     *  to ensure correct presentation.
145
     *
146
     *  @param text is the text of the complex expression.
147
     *
148
     *  @return the complex expression with directional formatting
149
     *          characters added at proper locations to ensure correct
150
     *          presentation.<br>
151
     *          The {@link #CxpHelper() no-op helper} returns <code>text</code>.
152
     */
153
    public String leanToFullText(String text) {
154
        return leanToFullText(text, STATE_NOTHING_GOING);
155
    }
156
157
    /**
158
     *  Add directional formatting characters to a complex expression
159
     *  to ensure correct presentation.
160
     *
161
     *  @param  text is the text of the complex expression.
162
     *
163
     *  @param  initState specifies that the first parameter is the
164
     *          continuation of text submitted in a previous call.
165
     *          The <code>initState</code> of the present call must be
166
     *          the final state obtained by calling
167
     *          {@link #getFinalState() getFinalState}
168
     *          after the previous call.
169
     *          <br>If the present call is not a continuation of
170
     *          text submitted in a previous call, the value
171
     *          {@link #STATE_NOTHING_GOING} should be used as argument.
172
     *
173
     *  @return the complex expression with directional formatting
174
     *          characters added at proper locations to ensure correct
175
     *          presentation.<br>
176
     *          The {@link #CxpHelper() no-op helper} returns <code>text</code>.
177
     *
178
     *  @see #getFinalState getFinalState
179
     */
180
    public String leanToFullText(String text, int initState) {
181
        if (ced == null)
182
            return text;
183
        return ced.leanToFullText(text, initState);
184
    }
185
186
    /**
187
     *  Given a complex expression, get the offsets of characters before
188
     *  which directional formatting characters must be added in order to
189
     *  ensure correct presentation.
190
     *  Only LRMs (for an expression with LTR base direction) and RLMs (for
191
     *  an expression with RTL base direction) are considered. Leading and
192
     *  trailing LRE, RLE and PDF which might be prefixed or suffixed
193
     *  depending on the {@link CxpEnv#orientation orientation} of the
194
     *  GUI component used for display are not reflected in this method.
195
     *  <p>
196
     *  This method assumes that a successful call to
197
     *  {@link #leanToFullText leanToFullText} has been performed, and it
198
     *  returns the offsets relevant for the last text submitted.
199
     *
200
     *  @return an array of offsets to the characters in the last submitted
201
     *          complex expression before which directional marks must be
202
     *          added to ensure correct presentation.
203
     *          The offsets are sorted in ascending order.<br>
204
     *          The {@link #CxpHelper() no-op helper} returns an array of 0 elements.
205
     */
206
    public int[] leanBidiCharOffsets() {
207
        if (ced == null)
208
            return EMPTY_INT_ARRAY;
209
        return ced.leanBidiCharOffsets();
210
    }
211
212
    /**
213
     *  Get the offsets of characters in the <i>full</i> text of a
214
     *  complex expression corresponding to directional formatting
215
     *  characters which have been added in order to ensure correct presentation.
216
     *  LRMs (for an expression with LTR base direction), RLMs (for
217
     *  an expression with RTL base direction) are considered as well as
218
     *  leading and trailing LRE, RLE and PDF which might be prefixed or suffixed
219
     *  depending on the {@link CxpEnv#orientation orientation} of the
220
     *  GUI component used for display.
221
     *  <p>
222
     *  This method assumes that a successful call to
223
     *  {@link #leanToFullText leanToFullText} has been performed, and it
224
     *  returns the offsets relevant for the last text submitted.
225
     *
226
     *  @return an array of offsets to the characters in the <i>full</i>
227
     *          text of the last submitted complex expression which are
228
     *          directional formatting characters added to ensure correct
229
     *          presentation.
230
     *          The offsets are sorted in ascending order.<br>
231
     *          The {@link #CxpHelper() no-op helper} returns an array of 0 elements.
232
     */
233
    public int[] fullBidiCharOffsets() {
234
        if (ced == null)
235
            return EMPTY_INT_ARRAY;
236
        return ced.fullBidiCharOffsets();
237
    }
238
239
    /**
240
     *  Remove directional formatting characters which were added to a
241
     *  complex expression to ensure correct presentation.
242
     *
243
     *  @param text is the text of the complex expression including
244
     *         directional formatting characters.
245
     *
246
     *  @return the complex expression without directional formatting
247
     *          characters which might have been added by processing it
248
     *          with {@link #leanToFullText leanToFullText}.<br>
249
     *          The {@link #CxpHelper() no-op helper} returns <code>text</code>
250
     *
251
     */
252
    public String fullToLeanText(String text) {
253
        return fullToLeanText(text, STATE_NOTHING_GOING);
254
    }
255
256
    /**
257
     *  Remove directional formatting characters which were added to a
258
     *  complex expression to ensure correct presentation.
259
     *
260
     *  @param text is the text of the complex expression including
261
     *         directional formatting characters.
262
     *
263
     *  @param initState specifies that the first parameter is the
264
     *         continuation of text submitted in a previous call.
265
     *         The <code>initState</code> of the present call must be
266
     *         the final state obtained by calling
267
     *         {@link #getFinalState getFinalState} after the previous call.
268
     *          <br>If the present call is not a continuation of
269
     *          text submitted in a previous call, the value
270
     *          {@link #STATE_NOTHING_GOING} should be used as argument.
271
     *
272
     *  @return the complex expression without directional formatting
273
     *          characters which might have been added by processing it
274
     *          with {@link #leanToFullText leanToFullText}.<br>
275
     *          The {@link #CxpHelper() no-op helper} returns <code>text</code>
276
     *
277
     *  @see #getFinalState getFinalState
278
     */
279
    public String fullToLeanText(String text, int initState) {
280
        if (ced == null)
281
            return text;
282
        return ced.fullToLeanText(text, initState);
283
    }
284
285
    /**
286
     *  Retrieve the final state achieved in a previous call to
287
     *  {@link #leanToFullText leanToFullText} or
288
     *  {@link #fullToLeanText fullToLeanText}.
289
     *  This state is an opaque value which is meaningful only
290
     *  within calls to the same complex expression processor.
291
     *  The only externalized value is
292
     *  {@link #STATE_NOTHING_GOING} which means that
293
     *  there is nothing to remember from the last call.
294
     *  <p>
295
     *  The state should be used only for complex expressions which come
296
     *  in parts, like when spanning multiple lines. The user can make
297
     *  a separate call to
298
     *  <code>leanToFullText</code> or <code>fullToLeanText</code> for each
299
     *  line in the expression. The final state value retrieved after the
300
     *  call for one line should be used as the initial state in the call
301
     *  which processes the next line.
302
     *  <p>
303
     *  If a line within a complex expression has already been processed by
304
     *  <code>leanToFullText</code> and the <i>lean</i> version of that line has
305
     *  not changed, and its initial state has not changed either, the user
306
     *  can be sure that the <i>full</i> version of that line is also
307
     *  identical to the result of the previous processing.
308
     *
309
     *  @see #leanToFullText(String text, int initState)
310
     *  @see #fullToLeanText(String text, int initState)
311
     *
312
     *  @return the last final state.<br>
313
     *          The {@link #CxpHelper() no-op helper} returns {@link #STATE_NOTHING_GOING}.
314
     */
315
    public int getFinalState() {
316
        if (ced == null)
317
            return STATE_NOTHING_GOING;
318
        return ced.getFinalState();
319
    }
320
321
    /**
322
     *  After transforming a <i>lean</i> string into a <i>full</i> string
323
     *  using {@link #leanToFullText leanToFullText}, compute the index in the
324
     *  <i>full</i> string of the character corresponding to the
325
     *  character with the specified position in the <i>lean</i> string.
326
     *
327
     *  @param pos is the index of a character in the <i>lean</i> string.
328
     *          It must be a non-negative number smaller than the length
329
     *          of the <i>lean</i> text.
330
     *
331
     *  @return the index of the corresponding character in the
332
     *          <i>full</i> string.<br>
333
     *          The {@link #CxpHelper() no-op helper} returns <code>pos</code>.
334
     */
335
    public int leanToFullPos(int pos) {
336
        if (ced == null)
337
            return pos;
338
        return ced.leanToFullPos(pos);
339
    }
340
341
    /**
342
     *  After transforming a <i>lean</i> string into a <i>full</i> string
343
     *  using {@link #leanToFullText leanToFullText}, compute the index in the
344
     *  <i>lean</i> string of the character corresponding to the
345
     *  character with the specified position in the <i>full</i> string.
346
     *
347
     *  @param pos is the index of a character in the <i>full</i> string.
348
     *          It must be a non-negative number smaller than the length
349
     *          of the <i>full</i> text.
350
     *
351
     *  @return the index of the corresponding character in the
352
     *          <i>lean</i> string. If there is no corresponding
353
     *          character in the <i>lean</i> string (because the
354
     *          specified character is a directional formatting character
355
     *          added when invoking {@link #leanToFullText leanToFullText}),
356
     *          the value returned will be that corresponding to the
357
     *          next character which is not a directional formatting
358
     *          character.<br>
359
     *          If <code>pos</code> corresponds to a directional formatting
360
     *          character beyond all characters of the original
361
     *          <i>lean</i> text, the value returned is the length of the
362
     *          <i>lean</i> text.<br>
363
     *          The {@link #CxpHelper() no-op helper} returns <code>pos</code>.
364
     */
365
    public int fullToLeanPos(int pos) {
366
        if (ced == null)
367
            return pos;
368
        return ced.fullToLeanPos(pos);
369
    }
370
371
    /**
372
     *  Get the base direction of the complex expression last
373
     *  submitted to {@link #leanToFullText leanToFullText}.
374
     *  This base direction may depend on
375
     *  whether the expression contains Arabic or Hebrew words
376
     *  (if it contains both, the first Arabic or Hebrew letter in the
377
     *  expression determines which is the governing script) and on
378
     *  whether the GUI is {@link CxpEnv#mirrored mirrored}.
379
     *
380
     *  @return the base direction of the last submitted complex
381
     *          expression. It must be one of the values
382
     *          {@link CxpFeatures#DIR_LTR} or {@link CxpFeatures#DIR_RTL}.<br>
383
     *          The {@link #CxpHelper() no-op helper} returns <code>DIR_LTR</code>.
384
     */
385
    public int getCurDirection() {
386
        if (ced == null)
387
            return CxpFeatures.DIR_LTR;
388
        return ced.getCurDirection();
389
    }
390
391
    /**
392
     *  Get the current environment under which the <code>CxpHelper</code>
393
     *  operates.
394
     *  This environment may have been specified in the constructor or
395
     *  specified later using {@link #setEnvironment setEnvironment}.<br>
396
     *
397
     *  @return the current environment.<br>
398
     *          The {@link #CxpHelper() no-op helper} returns a {@link CxpEnv#DEFAULT DEFAULT}
399
     *          environment.
400
     *
401
     *  @see #setEnvironment setEnvironment
402
     */
403
    public CxpEnv getEnvironment() {
404
        if (ced == null)
405
            return CxpEnv.DEFAULT;
406
        return ced.getEnvironment();
407
    }
408
409
    /**
410
     *  Specify the environment under which the <code>CxpHelper</code>
411
     *  must operate.
412
     *  <p>
413
     *  <b>Note</b> that calling this method causes the processor
414
     *  associated with this instance of <code>CxpHelper</code>
415
     *  to re-initialize its features. The effect of a previous call
416
     *  to {@link #setFeatures(CxpFeatures) setFeatures} is lost.<br>
417
     *  The {@link #CxpHelper() no-op helper} does nothing.
418
     *
419
     *  @see #getEnvironment getEnvironment
420
     *  @see ICxpProcessor#init2 ICxpProcessor.init2
421
     */
422
    public void setEnvironment(CxpEnv environment) {
423
        if (ced == null) {
424
            return; // do nothing
425
        }
426
        ced.setEnvironment(environment);
427
    }
428
429
    /**
430
     *  Get the current features of the processor associated with this
431
     *  <code>CxpHelper</code> instance.
432
     *
433
     *  @return the current features.<br>
434
     *          The {@link #CxpHelper() no-op helper} returns {@link CxpFeatures#DEFAULT DEFAULT}
435
     *          features.
436
     *
437
     *  @see #setFeatures setFeatures
438
     */
439
    public CxpFeatures getFeatures() {
440
        if (ced == null)
441
            return CxpFeatures.DEFAULT;
442
        return ced.getFeatures();
443
    }
444
445
    /**
446
     *  Specify the features to be applied to the processor associated with this
447
     *  <code>CxpHelper</code> instance.
448
     *  Note that the value of {@link CxpFeatures#specialsCount specialsCount}
449
     *  cannot be changed (the new value will be ignored).<br>
450
     *  The {@link #CxpHelper() no-op helper} does nothing.
451
     *
452
     *  @see #getFeatures getFeatures
453
     */
454
    public void setFeatures(CxpFeatures features) {
455
        if (ced == null) {
456
            return; // do nothing
457
        }
458
        ced.setFeatures(features);
459
    }
460
461
    /**
462
     *  This method can be called from within
463
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or
464
     *  {@link ICxpProcessor#processSpecial processSpecial} in implementations
465
     *  of {@link ICxpProcessor} to retrieve the bidirectional class of
466
     *  characters in the <i>lean</i> text.
467
     *
468
     *  @param index position of the character in the <i>lean</i> text.
469
     *          It must be a non-negative number smaller than the length
470
     *          of the <i>lean</i> text.
471
     *
472
     *  @return the bidirectional class of the character. It is one of the
473
     *          values which can be returned by
474
     *          <code>java.lang.Character#getDirectionality</code>.
475
     *          However, it is recommended to use <code>getDirProp</code>
476
     *          rather than <code>java.lang.Character.getDirectionality</code>
477
     *          since <code>getDirProp</code> manages a cache of character
478
     *          properties and so can be more efficient than calling the
479
     *          java.lang.Character method.<br>
480
     *          The {@link #CxpHelper() no-op helper} returns
481
     *          <code>Character.DIRECTIONALITY_UNDEFINED</code>.
482
     */
483
    public byte getDirProp(int index) {
484
        if (ced == null)
485
            return Character.DIRECTIONALITY_UNDEFINED;
486
        return ced.getDirProp(index);
487
    }
488
489
    /**
490
     *  This method can be called from within
491
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or
492
     *  {@link ICxpProcessor#processSpecial processSpecial} in implementations
493
     *  of {@link ICxpProcessor} to set or override the bidirectional
494
     *  class of characters in the <i>lean</i> text.
495
     *
496
     *  @param index position of the character in the <i>lean</i> text.
497
     *          It must be a non-negative number smaller than the length
498
     *          of the <i>lean</i> text.
499
     *
500
     *  @param  dirProp bidirectional class of the character. It is one of the
501
     *          values which can be returned by
502
     *          <code>java.lang.Character.getDirectionality</code>.<br>
503
     *          The {@link #CxpHelper() no-op helper} does nothing.
504
     */
505
    public void setDirProp(int index, byte dirProp) {
506
        if (ced != null)
507
            ced.getDirProp(index);
508
    }
509
510
    /**
511
     *  This method can be called from within
512
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or
513
     *  {@link ICxpProcessor#processSpecial processSpecial} in implementations
514
     *  of {@link ICxpProcessor}
515
     *  to specify that a mark character must be added before the character
516
     *  at the specified position of the <i>lean</i> text when generating the
517
     *  <i>full</i> text. The mark character will be LRM for complex expressions
518
     *  with a LTR base direction, and RLM for complex expressions with RTL
519
     *  base direction. The mark character is not added physically by this
520
     *  method, but its position is noted and will be used when generating
521
     *  the <i>full</i> text.
522
     *
523
     *  @param  offset position of the character in the <i>lean</i> text.
524
     *          It must be a non-negative number smaller than the length
525
     *          of the <i>lean</i> text.
526
     *          For the benefit of efficiency, it is better to insert
527
     *          multiple marks in ascending order of the offsets.<br>
528
     *          The {@link #CxpHelper() no-op helper} does nothing.
529
     */
530
    public void insertMark(int offset) {
531
        if (ced != null)
532
            ced.insertMark(offset);
533
    }
534
535
    /**
536
     *  This method can be called from within
537
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or
538
     *  {@link ICxpProcessor#processSpecial processSpecial} in
539
     *  implementations of {@link ICxpProcessor} to add a
540
     *  directional mark before an
541
     *  operator if needed for correct display, depending on the
542
     *  base direction of the expression and on the class of the
543
     *  characters in the <i>lean</i> text preceding and following
544
     *  the operator itself.<br>
545
     *  The {@link #CxpHelper() no-op helper} does nothing.
546
     *
547
     *  @param  operLocation offset of the operator in the <i>lean</i> text.
548
     *          It must be a non-negative number smaller than the length
549
     *          of the <i>lean</i> text.
550
     */
551
    public void processOperator(int operLocation) {
552
        if (ced != null)
553
            ced.processOperator(operLocation);
554
    }
555
556
    /**
557
     *  This method can be called from within
558
     *  {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or
559
     *  {@link ICxpProcessor#processSpecial processSpecial} in
560
     *  implementations of {@link ICxpProcessor} to
561
     *  set the final state which should be used for the next call to
562
     *  {@link #leanToFullText(java.lang.String, int)}.<br>
563
     *  The {@link #CxpHelper() no-op helper} does nothing.
564
     */
565
    public void setFinalState(int newState) {
566
        if (ced != null)
567
            ced.setFinalState(newState);
568
    }
569
570
}
(-)src/org/eclipse/equinox/bidi/complexp/CxpProcessor.java (+97 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import org.eclipse.equinox.bidi.internal.complexp.CxpDoer;
14
15
/**
16
 *  Generic processor which can be used as superclass (base class)
17
 *  for specific complex expression processors.
18
 *  <p>
19
 *  Here are some guidelines about how to write complex expression
20
 *  processors.
21
 *  <ul>
22
 *    <li>Processor instances may be accessed simultaneously by
23
 *        several threads. They should have no instance variables.</li>
24
 *    <li>Each use of a processor is initialized with the {@link #init init}
25
 *        or the {@link #init2 init2} methods.
26
 *        Both methods have a {@link CxpHelper} argument named <code>ceh</code>.
27
 *        All calls to methods of <code>CxpProcessor</code> have a
28
 *        <code>ceh</code> argument.
29
 *        If a processor needs to retain some data across invocations, it may
30
 *        access the field {@link CxpDoer#procData ceh.ced.procData}.
31
 *        It is guaranteed that this field will not be modified by any code
32
 *        except the processor itself.</li>
33
 *    <li>The behavior of a processor is governed by 3 factors:
34
 *        <ul>
35
 *          <li>The {@link CxpFeatures#operators operators} field of its
36
 *              {@link CxpFeatures features} determines how submitted
37
 *              complex expressions are split into tokens.</li>
38
 *          <li>The tokens are displayed one after the other according
39
 *              to the appropriate {@link CxpFeatures#dirArabic direction}.
40
 *          <li>The counter {@link CxpFeatures#specialsCount specialsCount}
41
 *              determines how many special cases need to be handled by
42
 *              code specific to that processor.
43
 *  </ul>
44
 *
45
 *  @author Matitiahu Allouche
46
 */
47
public class CxpProcessor implements ICxpProcessor {
48
49
    /**
50
     *  In <code>CxpProcessor</code> this method returns a
51
     *  {@link CxpFeatures#DEFAULT DEFAULT} value which
52
     *  directs the processor to do nothing.
53
     */
54
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
55
        return CxpFeatures.DEFAULT;
56
    }
57
58
    /**
59
     *  In <code>CxpProcessor</code> this method simply calls the
60
     *  {@link #init init} method. If this is good enough, i.e.
61
     *  if the {@link CxpFeatures features} of the processor are
62
     *  determined identically for initialization and after a
63
     *  change in the {@link CxpEnv environment}, subclasses of
64
     *  <code>CxpProcessor</code> don't need to override this
65
     *  method.
66
     */
67
    public CxpFeatures init2(CxpHelper ceh, CxpEnv env) {
68
        return init(ceh, env);
69
    }
70
71
    /**
72
     *  In <code>CxpProcessor</code> this method throws an
73
     *  <code>IllegalStateException</code>. This is appropriate behavior
74
     *  (and does not need to be overridden) for processors whose
75
     *  {@link CxpFeatures#specialsCount specialsCount} is zero, which
76
     *  means that <code>indexOfSpecial</code> should never be called
77
     *  for them.
78
     */
79
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
80
        // This method must be overridden by all subclasses with special cases.
81
        throw new IllegalStateException();
82
    }
83
84
    /**
85
     *  In <code>CxpProcessor</code> this method throws an
86
     *  <code>IllegalStateException</code>. This is appropriate behavior
87
     *  (and does not need to be overridden) for processors whose
88
     *  {@link CxpFeatures#specialsCount specialsCount} is zero, which
89
     *  means that <code>processSpecial</code> should never be called
90
     *  for them.
91
     */
92
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
93
        // This method must be overridden by all subclasses with any special case.
94
        throw new IllegalStateException();
95
    }
96
97
}
(-)src/org/eclipse/equinox/bidi/complexp/CxpUtil.java (+313 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
/**
14
 *  This class provides a number of convenience functions facilitating the
15
 *  processing of complex expressions.
16
 *
17
 *  @noextend This class is not intended to be subclassed by clients.
18
 *  @noinstantiate This class is not intended to be instantiated by clients.
19
 *
20
 *  @author Matitiahu Allouche
21
 */
22
final public class CxpUtil {
23
24
    /**
25
     *  prevent instantiation
26
     */
27
    private CxpUtil() {
28
        // empty
29
    }
30
31
    /** This is a convenience method which can add directional marks in a given
32
     *  text before the characters specified in the given array of offsets,
33
     *  and can add a prefix and/or a suffix of directional formatting characters.
34
     *  This can be used for instance after obtaining offsets by calling
35
     *  {@link CxpHelper#leanBidiCharOffsets() leanBidiCharOffsets} in order to
36
     *  produce a <i>full</i> text corresponding to the source text.
37
     *  The directional formatting characters that will be added at the given
38
     *  offsets will be LRMs for expressions with LTR base direction and
39
     *  RLMs for expressions with RTL base direction. Leading and
40
     *  trailing LRE, RLE and PDF which might be needed as prefix or suffix
41
     *  depending on the orientation of the GUI component used for display
42
     *  may be added depending on argument <code>affix</code>.
43
     *
44
     *  @param  text is the text of the complex expression.
45
     *
46
     *  @param  offsets is an array of offsets to characters in <code>text</code>
47
     *          before which an LRM or RLM will be inserted.
48
     *          Members of the array must be non-negative numbers smaller
49
     *          than the length of <code>text</code>.
50
     *          The array must be sorted in ascending order without duplicates.
51
     *          This argument may be null if there are no marks to add.
52
     *
53
     *  @param  direction specifies the base direction of the complex expression.
54
     *          It must be one of the values {@link CxpFeatures#DIR_LTR} or
55
     *          {@link CxpFeatures#DIR_RTL}.
56
     *
57
     *  @param  affix specifies if a prefix and a suffix should be added to
58
     *          the result to make sure that the <code>direction</code>
59
     *          specified as third argument is honored even if the expression
60
     *          is displayed in a GUI component with a different orientation.
61
     *
62
     *  @return a string corresponding to the source <code>text</code> with
63
     *          directional marks (LRMs or RLMs) added at the specified offsets,
64
     *          and directional formatting characters (LRE, RLE, PDF) added
65
     *          as prefix and suffix if so required.
66
     */
67
    public static String insertMarks(String text, int[] offsets, int direction, boolean affix) {
68
        int textLen = text.length();
69
        if (textLen == 0)
70
            return ""; //$NON-NLS-1$
71
72
        String curPrefix, curSuffix, full;
73
        char curMark, c;
74
        char[] fullChars;
75
        if (direction == CxpFeatures.DIR_LTR) {
76
            curMark = LRM;
77
            curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
78
            curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
79
        } else {
80
            curMark = RLM;
81
            curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$
82
            curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$
83
        }
84
        // add marks at offsets
85
        if ((offsets != null) && (offsets.length > 0)) {
86
            int offLen = offsets.length;
87
            fullChars = new char[textLen + offLen];
88
            int added = 0;
89
            for (int i = 0, j = 0; i < textLen; i++) {
90
                c = text.charAt(i);
91
                if ((j < offLen) && (i == offsets[j])) {
92
                    fullChars[i + added] = curMark;
93
                    added++;
94
                    j++;
95
                }
96
                fullChars[i + added] = c;
97
            }
98
            full = new String(fullChars);
99
        } else {
100
            full = text;
101
        }
102
        if (affix)
103
            return curPrefix + full + curSuffix;
104
        return full;
105
    }
106
107
    /*************************************************************************/
108
    /*                                                                       */
109
    /*  The following code is provided for compatibility with TextProcessor  */
110
    /*                                                                       */
111
    /*************************************************************************/
112
113
    //  The default set of delimiters to use to segment a string.
114
    private static final String defaultDelimiters = ".:/\\"; //$NON-NLS-1$
115
    // left to right mark
116
    private static final char LRM = '\u200e';
117
    // left to right mark
118
    private static final char RLM = '\u200f';
119
    // left to right embedding
120
    private static final char LRE = '\u202a';
121
    // right to left embedding
122
    private static final char RLE = '\u202b';
123
    // pop directional format
124
    private static final char PDF = '\u202c';
125
126
    static boolean isProcessingNeeded() {
127
        if (!CxpEnv.isSupportedOS())
128
            return false;
129
        return CxpEnv.DEFAULT.isBidi();
130
    }
131
132
    /**
133
     *  Process the given text and return a string with appropriate
134
     *  directional formatting characters if the locale is a bidi locale.
135
     *  This is equivalent to calling
136
     *  {@link #process(String str, String delimiters)} with the default
137
     *  set of delimiters (dot, colon, slash, backslash).
138
     *
139
     *  @param  str the text to be processed.
140
     *
141
     *  @return the processed string.
142
     */
143
    public static String process(String str) {
144
        return process(str, defaultDelimiters);
145
    }
146
147
    /**
148
     *  Process a string that has a particular semantic meaning to render
149
     *  it correctly on bidi locales. This is done by adding directional
150
     *  formatting characters so that presentation using the Unicode
151
     *  Bidirectional Algorithm will provide the expected result.
152
     *  The text is segmented according to the provided delimiters.
153
     *  Each segment has the Unicode Bidi Algorithm applied to it,
154
     *  but as a whole, the string is oriented left to right.
155
     *  <p>
156
     *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
157
     *  (where capital letters indicate RTL text) should render as
158
     *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
159
     *  <p>
160
     *  NOTE: this method inserts directional formatting characters into the
161
     *  text. Methods like <code>String.equals(String)</code> and
162
     *  <code>String.length()</code> called on the resulting string will not
163
     *  return the same values as would be returned for the original string.</p>
164
     *
165
     *  @param  str the text to process.
166
     *
167
     *  @param  delimiters delimiters by which the string will be segmented.
168
     *          If <code>null</code>, the default delimiters are used
169
     *          (dot, colon, slash, backslash).
170
     *
171
     *  @return the processed string.
172
     *          If <code>str</code> is <code>null</code>,
173
     *          or of length 0, or if the current locale is not a bidi one,
174
     *          return the original string.
175
     */
176
    public static String process(String str, String delimiters) {
177
        if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
178
            return str;
179
180
        // do not process a string that has already been processed.
181
        if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF)
182
            return str;
183
184
        // do not process a string if all the following conditions are true:
185
        //  a) it has no RTL characters
186
        //  b) it starts with a LTR character
187
        //  c) it ends with a LTR character or a digit
188
        boolean isStringBidi = false;
189
        int strLength = str.length();
190
        char c;
191
        for (int i = 0; i < strLength; i++) {
192
            c = str.charAt(i);
193
            if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) {
194
                isStringBidi = true;
195
                break;
196
            }
197
        }
198
        while (!isStringBidi) {
199
            if (!Character.isLetter(str.charAt(0)))
200
                break;
201
            c = str.charAt(strLength - 1);
202
            if (!Character.isDigit(c) && !Character.isLetter(c))
203
                break;
204
            return str;
205
        }
206
207
        if (delimiters == null)
208
            delimiters = defaultDelimiters;
209
210
        // make sure that LRE/PDF are added around the string
211
        CxpEnv env = new CxpEnv(null, false, CxpEnv.ORIENT_UNKNOWN);
212
        CxpHelper helper = new CxpHelper(new CxpProcessor(), env);
213
        helper.setFeatures(new CxpFeatures(delimiters, 0, -1, -1, false, false));
214
        return helper.leanToFullText(str);
215
    }
216
217
    /**
218
     *  Process a string that has a particular semantic meaning to render
219
     *  it correctly on bidi locales. This is done by adding directional
220
     *  formatting characters so that presentation using the Unicode
221
     *  Bidirectional Algorithm will provide the expected result..
222
     *  The text is segmented according to the syntax specified in the
223
     *  <code>type</code> argument.
224
     *  Each segment has the Unicode Bidi Algorithm applied to it, but the
225
     *  order of the segments is governed by the type of the complex expression.
226
     *  <p>
227
     *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
228
     *  (where capital letters indicate RTL text) should render as
229
     *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
230
     *  <p>
231
     *  NOTE: this method inserts directional formatting characters into the
232
     *  text. Methods like <code>String.equals(String)</code> and
233
     *  <code>String.length()</code> called on the resulting string will not
234
     *  return the same values as would be returned for the original string.</p>
235
     *
236
     *  @param  str the text to process.
237
     *
238
     *  @param  type specifies the type of the complex expression. It must
239
     *          be one of the values in {@link IProcessorTypes} or a value.
240
     *          added by a plug-in extension.
241
     *
242
     *  @return the processed string.
243
     *          If <code>str</code> is <code>null</code>,
244
     *          or of length 0, or if the current locale is not a bidi one,
245
     *          return the original string.
246
     */
247
    public static String processTyped(String str, String type) {
248
        if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
249
            return str;
250
251
        // do not process a string that has already been processed.
252
        char c = str.charAt(0);
253
        if (((c == LRE) || (c == RLE)) && str.charAt(str.length() - 1) == PDF)
254
            return str;
255
256
        // make sure that LRE/PDF are added around the string
257
        CxpEnv env = new CxpEnv(null, false, CxpEnv.ORIENT_UNKNOWN);
258
        CxpHelper helper = new CxpHelper(type, env);
259
        return helper.leanToFullText(str);
260
    }
261
262
    /**
263
     *  Remove directional formatting characters in the given string that
264
     *  were inserted by one of the {@link #process process} methods.
265
     *
266
     *  @param  str string with directional characters to remove.
267
     *
268
     *  @return string with no directional formatting characters.
269
     */
270
    public static String deprocess(String str) {
271
        if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
272
            return str;
273
274
        StringBuffer buf = new StringBuffer();
275
        int strLen = str.length();
276
        for (int i = 0; i < strLen; i++) {
277
            char c = str.charAt(i);
278
            switch (c) {
279
                case LRM :
280
                    continue;
281
                case LRE :
282
                    continue;
283
                case PDF :
284
                    continue;
285
                default :
286
                    buf.append(c);
287
            }
288
        }
289
        return buf.toString();
290
    }
291
292
    /**
293
     *  Remove directional formatting characters in the given string that
294
     *  were inserted by the {@link #processTyped processTyped} method.
295
     *
296
     *  @param  str string with directional characters to remove.
297
     *
298
     *  @param  type type of the complex expression as specified when
299
     *          calling {@link #processTyped processTyped}.
300
     *
301
     *  @return string with no directional formatting characters.
302
     */
303
    public static String deprocess(String str, String type) {
304
        if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
305
            return str;
306
307
        // make sure that LRE/PDF are added around the string
308
        CxpEnv env = new CxpEnv(null, false, CxpEnv.ORIENT_UNKNOWN);
309
        CxpHelper helper = new CxpHelper(type, env);
310
        return helper.fullToLeanText(str);
311
    }
312
313
}
(-)src/org/eclipse/equinox/bidi/complexp/IBiDiProcessor.java (-106 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
/**
14
 * Bi-directional processors supplied in this bundle.
15
 * 
16
 * @noextend This interface is not intended to be extended by clients.
17
 */
18
public interface IBiDiProcessor {
19
20
	/**
21
	 * Constant indicating a type of complex expression processor adapted
22
	 * to processing property file statements. It expects the following 
23
	 * string format:
24
	 * <pre>
25
	 *  name=value
26
	 * </pre>
27
	 */
28
	public String PROPERTY = "property"; //$NON-NLS-1$
29
30
	/**
31
	 * Constant indicating a type of complex expression processor adapted
32
	 * to processing compound names.
33
	 * This type covers names made of one or more parts separated by underscores:
34
	 * <pre>
35
	 *  part1_part2_part3
36
	 * </pre>
37
	 */
38
	public String UNDERSCORE = "underscore"; //$NON-NLS-1$
39
40
	/**
41
	 * Constant indicating a type of complex expression processor adapted
42
	 * to processing comma-delimited lists, such as:
43
	 * <pre>
44
	 *  part1,part2,part3
45
	 * </pre>
46
	 */
47
	public String COMMA_DELIMITED = "comma"; //$NON-NLS-1$
48
49
	/**
50
	 * Constant indicating a type of complex expression processor adapted
51
	 * to processing expressions with the following string format:
52
	 * <pre>
53
	 *  system(user)
54
	 * </pre>
55
	 */
56
	public String SYSTEM_USER = "system"; //$NON-NLS-1$
57
58
	/**
59
	 * Constant indicating a type of complex expression processor adapted
60
	 * to processing directory and file paths.
61
	 */
62
	public String FILE = "file"; //$NON-NLS-1$
63
64
	/**
65
	 *  Constant indicating a type of complex expression processor adapted
66
	 *  to processing e-mail addresses.
67
	 */
68
	public String EMAIL = "email"; //$NON-NLS-1$
69
70
	/**
71
	 *  Constant indicating a type of complex expression processor adapted
72
	 *  to processing URLs.
73
	 */
74
	public String URL = "url"; //$NON-NLS-1$
75
76
	/**
77
	 *  Constant indicating a type of complex expression processor adapted
78
	 *  to processing regular expressions, possibly spanning more than one
79
	 *  line.
80
	 */
81
	public String REGEXP = "regex"; //$NON-NLS-1$
82
83
	/**
84
	 *  Constant indicating a type of complex expression processor adapted
85
	 *  to processing XPath expressions.
86
	 */
87
	public String XPATH = "xpath"; //$NON-NLS-1$
88
89
	/**
90
	 *  Constant indicating a type of complex expression processor adapted
91
	 *  to processing Java code, possibly spanning more than one line.
92
	 */
93
	public String JAVA = "java"; //$NON-NLS-1$
94
95
	/**
96
	 *  Constant indicating a type of complex expression processor adapted
97
	 *  to processing SQL statements, possibly spanning more than one line.
98
	 */
99
	public String SQL = "sql"; //$NON-NLS-1$
100
101
	/**
102
	 *  Constant indicating a type of complex expression processor adapted
103
	 *  to processing arithmetic expressions with a RTL base direction.
104
	 */
105
	public String RTL_ARITHMETIC = "math"; //$NON-NLS-1$
106
}
(-)src/org/eclipse/equinox/bidi/complexp/ICxpProcessor.java (+149 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
import org.eclipse.equinox.bidi.internal.complexp.CxpDoer;
14
15
/**
16
 *  Interface for all complex expression processors.
17
 *  For guidelines about implementation, see
18
 *  {@link CxpProcessor}.
19
 *
20
 *  @author Matitiahu Allouche
21
 */
22
public interface ICxpProcessor {
23
24
    /**
25
     *  Do whatever initializations are needed and return the
26
     *  {@link CxpFeatures} characterizing the processor.
27
     *
28
     *  @param env the current environment, which may affect the
29
     *          initializations.
30
     *
31
     *  @param ceh <code>CxpHelper</code> instance which called this method.
32
     *          This allows access to the field
33
     *          {@link CxpDoer#procData ceh.ced.procData} where
34
     *          the processor can keep whatever data it needs.
35
     *
36
     *  @return the features in use for this processor.
37
     */
38
    public abstract CxpFeatures init(CxpHelper ceh, CxpEnv env);
39
40
    /**
41
     *  Do whatever renewed initializations are needed after a
42
     *  change in the environment and return the possibly updated
43
     *  {@link CxpFeatures} characterizing the processor.
44
     *
45
     *  @param env the updated environment, which may affect the
46
     *          initializations.
47
     *
48
     *  @param ceh <code>CxpHelper</code> instance which called this method.
49
     *          This allows access to the field
50
     *          {@link CxpDoer#procData ceh.ced.procData} where
51
     *          the processor can keep whatever data it needs.
52
     *
53
     *  @return the features to use for this processor.
54
     */
55
    public CxpFeatures init2(CxpHelper ceh, CxpEnv env);
56
57
    /**
58
     *  Locate occurrences of special strings within a complex expression
59
     *  and return their indexes one after the other in successive calls.
60
     *  <p>
61
     *  This method is called repeatedly from the code implementing
62
     *  {@link CxpHelper#leanToFullText leanToFullText} if the field
63
     *  {@link CxpFeatures#specialsCount specialsCount} returned when
64
     *  {@link #init initializing} the processor is greater than zero.
65
     *  <p>
66
     *  The code implementing this method may use the following methods
67
     *  in {@link CxpHelper}:
68
     *  <ul>
69
     *    <li>{@link CxpHelper#getDirProp getDirProp}</li>
70
     *    <li>{@link CxpHelper#setDirProp setDirProp}</li>
71
     *    <li>{@link CxpHelper#insertMark insertMark}</li>
72
     *    <li>{@link CxpHelper#processOperator processOperator}</li>
73
     *    <li>{@link CxpHelper#setFinalState setFinalState}</li>
74
     *  </ul>
75
     *
76
     *  @param  whichSpecial number of the special case to locate.
77
     *          This number varies from zero to <code>specialsCount - 1</code>.
78
     *          The meaning of this number is internal to the class
79
     *          implementing <code>indexOfSpecial</code>.
80
     *
81
     *  @param  srcText text of the complex expression before addition of any
82
     *          directional formatting characters.
83
     *
84
     *  @param  fromIndex the index within <code>srcText</code> to start
85
     *          the search from.
86
     *
87
     *  @return the position where the start of the special case was located.
88
     *          The method must return the first occurrence of whatever
89
     *          identifies the start of the special case starting from
90
     *          <code>fromIndex</code>. The method does not have to check if
91
     *          this occurrence appears within the scope of another special
92
     *          case (e.g. a comment starting delimiter within the scope of
93
     *          a literal or vice-versa).
94
     *          <br>If no occurrence is found, the method must return -1.
95
     */
96
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex);
97
98
    /**
99
     *  This method is called by {@link CxpHelper#leanToFullText leanToFullText}
100
     *  when a special case occurrence is located by
101
     *  {@link #indexOfSpecial indexOfSpecial}.
102
     *  <p>
103
     *  The code implementing this method may use the following methods
104
     *  in {@link CxpHelper}:
105
     *  <ul>
106
     *    <li>{@link CxpHelper#getDirProp getDirProp}</li>
107
     *    <li>{@link CxpHelper#setDirProp setDirProp}</li>
108
     *    <li>{@link CxpHelper#insertMark insertMark}</li>
109
     *    <li>{@link CxpHelper#processOperator processOperator}</li>
110
     *    <li>{@link CxpHelper#setFinalState setFinalState}</li>
111
     *  </ul>
112
     *  <p>
113
     *  If a special processing cannot be completed within a current call to
114
     *  <code>processSpecial</code> (for instance, a comment has been started
115
     *  in the current line but its end appears in a following line),
116
     *  <code>processSpecial</code> should specify a final state using
117
     *  the method {@link CxpHelper#setFinalState setFinalState}.
118
     *  The meaning of this state is internal to the processor.
119
     *  On a later call to
120
     *  {@link CxpHelper#leanToFullText(String text, int initState)}
121
     *  specifying that state value, <code>processSpecial</code> will be
122
     *  called with that value for parameter <code>whichSpecial</code> and
123
     *  <code>-1</code> for parameter <code>operLocation</code> and should
124
     *  perform whatever initializations are required depending on the state.
125
     *
126
     *  @param  whichSpecial number of the special case to handle.
127
     *
128
     *  @param  srcText text of the complex expression.
129
     *
130
     *  @param  operLocation the position returned by
131
     *          {@link #indexOfSpecial indexOfSpecial}. In calls to
132
     *          {@link CxpHelper#leanToFullText(String text, int initState)} or
133
     *          {@link CxpHelper#fullToLeanText(String text, int initState)}
134
     *          specifying an <code>initState</code>
135
     *          parameter, <code>processSpecial</code> is called when initializing
136
     *          the processing with the value of <code>whichSpecial</code>
137
     *          equal to <code>initState</code> and the value of
138
     *          <code>operLocation</code> equal to <code>-1</code>.
139
     *
140
     *  @return the position after the scope of the special case ends.
141
     *          For instance, the position after the end of a comment,
142
     *          the position after the end of a literal.
143
     *          <br>A value greater or equal to the length of <code>srcText</code>
144
     *          means that there is no further occurrence of this case in the
145
     *          current complex expression.
146
     */
147
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation);
148
149
}
(-)src/org/eclipse/equinox/bidi/complexp/IProcessorTypes.java (+106 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.complexp;
12
13
/**
14
 * Bidirectional processors supplied in this bundle.
15
 *
16
 * @noextend This interface is not intended to be extended by clients.
17
 */
18
public interface IProcessorTypes {
19
20
    /**
21
     * Constant indicating a type of complex expression processor adapted
22
     * to processing property file statements. It expects the following
23
     * string format:
24
     * <pre>
25
     *  name=value
26
     * </pre>
27
     */
28
    public String PROPERTY = "property"; //$NON-NLS-1$
29
30
    /**
31
     * Constant indicating a type of complex expression processor adapted
32
     * to processing compound names.
33
     * This type covers names made of one or more parts separated by underscores:
34
     * <pre>
35
     *  part1_part2_part3
36
     * </pre>
37
     */
38
    public String UNDERSCORE = "underscore"; //$NON-NLS-1$
39
40
    /**
41
     * Constant indicating a type of complex expression processor adapted
42
     * to processing comma-delimited lists, such as:
43
     * <pre>
44
     *  part1,part2,part3
45
     * </pre>
46
     */
47
    public String COMMA_DELIMITED = "comma"; //$NON-NLS-1$
48
49
    /**
50
     * Constant indicating a type of complex expression processor adapted
51
     * to processing expressions with the following string format:
52
     * <pre>
53
     *  system(user)
54
     * </pre>
55
     */
56
    public String SYSTEM_USER = "system"; //$NON-NLS-1$
57
58
    /**
59
     * Constant indicating a type of complex expression processor adapted
60
     * to processing directory and file paths.
61
     */
62
    public String FILE = "file"; //$NON-NLS-1$
63
64
    /**
65
     *  Constant indicating a type of complex expression processor adapted
66
     *  to processing e-mail addresses.
67
     */
68
    public String EMAIL = "email"; //$NON-NLS-1$
69
70
    /**
71
     *  Constant indicating a type of complex expression processor adapted
72
     *  to processing URLs.
73
     */
74
    public String URL = "url"; //$NON-NLS-1$
75
76
    /**
77
     *  Constant indicating a type of complex expression processor adapted
78
     *  to processing regular expressions, possibly spanning more than one
79
     *  line.
80
     */
81
    public String REGEXP = "regex"; //$NON-NLS-1$
82
83
    /**
84
     *  Constant indicating a type of complex expression processor adapted
85
     *  to processing XPath expressions.
86
     */
87
    public String XPATH = "xpath"; //$NON-NLS-1$
88
89
    /**
90
     *  Constant indicating a type of complex expression processor adapted
91
     *  to processing Java code, possibly spanning more than one line.
92
     */
93
    public String JAVA = "java"; //$NON-NLS-1$
94
95
    /**
96
     *  Constant indicating a type of complex expression processor adapted
97
     *  to processing SQL statements, possibly spanning more than one line.
98
     */
99
    public String SQL = "sql"; //$NON-NLS-1$
100
101
    /**
102
     *  Constant indicating a type of complex expression processor adapted
103
     *  to processing arithmetic expressions with a RTL base direction.
104
     */
105
    public String RTL_ARITHMETIC = "math"; //$NON-NLS-1$
106
}
(-)src/org/eclipse/equinox/bidi/complexp/StringProcessor.java (-13 / +22 lines)
Lines 10-31 Link Here
10
 ******************************************************************************/
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.complexp;
11
package org.eclipse.equinox.bidi.complexp;
12
12
13
import org.eclipse.equinox.bidi.internal.complexp.BiDiTypesCollector;
13
import org.eclipse.equinox.bidi.internal.complexp.BidiTypesCollector;
14
14
15
/**
15
/**
16
 * The API part for the TextProcessor replacement.
16
 * This class provides access to registered complex expression processors.
17
 */
17
 */
18
// TBD processors currently are not thread-safe (ComplExpBasic has class variables containing
19
// parsing state). This means that either:
20
// a) a new instance of the processor needs to be created for every call;
21
// b) processors have to be made thread-safe.
22
public class StringProcessor {
18
public class StringProcessor {
19
    /**
20
     *  Retrieve all registered types of complex expression processors.
21
     *
22
     *  @return an array of strings, each string identifying a type of
23
     *  complex expression processor.
24
     */
25
    static public String[] getKnownTypes() {
26
        return BidiTypesCollector.getInstance().getTypes();
27
    }
23
28
24
	static public String[] getKnownTypes() {
29
    /**
25
		return BiDiTypesCollector.getInstance().getTypes();
30
     *  Get access to a complex expression processor of a given type.
26
	}
31
     *
27
32
     *  @param type string identifying a type of processor
28
	static public IComplExpProcessor getProcessor(String type) {
33
     *
29
		return BiDiTypesCollector.getInstance().getProcessor(type);
34
     *  @return a reference to an instance of a processor of the
30
	}
35
     *  required type. If the type is unknown, return <code>null</code>.
36
     */
37
    static public ICxpProcessor getProcessor(String type) {
38
        return BidiTypesCollector.getInstance().getProcessor(type);
39
    }
31
}
40
}
(-)src/org/eclipse/equinox/bidi/complexp/package.html (-53 / +67 lines)
Lines 5-11 Link Here
5
</head>
5
</head>
6
<body bgcolor="white">
6
<body bgcolor="white">
7
7
8
This package provides an interface and implementing classes for
8
This package provides interfaces and classes for
9
processing complex expressions.
9
processing complex expressions.
10
10
11
11
Lines 14-23 Link Here
14
Bidirectional text offers interesting challenges to presentation systems.
14
Bidirectional text offers interesting challenges to presentation systems.
15
For plain text, the Unicode Bidirectional Algorithm
15
For plain text, the Unicode Bidirectional Algorithm
16
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
16
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
17
generally specifies satisfactorily how to reorder Bidirectional text for
17
generally specifies satisfactorily how to reorder bidirectional text for
18
display. This algorithm is implemented in Java's presentation system.</p>
18
display. This algorithm is implemented in Java's presentation system.</p>
19
<p>
19
<p>
20
However, all Bidirectional text is not necessarily plain text. There
20
However, all bidirectional text is not necessarily plain text. There
21
are also instances of text structured to follow a given syntax, which
21
are also instances of text structured to follow a given syntax, which
22
should be reflected in the display order. The general algorithm, which
22
should be reflected in the display order. The general algorithm, which
23
has no awareness of these special cases, often gives incorrect results
23
has no awareness of these special cases, often gives incorrect results
Lines 27-63 Link Here
27
formatting characters at proper locations in the text to supplement the
27
formatting characters at proper locations in the text to supplement the
28
standard algorithm, so that the final result is correctly displayed
28
standard algorithm, so that the final result is correctly displayed
29
using the UBA.
29
using the UBA.
30
A class which handles complex expressions is thus a transformation
30
A class which handles complex expressions is thus essentially a
31
engine which receives text without directional formatting characters
31
transformation engine which receives text without directional formatting
32
as input and produces as output the same text with added directional
32
characters as input and produces as output the same text with added
33
formatting characters, hopefully in the minimum quantity which is
33
directional formatting characters, hopefully in the minimum quantity
34
sufficient to ensure correct display, considering the type of complex
34
which is sufficient to ensure correct display, considering the type of
35
expression involved.</p>
35
complex expression involved.</p>
36
<p>
36
<p>
37
In this package, text without directional formatting characters is
37
In this package, text without directional formatting characters is
38
called <b><i>lean</i></b> text while the text with added directional
38
called <b><i>lean</i></b> text while the text with added directional
39
formatting characters is called <b><i>full</i></b> text.</p>
39
formatting characters is called <b><i>full</i></b> text.</p>
40
<p>
40
<p>
41
{@link <a href="IComplExpProcessor.html">IComplExpProcessor</a>} provides
41
The class {@link <a href="CxpHelper.html"><b>CxpHelper</b></a>} is the main
42
an interface for processing complex expressions.  This package also
42
tool for processing complex expressions. It facilitates
43
includes several classes which implement <code>IComplExpProcessor</code>,
43
handling several types of complex expressions, each type
44
all of them based on class
44
being handled by a specific
45
{@link <a href="ComplExpBasic.html">ComplExpBasic</a>}.
45
{@link <a href="ICxpProcessor.html"><b><i>processor</i></b></a>} :</p>
46
<p>
47
There is also a class named
48
<code>ComplExpDoNothing</code> which actually adds no directional
49
formatting characters. It can be considered as a null processor in
50
relation to complex expressions. This class has a very small overhead and
51
can be used as a low-cost default processor when no complex expression is
52
involved and no processing is needed, but a general framework of
53
handling complex expressions must be preserved.</p>
54
<p>
55
The class {@link <a href="ComplExpBasic.html">ComplExpBasic</a>} can
56
handle several types of relatively simple complex expressions.</p>
57
<p>
58
A number of subclasses of <code>ComplExpBasic</code> are included in this
59
package, each one adapted to handle some type of complex expression.
60
The explicitly supported types are:
61
<ul>
46
<ul>
62
  <li>property (name=value)</li>
47
  <li>property (name=value)</li>
63
  <li>compound name (xxx_yy_zzzz)</li>
48
  <li>compound name (xxx_yy_zzzz)</li>
Lines 73-92 Link Here
73
  <li>RTL arithmetic expressions</li>
58
  <li>RTL arithmetic expressions</li>
74
</ul>
59
</ul>
75
<p>
60
<p>
76
More types can be supported using the classes provided in the package.
61
Other classes and one interface in this package may be used to
77
It is also possible to develop new classes to handle types of
62
complement and facilitate the action of
78
complex expressions which cannot be supported with the existing classes.
63
{@link <a href="CxpHelper.html">CxpHelper</a>}:
79
Using the framework provided by <code>IComplExpProcessor</code> and
64
<ul>
80
<code>ComplExpBasic</code> can facilitate
65
  <li>{@link <a href="CxpEnv.html">CxpEnv</a>} which regroups
81
considerably the development of such new support.</p>
66
      details about the environment</li>
82
<p>
67
  <li>{@link <a href="CxpFeatures.html">CxpFeatures</a>} which allows viewing
83
The class {@link <a href="ComplExpUtil.html">ComplExpUtil</a>} provides
68
      and manipulating some factors which affect
84
a number of convenience methods to process some common types of
69
      a complex expression processor's behavior</li>
85
complex expressions. When using methods in this class, there is no need
70
  <li>{@link <a href="CxpUtil.html">CxpUtil</a>} provides a number of
86
to refer to members of other classes of this package.
71
      convenience methods to process some common types of complex expressions.
87
However, the other classes allow more precise control and possibly better
72
      When using methods in this class, there is no need to use
88
performance.</p>
73
      other classes of this package.  However, the other classes allow more
74
      precise control and possibly better performance.</li>
75
  <li>{@link <a href="IProcessorTypes.html">IProcessorTypes</a>} is an
76
      interface which contains only literals identifying the various types
77
      of complex expressions currently supported.</li>
78
</ul>
79
<p>
80
{@link <a href="CxpHelper.html">CxpHelper</a>} and the other classes and
81
interface mentioned above are intended for users who need to process
82
complex expressions for which there already exist processors.
83
<p>
84
Developers who want to develop new processors to support types of complex
85
expressions not currently supported can use the following components of the
86
present package:
87
<ul>
88
  <li>{@link <a href="ICxpProcessor.html">ICxpProcessor</a>} is an interface
89
      specifying which methods a processor must provide.</li>
90
  <li>{@link <a href="CxpProcessor.html">CxpProcessor</a>} is a generic
91
      processor which can be used as superclass for specific processors.
92
  <li>{@link <a href="StringProcessor.html">StringProcessor</a>} is a class
93
      which allows retrieval of the defined processor types and of the
94
      corresponding processors.
95
</ul>
89
<p>
96
<p>
97
There are two other packages associated with the current one:
98
<ul>
99
  <li>{@link <a href="..\internal\complexp\package-summary.html">
100
      org.eclipse.equinox.bidi.internal.complexp</a>}</li>
101
  <li>{@link <a href="..\internal\complexp\consumable\package-summary.html">
102
       org.eclipse.equinox.bidi.internal.complexp.consumable</a>}</li>
103
</ul>
104
The tools in the first package can serve as example of how to develop
105
processors for currently unsupported types of complex expressions.<br>
106
The latter package contains classes for the processors implementing
107
the currently supported types of complex expressions.
108
<p>
109
However, users wishing to process the currently supported types of
110
complex expressions typically don't need to interact with these
111
two packages.
90
112
91
<p>&nbsp;</p>
113
<p>&nbsp;</p>
92
114
Lines 121-135 Link Here
121
<h2>Known Limitations</h2>
143
<h2>Known Limitations</h2>
122
144
123
<p>The proposed solution is making extensive usage of LRM, RLM, LRE, RLE
145
<p>The proposed solution is making extensive usage of LRM, RLM, LRE, RLE
124
and PDF directional controls which are invisible but affect the way Bidi
146
and PDF directional controls which are invisible but affect the way bidi
125
text is displayed. The following related two key points merit special
147
text is displayed. The following related key points merit special
126
attention:</p>
148
attention:</p>
127
149
128
<ul>
150
<ul>
129
<li>Implementations of the UBA on various platforms (e.g., Windows and
151
<li>Implementations of the UBA on various platforms (e.g., Windows and
130
Linux) are very similar but nevertheless have known differences. Those
152
Linux) are very similar but nevertheless have known differences. Those
131
differences are minor and will not have a visible effect in most cases.
153
differences are minor and will not have a visible effect in most cases.
132
However there might be cases in which the same Bidi text on two
154
However there might be cases in which the same bidi text on two
133
platforms might look different. These differences will surface in Java
155
platforms might look different. These differences will surface in Java
134
applications when they use the platform visual components for their UI
156
applications when they use the platform visual components for their UI
135
(e.g., AWT, SWT).</li>
157
(e.g., AWT, SWT).</li>
Lines 146-158 Link Here
146
achieve the desired presentation.</li>
168
achieve the desired presentation.</li>
147
</ul>
169
</ul>
148
170
149
<p>&nbsp;</p>
150
151
<h2>References</h2>
152
153
@see <a href="IComplExpProcessor.html">IComplExpProcessor</a>
154
@see <a href="ComplExpBasic.html">ComplExpBasic</a>
155
@see <a href="ComplExpDoNothing.html">ComplExpDoNothing</a>
156
157
</body>
171
</body>
158
</html>
172
</html>
(-)src/org/eclipse/equinox/bidi/internal/complexp/BiDiActivator.java (-62 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.osgi.framework.log.FrameworkLog;
14
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
15
import org.osgi.framework.BundleActivator;
16
import org.osgi.framework.BundleContext;
17
import org.osgi.util.tracker.ServiceTracker;
18
19
public class BiDiActivator implements BundleActivator {
20
21
	private ServiceTracker logTracker = null;
22
	private BundleContext bundleContext;
23
24
	private static BiDiActivator instance;
25
26
	public BiDiActivator() {
27
		instance = this; // there is only one bundle activator
28
	}
29
30
	public void start(BundleContext context) throws Exception {
31
		bundleContext = context;
32
		instance = this;
33
	}
34
35
	public void stop(BundleContext context) throws Exception {
36
		if (logTracker != null) {
37
			logTracker.close();
38
			logTracker = null;
39
		}
40
		bundleContext = null;
41
	}
42
43
	private FrameworkLog getFrameworkLog() {
44
		if (logTracker == null) {
45
			logTracker = new ServiceTracker(bundleContext, FrameworkLog.class.getName(), null);
46
			logTracker.open();
47
		}
48
		return (FrameworkLog) logTracker.getService();
49
	}
50
51
	static public void logError(String message, Exception e) {
52
		FrameworkLog frameworkLog = instance.getFrameworkLog();
53
		if (frameworkLog != null) {
54
			frameworkLog.log(new FrameworkLogEntry("org.eclipse.equinox.bidi", FrameworkLogEntry.ERROR, 1, message, 0, e, null)); //$NON-NLS-1$
55
			return;
56
		}
57
		System.err.println(message);
58
		if (e != null)
59
			e.printStackTrace();
60
	}
61
62
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/BiDiTypesCollector.java (-129 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import java.util.HashMap;
14
import java.util.Map;
15
import org.eclipse.core.runtime.*;
16
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
17
18
public class BiDiTypesCollector implements IRegistryEventListener {
19
20
	private static final String EXT_POINT = "org.eclipse.equinox.bidi.bidiTypes"; //$NON-NLS-1$
21
22
	private static final String CE_NAME = "typeDescription"; //$NON-NLS-1$
23
	private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
24
	private static final String ATTR_PROCESSOR = "class"; //$NON-NLS-1$
25
26
	private Map types;
27
	private Map factories;
28
29
	static private BiDiTypesCollector instance = new BiDiTypesCollector();
30
31
	private BiDiTypesCollector() {
32
		IExtensionRegistry registry = RegistryFactory.getRegistry();
33
		registry.addListener(this, EXT_POINT);
34
	}
35
36
	static public BiDiTypesCollector getInstance() {
37
		return instance;
38
	}
39
40
	public String[] getTypes() {
41
		if (types == null)
42
			read();
43
		int size = types.size();
44
		String[] result = new String[size];
45
		types.keySet().toArray(result);
46
		return result;
47
	}
48
49
	public IComplExpProcessor getProcessor(String type) {
50
		if (types == null)
51
			read();
52
		Object processor = types.get(type);
53
		if (processor instanceof IComplExpProcessor)
54
			return (IComplExpProcessor) processor;
55
		return null;
56
	}
57
58
	public IComplExpProcessor makeProcessor(String type) {
59
		if (factories == null)
60
			read();
61
		IConfigurationElement ce = (IConfigurationElement) factories.get(type);
62
		if (ce == null)
63
			return null;
64
		Object processor;
65
		try {
66
			processor = ce.createExecutableExtension(ATTR_PROCESSOR);
67
		} catch (CoreException e) {
68
			BiDiActivator.logError("BiDi types: unable to create processor for " + type, e); //$NON-NLS-1$
69
			return null;
70
		}
71
		if (processor instanceof IComplExpProcessor)
72
			return (IComplExpProcessor) processor;
73
		return null;
74
	}
75
76
	private void read() {
77
		if (types == null)
78
			types = new HashMap();
79
		else
80
			types.clear();
81
82
		if (factories == null)
83
			factories = new HashMap();
84
		else
85
			factories.clear();
86
87
		IExtensionRegistry registry = RegistryFactory.getRegistry();
88
		IExtensionPoint extPoint = registry.getExtensionPoint(EXT_POINT);
89
		IExtension[] extensions = extPoint.getExtensions();
90
91
		for (int i = 0; i < extensions.length; i++) {
92
			IConfigurationElement[] confElements = extensions[i].getConfigurationElements();
93
			for (int j = 0; j < confElements.length; j++) {
94
				if (CE_NAME != confElements[j].getName())
95
					BiDiActivator.logError("BiDi types: unexpected element name " + confElements[j].getName(), new IllegalArgumentException()); //$NON-NLS-1$
96
				String type = confElements[j].getAttribute(ATTR_TYPE);
97
				Object processor;
98
				try {
99
					processor = confElements[j].createExecutableExtension(ATTR_PROCESSOR);
100
				} catch (CoreException e) {
101
					BiDiActivator.logError("BiDi types: unable to create processor for " + type, e); //$NON-NLS-1$
102
					continue;
103
				}
104
				types.put(type, processor);
105
				factories.put(type, confElements[j]);
106
			}
107
		}
108
	}
109
110
	public void added(IExtension[] extensions) {
111
		types = null;
112
		factories = null;
113
	}
114
115
	public void removed(IExtension[] extensions) {
116
		types = null;
117
		factories = null;
118
	}
119
120
	public void added(IExtensionPoint[] extensionPoints) {
121
		types = null;
122
		factories = null;
123
	}
124
125
	public void removed(IExtensionPoint[] extensionPoints) {
126
		types = null;
127
		factories = null;
128
	}
129
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/BidiActivator.java (+62 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.osgi.framework.log.FrameworkLog;
14
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
15
import org.osgi.framework.BundleActivator;
16
import org.osgi.framework.BundleContext;
17
import org.osgi.util.tracker.ServiceTracker;
18
19
public class BidiActivator implements BundleActivator {
20
21
	private ServiceTracker logTracker = null;
22
	private BundleContext bundleContext;
23
24
	private static BidiActivator instance;
25
26
	public BidiActivator() {
27
		instance = this; // there is only one bundle activator
28
	}
29
30
	public void start(BundleContext context) throws Exception {
31
		bundleContext = context;
32
		instance = this;
33
	}
34
35
	public void stop(BundleContext context) throws Exception {
36
		if (logTracker != null) {
37
			logTracker.close();
38
			logTracker = null;
39
		}
40
		bundleContext = null;
41
	}
42
43
	private FrameworkLog getFrameworkLog() {
44
		if (logTracker == null) {
45
			logTracker = new ServiceTracker(bundleContext, FrameworkLog.class.getName(), null);
46
			logTracker.open();
47
		}
48
		return (FrameworkLog) logTracker.getService();
49
	}
50
51
	static public void logError(String message, Exception e) {
52
		FrameworkLog frameworkLog = instance.getFrameworkLog();
53
		if (frameworkLog != null) {
54
			frameworkLog.log(new FrameworkLogEntry("org.eclipse.equinox.bidi", FrameworkLogEntry.ERROR, 1, message, 0, e, null)); //$NON-NLS-1$
55
			return;
56
		}
57
		System.err.println(message);
58
		if (e != null)
59
			e.printStackTrace();
60
	}
61
62
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/BidiTypesCollector.java (+111 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import java.util.HashMap;
14
import java.util.Map;
15
import org.eclipse.core.runtime.*;
16
import org.eclipse.equinox.bidi.complexp.ICxpProcessor;
17
18
public class BidiTypesCollector implements IRegistryEventListener {
19
20
	private static final String EXT_POINT = "org.eclipse.equinox.bidi.bidiTypes"; //$NON-NLS-1$
21
22
	private static final String CE_NAME = "typeDescription"; //$NON-NLS-1$
23
	private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
24
	private static final String ATTR_PROCESSOR = "class"; //$NON-NLS-1$
25
26
	private Map types;
27
	private Map factories;
28
29
	static private BidiTypesCollector instance = new BidiTypesCollector();
30
31
	private BidiTypesCollector() {
32
		IExtensionRegistry registry = RegistryFactory.getRegistry();
33
		registry.addListener(this, EXT_POINT);
34
	}
35
36
	static public BidiTypesCollector getInstance() {
37
		return instance;
38
	}
39
40
	public String[] getTypes() {
41
		if (types == null)
42
			read();
43
		int size = types.size();
44
		String[] result = new String[size];
45
		types.keySet().toArray(result);
46
		return result;
47
	}
48
49
	public ICxpProcessor getProcessor(String type) {
50
		if (types == null)
51
			read();
52
		Object processor = types.get(type);
53
		if (processor instanceof ICxpProcessor)
54
			return (ICxpProcessor) processor;
55
		return null;
56
	}
57
58
	private void read() {
59
		if (types == null)
60
			types = new HashMap();
61
		else
62
			types.clear();
63
64
		if (factories == null)
65
			factories = new HashMap();
66
		else
67
			factories.clear();
68
69
		IExtensionRegistry registry = RegistryFactory.getRegistry();
70
		IExtensionPoint extPoint = registry.getExtensionPoint(EXT_POINT);
71
		IExtension[] extensions = extPoint.getExtensions();
72
73
		for (int i = 0; i < extensions.length; i++) {
74
			IConfigurationElement[] confElements = extensions[i].getConfigurationElements();
75
			for (int j = 0; j < confElements.length; j++) {
76
				if (CE_NAME != confElements[j].getName())
77
					BidiActivator.logError("BiDi types: unexpected element name " + confElements[j].getName(), new IllegalArgumentException()); //$NON-NLS-1$
78
				String type = confElements[j].getAttribute(ATTR_TYPE);
79
				Object processor;
80
				try {
81
					processor = confElements[j].createExecutableExtension(ATTR_PROCESSOR);
82
				} catch (CoreException e) {
83
					BidiActivator.logError("BiDi types: unable to create processor for " + type, e); //$NON-NLS-1$
84
					continue;
85
				}
86
				types.put(type, processor);
87
				factories.put(type, confElements[j]);
88
			}
89
		}
90
	}
91
92
	public void added(IExtension[] extensions) {
93
		types = null;
94
		factories = null;
95
	}
96
97
	public void removed(IExtension[] extensions) {
98
		types = null;
99
		factories = null;
100
	}
101
102
	public void added(IExtensionPoint[] extensionPoints) {
103
		types = null;
104
		factories = null;
105
	}
106
107
	public void removed(IExtensionPoint[] extensionPoints) {
108
		types = null;
109
		factories = null;
110
	}
111
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java (-75 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
15
/**
16
 *  <code>ComplExpDelims</code> is a processor for complex expressions
17
 *  composed of text segments separated by operators where the text segments
18
 *  may include delimited parts within which operators are treated like
19
 *  regular characters.
20
 *
21
 *  @see IComplExpProcessor
22
 *  @see ComplExpBasic
23
 *
24
 *  @author Matitiahu Allouche
25
 */
26
public class ComplExpDelims extends ComplExpBasic {
27
	char[] delims;
28
29
	/**
30
	 *  Constructor for a complex expressions processor with support for
31
	 *  operators and delimiters.
32
	 *
33
	 *  @param operators string grouping one-character operators which
34
	 *         separate the text of the complex expression into segments.
35
	 *
36
	 *  @param delims delimiters implemented in this class instance.
37
	 *         This parameter is a string which must include an even
38
	 *         number of characters. The first 2 characters of a string
39
	 *         constitute a pair, the next 2 characters are a second pair, etc...
40
	 *         In each pair, the first character is a start delimiter and
41
	 *         the second character is an end delimiter. In the <i>lean</i>
42
	 *         text, any part starting with a start delimiter and ending with
43
	 *         the corresponding end delimiter is a delimited part. Within a
44
	 *         delimited part, operators are treated like regular characters,
45
	 *         which means that they do not define new segments.
46
	 */
47
	public ComplExpDelims(String operators, String delims) {
48
		super(operators, delims.length() / 2);
49
		this.delims = delims.toCharArray();
50
	}
51
52
	/**
53
	 *  This method is not supposed to be invoked directly by users of this
54
	 *  class. It may  be overridden by subclasses of this class.
55
	 */
56
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
57
		char delim = delims[whichSpecial * 2];
58
59
		return srcText.indexOf(delim, fromIndex);
60
	}
61
62
	/**
63
	 *  This method is not supposed to be invoked directly by users of this
64
	 *  class. It may  be overridden by subclasses of this class.
65
	 */
66
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
67
		processOperator(operLocation);
68
		int loc = operLocation + 1;
69
		char delim = delims[(whichSpecial * 2) + 1];
70
		loc = srcText.indexOf(delim, loc);
71
		if (loc < 0)
72
			return srcText.length();
73
		return loc + 1;
74
	}
75
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java (-82 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
15
/**
16
 *  <code>ComplExpDelims</code> is a processor for complex expressions
17
 *  composed of text segments separated by operators where the text segments
18
 *  may include delimited parts within which operators are treated like
19
 *  regular characters and the delimiters may be escaped.
20
 *  This is similar to {@link ComplExpDelims} except
21
 *  that delimiters can be escaped using the backslash character.
22
 *  <ul>
23
 *    <li>Two consecutive backslashes in a delimited part are treated like
24
 *        regular characters.</li>
25
 *    <li>An ending delimiter preceded by an odd number of backslashes is
26
 *        treated like a regular character of a delimited part.</li>
27
 *  </ul>
28
 *
29
 *  @see IComplExpProcessor
30
 *  @see ComplExpBasic
31
 *
32
 *  @author Matitiahu Allouche
33
 */
34
public class ComplExpDelimsEsc extends ComplExpDelims {
35
	/**
36
	 *  Constructor for a complex expressions processor with support for
37
	 *  operators and delimiters which can be escaped.
38
	 *
39
	 *  @param operators string grouping one-character operators which
40
	 *         separate the text of the complex expression into segments.
41
	 *
42
	 *  @param delims delimiters implemented in this class instance.
43
	 *         This parameter is a string which must include an even
44
	 *         number of characters. The first 2 characters of a string
45
	 *         constitute a pair, the next 2 characters are a second pair, etc...
46
	 *         In each pair, the first character is a start delimiter and
47
	 *         the second character is an end delimiter. In the <i>lean</i>
48
	 *         text, any part starting with a start delimiter and ending with
49
	 *         the corresponding end delimiter is a delimited part. Within a
50
	 *         delimited part, operators are treated like regular characters,
51
	 *         which means that they do not define new segments.<br>
52
	 *         &nbsp;<br>
53
	 *         Note however that an ending delimiter preceded by an odd
54
	 *         number of backslashes is considered as a regular character
55
	 *         and does not mark the termination of a delimited part.
56
	 */
57
	public ComplExpDelimsEsc(String operators, String delims) {
58
		super(operators, delims);
59
	}
60
61
	/**
62
	 *  This method is not supposed to be invoked directly by users of this
63
	 *  class. It may  be overridden by subclasses of this class.
64
	 */
65
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
66
		processOperator(operLocation);
67
		int loc = operLocation + 1;
68
		char delim = delims[(whichSpecial * 2) + 1];
69
		while (true) {
70
			loc = srcText.indexOf(delim, loc);
71
			if (loc < 0)
72
				return srcText.length();
73
			int cnt = 0;
74
			for (int i = loc - 1; srcText.charAt(i) == '\\'; i--) {
75
				cnt++;
76
			}
77
			loc++;
78
			if ((cnt & 1) == 0)
79
				return loc;
80
		}
81
	}
82
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java (-65 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
15
/**
16
 *  <code>ComplExpSingle</code> is a processor for complex expressions
17
 *  composed of two parts separated by an operator.
18
 *  The first occurrence of the operator delimits the end of the first part
19
 *  and the start of the second part. Further occurrences of the operator,
20
 *  if any, are treated like regular characters of the second text part.
21
 *  The processor makes sure that the expression be presented in the form
22
 *  (assuming that the equal sign is the operator):
23
 *  <pre>
24
 *  part1=part2
25
 *  </pre>
26
 *
27
 *  @see IComplExpProcessor
28
 *  @see ComplExpBasic
29
 *
30
 *  @author Matitiahu Allouche
31
 */
32
public class ComplExpSingle extends ComplExpBasic {
33
	char separator;
34
35
	/**
36
	 *  Constructor for a complex expressions processor with support for one
37
	 *  operator.
38
	 *
39
	 *  @param operators string including at least one character. The
40
	 *         first character of the string is the operator which divides
41
	 *         the expression into 2 parts.
42
	 *
43
	 */
44
	public ComplExpSingle(String operators) {
45
		super(operators, 1);
46
		separator = operators.charAt(0);
47
	}
48
49
	/**
50
	 *  This method is not supposed to be invoked directly by users of this
51
	 *  class. It may  be overridden by subclasses of this class.
52
	 */
53
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
54
		return srcText.indexOf(separator, fromIndex);
55
	}
56
57
	/**
58
	 *  This method is not supposed to be invoked directly by users of this
59
	 *  class. It may  be overridden by subclasses of this class.
60
	 */
61
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
62
		processOperator(operLocation);
63
		return srcText.length();
64
	}
65
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/CxpDelims.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.CxpHelper;
14
import org.eclipse.equinox.bidi.complexp.CxpProcessor;
15
16
/**
17
 *  <code>CxpDelims</code> is a processor for complex expressions
18
 *  composed of text segments separated by operators where the text segments
19
 *  may include delimited parts within which operators are treated like
20
 *  regular characters.
21
 *
22
 *  @author Matitiahu Allouche
23
 */
24
public abstract class CxpDelims extends CxpProcessor {
25
26
    /**
27
     *  This method locates occurrences of start delimiters.
28
     */
29
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
30
        char delim = getDelimiters().charAt(whichSpecial * 2);
31
        return srcText.indexOf(delim, fromIndex);
32
    }
33
34
    /**
35
     *  This method skips until after the matching end delimiter.
36
     */
37
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
38
        ceh.processOperator(operLocation);
39
        int loc = operLocation + 1;
40
        char delim = getDelimiters().charAt((whichSpecial * 2) + 1);
41
        loc = srcText.indexOf(delim, loc);
42
        if (loc < 0)
43
            return srcText.length();
44
        return loc + 1;
45
    }
46
47
    /**
48
     *  @return a string containing the delimiters implemented in this class
49
     *         instance. This string must include an even
50
     *         number of characters. The first 2 characters of a string
51
     *         constitute a pair, the next 2 characters are a second pair, etc...
52
     *         In each pair, the first character is a start delimiter and
53
     *         the second character is an end delimiter. In the <i>lean</i>
54
     *         text, any part starting with a start delimiter and ending with
55
     *         the corresponding end delimiter is a delimited part. Within a
56
     *         delimited part, operators are treated like regular characters,
57
     *         which means that they do not define new segments.
58
     */
59
    protected abstract String getDelimiters();
60
61
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/CxpDelimsEsc.java (+55 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.CxpHelper;
14
15
/**
16
 *  <code>CxpDelims</code> is a processor for complex expressions
17
 *  composed of text segments separated by operators where the text segments
18
 *  may include delimited parts within which operators are treated like
19
 *  regular characters and the delimiters may be escaped.
20
 *  This is similar to {@link CxpDelims} except
21
 *  that delimiters can be escaped using the backslash character.
22
 *  <ul>
23
 *    <li>Two consecutive backslashes in a delimited part are treated like
24
 *        one regular characters.</li>
25
 *    <li>An ending delimiter preceded by an odd number of backslashes is
26
 *        treated like a regular character of a delimited part.</li>
27
 *  </ul>
28
 *
29
 *  @author Matitiahu Allouche
30
 */
31
public abstract class CxpDelimsEsc extends CxpDelims {
32
33
     /**
34
     *  This method skips until after the matching end delimiter,
35
     *  ignoring possibly escaped end delimiters.
36
     */
37
   public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
38
        ceh.processOperator(operLocation);
39
        int loc = operLocation + 1;
40
        char delim = getDelimiters().charAt((whichSpecial * 2) + 1);
41
        while (true) {
42
            loc = srcText.indexOf(delim, loc);
43
            if (loc < 0)
44
                return srcText.length();
45
            int cnt = 0;
46
            for (int i = loc - 1; srcText.charAt(i) == '\\'; i--) {
47
                cnt++;
48
            }
49
            loc++;
50
            if ((cnt & 1) == 0)
51
                return loc;
52
        }
53
    }
54
55
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/CxpDoer.java (+712 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 *  <code>CxpDoer</code> provides the code which implements the API in
17
 *  {@link CxpHelper}. All its public methods are shadows of similarly
18
 *  signed methods of <code>CxpHelper</code>, and their documentation
19
 *  is by reference to the methods in <code>CxpHelper</code>.
20
 *
21
 *  @author Matitiahu Allouche
22
 */
23
public class CxpDoer {
24
25
    static final String EMPTY_STRING = ""; //$NON-NLS-1$
26
    static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
27
    static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
28
    static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
29
    static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
30
    static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
31
    static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
32
    static final char LRM = 0x200E;
33
    static final char RLM = 0x200F;
34
    static final char LRE = 0x202A;
35
    static final char RLE = 0x202B;
36
    static final char PDF = 0x202C;
37
    static final char[] MARKS = {LRM, RLM};
38
    static final char[] EMBEDS = {LRE, RLE};
39
    static final byte[] STRONGS = {L, R};
40
    static final int PREFIX_LENGTH = 2;
41
    static final int SUFFIX_LENGTH = 2;
42
    static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
43
44
    CxpHelper ceh;
45
46
    CxpEnv env;
47
48
    ICxpProcessor proc;
49
50
    /**
51
     *  This field is reserved for use of the complex expression
52
     *  processor associated with this instance of <code>CxpDoer</code>.
53
     *  The processor can keep here a reference to an object that it
54
     *  has sole control of.
55
     */
56
    public Object procData;
57
58
    /**
59
     *  Features of the associated processor.
60
     *
61
     */
62
    public CxpFeatures cef;
63
64
    int state = CxpHelper.STATE_NOTHING_GOING;
65
66
    byte curStrong = -1;
67
    char curMark;
68
    char curEmbed;
69
    int prefixLength;
70
    int[] locations;
71
    int specialsCount;
72
    String leanText;
73
    int[] offsets;
74
    int count;
75
    // For positions where it has been looked up, the entry will receive
76
    // the Character directionality + 2 (so that 0 indicates that the
77
    // the directionality has not been looked up yet.
78
    byte[] dirProps;
79
    // current UI orientation (after resolution if contextual)
80
    int curOrient = -1;
81
    // Current expression base direction (after resolution if depending on
82
    // script and/or on GUI mirroring (0=LTR, 1=RTL))
83
    int curDirection = -1;
84
85
    /**
86
     *  @see CxpHelper#CxpHelper(ICxpProcessor proc, CxpEnv env)
87
     */
88
    public CxpDoer(CxpHelper caller, ICxpProcessor proc, CxpEnv env) {
89
        ceh = caller;
90
        if (env == null) {
91
            this.env = CxpEnv.DEFAULT;
92
        } else {
93
            this.env = env;
94
        }
95
        this.proc = proc;
96
        cef = proc.init(ceh, this.env);
97
        // keep private copy of specialsCount to avoid later modification
98
        specialsCount = cef.specialsCount;
99
        locations = new int[cef.operators.length() + specialsCount];
100
    }
101
102
    long computeNextLocation(int curPos) {
103
        int operCount = cef.operators.length();
104
        int len = leanText.length();
105
        int nextLocation = len;
106
        int idxLocation = 0;
107
        // Start with special sequences to give them precedence over simple
108
        // operators. This may apply to cases like slash+asterisk versus slash.
109
        for (int i = 0; i < specialsCount; i++) {
110
            int loc = locations[operCount + i];
111
            if (loc < curPos) {
112
                loc = proc.indexOfSpecial(ceh, i, leanText, curPos);
113
                if (loc < 0)
114
                    loc = len;
115
                locations[operCount + i] = loc;
116
            }
117
            if (loc < nextLocation) {
118
                nextLocation = loc;
119
                idxLocation = operCount + i;
120
            }
121
        }
122
        for (int i = 0; i < operCount; i++) {
123
            int loc = locations[i];
124
            if (loc < curPos) {
125
                loc = leanText.indexOf(cef.operators.charAt(i), curPos);
126
                if (loc < 0)
127
                    loc = len;
128
                locations[i] = loc;
129
            }
130
            if (loc < nextLocation) {
131
                nextLocation = loc;
132
                idxLocation = i;
133
            }
134
        }
135
        return nextLocation + (((long) idxLocation) << 32);
136
    }
137
138
    int getCurOrient() {
139
        if (curOrient >= 0)
140
            return curOrient;
141
142
        if ((env.orientation & CxpEnv.ORIENT_CONTEXTUAL_LTR) == 0) {
143
            // absolute orientation
144
            curOrient = env.orientation;
145
            return curOrient;
146
        }
147
        // contextual orientation
148
        int len = leanText.length();
149
        byte dirProp;
150
        for (int i = 0; i < len; i++) {
151
            dirProp = dirProps[i];
152
            if (dirProp == 0) {
153
                dirProp = Character.getDirectionality(leanText.charAt(i));
154
                if (dirProp == B) // B char resolves to L or R depending on orientation
155
                    continue;
156
                dirProps[i] = (byte) (dirProp + 2);
157
            } else {
158
                dirProp -= 2;
159
            }
160
            if (dirProp == L) {
161
                curOrient = CxpEnv.ORIENT_LTR;
162
                return curOrient;
163
            }
164
            if (dirProp == R || dirProp == AL) {
165
                curOrient = CxpEnv.ORIENT_RTL;
166
                return curOrient;
167
            }
168
        }
169
        curOrient = env.orientation & 1;
170
        return curOrient;
171
    }
172
173
    /**
174
     *  @see CxpHelper#getCurDirection
175
     */
176
    public int getCurDirection() {
177
        if (curDirection >= 0)
178
            return curDirection;
179
180
        curStrong = -1;
181
        // same direction for Arabic and Hebrew?
182
        if (cef.dirArabic == cef.dirHebrew) {
183
            curDirection = cef.dirArabic;
184
            return curDirection;
185
        }
186
        // check if Arabic or Hebrew letter comes first
187
        int len = leanText.length();
188
        byte dirProp;
189
        for (int i = 0; i < len; i++) {
190
            dirProp = getDirProp(i);
191
            if (dirProp == AL) {
192
                curDirection = cef.dirArabic;
193
                return curDirection;
194
            }
195
            if (dirProp == R) {
196
                curDirection = cef.dirHebrew;
197
                return curDirection;
198
            }
199
        }
200
        // found no Arabic or Hebrew character
201
        curDirection = CxpFeatures.DIR_LTR;
202
        return curDirection;
203
    }
204
205
    void setMarkAndFixes() {
206
        int dir = getCurDirection();
207
        if (curStrong == STRONGS[dir])
208
            return;
209
        curStrong = STRONGS[dir];
210
        curMark = MARKS[dir];
211
        curEmbed = EMBEDS[dir];
212
    }
213
214
    /**
215
     *  @see CxpHelper#getDirProp(int index)
216
     */
217
    public byte getDirProp(int index) {
218
        byte dirProp = dirProps[index];
219
        if (dirProp == 0) {
220
            dirProp = Character.getDirectionality(leanText.charAt(index));
221
            if (dirProp == B)
222
                dirProp = getCurOrient() == CxpEnv.ORIENT_RTL ? R : L;
223
            dirProps[index] = (byte) (dirProp + 2);
224
            return dirProp;
225
        }
226
        return (byte) (dirProp - 2);
227
    }
228
229
    /**
230
     *  @see CxpHelper#setDirProp(int index, byte dirProp)
231
     */
232
    public void setDirProp(int index, byte dirProp) {
233
        dirProps[index] = (byte) (dirProp + 2);
234
    }
235
236
    /**
237
     *  @see CxpHelper#processOperator(int operLocation)
238
     */
239
    public void processOperator(int operLocation) {
240
        int len = leanText.length();
241
        boolean doneAN = false;
242
243
        if (getCurDirection() == CxpFeatures.DIR_RTL) {
244
            // the expression base direction is RTL
245
            for (int i = operLocation - 1; i >= 0; i--) {
246
                byte dirProp = getDirProp(i);
247
                if (dirProp == R || dirProp == AL)
248
                    return;
249
250
                if (dirProp == L) {
251
                    for (int j = operLocation; j < len; j++) {
252
                        dirProp = getDirProp(j);
253
                        if (dirProp == R || dirProp == AL)
254
                            return;
255
                        if (dirProp == L || dirProp == EN) {
256
                            insertMark(operLocation);
257
                            return;
258
                        }
259
                    }
260
                    return;
261
                }
262
            }
263
            return;
264
        }
265
266
        // the expression base direction is LTR
267
        if (cef.ignoreArabic) {
268
            if (cef.ignoreHebrew) /* process neither Arabic nor Hebrew */
269
                return;
270
            /* process Hebrew, not Arabic */
271
            for (int i = operLocation - 1; i >= 0; i--) {
272
                byte dirProp = getDirProp(i);
273
                if (dirProp == L)
274
                    return;
275
                if (dirProp == R) {
276
                    for (int j = operLocation; j < len; j++) {
277
                        dirProp = getDirProp(j);
278
                        if (dirProp == L)
279
                            return;
280
                        if (dirProp == R || dirProp == EN) {
281
                            insertMark(operLocation);
282
                            return;
283
                        }
284
                    }
285
                    return;
286
                }
287
            }
288
        } else {
289
            if (cef.ignoreHebrew) { /* process Arabic, not Hebrew */
290
                for (int i = operLocation - 1; i >= 0; i--) {
291
                    byte dirProp = getDirProp(i);
292
                    if (dirProp == L)
293
                        return;
294
                    if (dirProp == AL) {
295
                        for (int j = operLocation; j < len; j++) {
296
                            dirProp = getDirProp(j);
297
                            if (dirProp == L)
298
                                return;
299
                            if (dirProp == EN || dirProp == AL || dirProp == AN) {
300
                                insertMark(operLocation);
301
                                return;
302
                            }
303
                        }
304
                        return;
305
                    }
306
                    if (dirProp == AN && !doneAN) {
307
                        for (int j = operLocation; j < len; j++) {
308
                            dirProp = getDirProp(j);
309
                            if (dirProp == L)
310
                                return;
311
                            if (dirProp == AL || dirProp == AN) {
312
                                insertMark(operLocation);
313
                                return;
314
                            }
315
                        }
316
                        doneAN = true;
317
                    }
318
                }
319
            } else { /* process Arabic and Hebrew */
320
                for (int i = operLocation - 1; i >= 0; i--) {
321
                    byte dirProp = getDirProp(i);
322
                    if (dirProp == L)
323
                        return;
324
                    if (dirProp == R || dirProp == AL) {
325
                        for (int j = operLocation; j < len; j++) {
326
                            dirProp = getDirProp(j);
327
                            if (dirProp == L)
328
                                return;
329
                            if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
330
                                insertMark(operLocation);
331
                                return;
332
                            }
333
                        }
334
                        return;
335
                    }
336
                    if (dirProp == AN && !doneAN) {
337
                        for (int j = operLocation; j < len; j++) {
338
                            dirProp = getDirProp(j);
339
                            if (dirProp == L)
340
                                return;
341
                            if (dirProp == AL || dirProp == AN || dirProp == R) {
342
                                insertMark(operLocation);
343
                                return;
344
                            }
345
                        }
346
                        doneAN = true;
347
                    }
348
                }
349
            }
350
        }
351
    }
352
353
    /**
354
     *  @see CxpHelper#getFinalState()
355
     */
356
    public int getFinalState() {
357
        return state;
358
    }
359
360
    /**
361
     *  @see CxpHelper#setFinalState(int newState)
362
     */
363
    public void setFinalState(int newState) {
364
        state = newState;
365
    }
366
367
    /**
368
     *  @see CxpHelper#leanToFullText(String text, int initState)
369
     */
370
    public String leanToFullText(String text, int initState) {
371
        if (text.length() == 0) {
372
            prefixLength = 0;
373
            count = 0;
374
            return text;
375
        }
376
        leanToFullTextNofix(text, initState);
377
        return addMarks(true);
378
    }
379
380
    void leanToFullTextNofix(String text, int initState) {
381
        int operCount = cef.operators.length();
382
        int curPos = 0;
383
        int len = text.length();
384
        int nextLocation, idxLocation;
385
        leanText = text;
386
        offsets = new int[20];
387
        count = 0;
388
        dirProps = new byte[len];
389
        curOrient = -1;
390
        curDirection = -1;
391
        // initialize locations
392
        int k = locations.length;
393
        for (int i = 0; i < k; i++) {
394
            locations[i] = -1;
395
        }
396
        state = CxpHelper.STATE_NOTHING_GOING;
397
        if (initState != CxpHelper.STATE_NOTHING_GOING)
398
            curPos = proc.processSpecial(ceh, initState, leanText, -1);
399
400
        while (true) {
401
            long res = computeNextLocation(curPos);
402
            nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
403
            if (nextLocation >= len)
404
                break;
405
            idxLocation = (int) (res >> 32); /* high word */
406
            if (idxLocation < operCount) {
407
                processOperator(nextLocation);
408
                curPos = nextLocation + 1;
409
            } else {
410
                curPos = proc.processSpecial(ceh, idxLocation - operCount, leanText, nextLocation);
411
            }
412
        }
413
    }
414
415
    /**
416
     *  @see CxpHelper#leanBidiCharOffsets()
417
     */
418
    public int[] leanBidiCharOffsets() {
419
        int[] result = new int[count];
420
        System.arraycopy(offsets, 0, result, 0, count);
421
        return result;
422
    }
423
424
    /**
425
     *  @see CxpHelper#fullBidiCharOffsets()
426
     */
427
    public int[] fullBidiCharOffsets() {
428
        int lim = count;
429
        if (prefixLength > 0) {
430
            if (prefixLength == 1)
431
                lim++;
432
            else
433
                lim += FIXES_LENGTH;
434
        }
435
        int[] fullOffsets = new int[lim];
436
        for (int i = 0; i < prefixLength; i++) {
437
            fullOffsets[i] = i;
438
        }
439
        int added = prefixLength;
440
        for (int i = 0; i < count; i++) {
441
            fullOffsets[prefixLength + i] = offsets[i] + added;
442
            added++;
443
        }
444
        if (prefixLength > 1) {
445
            int len = leanText.length();
446
            fullOffsets[lim - 2] = len + lim - 2;
447
            fullOffsets[lim - 1] = len + lim - 1;
448
        }
449
        return fullOffsets;
450
    }
451
452
    /**
453
     *  @see CxpHelper#fullToLeanText(String text, int initState)
454
     */
455
    public String fullToLeanText(String text, int initState) {
456
        int i; // used as loop index
457
        setMarkAndFixes();
458
        // remove any prefix and leading mark
459
        int lenText = text.length();
460
        for (i = 0; i < lenText; i++) {
461
            char c = text.charAt(i);
462
            if (c != curEmbed && c != curMark)
463
                break;
464
        }
465
        if (i > 0) { // found at least one prefix or leading mark
466
            text = text.substring(i);
467
            lenText = text.length();
468
        }
469
        // remove any suffix and trailing mark
470
        for (i = lenText - 1; i >= 0; i--) {
471
            char c = text.charAt(i);
472
            if (c != PDF && c != curMark)
473
                break;
474
        }
475
        if (i < 0) { // only suffix and trailing marks, no real data
476
            leanText = EMPTY_STRING;
477
            prefixLength = 0;
478
            count = 0;
479
            return leanText;
480
        }
481
        if (i < (lenText - 1)) { // found at least one suffix or trailing mark
482
            text = text.substring(0, i + 1);
483
            lenText = text.length();
484
        }
485
        char[] chars = text.toCharArray();
486
        // remove marks from chars
487
        int cnt = 0;
488
        for (i = 0; i < lenText; i++) {
489
            char c = chars[i];
490
            if (c == curMark)
491
                cnt++;
492
            else if (cnt > 0)
493
                chars[i - cnt] = c;
494
        }
495
        String lean = new String(chars, 0, lenText - cnt);
496
        leanToFullTextNofix(lean, initState);
497
        String full = addMarks(false); /* only marks, no prefix/suffix */
498
        if (full.equals(text))
499
            return lean;
500
501
        // There are some marks in full which are not in text and/or vice versa.
502
        // We need to add to lean any mark appearing in text and not in full.
503
        // The completed lean can never be longer than text itself.
504
        char[] newChars = new char[lenText];
505
        char cFull, cText;
506
        int idxFull, idxText, idxLean, markPos, newCharsPos;
507
        int lenFull = full.length();
508
        idxFull = idxText = idxLean = newCharsPos = 0;
509
        while (idxText < lenText && idxFull < lenFull) {
510
            cFull = full.charAt(idxFull);
511
            cText = text.charAt(idxText);
512
            if (cFull == cText) { /* chars are equal, proceed */
513
                idxText++;
514
                idxFull++;
515
                continue;
516
            }
517
            if (cFull == curMark) { /* extra Mark in full text */
518
                idxFull++;
519
                continue;
520
            }
521
            if (cText == curMark) { /* extra Mark in source full text */
522
                idxText++;
523
                // idxText-2 always >= 0 since leading Marks were removed from text
524
                if (text.charAt(idxText - 2) == curMark)
525
                    continue; // ignore successive Marks in text after the first one
526
                markPos = fullToLeanPos(idxFull);
527
                // copy from chars (== lean) to newChars until here
528
                for (i = idxLean; i < markPos; i++) {
529
                    newChars[newCharsPos++] = chars[i];
530
                }
531
                idxLean = markPos;
532
                newChars[newCharsPos++] = curMark;
533
                continue;
534
            }
535
            // we should never get here (extra char which is not a Mark)
536
            throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$
537
        }
538
        if (idxText < lenText) /* full ended before text - this should never happen */
539
            throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$
540
541
        // copy the last part of chars to newChars
542
        for (i = idxLean; i < lean.length(); i++) {
543
            newChars[newCharsPos++] = chars[i];
544
        }
545
        lean = new String(newChars, 0, newCharsPos);
546
        leanText = lean;
547
        return lean;
548
    }
549
550
    /**
551
     *  @see CxpHelper#leanToFullPos(int pos)
552
     */
553
    public int leanToFullPos(int pos) {
554
        int added = prefixLength;
555
        for (int i = 0; i < count; i++) {
556
            if (offsets[i] <= pos)
557
                added++;
558
            else
559
                return pos + added;
560
        }
561
        return pos + added;
562
    }
563
564
    /**
565
     *  @see CxpHelper#fullToLeanPos(int pos)
566
     */
567
    public int fullToLeanPos(int pos) {
568
        int len = leanText.length();
569
        int added = 0;
570
        pos -= prefixLength;
571
        for (int i = 0; i < count; i++) {
572
            if ((offsets[i] + added) < pos)
573
                added++;
574
            else
575
                break;
576
        }
577
        pos -= added;
578
        if (pos < 0)
579
            pos = 0;
580
        else if (pos > len)
581
            pos = len;
582
        return pos;
583
    }
584
585
    /**
586
     *  @see CxpHelper#insertMark(int offset)
587
     */
588
    public void insertMark(int offset) {
589
        int index = count - 1; // index of greatest member <= offset
590
        // look up after which member the new offset should be inserted
591
        while (index >= 0) {
592
            int wrkOffset = offsets[index];
593
            if (offset > wrkOffset)
594
                break;
595
            if (offset == wrkOffset)
596
                return; // avoid duplicates
597
            index--;
598
        }
599
        index++; // index now points at where to insert
600
        // check if we have an available slot for new member
601
        if (count >= (offsets.length - 1)) {
602
            int[] newOffsets = new int[offsets.length * 2];
603
            System.arraycopy(offsets, 0, newOffsets, 0, count);
604
            offsets = newOffsets;
605
        }
606
607
        int length = count - index; // number of members to move up
608
        if (length > 0) // shift right all members greater than offset
609
            System.arraycopy(offsets, index, offsets, index + 1, length);
610
611
        offsets[index] = offset;
612
        count++;
613
        // if the offset is 0, adding a mark does not change anything
614
        if (offset < 1)
615
            return;
616
617
        byte dirProp = getDirProp(offset);
618
        // if the current char is a strong one or a digit, we change the
619
        //   dirProp of the previous char to account for the inserted mark
620
        if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
621
            index = offset - 1;
622
        else
623
            // if the current char is a neutral, we change its own dirProp
624
            index = offset;
625
        setMarkAndFixes();
626
        setDirProp(index, curStrong);
627
    }
628
629
    String addMarks(boolean addFixes) {
630
        // add prefix/suffix only if addFixes is true
631
        if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == CxpEnv.ORIENT_IGNORE))) {
632
            prefixLength = 0;
633
            return leanText;
634
        }
635
        int len = leanText.length();
636
        int newLen = len + count;
637
        if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == CxpEnv.ORIENT_UNKNOWN))) {
638
            if ((env.orientation & CxpEnv.ORIENT_CONTEXTUAL_LTR) == 0) {
639
                prefixLength = PREFIX_LENGTH;
640
                newLen += FIXES_LENGTH;
641
            } else { /* contextual orientation */
642
                prefixLength = 1;
643
                newLen++; /* +1 for a mark char */
644
            }
645
        } else {
646
            prefixLength = 0;
647
        }
648
        char[] fullChars = new char[newLen];
649
        // add a dummy offset as fence
650
        offsets[count] = len;
651
        int added = prefixLength;
652
        // add marks at offsets
653
        setMarkAndFixes();
654
        for (int i = 0, j = 0; i < len; i++) {
655
            char c = leanText.charAt(i);
656
            if (i == offsets[j]) {
657
                fullChars[i + added] = curMark;
658
                added++;
659
                j++;
660
            }
661
            fullChars[i + added] = c;
662
        }
663
        if (prefixLength > 0) { /* add prefix/suffix ? */
664
            if (prefixLength == 1) { /* contextual orientation */
665
                fullChars[0] = curMark;
666
            } else {
667
                // When the orientation is RTL, we need to add EMBED at the
668
                // start of the text and PDF at its end.
669
                // However, because of a bug in Windows' handling of LRE/PDF,
670
                // we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
671
                fullChars[0] = curEmbed;
672
                fullChars[1] = curMark;
673
                fullChars[newLen - 1] = PDF;
674
                fullChars[newLen - 2] = curMark;
675
            }
676
        }
677
        return new String(fullChars);
678
    }
679
680
    /**
681
     *  @see CxpHelper#getEnvironment()
682
     */
683
    public CxpEnv getEnvironment() {
684
        return env;
685
    }
686
687
    /**
688
     *  @see CxpHelper#setEnvironment(CxpEnv environment)
689
     */
690
    public void setEnvironment(CxpEnv environment) {
691
        env = environment;
692
        cef = proc.init2(ceh, env);
693
        specialsCount = cef.specialsCount;
694
    }
695
696
    /**
697
     *  @see CxpHelper#getFeatures()
698
     */
699
    public CxpFeatures getFeatures() {
700
        return cef;
701
    }
702
703
    /**
704
     *  @see CxpHelper#setFeatures(CxpFeatures features)
705
     */
706
    public void setFeatures(CxpFeatures features) {
707
        if (features.operators.length() > cef.operators.length())
708
            locations = new int[features.operators.length() + specialsCount];
709
        cef = features;
710
    }
711
712
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/CxpSingle.java (+51 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 *  <code>CxpSingle</code> is a processor for complex expressions
17
 *  composed of two parts separated by an operator.
18
 *  The first occurrence of the operator delimits the end of the first part
19
 *  and the start of the second part. Further occurrences of the operator,
20
 *  if any, are treated like regular characters of the second text part.
21
 *  The processor makes sure that the expression be presented in the form
22
 *  (assuming that the equal sign is the operator):
23
 *  <pre>
24
 *  part1=part2
25
 *  </pre>
26
 *  The {@link CxpFeatures#operators operators}
27
 *  field in the {@link CxpFeatures features}
28
 *  of this processor should contain exactly one character.
29
 *  Additional characters will be ignored.
30
 *
31
 *  @author Matitiahu Allouche
32
 */
33
public abstract class CxpSingle extends CxpProcessor {
34
35
	/**
36
	 *  This method locates occurrences of the operator.
37
	 */
38
	public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
39
		return srcText.indexOf(ceh.ced.cef.operators.charAt(0), fromIndex);
40
	}
41
42
	/**
43
	 *  This method inserts a mark before the operator if needed and
44
	 *  skips to the end of the source string.
45
	 */
46
	public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
47
		ceh.processOperator(operLocation);
48
		return srcText.length();
49
	}
50
51
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpComma.java (-25 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
14
15
/**
16
 * Processor adapted to processing comma-delimited lists, such as: 
17
 * <pre>
18
 *  part1,part2,part3
19
 * </pre>
20
 */
21
public class ComplExpComma extends ComplExpBasic {
22
	public ComplExpComma() {
23
		super(","); //$NON-NLS-1$
24
	}
25
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpEmail.java (-22 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpDelimsEsc;
14
15
/**
16
 * Processor adapted to processing e-mail addresses. 
17
 */
18
public class ComplExpEmail extends ComplExpDelimsEsc {
19
	public ComplExpEmail() {
20
		super("<>.:,;@", "()\"\""); //$NON-NLS-1$ //$NON-NLS-2$
21
	}
22
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpFile.java (-22 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
14
15
/**
16
 * Processor adapted to processing directory and file paths. 
17
 */
18
public class ComplExpFile extends ComplExpBasic {
19
	public ComplExpFile() {
20
		super(":/\\."); //$NON-NLS-1$
21
	}
22
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java (-117 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
15
16
/**
17
 *  <code>ComplExpJava</code> is a processor for complex expressions
18
 *  composed of Java statements. Such a complex expression may span
19
 *  multiple lines.
20
 *  <p>
21
 *  In applications like an editor where parts of the text might be modified
22
 *  while other parts are not, the user may want to call
23
 *  {@link IComplExpProcessor#leanToFullText leanToFullText}
24
 *  separately on each line and save the initial state of each line (this is
25
 *  the final state of the previous line which can be retrieved using
26
 *  {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
27
 *  of a line and its initial state have not changed, the user can be sure that
28
 *  the last <i>full</i> text computed for this line has not changed either.
29
 *
30
 *  @see IComplExpProcessor
31
 *  @author Matitiahu Allouche
32
 */
33
public class ComplExpJava extends ComplExpBasic {
34
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
35
	static final String operators = "[](){}.+-<>=~!&*/%^|?:,;\t"; //$NON-NLS-1$
36
	static String lineSep;
37
38
	/**
39
	 *  Constructor for a complex expressions processor with support for
40
	 *  Java statements.
41
	 */
42
	public ComplExpJava() {
43
		super(operators, 4);
44
		// TBD use bundle properties
45
		if (lineSep == null)
46
			lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
47
	}
48
49
	/**
50
	 *  This method is not supposed to be invoked directly by users of this
51
	 *  class. It may  be overridden by subclasses of this class.
52
	 */
53
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
54
		switch (whichSpecial) {
55
			case 0 : /* space */
56
				return srcText.indexOf(' ', fromIndex);
57
			case 1 : /* literal */
58
				return srcText.indexOf('"', fromIndex);
59
			case 2 : /* slash-aster comment */
60
				return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
61
			case 3 : /* slash-slash comment */
62
				return srcText.indexOf("//", fromIndex); //$NON-NLS-1$
63
		}
64
		// we should never get here
65
		return -1;
66
	}
67
68
	/**
69
	 *  This method is not supposed to be invoked directly by users of this
70
	 *  class. It may  be overridden by subclasses of this class.
71
	 */
72
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
73
		int loc, cnt, i;
74
75
		processOperator(operLocation);
76
		switch (whichSpecial) {
77
			case 0 : /* space */
78
				operLocation++;
79
				while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
80
					setDirProp(operLocation, WS);
81
					operLocation++;
82
				}
83
				return operLocation;
84
			case 1 : /* literal */
85
				loc = operLocation + 1;
86
				while (true) {
87
					loc = srcText.indexOf('"', loc);
88
					if (loc < 0)
89
						return srcText.length();
90
					for (cnt = 0, i = loc - 1; srcText.charAt(i) == '\\'; i--) {
91
						cnt++;
92
					}
93
					loc++;
94
					if ((cnt & 1) == 0)
95
						return loc;
96
				}
97
			case 2 : /* slash-aster comment */
98
				if (operLocation < 0)
99
					loc = 0; // initial state from previous line
100
				else
101
					loc = operLocation + 2; // skip the opening slash-aster
102
				loc = srcText.indexOf("*/", loc); //$NON-NLS-1$
103
				if (loc < 0) {
104
					state = 2;
105
					return srcText.length();
106
				}
107
				return loc + 2;
108
			case 3 : /* slash-slash comment */
109
				loc = srcText.indexOf(lineSep, operLocation + 2);
110
				if (loc < 0)
111
					return srcText.length();
112
				return loc + lineSep.length();
113
		}
114
		// we should never get here
115
		return operLocation + 1;
116
	}
117
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpMath.java (-24 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
14
15
/**
16
 * Processor adapted to processing arithmetic expressions with right-to-left 
17
 * base direction. 
18
 */
19
public class ComplExpMath extends ComplExpBasic {
20
	public ComplExpMath() {
21
		super("+-/*()="); //$NON-NLS-1$
22
		setDirection(DIRECTION_RTL);
23
	}
24
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpProperty.java (-28 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpSingle;
14
15
/**
16
 * Processor adapted to processing property file statements. 
17
 * It expects the following string format:
18
 * <pre>
19
 *  name=value
20
 * </pre>
21
 */
22
public class ComplExpProperty extends ComplExpSingle {
23
24
	public ComplExpProperty() {
25
		super("="); //$NON-NLS-1$
26
	}
27
28
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java (-201 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
15
16
/**
17
 *  <code>ComplExpRegex</code> is a processor for regular expressions.
18
 *  Such expressions may span multiple lines.
19
 *  <p>
20
 *  In applications like an editor where parts of the text might be modified
21
 *  while other parts are not, the user may want to call
22
 *  {@link IComplExpProcessor#leanToFullText leanToFullText}
23
 *  separately on each line and save the initial state of each line (this is
24
 *  the final state of the previous line which can be retrieved using
25
 *  {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
26
 *  of a line and its initial state have not changed, the user can be sure that
27
 *  the last <i>full</i> text computed for this line has not changed either.
28
 *
29
 *  @see IComplExpProcessor
30
 *  @author Matitiahu Allouche
31
 */
32
public class ComplExpRegex extends ComplExpBasic {
33
	static final String operators = ""; //$NON-NLS-1$
34
	static final String[] startStrings = {"(?#", /*  0 *//* comment (?#...) *///$NON-NLS-1$
35
			"(?<", /*  1 *//* named group (?<name> *///$NON-NLS-1$
36
			"(?'", /*  2 *//* named group (?'name' *///$NON-NLS-1$
37
			"(?(<", /*  3 *//* conditional named back reference (?(<name>) *///$NON-NLS-1$
38
			"(?('", /*  4 *//* conditional named back reference (?('name') *///$NON-NLS-1$
39
			"(?(", /*  5 *//* conditional named back reference (?(name) *///$NON-NLS-1$
40
			"(?&", /*  6 *//* named parentheses reference (?&name) *///$NON-NLS-1$
41
			"(?P<", /*  7 *//* named group (?P<name> *///$NON-NLS-1$
42
			"\\k<", /*  8 *//* named back reference \k<name> *///$NON-NLS-1$
43
			"\\k'", /*  9 *//* named back reference \k'name' *///$NON-NLS-1$
44
			"\\k{", /* 10 *//* named back reference \k{name} *///$NON-NLS-1$
45
			"(?P=", /* 11 *//* named back reference (?P=name) *///$NON-NLS-1$
46
			"\\g{", /* 12 *//* named back reference \g{name} *///$NON-NLS-1$
47
			"\\g<", /* 13 *//* subroutine call \g<name> *///$NON-NLS-1$
48
			"\\g'", /* 14 *//* subroutine call \g'name' *///$NON-NLS-1$
49
			"(?(R&", /* 15 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$
50
			"\\Q" /* 16 *//* quoted sequence \Q...\E *///$NON-NLS-1$
51
	};
52
	static final char[] endChars = {
53
			// 0    1     2    3    4    5    6    7    8     9   10   11   12   13    14   15
54
			')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'};
55
	static final int numberOfStrings = startStrings.length;
56
	static final int maxSpecial = numberOfStrings + 1;
57
58
	/**
59
	 *  Constructor for a complex expressions processor with support for
60
	 *  regular expressions.
61
	 */
62
	public ComplExpRegex() {
63
		super(operators, maxSpecial);
64
	}
65
66
	/**
67
	 *  This method is not supposed to be invoked directly by users of this
68
	 *  class. It may  be overridden by subclasses of this class.
69
	 */
70
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
71
		byte dirProp;
72
73
		if (whichSpecial < numberOfStrings) {
74
			/*  0 *//* comment (?#...) */
75
			/*  1 *//* named group (?<name> */
76
			/*  2 *//* named group (?'name' */
77
			/*  3 *//* conditional named back reference (?(name) */
78
			/*  4 *//* conditional named back reference (?(<name>) */
79
			/*  5 *//* conditional named back reference (?('name') */
80
			/*  6 *//* named parentheses reference (?&name) */
81
			/*  7 *//* named group (?P<name> */
82
			/*  8 *//* named back reference \k<name> */
83
			/*  9 *//* named back reference \k'name' */
84
			/* 10 *//* named back reference \k{name} */
85
			/* 11 *//* named back reference (?P=name) */
86
			/* 12 *//* named back reference \g{name} */
87
			/* 13 *//* subroutine call \g<name> */
88
			/* 14 *//* subroutine call \g'name' */
89
			/* 15 *//* named back reference recursion (?(R&name) */
90
			/* 16 *//* quoted sequence \Q...\E */
91
			return srcText.indexOf(startStrings[whichSpecial], fromIndex);
92
		}
93
		// look for R, AL, AN, EN which are potentially needing a mark
94
		for (; fromIndex < srcText.length(); fromIndex++) {
95
			// there never is a need for a mark before the first char
96
			if (fromIndex <= 0)
97
				continue;
98
99
			dirProp = getDirProp(fromIndex);
100
			// R and AL will always be examined using processOperator()
101
			if (dirProp == R || dirProp == AL)
102
				return fromIndex;
103
104
			if (dirProp == EN || dirProp == AN) {
105
				// no need for a mark after the first digit in a number
106
				if (getDirProp(fromIndex - 1) == dirProp)
107
					continue;
108
109
				for (int i = fromIndex - 1; i >= 0; i--) {
110
					dirProp = getDirProp(i);
111
					// after a L char, no need for a mark
112
					if (dirProp == L)
113
						continue;
114
115
					// digit after R or AL or AN need a mark, except for EN
116
					//   following AN, but this is a contrived case, so we
117
					//   don't check for it (and calling processOperator()
118
					//   for it will do no harm)
119
					if (dirProp == R || dirProp == AL || dirProp == AN)
120
						return fromIndex;
121
				}
122
				continue;
123
			}
124
		}
125
		return -1;
126
	}
127
128
	/**
129
	 *  This method is not supposed to be invoked directly by users of this
130
	 *  class. It may  be overridden by subclasses of this class.
131
	 */
132
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
133
		int loc;
134
135
		switch (whichSpecial) {
136
			case 0 : /* comment (?#...) */
137
				if (operLocation < 0) {
138
					// initial state from previous line
139
					loc = 0;
140
				} else {
141
					processOperator(operLocation);
142
					// skip the opening "(?#"
143
					loc = operLocation + 3;
144
				}
145
				loc = srcText.indexOf(')', loc);
146
				if (loc < 0) {
147
					state = whichSpecial;
148
					return srcText.length();
149
				}
150
				return loc + 1;
151
			case 1 : /* named group (?<name> */
152
			case 2 : /* named group (?'name' */
153
			case 3 : /* conditional named back reference (?(name) */
154
			case 4 : /* conditional named back reference (?(<name>) */
155
			case 5 : /* conditional named back reference (?('name') */
156
			case 6 : /* named parentheses reference (?&name) */
157
				processOperator(operLocation);
158
				// no need for calling processOperator() for the following cases
159
				//   since the starting string contains a L char
160
			case 7 : /* named group (?P<name> */
161
			case 8 : /* named back reference \k<name> */
162
			case 9 : /* named back reference \k'name' */
163
			case 10 : /* named back reference \k{name} */
164
			case 11 : /* named back reference (?P=name) */
165
			case 12 : /* named back reference \g{name} */
166
			case 13 : /* subroutine call \g<name> */
167
			case 14 : /* subroutine call \g'name' */
168
			case 15 : /* named back reference recursion (?(R&name) */
169
				// skip the opening string
170
				loc = operLocation + startStrings[whichSpecial].length();
171
				// look for ending character
172
				loc = srcText.indexOf(endChars[whichSpecial], loc);
173
				if (loc < 0)
174
					return srcText.length();
175
				return loc + 1;
176
			case 16 : /* quoted sequence \Q...\E */
177
				if (operLocation < 0) {
178
					// initial state from previous line
179
					loc = 0;
180
				} else {
181
					processOperator(operLocation);
182
					// skip the opening "\Q"
183
					loc = operLocation + 2;
184
				}
185
				loc = srcText.indexOf("\\E", loc); //$NON-NLS-1$
186
				if (loc < 0) {
187
					state = whichSpecial;
188
					return srcText.length();
189
				}
190
				// set the dirProp for the "E"
191
				setDirProp(loc + 1, L);
192
				return loc + 2;
193
			case 17 : /* R, AL, AN, EN */
194
				processOperator(operLocation);
195
				return operLocation + 1;
196
197
		}
198
		// we should never get here
199
		return srcText.length();
200
	}
201
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSql.java (-136 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
15
16
/**
17
 *  <code>ComplExpSql</code> is a processor for complex expressions
18
 *  composed of SQL statements. Such a complex expression may span
19
 *  multiple lines.
20
 *  <p>
21
 *  In applications like an editor where parts of the text might be modified
22
 *  while other parts are not, the user may want to call
23
 *  {@link IComplExpProcessor#leanToFullText leanToFullText}
24
 *  separately on each line and save the initial state of each line (this is
25
 *  the final state of the previous line which can be retrieved using
26
 *  {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
27
 *  of a line and its initial state have not changed, the user can be sure that
28
 *  the last <i>full</i> text computed for this line has not changed either.
29
 *
30
 *  @see IComplExpProcessor
31
 *  @author Matitiahu Allouche
32
 */
33
public class ComplExpSql extends ComplExpBasic {
34
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
35
	static final String operators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$
36
	static String lineSep;
37
38
	/**
39
	 *  Constructor for a complex expressions processor with support for
40
	 *  SQL statements.
41
	 */
42
	public ComplExpSql() {
43
		super(operators, 5);
44
		// TBD use bundle properties
45
		if (lineSep == null)
46
			lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
47
	}
48
49
	/**
50
	 *  This method is not supposed to be invoked directly by users of this
51
	 *  class. It may  be overridden by subclasses of this class.
52
	 */
53
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
54
		switch (whichSpecial) {
55
			case 0 : /* space */
56
				return srcText.indexOf(" ", fromIndex); //$NON-NLS-1$
57
			case 1 : /* literal */
58
				return srcText.indexOf('\'', fromIndex);
59
			case 2 : /* delimited identifier */
60
				return srcText.indexOf('"', fromIndex);
61
			case 3 : /* slash-aster comment */
62
				return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
63
			case 4 : /* hyphen-hyphen comment */
64
				return srcText.indexOf("--", fromIndex); //$NON-NLS-1$
65
		}
66
		// we should never get here
67
		return -1;
68
	}
69
70
	/**
71
	 *  This method is not supposed to be invoked directly by users of this
72
	 *  class. It may  be overridden by subclasses of this class.
73
	 */
74
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
75
		int loc;
76
77
		processOperator(operLocation);
78
		switch (whichSpecial) {
79
			case 0 : /* space */
80
				operLocation++;
81
				while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
82
					setDirProp(operLocation, WS);
83
					operLocation++;
84
				}
85
				return operLocation;
86
			case 1 : /* literal */
87
				loc = operLocation + 1;
88
				while (true) {
89
					loc = srcText.indexOf('\'', loc);
90
					if (loc < 0) {
91
						state = whichSpecial;
92
						return srcText.length();
93
					}
94
					if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '\'') {
95
						loc += 2;
96
						continue;
97
					}
98
					return loc + 1;
99
				}
100
			case 2 : /* delimited identifier */
101
				loc = operLocation + 1;
102
				while (true) {
103
					loc = srcText.indexOf('"', loc);
104
					if (loc < 0)
105
						return srcText.length();
106
107
					if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '"') {
108
						loc += 2;
109
						continue;
110
					}
111
					return loc + 1;
112
				}
113
			case 3 : /* slash-aster comment */
114
				if (operLocation < 0)
115
					loc = 0; // initial state from previous line
116
				else
117
					loc = operLocation + 2; // skip the opening slash-aster
118
				loc = srcText.indexOf("*/", loc); //$NON-NLS-1$
119
				if (loc < 0) {
120
					state = whichSpecial;
121
					return srcText.length();
122
				}
123
				// we need to call processOperator since text may follow the
124
				//  end of comment immediately without even a space
125
				processOperator(loc);
126
				return loc + 2;
127
			case 4 : /* hyphen-hyphen comment */
128
				loc = srcText.indexOf(lineSep, operLocation + 2);
129
				if (loc < 0)
130
					return srcText.length();
131
				return loc + lineSep.length();
132
		}
133
		// we should never get here
134
		return srcText.length();
135
	}
136
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSystem.java (-27 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpSingle;
14
15
/**
16
 * Processor adapted to processing expressions with the following string format:
17
 * <pre>
18
 *  system(user)
19
 * </pre>
20
 */
21
public class ComplExpSystem extends ComplExpSingle {
22
23
	public ComplExpSystem() {
24
		super("("); //$NON-NLS-1$
25
	}
26
27
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpURL.java (-22 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
14
15
/**
16
 * Processor adapted to processing URLs. 
17
 */
18
public class ComplExpURL extends ComplExpBasic {
19
	public ComplExpURL() {
20
		super(":?#/@.[]"); //$NON-NLS-1$
21
	}
22
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpUnderscore.java (-27 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
14
15
/**
16
 * Processor adapted to processing compound names. 
17
 * This type covers names made of one or more parts, separated by underscores:
18
 * <pre>
19
 *  part1_part2_part3
20
 * </pre>
21
 */
22
public class ComplExpUnderscore extends ComplExpBasic {
23
	public ComplExpUnderscore() {
24
		super("_"); //$NON-NLS-1$
25
	}
26
27
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpXPath.java (-22 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.internal.complexp.ComplExpDelims;
14
15
/**
16
 * Processor adapted to processing XPath expressions. 
17
 */
18
public class ComplExpXPath extends ComplExpDelims {
19
	public ComplExpXPath() {
20
		super(" /[]<>=!:@.|()+-*", "''\"\""); //$NON-NLS-1$ //$NON-NLS-2$
21
	}
22
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpComma.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 * Processor adapted to processing comma-delimited lists, such as:
17
 * <pre>
18
 *  part1,part2,part3
19
 * </pre>
20
 */
21
public class CxpComma extends CxpProcessor {
22
    static final CxpFeatures FEATURES = new CxpFeatures(",", 0, -1, -1, false, false); //$NON-NLS-1$
23
24
    /**
25
     *  This method retrieves the features specific to this processor.
26
     *
27
     *  @return features with one operator (comma), no special cases,
28
     *          LTR direction for Arabic and Hebrew, and support for both.
29
     */
30
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
31
        return FEATURES;
32
    }
33
34
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpEmail.java (+45 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
import org.eclipse.equinox.bidi.internal.complexp.CxpDelimsEsc;
15
16
/**
17
 * Processor adapted to processing e-mail addresses.
18
 */
19
public class CxpEmail extends CxpDelimsEsc {
20
    static final int LTR = CxpFeatures.DIR_LTR;
21
    static final int RTL = CxpFeatures.DIR_RTL;
22
    static final CxpFeatures MIRRORED = new CxpFeatures("<>.:,;@", 2, RTL, LTR, false, false); //$NON-NLS-1$
23
    static final CxpFeatures NOT_MIRRORED = new CxpFeatures("<>.:,;@", 2, LTR, LTR, false, false); //$NON-NLS-1$
24
25
    /**
26
     *  This method retrieves the features specific to this processor.
27
     *
28
     *  @return features with operators "<>.:,;@", 2 special cases,
29
     *          LTR direction for Arabic when the GUI is not mirrored,
30
     *          RTL direction for Arabic when the GUI is mirrored,
31
     *          LTR direction for Hebrew in all cases,
32
     *          and support for both Arabic and Hebrew.
33
     */
34
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
35
        return env.mirrored ? MIRRORED : NOT_MIRRORED;
36
    }
37
38
    /**
39
     *  @return parentheses and quotation marks as delimiters.
40
     */
41
    protected String getDelimiters() {
42
        return "()\"\""; //$NON-NLS-1$
43
    }
44
45
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpFile.java (+31 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 * Processor adapted to processing directory and file paths.
17
 */
18
public class CxpFile extends CxpProcessor {
19
    static final CxpFeatures FEATURES = new CxpFeatures(":/\\.", 0, -1, -1, false, false); //$NON-NLS-1$
20
21
    /**
22
     *  This method retrieves the features specific to this processor.
23
     *
24
     *  @return features with operators ":/\.", no special cases,
25
     *          LTR direction for Arabic and Hebrew, and support for both.
26
     */
27
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
28
        return FEATURES;
29
    }
30
31
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpJava.java (+127 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 *  <code>CxpJava</code> is a processor for complex expressions
17
 *  composed of Java statements. Such a complex expression may span
18
 *  multiple lines.
19
 *  <p>
20
 *  In applications like an editor where parts of the text might be modified
21
 *  while other parts are not, the user may want to call
22
 *  {@link CxpHelper#leanToFullText leanToFullText}
23
 *  separately on each line and save the initial state of each line (this is
24
 *  the final state of the previous line which can be retrieved using
25
 *  {@link CxpHelper#getFinalState getFinalState}. If both the content
26
 *  of a line and its initial state have not changed, the user can be sure that
27
 *  the last <i>full</i> text computed for this line has not changed either.
28
 *
29
 *  @see CxpHelper
30
 *
31
 *  @author Matitiahu Allouche
32
 */
33
public class CxpJava extends CxpProcessor {
34
    private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
35
    static final CxpFeatures FEATURES = new CxpFeatures("[](){}.+-<>=~!&*/%^|?:,;\t", 4, -1, -1, false, false); //$NON-NLS-1$
36
    static final String lineSep = CxpEnv.getLineSep();
37
38
    /**
39
     *  This method retrieves the features specific to this processor.
40
     *
41
     *  @return features with operators "[](){}.+-<>=~!&/*%^|?:,;\t",
42
     *          4 special cases, LTR direction for Arabic and Hebrew,
43
     *          and support for both.
44
     */
45
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
46
        return FEATURES;
47
    }
48
49
    /**
50
         *  This method looks for occurrences of 4 special strings:
51
         *  <ol>
52
         *    <li>spaces</li>
53
         *    <li>literals starting with quotation mark</li>
54
         *    <li>comments starting with slash-asterisk</li>
55
         *    <li>comments starting with slash-slash</li>
56
         *  </ol>
57
         */
58
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
59
        switch (whichSpecial) {
60
            case 0 : /* space */
61
                return srcText.indexOf(' ', fromIndex);
62
            case 1 : /* literal */
63
                return srcText.indexOf('"', fromIndex);
64
            case 2 : /* slash-aster comment */
65
                return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
66
            case 3 : /* slash-slash comment */
67
                return srcText.indexOf("//", fromIndex); //$NON-NLS-1$
68
        }
69
        // we should never get here
70
        return -1;
71
    }
72
73
    /**
74
     *  This method processes the 4 special cases as follows.
75
         *  <ol>
76
         *    <li>skip the run of spaces</li>
77
         *    <li>look for a matching quotation mark and skip until after it</li>
78
         *    <li>skip until after the closing asterisk-slash</li>
79
         *    <li>skip until after a line separator</li>
80
         *  </ol>
81
     */
82
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
83
        int loc, cnt, i;
84
85
        ceh.processOperator(operLocation);
86
        switch (whichSpecial) {
87
            case 0 : /* space */
88
                operLocation++;
89
                while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
90
                    ceh.setDirProp(operLocation, WS);
91
                    operLocation++;
92
                }
93
                return operLocation;
94
            case 1 : /* literal */
95
                loc = operLocation + 1;
96
                while (true) {
97
                    loc = srcText.indexOf('"', loc);
98
                    if (loc < 0)
99
                        return srcText.length();
100
                    for (cnt = 0, i = loc - 1; srcText.charAt(i) == '\\'; i--) {
101
                        cnt++;
102
                    }
103
                    loc++;
104
                    if ((cnt & 1) == 0)
105
                        return loc;
106
                }
107
            case 2 : /* slash-aster comment */
108
                if (operLocation < 0)
109
                    loc = 0; // initial state from previous line
110
                else
111
                    loc = operLocation + 2; // skip the opening slash-aster
112
                loc = srcText.indexOf("*/", loc); //$NON-NLS-1$
113
                if (loc < 0) {
114
                    ceh.setFinalState(2);
115
                    return srcText.length();
116
                }
117
                return loc + 2;
118
            case 3 : /* slash-slash comment */
119
                loc = srcText.indexOf(lineSep, operLocation + 2);
120
                if (loc < 0)
121
                    return srcText.length();
122
                return loc + lineSep.length();
123
        }
124
        // we should never get here
125
        return srcText.length();
126
    }
127
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpMath.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 * Processor adapted to processing arithmetic expressions with right-to-left
17
 * base direction.
18
 */
19
public class CxpMath extends CxpProcessor {
20
    static final int RTL = CxpFeatures.DIR_RTL;
21
    static final CxpFeatures FEATURES = new CxpFeatures("+-/*()=", 0, RTL, RTL, false, false); //$NON-NLS-1$
22
23
    /**
24
     *  This method retrieves the features specific to this processor.
25
     *
26
     *  @return features with operators "+-/*()=", no special cases,
27
     *          RTL direction for Arabic and Hebrew, and support for both.
28
     */
29
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
30
        return FEATURES;
31
    }
32
33
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpProperty.java (+36 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
import org.eclipse.equinox.bidi.internal.complexp.CxpSingle;
15
16
/**
17
 * Processor adapted to processing property file statements.
18
 * It expects the following string format:
19
 * <pre>
20
 *  name=value
21
 * </pre>
22
 */
23
public class CxpProperty extends CxpSingle {
24
    static final CxpFeatures FEATURES = new CxpFeatures("=", 1, -1, -1, false, false); //$NON-NLS-1$
25
26
    /**
27
     *  This method retrieves the features specific to this processor.
28
     *
29
     *  @return features with one operator (equal sign), 1 special case,
30
     *          LTR direction for Arabic and Hebrew, and support for both.
31
     */
32
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
33
        return FEATURES;
34
    }
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpRegex.java (+207 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 *  <code>CxpRegex</code> is a processor for regular expressions.
17
 *  Such expressions may span multiple lines.
18
 *  <p>
19
 *  In applications like an editor where parts of the text might be modified
20
 *  while other parts are not, the user may want to call
21
 *  {@link CxpHelper#leanToFullText leanToFullText}
22
 *  separately on each line and save the initial state of each line (this is
23
 *  the final state of the previous line which can be retrieved using
24
 *  {@link CxpHelper#getFinalState getFinalState}. If both the content
25
 *  of a line and its initial state have not changed, the user can be sure that
26
 *  the last <i>full</i> text computed for this line has not changed either.
27
 *
28
 *  @see CxpHelper
29
 *
30
 *  @author Matitiahu Allouche
31
 */
32
public class CxpRegex extends CxpProcessor {
33
    static final String[] startStrings = {"(?#", /*  0 *//* comment (?#...) *///$NON-NLS-1$
34
            "(?<", /*  1 *//* named group (?<name> *///$NON-NLS-1$
35
            "(?'", /*  2 *//* named group (?'name' *///$NON-NLS-1$
36
            "(?(<", /*  3 *//* conditional named back reference (?(<name>) *///$NON-NLS-1$
37
            "(?('", /*  4 *//* conditional named back reference (?('name') *///$NON-NLS-1$
38
            "(?(", /*  5 *//* conditional named back reference (?(name) *///$NON-NLS-1$
39
            "(?&", /*  6 *//* named parentheses reference (?&name) *///$NON-NLS-1$
40
            "(?P<", /*  7 *//* named group (?P<name> *///$NON-NLS-1$
41
            "\\k<", /*  8 *//* named back reference \k<name> *///$NON-NLS-1$
42
            "\\k'", /*  9 *//* named back reference \k'name' *///$NON-NLS-1$
43
            "\\k{", /* 10 *//* named back reference \k{name} *///$NON-NLS-1$
44
            "(?P=", /* 11 *//* named back reference (?P=name) *///$NON-NLS-1$
45
            "\\g{", /* 12 *//* named back reference \g{name} *///$NON-NLS-1$
46
            "\\g<", /* 13 *//* subroutine call \g<name> *///$NON-NLS-1$
47
            "\\g'", /* 14 *//* subroutine call \g'name' *///$NON-NLS-1$
48
            "(?(R&", /* 15 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$
49
            "\\Q" /* 16 *//* quoted sequence \Q...\E *///$NON-NLS-1$
50
    };
51
    static final char[] endChars = {
52
            // 0    1     2    3    4    5    6    7    8     9   10   11   12   13    14   15
53
            ')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'};
54
    static final int numberOfStrings = startStrings.length;
55
    static final int maxSpecial = numberOfStrings + 1;
56
    static final CxpFeatures FEATURES = new CxpFeatures(null, maxSpecial, -1, -1, false, false);
57
    static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
58
    static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
59
    static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
60
    static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
61
    static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
62
63
    /**
64
     *  This method retrieves the features specific to this processor.
65
     *
66
     *  @return features with no operators , special cases for each kind of
67
     *          regular expression syntactic string,
68
     *          LTR direction for Arabic and Hebrew, and support for both.
69
     */
70
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
71
        return FEATURES;
72
    }
73
74
    /**
75
     *  This method locates occurrences of the syntactic strings and of
76
     *  R, AL, EN, AN characters.
77
     */
78
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
79
        byte dirProp;
80
81
        if (whichSpecial < numberOfStrings) {
82
            /*  0 *//* comment (?#...) */
83
            /*  1 *//* named group (?<name> */
84
            /*  2 *//* named group (?'name' */
85
            /*  3 *//* conditional named back reference (?(name) */
86
            /*  4 *//* conditional named back reference (?(<name>) */
87
            /*  5 *//* conditional named back reference (?('name') */
88
            /*  6 *//* named parentheses reference (?&name) */
89
            /*  7 *//* named group (?P<name> */
90
            /*  8 *//* named back reference \k<name> */
91
            /*  9 *//* named back reference \k'name' */
92
            /* 10 *//* named back reference \k{name} */
93
            /* 11 *//* named back reference (?P=name) */
94
            /* 12 *//* named back reference \g{name} */
95
            /* 13 *//* subroutine call \g<name> */
96
            /* 14 *//* subroutine call \g'name' */
97
            /* 15 *//* named back reference recursion (?(R&name) */
98
            /* 16 *//* quoted sequence \Q...\E */
99
            return srcText.indexOf(startStrings[whichSpecial], fromIndex);
100
        }
101
        // there never is a need for a mark before the first char
102
        if (fromIndex <= 0)
103
            fromIndex = 1;
104
        // look for R, AL, AN, EN which are potentially needing a mark
105
        for (; fromIndex < srcText.length(); fromIndex++) {
106
            dirProp = ceh.getDirProp(fromIndex);
107
            // R and AL will always be examined using processOperator()
108
            if (dirProp == R || dirProp == AL)
109
                return fromIndex;
110
111
            if (dirProp == EN || dirProp == AN) {
112
                // no need for a mark after the first digit in a number
113
                if (ceh.getDirProp(fromIndex - 1) == dirProp)
114
                    continue;
115
116
                for (int i = fromIndex - 1; i >= 0; i--) {
117
                    dirProp = ceh.getDirProp(i);
118
                    // after a L char, no need for a mark
119
                    if (dirProp == L)
120
                        continue;
121
122
                    // digit after R or AL or AN need a mark, except for EN
123
                    //   following AN, but this is a contrived case, so we
124
                    //   don't check for it (and calling processOperator()
125
                    //   for it will do no harm)
126
                    if (dirProp == R || dirProp == AL || dirProp == AN)
127
                        return fromIndex;
128
                }
129
                continue;
130
            }
131
        }
132
        return -1;
133
    }
134
135
    /**
136
     *  This method process the special cases.
137
     */
138
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
139
        int loc;
140
141
        switch (whichSpecial) {
142
            case 0 : /* comment (?#...) */
143
                if (operLocation < 0) {
144
                    // initial state from previous line
145
                    loc = 0;
146
                } else {
147
                    ceh.processOperator(operLocation);
148
                    // skip the opening "(?#"
149
                    loc = operLocation + 3;
150
                }
151
                loc = srcText.indexOf(')', loc);
152
                if (loc < 0) {
153
                    ceh.setFinalState(whichSpecial);
154
                    return srcText.length();
155
                }
156
                return loc + 1;
157
            case 1 : /* named group (?<name> */
158
            case 2 : /* named group (?'name' */
159
            case 3 : /* conditional named back reference (?(name) */
160
            case 4 : /* conditional named back reference (?(<name>) */
161
            case 5 : /* conditional named back reference (?('name') */
162
            case 6 : /* named parentheses reference (?&name) */
163
                ceh.processOperator(operLocation);
164
                // no need for calling processOperator() for the following cases
165
                //   since the starting string contains a L char
166
            case 7 : /* named group (?P<name> */
167
            case 8 : /* named back reference \k<name> */
168
            case 9 : /* named back reference \k'name' */
169
            case 10 : /* named back reference \k{name} */
170
            case 11 : /* named back reference (?P=name) */
171
            case 12 : /* named back reference \g{name} */
172
            case 13 : /* subroutine call \g<name> */
173
            case 14 : /* subroutine call \g'name' */
174
            case 15 : /* named back reference recursion (?(R&name) */
175
                // skip the opening string
176
                loc = operLocation + startStrings[whichSpecial].length();
177
                // look for ending character
178
                loc = srcText.indexOf(endChars[whichSpecial], loc);
179
                if (loc < 0)
180
                    return srcText.length();
181
                return loc + 1;
182
            case 16 : /* quoted sequence \Q...\E */
183
                if (operLocation < 0) {
184
                    // initial state from previous line
185
                    loc = 0;
186
                } else {
187
                    ceh.processOperator(operLocation);
188
                    // skip the opening "\Q"
189
                    loc = operLocation + 2;
190
                }
191
                loc = srcText.indexOf("\\E", loc); //$NON-NLS-1$
192
                if (loc < 0) {
193
                    ceh.setFinalState(whichSpecial);
194
                    return srcText.length();
195
                }
196
                // set the dirProp for the "E"
197
                ceh.setDirProp(loc + 1, L);
198
                return loc + 2;
199
            case 17 : /* R, AL, AN, EN */
200
                ceh.processOperator(operLocation);
201
                return operLocation + 1;
202
203
        }
204
        // we should never get here
205
        return srcText.length();
206
    }
207
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpSql.java (+148 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 *  <code>CxpSql</code> is a processor for complex expressions
17
 *  composed of SQL statements. Such a complex expression may span
18
 *  multiple lines.
19
 *  <p>
20
 *  In applications like an editor where parts of the text might be modified
21
 *  while other parts are not, the user may want to call
22
 *  {@link CxpHelper#leanToFullText leanToFullText}
23
 *  separately on each line and save the initial state of each line (this is
24
 *  the final state of the previous line which can be retrieved using
25
 *  {@link CxpHelper#getFinalState getFinalState}. If both the content
26
 *  of a line and its initial state have not changed, the user can be sure that
27
 *  the last <i>full</i> text computed for this line has not changed either.
28
 *
29
 *  @see CxpHelper
30
 *
31
 *  @author Matitiahu Allouche
32
 */
33
public class CxpSql extends CxpProcessor {
34
    private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
35
    static final String operators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$
36
    static final CxpFeatures FEATURES = new CxpFeatures(operators, 5, -1, -1, false, false);
37
    static final String lineSep = CxpEnv.getLineSep();
38
39
    /**
40
     *  This method retrieves the features specific to this processor.
41
     *
42
     *  @return features with operators "\t!#%&()*+,-./:;<=>?|[]{}", 5 special cases,
43
     *          LTR direction for Arabic and Hebrew, and support for both.
44
     */
45
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
46
        return FEATURES;
47
    }
48
49
    /**
50
      *  This method looks for occurrences of 5 special strings:
51
      *  <ol>
52
      *    <li>spaces</li>
53
      *    <li>literals starting with apostrophe</li>
54
      *    <li>identifiers starting with quotation mark</li>
55
      *    <li>comments starting with slash-asterisk</li>
56
      *    <li>comments starting with hyphen-hyphen</li>
57
      *  </ol>
58
      */
59
    public int indexOfSpecial(CxpHelper ceh, int whichSpecial, String srcText, int fromIndex) {
60
        switch (whichSpecial) {
61
            case 0 : /* space */
62
                return srcText.indexOf(" ", fromIndex); //$NON-NLS-1$
63
            case 1 : /* literal */
64
                return srcText.indexOf('\'', fromIndex);
65
            case 2 : /* delimited identifier */
66
                return srcText.indexOf('"', fromIndex);
67
            case 3 : /* slash-aster comment */
68
                return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
69
            case 4 : /* hyphen-hyphen comment */
70
                return srcText.indexOf("--", fromIndex); //$NON-NLS-1$
71
        }
72
        // we should never get here
73
        return -1;
74
    }
75
76
    /**
77
     *  This method processes the 5 special cases as follows.
78
         *  <ol>
79
         *    <li>skip the run of spaces</li>
80
         *    <li>look for a matching apostrophe and skip until after it</li>
81
         *    <li>look for a matching quotation mark and skip until after it</li>
82
         *    <li>skip until after the closing asterisk-slash</li>
83
         *    <li>skip until after a line separator</li>
84
         *  </ol>
85
     */
86
    public int processSpecial(CxpHelper ceh, int whichSpecial, String srcText, int operLocation) {
87
        int loc;
88
89
        ceh.processOperator(operLocation);
90
        switch (whichSpecial) {
91
            case 0 : /* space */
92
                operLocation++;
93
                while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
94
                    ceh.setDirProp(operLocation, WS);
95
                    operLocation++;
96
                }
97
                return operLocation;
98
            case 1 : /* literal */
99
                loc = operLocation + 1;
100
                while (true) {
101
                    loc = srcText.indexOf('\'', loc);
102
                    if (loc < 0) {
103
                        ceh.setFinalState(whichSpecial);
104
                        return srcText.length();
105
                    }
106
                    if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '\'') {
107
                        loc += 2;
108
                        continue;
109
                    }
110
                    return loc + 1;
111
                }
112
            case 2 : /* delimited identifier */
113
                loc = operLocation + 1;
114
                while (true) {
115
                    loc = srcText.indexOf('"', loc);
116
                    if (loc < 0)
117
                        return srcText.length();
118
119
                    if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '"') {
120
                        loc += 2;
121
                        continue;
122
                    }
123
                    return loc + 1;
124
                }
125
            case 3 : /* slash-aster comment */
126
                if (operLocation < 0)
127
                    loc = 0; // initial state from previous line
128
                else
129
                    loc = operLocation + 2; // skip the opening slash-aster
130
                loc = srcText.indexOf("*/", loc); //$NON-NLS-1$
131
                if (loc < 0) {
132
                    ceh.setFinalState(whichSpecial);
133
                    return srcText.length();
134
                }
135
                // we need to call processOperator since text may follow the
136
                //  end of comment immediately without even a space
137
                ceh.processOperator(loc);
138
                return loc + 2;
139
            case 4 : /* hyphen-hyphen comment */
140
                loc = srcText.indexOf(lineSep, operLocation + 2);
141
                if (loc < 0)
142
                    return srcText.length();
143
                return loc + lineSep.length();
144
        }
145
        // we should never get here
146
        return srcText.length();
147
    }
148
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpSystem.java (+35 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
import org.eclipse.equinox.bidi.internal.complexp.CxpSingle;
15
16
/**
17
 * Processor adapted to processing expressions with the following string format:
18
 * <pre>
19
 *  system(user)
20
 * </pre>
21
 */
22
public class CxpSystem extends CxpSingle {
23
    static final CxpFeatures FEATURES = new CxpFeatures("(", 0, -1, -1, false, false); //$NON-NLS-1$
24
25
    /**
26
     *  This method retrieves the features specific to this processor.
27
     *
28
     *  @return features with one operator (opening parhenthesis),
29
     *          no special cases, LTR direction for Arabic and Hebrew,
30
     *          and support for both.
31
     */
32
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
33
        return FEATURES;
34
    }
35
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpURL.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 * Processor adapted to processing URLs.
17
 */
18
public class CxpURL extends CxpProcessor {
19
    static final CxpFeatures FEATURES = new CxpFeatures(":?#/@.[]", 0, -1, -1, false, false); //$NON-NLS-1$
20
21
    /**
22
     *  This method retrieves the features specific to this processor.
23
     *
24
     *  @return features with operators ":?#/@.[]",
25
     *          no special cases, LTR direction for Arabic and Hebrew,
26
     *          and support for both.
27
     */
28
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
29
        return FEATURES;
30
    }
31
32
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpUnderscore.java (+36 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
15
/**
16
 * Processor adapted to processing compound names.
17
 * This type covers names made of one or more parts, separated by underscores:
18
 * <pre>
19
 *  part1_part2_part3
20
 * </pre>
21
 */
22
public class CxpUnderscore extends CxpProcessor {
23
    static final CxpFeatures FEATURES = new CxpFeatures("_", 0, -1, -1, false, false); //$NON-NLS-1$
24
25
    /**
26
     *  This method retrieves the features specific to this processor.
27
     *
28
     *  @return features with one operator (underscore),
29
     *          no special cases, LTR direction for Arabic and Hebrew,
30
     *          and support for both.
31
     */
32
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
33
        return FEATURES;
34
    }
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/CxpXPath.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 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.internal.complexp.consumable;
12
13
import org.eclipse.equinox.bidi.complexp.*;
14
import org.eclipse.equinox.bidi.internal.complexp.CxpDelims;
15
16
/**
17
 * Processor adapted to processing XPath expressions.
18
 */
19
public class CxpXPath extends CxpDelims {
20
    static final CxpFeatures FEATURES = new CxpFeatures(" /[]<>=!:@.|()+-*", 2, -1, -1, false, false); //$NON-NLS-1$
21
22
    /**
23
     *  This method retrieves the features specific to this processor.
24
     *
25
     *  @return features with operators " /[]<>=!:@.|()+-*",
26
     *          2 special cases, LTR direction for Arabic and Hebrew,
27
     *          and support for both.
28
     */
29
    public CxpFeatures init(CxpHelper ceh, CxpEnv env) {
30
        return FEATURES;
31
    }
32
33
    /**
34
     *  @return parentheses apostrophe and quotation mark as delimiters.
35
     */
36
    protected String getDelimiters() {
37
        return "''\"\""; //$NON-NLS-1$
38
    }
39
40
}
(-)src/org/eclipse/equinox/bidi/internal/complexp/consumable/package.html (+14 lines)
Added Link Here
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
<html>
3
<head>
4
<META name="Author" content="Matitiahu Allouche">
5
</head>
6
<body bgcolor="white">
7
8
This package provides implementations for complex expression processors.
9
More specifically, it provides implementations for all the
10
complex expression processors whose types are listed in
11
{@link <a href="..\..\..\complexp\IProcessorTypes.html">IProcessorTypes</a>}.
12
13
</body>
14
</html>
(-)src/org/eclipse/equinox/bidi/internal/complexp/package.html (+12 lines)
Added Link Here
1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
<html>
3
<head>
4
<META name="Author" content="Matitiahu Allouche">
5
</head>
6
<body bgcolor="white">
7
8
This package provides internal tools for the implementation
9
of complex expression processors.
10
11
</body>
12
</html>

Return to bug 183164