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

Collapse All | Expand All

(-)META-INF/MANIFEST.MF (-4 / +6 lines)
Lines 7-19 Link Here
7
Bundle-Localization: plugin
7
Bundle-Localization: plugin
8
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
8
Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.2
9
Bundle-ActivationPolicy: lazy
9
Bundle-ActivationPolicy: lazy
10
Export-Package: org.eclipse.equinox.bidi.complexp,
10
Export-Package: org.eclipse.equinox.bidi,
11
 org.eclipse.equinox.bidi.internal.complexp;x-internal:=true,
11
 org.eclipse.equinox.bidi.custom,
12
 org.eclipse.equinox.bidi.internal.complexp.consumable;x-internal:=true
12
 org.eclipse.equinox.bidi.internal;x-internal:=true,
13
 org.eclipse.equinox.bidi.internal.consumable;x-internal:=true
13
Require-Bundle: org.eclipse.equinox.common;bundle-version="3.6.0",
14
Require-Bundle: org.eclipse.equinox.common;bundle-version="3.6.0",
14
 org.eclipse.equinox.registry;bundle-version="3.5.0"
15
 org.eclipse.equinox.registry;bundle-version="3.5.0"
15
Import-Package: org.eclipse.osgi.framework.log;version="1.0.0",
16
Import-Package: org.eclipse.osgi.framework.log;version="1.0.0",
17
 org.eclipse.osgi.service.localization;version="1.1.0",
16
 org.eclipse.osgi.util;version="1.1.0",
18
 org.eclipse.osgi.util;version="1.1.0",
17
 org.osgi.framework;version="1.5.0",
19
 org.osgi.framework;version="1.5.0",
18
 org.osgi.util.tracker;version="1.4.0"
20
 org.osgi.util.tracker;version="1.4.0"
19
Bundle-Activator: org.eclipse.equinox.bidi.internal.complexp.BiDiActivator
21
Bundle-Activator: org.eclipse.equinox.bidi.internal.BidiComplexActivator
(-)build.properties (-2 / +2 lines)
Lines 13-21 Link Here
13
bin.includes = plugin.xml,\
13
bin.includes = plugin.xml,\
14
               META-INF/,\
14
               META-INF/,\
15
               .,\
15
               .,\
16
               .options,\
17
               about.html,\
16
               about.html,\
18
               plugin.properties
17
               plugin.properties,\
18
               schema/
19
src.includes = about.html,\
19
src.includes = about.html,\
20
               schema/
20
               schema/
21
jre.compilation.profile = J2SE-1.3
21
jre.compilation.profile = J2SE-1.3
(-)plugin.xml (-12 / +12 lines)
Lines 8-68 Link Here
8
         point="org.eclipse.equinox.bidi.bidiTypes">
8
         point="org.eclipse.equinox.bidi.bidiTypes">
9
      <typeDescription
9
      <typeDescription
10
            description="%sqlProcessorName"
10
            description="%sqlProcessorName"
11
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpSql"
11
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexSql"
12
            type="sql">
12
            type="sql">
13
      </typeDescription>
13
      </typeDescription>
14
      <typeDescription
14
      <typeDescription
15
            description="%regexProcessorName"
15
            description="%regexProcessorName"
16
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpRegex"
16
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexRegex"
17
            type="regex">
17
            type="regex">
18
      </typeDescription>
18
      </typeDescription>
19
      <typeDescription
19
      <typeDescription
20
            description="%javaProcessorName"
20
            description="%javaProcessorName"
21
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpJava"
21
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexJava"
22
            type="java">
22
            type="java">
23
      </typeDescription>
23
      </typeDescription>
24
      <typeDescription
24
      <typeDescription
25
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpComma"
25
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexComma"
26
            description="%commaProcessorName"
26
            description="%commaProcessorName"
27
            type="comma">
27
            type="comma">
28
      </typeDescription>
28
      </typeDescription>
29
      <typeDescription
29
      <typeDescription
30
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpEmail"
30
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexEmail"
31
            description="%emailProcessorName"
31
            description="%emailProcessorName"
32
            type="email">
32
            type="email">
33
      </typeDescription>
33
      </typeDescription>
34
      <typeDescription
34
      <typeDescription
35
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpFile"
35
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexFile"
36
            description="%fileProcessorName"
36
            description="%fileProcessorName"
37
            type="file">
37
            type="file">
38
      </typeDescription>
38
      </typeDescription>
39
      <typeDescription
39
      <typeDescription
40
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpMath"
40
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexMath"
41
            description="%mathProcessorName"
41
            description="%mathProcessorName"
42
            type="math">
42
            type="math">
43
      </typeDescription>
43
      </typeDescription>
44
      <typeDescription
44
      <typeDescription
45
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpProperty"
45
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexProperty"
46
            description="%propertyProcessorName"
46
            description="%propertyProcessorName"
47
            type="property">
47
            type="property">
48
      </typeDescription>
48
      </typeDescription>
49
      <typeDescription
49
      <typeDescription
50
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpSystem"
50
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexSystem"
51
            description="%systemProcessorName"
51
            description="%systemProcessorName"
52
            type="system">
52
            type="system">
53
      </typeDescription>
53
      </typeDescription>
54
      <typeDescription
54
      <typeDescription
55
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpUnderscore"
55
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexUnderscore"
56
            description="%underscoreProcessorName"
56
            description="%underscoreProcessorName"
57
            type="underscore">
57
            type="underscore">
58
      </typeDescription>
58
      </typeDescription>
59
      <typeDescription
59
      <typeDescription
60
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpURL"
60
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexURL"
61
            description="%urlProcessorName"
61
            description="%urlProcessorName"
62
            type="url">
62
            type="url">
63
      </typeDescription>
63
      </typeDescription>
64
      <typeDescription
64
      <typeDescription
65
            class="org.eclipse.equinox.bidi.internal.complexp.consumable.ComplExpXPath"
65
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexXPath"
66
            description="%xpathProcessorName"
66
            description="%xpathProcessorName"
67
            type="xpath">
67
            type="xpath">
68
      </typeDescription>
68
      </typeDescription>
(-)schema/BiDiExpressionType.exsd (-1 / +1 lines)
Lines 63-69 Link Here
63
                  The processor that provides specialized bi-directional handling for this type of strings.
63
                  The processor that provides specialized bi-directional handling for this type of strings.
64
               </documentation>
64
               </documentation>
65
               <appInfo>
65
               <appInfo>
66
                  <meta.attribute kind="java" basedOn=":org.eclipse.equinox.bidi.complexp.IComplExpProcessor"/>
66
                  <meta.attribute kind="java" basedOn=":org.eclipse.equinox.bidi.custom.IBidiComplexProcessor"/>
67
               </appInfo>
67
               </appInfo>
68
            </annotation>
68
            </annotation>
69
         </attribute>
69
         </attribute>
(-)src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java (+315 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import java.util.Locale;
14
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
15
import org.eclipse.equinox.bidi.internal.BidiComplexActivator;
16
17
/**
18
 *  This class defines certain details of the environment within which
19
 *  complex expressions are processed.
20
 *  <p>
21
 *  All public fields in this class are <code>final</code>, i.e. cannot be
22
 *  changed after creating an instance.
23
 *  <p>
24
 *  A <code>BidiComplexEnvironment</code> instance can be associated with a <code>BidiComplexHelper</code>
25
 *  instance either when creating the
26
 * {@link BidiComplexHelper#BidiComplexHelper(java.lang.String, BidiComplexEnvironment) BidiComplexHelper} instance
27
 *  or using the {@link BidiComplexHelper#setEnvironment setEnvironment} method.
28
 *
29
 *  <h2>Code Samples</h2>
30
 *  <p>Example 1 (set all environment parameters)
31
 *  <pre>
32
 *
33
 *    BidiComplexEnvironment myEnv = new BidiComplexEnvironment("he_IL", true, BidiComplexEnvironment.ORIENT_RTL);
34
 *    BidiComplexHelper myHelper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE, myEnv);
35
 *
36
 *  </pre>
37
 *  <p>Example 2 (change only the orientation)
38
 *  <pre>
39
 *
40
 *    BidiComplexEnvironment env1 = myHelper.getEnvironment();
41
 *    BidiComplexEnvironment env2 = new BidiComplexEnvironment(env1.language, env1.mirrored, BidiComplexEnvironment.ORIENT_UNKNOWN);
42
 *    myHelper.setEnvironment(env2);
43
 *
44
 *  </pre>
45
 *  <p>
46
 *  This class also provides a number of convenience methods related to the environment.
47
 *  <p>&nbsp;</p>
48
 *  @see BidiComplexHelper#BidiComplexHelper(String, BidiComplexEnvironment)
49
 *  @see BidiComplexHelper#BidiComplexHelper(IBidiComplexProcessor, BidiComplexEnvironment)
50
 *  @see BidiComplexHelper#getEnvironment BidiComplexHelper.getEnvironment
51
 *  @see BidiComplexHelper#setEnvironment BidiComplexHelper.setEnvironment
52
 *  @see IBidiComplexProcessor#init IBidiComplexProcessor.init
53
 *  @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment
54
 *
55
 *  @author Matitiahu Allouche
56
 */
57
public class BidiComplexEnvironment {
58
59
	/**
60
	 *  Constant specifying that the orientation of the GUI component
61
	 *  where a complex expression will be displayed is LTR.
62
	 *  It can appear as <code>orientation</code> argument for
63
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
64
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
65
	 */
66
	public static final int ORIENT_LTR = 0;
67
68
	/**
69
	 *  Constant specifying that the orientation of the GUI component
70
	 *  where a complex expression will be displayed is RTL.
71
	 *  It can appear as <code>orientation</code> argument for
72
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
73
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
74
	 */
75
	public static final int ORIENT_RTL = 1;
76
77
	/**
78
	 *  Constant specifying that the orientation of the GUI component
79
	 *  where a complex expression will be displayed is contextual with
80
	 *  a default of LTR (if no strong character appears in the text).
81
	 *  It can appear as <code>orientation</code> argument for
82
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
83
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
84
	 */
85
	public static final int ORIENT_CONTEXTUAL_LTR = 2;
86
87
	/**
88
	 *  Constant specifying that the orientation of the GUI component
89
	 *  where a complex expression will be displayed is contextual with
90
	 *  a default of RTL (if no strong character appears in the text).
91
	 *  It can appear as <code>orientation</code> argument for
92
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
93
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
94
	 */
95
	public static final int ORIENT_CONTEXTUAL_RTL = 3;
96
97
	/**
98
	 *  Constant specifying that the orientation of the GUI component
99
	 *  where a complex expression will be displayed is not known.
100
	 *  Directional formatting characters must be added as prefix and
101
	 *  suffix whenever a <i>full</i> text is generated using
102
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}.
103
	 *  It can appear as <code>orientation</code> argument for
104
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
105
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
106
	 */
107
	public static final int ORIENT_UNKNOWN = 4;
108
109
	/**
110
	 *  Constant specifying that whatever the orientation of the
111
	 *  GUI component where a complex expression will be displayed, no
112
	 *  directional formatting characters must be added as prefix or
113
	 *  suffix when a <i>full</i> text is generated using
114
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}.
115
	 *  It can appear as <code>orientation</code> argument for
116
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the
117
	 *  {@link BidiComplexEnvironment#orientation} member of <code>BidiComplexEnvironment</code>.
118
	 */
119
	public static final int ORIENT_IGNORE = 5;
120
121
	/**
122
	 *  Pre-defined <code>BidiComplexEnvironment</code> instance with values for a non-mirrored GUI
123
	 *  and a Left-to-Right presentation component.<br>
124
	 *  The language is set to <code>null</code>, which defaults to the language
125
	 *  of the current default locale.
126
	 */
127
	public static final BidiComplexEnvironment DEFAULT = new BidiComplexEnvironment(null, false, ORIENT_LTR);
128
129
	/**
130
	 *  This string is a 2-letters code representing a language as defined by
131
	 *  ISO-639. If left as <code>null</code>, it defaults to the language
132
	 *  of the current default locale.
133
	 */
134
	public final String language;
135
136
	/**
137
	 *  Flag specifying that complex expressions processed under this environment
138
	 *  should assume that the GUI is mirrored (globally going from right to left).
139
	 */
140
	public final boolean mirrored;
141
142
	/** Specify the orientation (a.k.a. base direction) of the GUI
143
	 *  component in which the <i>full</i> text of the complex expression will
144
	 *  be displayed.<br>
145
	 *  The orientation must have one of the values
146
	 *  {@link #ORIENT_LTR ORIENT_LTR},
147
	 *  {@link #ORIENT_LTR ORIENT_RTL},
148
	 *  {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
149
	 *  {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
150
	 *  {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
151
	 *  {@link #ORIENT_IGNORE ORIENT_IGNORE}.
152
	  *  <p>
153
	 *  When the orientation is <code>ORIENT_LTR</code> and the complex
154
	 *  expression has a RTL base direction,
155
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}
156
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
157
	 *  end.
158
	 *  <p>
159
	 *  When the orientation is <code>ORIENT_RTL</code> and the complex
160
	 *  expression has a LTR base direction,
161
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}
162
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
163
	 *  end.
164
	 *  <p>
165
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
166
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
167
	 *  to a RTL orientation while the complex expression has a LTR base
168
	 *  direction, {@link BidiComplexHelper#leanToFullText leanToFullText}
169
	 *  adds LRM at the head of the <i>full</i> text.
170
	 *  <p>
171
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
172
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
173
	 *  to a LTR orientation while the complex expression has a RTL base
174
	 *  direction, {@link BidiComplexHelper#leanToFullText leanToFullText}
175
	 *  adds RLM at the head of the <i>full</i> text.
176
	 *  <p>
177
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
178
	 *  expression has a LTR base direction,
179
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}
180
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
181
	 *  end.
182
	 *  <p>
183
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
184
	 *  expression has a RTL base direction,
185
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText}
186
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
187
	 *  end.
188
	 *  <p>
189
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
190
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText} does not add any directional
191
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
192
	 *  <p>
193
	 */
194
	public final int orientation;
195
196
	static Locale defaultLocale;
197
	static String defaultLanguage;
198
	static boolean defaultBidi;
199
	boolean bidiFlag;
200
201
	/**
202
	 *  Constructor
203
	 *
204
	 *  @param lang represents the language to be used in this environment.
205
	 *          It should be specified as a 2-letters code as defined by
206
	 *          ISO-639.<br>
207
	 *          If longer than 2 letters, the extra letters are ignored.<br>
208
	 *          If set to <code>null</code>, it defaults to the language
209
	 *          of the default locale.
210
	 *  @see #language
211
	 *
212
	 *  @param mirrored specifies if the GUI is mirrored.
213
	 *  @see #mirrored
214
	 *
215
	 *  @param orientation specifies the orientation of the component
216
	 *          which is to display the complex expression. It must be
217
	 *          one of the values
218
	 *          {@link #ORIENT_LTR ORIENT_LTR},
219
	 *          {@link #ORIENT_LTR ORIENT_RTL},
220
	 *          {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
221
	 *          {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
222
	 *          {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
223
	 *          {@link #ORIENT_IGNORE ORIENT_IGNORE}.<br>
224
	 *          If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}.
225
	 *  @see #orientation
226
	 */
227
	public BidiComplexEnvironment(String lang, boolean mirrored, int orientation) {
228
		if (lang == null) {
229
			language = null;
230
		} else {
231
			if (lang.length() > 2)
232
				language = lang.substring(0, 2);
233
			else
234
				language = lang;
235
			bidiFlag = isBidiLanguage(language);
236
		}
237
		this.mirrored = mirrored;
238
		this.orientation = orientation >= ORIENT_LTR && orientation <= ORIENT_IGNORE ? orientation : ORIENT_UNKNOWN;
239
	}
240
241
	/**
242
	 *  Check whether the current language uses a
243
	 *  bidi script (Arabic, Hebrew, Farsi or Urdu).
244
	 *
245
	 *  @return <code>true</code> if the current language uses a bidi script.
246
	 *          The language may have been set explicitly when creating the
247
	 *          <code>BidiComplexEnvironment</code> instance, or it may have defaulted to
248
	 *          the language of the current default locale.
249
	 *  @see #BidiComplexEnvironment BidiComplexEnvironment
250
	 */
251
	public boolean isBidi() {
252
		if (defaultLanguage != null && defaultLocale.equals(getDefaultLocale()))
253
			return defaultBidi;
254
255
		if (language == null) {
256
			defaultLocale = getDefaultLocale();
257
			defaultLanguage = defaultLocale.getLanguage();
258
			defaultBidi = isBidiLanguage(defaultLanguage);
259
			return defaultBidi;
260
		}
261
262
		return bidiFlag;
263
	}
264
265
	static boolean isBidiLanguage(String lang) {
266
		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$
267
	}
268
269
	static String lineSep;
270
271
	/**
272
	 *  Retrieve the string which represents a line separator in this environment.
273
	 *
274
	 *  @return the string which is used as line separator (e.g. CRLF).
275
	 */
276
	public static String getLineSep() {
277
		// use bundle properties
278
		if (lineSep == null) {
279
			//          lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
280
			lineSep = getProperty("line.separator"); //$NON-NLS-1$/
281
		}
282
		return lineSep;
283
	}
284
285
	static String osName;
286
	static boolean flagOS;
287
288
	private static String getProperty(String key) {
289
		// use bundle properties
290
		//      osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
291
		BidiComplexActivator bidiComplexActivator = BidiComplexActivator.getInstance();
292
		return bidiComplexActivator.getProperty(key);
293
	}
294
295
	private Locale getDefaultLocale() {
296
		BidiComplexActivator bidiComplexActivator = BidiComplexActivator.getInstance();
297
		return bidiComplexActivator.getDefaultLocale();
298
	}
299
300
	/**
301
	 *  Check if the current OS is supported by the complex expression packages.
302
	 *
303
	 *  @return <code>true</code> if the current OS is supported.
304
	 */
305
	public static boolean isSupportedOS() {
306
		if (osName == null) {
307
			// use bundle properties
308
			// osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
309
			osName = getProperty("os.name").toLowerCase(); //$NON-NLS-1$/
310
			flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$
311
		}
312
		return flagOS;
313
	}
314
315
}
(-)src/org/eclipse/equinox/bidi/BidiComplexFeatures.java (+190 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
14
15
/**
16
 *  This class defines features of a complex expression processor.
17
 *  <p>
18
 *  All public fields in this class are <code>final</code>, i.e. cannot be
19
 *  changed after creating an instance.
20
 *  <p>
21
 *  A <code>BidiComplexFeatures</code> instance can be associated with a
22
 *  <code>BidiComplexHelper</code> instance using
23
 *  the {@link BidiComplexHelper#setFeatures setFeatures} method.
24
 *
25
 *  <h2>Code Samples</h2>
26
 *  <p>Example 1 (set all features)
27
 *  <pre>
28
 *
29
 *    BidiComplexFeatures myFeatures = new BidiComplexFeatures("+-=", 0, -1, -1, false, false);
30
 *    BidiComplexHelper myHelper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE, myEnv);
31
 *    myHelper.setFeatures(myFeatures);
32
 *
33
 *  </pre>
34
 *  <p>Example 2 (change only the operators)
35
 *  <pre>
36
 *
37
 *    BidiComplexFeatures f1 = myHelper.getFeatures();
38
 *    BidiComplexFeatures f2 = new BidiComplexFeatures("[]|()", f1.specialsCount,
39
 *                                     f1.dirArabic, f1.dirHebrew,
40
 *                                     f1.ignoreArabic, f1.ignoreHebrew);
41
 *    myHelper.setFeatures(f2);
42
 *
43
 *  </pre>
44
 *
45
 *  @see BidiComplexHelper#getFeatures BidiComplexHelper.getFeatures
46
 *  @see BidiComplexHelper#setFeatures BidiComplexHelper.setFeatures
47
 *  @see IBidiComplexProcessor#init IBidiComplexProcessor.init
48
 *  @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment
49
 *
50
 *  @author Matitiahu Allouche
51
 */
52
public class BidiComplexFeatures {
53
54
	/**
55
	 *  Constant specifying that the base direction of a complex expression is LTR.
56
	 *  The base direction may depend on whether the GUI is
57
	 *  {@link BidiComplexEnvironment#mirrored mirrored} and may
58
	 *  may be different for Arabic and for Hebrew.
59
	 *  This constant can appear as <code>dirArabic</code>
60
	 *  or <code>dirHebrew</code> argument for
61
	 *  {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} and as value
62
	 *  for the {@link #dirArabic} or {@link #dirHebrew} members of
63
	 *  <code>BidiComplexFeatures</code>.
64
	 */
65
	public static final int DIR_LTR = 0;
66
67
	/**
68
	 *  Constant specifying that the base direction of a complex expression is RTL.
69
	 *  The base direction may depend on whether the GUI is
70
	 *  {@link BidiComplexEnvironment#mirrored mirrored} and may
71
	 *  may be different for Arabic and for Hebrew.
72
	 *  This constant can appear as <code>dirArabic</code>
73
	 *  or <code>dirHebrew</code> argument for
74
	 *  {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} and as value
75
	 *  for the {@link #dirArabic} or {@link #dirHebrew} members of
76
	 *  <code>BidiComplexFeatures</code>.
77
	 */
78
	public static final int DIR_RTL = 1;
79
80
	/**
81
	 *  Pre-defined <code>BidiComplexFeatures</code> instance with values for no
82
	 *  operators, no special processing, all directions LTR
83
	 *  and support for neither Arabic nor Hebrew.<br>
84
	 *  Since there are no operators and no special processing, a complex
85
	 *  expression processor with such features would do nothing.<br>
86
	 *  It is more efficient to do nothing with a
87
	 *  {@link BidiComplexHelper#BidiComplexHelper() BidiComplexHelper}
88
	 *  instantiated with no arguments.
89
	 */
90
	public static final BidiComplexFeatures DEFAULT = new BidiComplexFeatures(null, 0, -1, -1, true, true);
91
92
	/**
93
	 *  String grouping one-character operators which
94
	 *  separate the text of the complex expression into tokens.
95
	 */
96
	public final String operators;
97
98
	/**
99
	 *  Number of special cases for the associated processor.
100
	 *  Special cases exist for some types of complex expression processors.
101
	 *  They are implemented by overriding methods
102
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and
103
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial}.
104
	 *  Examples of special cases are comments, literals, or anything which
105
	 *  is not identified by a one-character operator.
106
	 */
107
	public final int specialsCount;
108
109
	/**
110
	 *  Base direction of the complex expression for Arabic.
111
	 *  If a complex expression contains both Arabic and
112
	 *  Hebrew words, the first Arabic or Hebrew letter in the
113
	 *  expression determines which is the governing script).<br>
114
	 *  The value of this field must be one of
115
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
116
	 *
117
	 *  @see #dirHebrew
118
	 */
119
	public final int dirArabic;
120
121
	/**
122
	 *  Base direction of the complex expression for Hebrew.
123
	 *  If a complex expression contains both Arabic and
124
	 *  Hebrew words, the first Arabic or Hebrew letter in the
125
	 *  expression determines which is the governing script).<br>
126
	 *  The value of this field must be one of
127
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
128
	 *
129
	 *  @see #dirArabic
130
	 */
131
	public final int dirHebrew;
132
133
	/**
134
	 *  Flag indicating that Arabic letters will not be considered for
135
	 *  processing complex expressions. If both this flag and
136
	 *  {@link #ignoreHebrew} are set to <code>true</code>, the
137
	 *  processor will do nothing (but some overhead can be expected).
138
	 */
139
	public final boolean ignoreArabic;
140
141
	/**
142
	 *  Flag indicating that Hebrew letters will not be considered for
143
	 *  processing complex expressions. If both this flag and
144
	 *  {@link #ignoreArabic} are set to <code>true</code>, the
145
	 *  processor will do nothing (but some overhead can be expected).
146
	 */
147
	public final boolean ignoreHebrew;
148
149
	/**
150
	 *  Constructor
151
	 *
152
	 *  @param operators is a string where each character is a delimiter
153
	 *          which separates the complex expression into tokens.
154
	 *  @see #operators
155
	 *
156
	 *  @param specialsCount specifies the number of special cases handled
157
	 *          by the processor.
158
	 *  @see #specialsCount
159
	 *
160
	 *  @param dirArabic specifies the base direction of the complex expression
161
	 *          for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
162
	 *          If it is not (for instance if it is a negative value), it
163
	 *          defaults to <code>DIR_LTR</code>.
164
	 *  @see #dirArabic
165
	 *
166
	 *  @param dirHebrew specifies the base direction of the complex expression
167
	 *          for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
168
	 *          If it is not (for instance if it is a negative value), it
169
	 *          defaults to <code>DIR_LTR</code>.
170
	 *  @see #dirHebrew
171
	 *
172
	 *  @param ignoreArabic indicates that Arabic letters will not be
173
	 *          considered for processing complex expressions.
174
	 *  @see #ignoreArabic
175
	 *
176
	 *  @param ignoreHebrew indicates that Hebrew letters will not be
177
	 *          considered for processing complex expressions.
178
	 *  @see #ignoreHebrew
179
	 */
180
	public BidiComplexFeatures(String operators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) {
181
182
		this.operators = operators == null ? "" : operators; //$NON-NLS-1$
183
		this.specialsCount = specialsCount;
184
		this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR;
185
		this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR;
186
		this.ignoreArabic = ignoreArabic;
187
		this.ignoreHebrew = ignoreHebrew;
188
	}
189
190
}
(-)src/org/eclipse/equinox/bidi/BidiComplexHelper.java (+568 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import org.eclipse.equinox.bidi.custom.BidiComplexStringProcessor;
14
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
15
import org.eclipse.equinox.bidi.internal.BidiComplexImpl;
16
17
/**
18
 *  This class acts as a mediator between applications and complex
19
 *  expression processors.
20
 *  The purpose of complex expression processors is to add directional
21
 *  formatting characters to ensure correct display.
22
 *  This class shields applications from the
23
 *  intricacies of complex expression processors.
24
 *  <p>
25
 *  For a general introduction to complex expressions, see
26
 *  {@link <a href="package-summary.html">
27
 *  the package documentation</a>}.
28
 *
29
 *  <h2>Code Sample</h2>
30
 *
31
 *  <p>The following code shows how to instantiate a BidiComplexHelper adapted for a
32
 *  certain type of complex expression (directory and file paths), and how
33
 *  to obtain the <i>full</i> text corresponding to the <i>lean</i> text
34
 *  of such an expression.
35
 *
36
 *  <pre>
37
 *
38
 *    BidiComplexHelper helper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE);
39
 *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
40
 *    String fullText = helper.leanToFullText(leanText);
41
 *    System.out.println("full text = " + fullText);
42
 *
43
 *  </pre>
44
 *  This class provides a user-oriented API but does not provides
45
 *  an actual implementation. The real work is done by the class
46
 *  {@link BidiComplexImpl}. Users of the API need not be concerned by, and
47
 *  should not depend upon, details of the implementation by
48
 *  <code>BidiComplexImpl</code>.
49
 *
50
 *  @author Matitiahu Allouche
51
 *
52
 */
53
public class BidiComplexHelper {
54
	/**
55
	 *  Constant to use as <code>initState</code> argument when calling
56
	 *  {@link #leanToFullText(java.lang.String, int) leanToFullText} or
57
	 *  {@link #fullToLeanText(java.lang.String, int) fullToLeanText}
58
	 *  to indicate that there is no context of previous lines which
59
	 *  should be initialized before performing the operation.
60
	 */
61
	public static final int STATE_NOTHING_GOING = -1;
62
63
	private static final int[] EMPTY_INT_ARRAY = new int[0];
64
65
	/**
66
	 *  Reference to the {@link BidiComplexImpl} instance which accomplishes
67
	 *  most of the work. This member should be accessed only by
68
	 *  complex expression processors (implementing {@link IBidiComplexProcessor}).
69
	 */
70
	public BidiComplexImpl impl;
71
72
	/**
73
	 *  Create a <code>BidiComplexHelper</code> instance which does nothing tangible
74
	 *  but does it quickly. We will call it a <i>no-op helper</i>.
75
	 *  The {@link #BidiComplexHelper() no-op helper} does not modify text submitted to it, and can be
76
	 *  used when it is known that no complex expression processing
77
	 *  is needed, for instance because no bidi text is expected. With this
78
	 *  helper, the cost of invoking the complex expression API is minimal.
79
	 */
80
	public BidiComplexHelper() {
81
		// let impl stay null
82
	}
83
84
	/**
85
	 *  Create a <code>BidiComplexHelper</code> instance to process expressions
86
	 *  of type <code>type</code> with a
87
	 *  {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment.
88
	 *
89
	 *  @param type represents the type of the complex expression. It must
90
	 *          be one of the values in {@link IBidiComplexExpressionTypes}, or a type
91
	 *          added in a plug-in extension.
92
	 *
93
	 *  @throws IllegalArgumentException if the <code>type</code> is not
94
	 *          supported.
95
	 */
96
	public BidiComplexHelper(String type) {
97
		this(type, null);
98
	}
99
100
	/**
101
	 *  Create a <code>BidiComplexHelper</code> instance to process expressions
102
	 *  of type <code>type</code> operating under the environment
103
	 *  {@link BidiComplexEnvironment environment}.
104
	 *
105
	 *  @param type represents the type of the complex expression. It must
106
	 *          be one of the values in {@link IBidiComplexExpressionTypes}, or a type
107
	 *          added in a plug-in extension.
108
	 *
109
	 *  @param environment represents the environment where the complex expression
110
	 *          will be displayed. It is better to specify the environment
111
	 *          when instantiating a <code>BidiComplexHelper</code> than to specify
112
	 *          it later using {@link #setEnvironment setEnvironment}.<br>
113
	 *          <code>null</code> can be specified here for a
114
	 *          {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment.
115
	 *
116
	 *  @throws IllegalArgumentException if the <code>type</code> is not
117
	 *          supported.
118
	 */
119
	public BidiComplexHelper(String type, BidiComplexEnvironment environment) {
120
		IBidiComplexProcessor processor = BidiComplexStringProcessor.getProcessor(type);
121
		if (processor == null) {
122
			throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
123
		}
124
		impl = new BidiComplexImpl(this, processor, environment);
125
	}
126
127
	/**
128
	 *  Create a <code>BidiComplexHelper</code> instance to process complex
129
	 *  expressions by means of a given processor <code>myProcessor</code>,
130
	 *  operating under the environment {@link BidiComplexEnvironment environment}.
131
	 *
132
	 *  @param myProcessor is a complex expression processor.
133
	 *
134
	 *  @param environment represents the environment where the complex expression
135
	 *          will be displayed. It is better to specify the environment
136
	 *          when instantiating a <code>BidiComplexHelper</code> than to specify
137
	 *          it later using {@link #setEnvironment setEnvironment}.<br>
138
	 *          <code>null</code> can be specified here for a
139
	 *          {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment.
140
	 */
141
	public BidiComplexHelper(IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment) {
142
		impl = new BidiComplexImpl(this, myProcessor, environment);
143
	}
144
145
	/** Add directional formatting characters to a complex expression
146
	 *  to ensure correct presentation.
147
	 *
148
	 *  @param text is the text of the complex expression.
149
	 *
150
	 *  @return the complex expression with directional formatting
151
	 *          characters added at proper locations to ensure correct
152
	 *          presentation.<br>
153
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>text</code>.
154
	 */
155
	public String leanToFullText(String text) {
156
		return leanToFullText(text, STATE_NOTHING_GOING);
157
	}
158
159
	/**
160
	 *  Add directional formatting characters to a complex expression
161
	 *  to ensure correct presentation.
162
	 *
163
	 *  @param  text is the text of the complex expression.
164
	 *
165
	 *  @param  initState specifies that the first parameter is the
166
	 *          continuation of text submitted in a previous call.
167
	 *          The <code>initState</code> of the present call must be
168
	 *          the final state obtained by calling
169
	 *          {@link #getFinalState() getFinalState}
170
	 *          after the previous call.
171
	 *          <br>If the present call is not a continuation of
172
	 *          text submitted in a previous call, the value
173
	 *          {@link #STATE_NOTHING_GOING} should be used as argument.
174
	 *
175
	 *  @return the complex expression with directional formatting
176
	 *          characters added at proper locations to ensure correct
177
	 *          presentation.<br>
178
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>text</code>.
179
	 *
180
	 *  @see #getFinalState getFinalState
181
	 */
182
	public String leanToFullText(String text, int initState) {
183
		if (impl == null)
184
			return text;
185
		return impl.leanToFullText(text, initState);
186
	}
187
188
	/**
189
	 *  Given a complex expression, get the offsets of characters before
190
	 *  which directional formatting characters must be added in order to
191
	 *  ensure correct presentation.
192
	 *  Only LRMs (for an expression with LTR base direction) and RLMs (for
193
	 *  an expression with RTL base direction) are considered. Leading and
194
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
195
	 *  depending on the {@link BidiComplexEnvironment#orientation orientation} of the
196
	 *  GUI component used for display are not reflected in this method.
197
	 *  <p>
198
	 *  This method assumes that a successful call to
199
	 *  {@link #leanToFullText leanToFullText} has been performed, and it
200
	 *  returns the offsets relevant for the last text submitted.
201
	 *
202
	 *  @return an array of offsets to the characters in the last submitted
203
	 *          complex expression before which directional marks must be
204
	 *          added to ensure correct presentation.
205
	 *          The offsets are sorted in ascending order.<br>
206
	 *          The {@link #BidiComplexHelper() no-op helper} returns an array of 0 elements.
207
	 */
208
	public int[] leanBidiCharOffsets() {
209
		if (impl == null)
210
			return EMPTY_INT_ARRAY;
211
		return impl.leanBidiCharOffsets();
212
	}
213
214
	/**
215
	 *  Get the offsets of characters in the <i>full</i> text of a
216
	 *  complex expression corresponding to directional formatting
217
	 *  characters which have been added in order to ensure correct presentation.
218
	 *  LRMs (for an expression with LTR base direction), RLMs (for
219
	 *  an expression with RTL base direction) are considered as well as
220
	 *  leading and trailing LRE, RLE and PDF which might be prefixed or suffixed
221
	 *  depending on the {@link BidiComplexEnvironment#orientation orientation} of the
222
	 *  GUI component used for display.
223
	 *  <p>
224
	 *  This method assumes that a successful call to
225
	 *  {@link #leanToFullText leanToFullText} has been performed, and it
226
	 *  returns the offsets relevant for the last text submitted.
227
	 *
228
	 *  @return an array of offsets to the characters in the <i>full</i>
229
	 *          text of the last submitted complex expression which are
230
	 *          directional formatting characters added to ensure correct
231
	 *          presentation.
232
	 *          The offsets are sorted in ascending order.<br>
233
	 *          The {@link #BidiComplexHelper() no-op helper} returns an array of 0 elements.
234
	 */
235
	public int[] fullBidiCharOffsets() {
236
		if (impl == null)
237
			return EMPTY_INT_ARRAY;
238
		return impl.fullBidiCharOffsets();
239
	}
240
241
	/**
242
	 *  Remove directional formatting characters which were added to a
243
	 *  complex expression to ensure correct presentation.
244
	 *
245
	 *  @param text is the text of the complex expression including
246
	 *         directional formatting characters.
247
	 *
248
	 *  @return the complex expression without directional formatting
249
	 *          characters which might have been added by processing it
250
	 *          with {@link #leanToFullText leanToFullText}.<br>
251
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>text</code>
252
	 *
253
	 */
254
	public String fullToLeanText(String text) {
255
		return fullToLeanText(text, STATE_NOTHING_GOING);
256
	}
257
258
	/**
259
	 *  Remove directional formatting characters which were added to a
260
	 *  complex expression to ensure correct presentation.
261
	 *
262
	 *  @param text is the text of the complex expression including
263
	 *         directional formatting characters.
264
	 *
265
	 *  @param initState specifies that the first parameter is the
266
	 *         continuation of text submitted in a previous call.
267
	 *         The <code>initState</code> of the present call must be
268
	 *         the final state obtained by calling
269
	 *         {@link #getFinalState getFinalState} after the previous call.
270
	 *          <br>If the present call is not a continuation of
271
	 *          text submitted in a previous call, the value
272
	 *          {@link #STATE_NOTHING_GOING} should be used as argument.
273
	 *
274
	 *  @return the complex expression without directional formatting
275
	 *          characters which might have been added by processing it
276
	 *          with {@link #leanToFullText leanToFullText}.<br>
277
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>text</code>
278
	 *
279
	 *  @see #getFinalState getFinalState
280
	 */
281
	public String fullToLeanText(String text, int initState) {
282
		if (impl == null)
283
			return text;
284
		return impl.fullToLeanText(text, initState);
285
	}
286
287
	/**
288
	 *  Retrieve the final state achieved in a previous call to
289
	 *  {@link #leanToFullText leanToFullText} or
290
	 *  {@link #fullToLeanText fullToLeanText}.
291
	 *  This state is an opaque value which is meaningful only
292
	 *  within calls to the same complex expression processor.
293
	 *  The only externalized value is
294
	 *  {@link #STATE_NOTHING_GOING} which means that
295
	 *  there is nothing to remember from the last call.
296
	 *  <p>
297
	 *  The state should be used only for complex expressions which come
298
	 *  in parts, like when spanning multiple lines. The user can make
299
	 *  a separate call to
300
	 *  <code>leanToFullText</code> or <code>fullToLeanText</code> for each
301
	 *  line in the expression. The final state value retrieved after the
302
	 *  call for one line should be used as the initial state in the call
303
	 *  which processes the next line.
304
	 *  <p>
305
	 *  If a line within a complex expression has already been processed by
306
	 *  <code>leanToFullText</code> and the <i>lean</i> version of that line has
307
	 *  not changed, and its initial state has not changed either, the user
308
	 *  can be sure that the <i>full</i> version of that line is also
309
	 *  identical to the result of the previous processing.
310
	 *
311
	 *  @see #leanToFullText(String text, int initState)
312
	 *  @see #fullToLeanText(String text, int initState)
313
	 *
314
	 *  @return the last final state.<br>
315
	 *          The {@link #BidiComplexHelper() no-op helper} returns {@link #STATE_NOTHING_GOING}.
316
	 */
317
	public int getFinalState() {
318
		if (impl == null)
319
			return STATE_NOTHING_GOING;
320
		return impl.getFinalState();
321
	}
322
323
	/**
324
	 *  After transforming a <i>lean</i> string into a <i>full</i> string
325
	 *  using {@link #leanToFullText leanToFullText}, compute the index in the
326
	 *  <i>full</i> string of the character corresponding to the
327
	 *  character with the specified position in the <i>lean</i> string.
328
	 *
329
	 *  @param position is the index of a character in the <i>lean</i> string.
330
	 *          It must be a non-negative number smaller than the length
331
	 *          of the <i>lean</i> text.
332
	 *
333
	 *  @return the index of the corresponding character in the
334
	 *          <i>full</i> string.<br>
335
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>position</code>.
336
	 */
337
	public int leanToFullPos(int position) {
338
		if (impl == null)
339
			return position;
340
		return impl.leanToFullPos(position);
341
	}
342
343
	/**
344
	 *  After transforming a <i>lean</i> string into a <i>full</i> string
345
	 *  using {@link #leanToFullText leanToFullText}, compute the index in the
346
	 *  <i>lean</i> string of the character corresponding to the
347
	 *  character with the specified position in the <i>full</i> string.
348
	 *
349
	 *  @param position is the index of a character in the <i>full</i> string.
350
	 *          It must be a non-negative number smaller than the length
351
	 *          of the <i>full</i> text.
352
	 *
353
	 *  @return the index of the corresponding character in the
354
	 *          <i>lean</i> string. If there is no corresponding
355
	 *          character in the <i>lean</i> string (because the
356
	 *          specified character is a directional formatting character
357
	 *          added when invoking {@link #leanToFullText leanToFullText}),
358
	 *          the value returned will be that corresponding to the
359
	 *          next character which is not a directional formatting
360
	 *          character.<br>
361
	 *          If <code>position</code> corresponds to a directional formatting
362
	 *          character beyond all characters of the original
363
	 *          <i>lean</i> text, the value returned is the length of the
364
	 *          <i>lean</i> text.<br>
365
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>position</code>.
366
	 */
367
	public int fullToLeanPos(int position) {
368
		if (impl == null)
369
			return position;
370
		return impl.fullToLeanPos(position);
371
	}
372
373
	/**
374
	 *  Get the base direction of the complex expression last
375
	 *  submitted to {@link #leanToFullText leanToFullText}.
376
	 *  This base direction may depend on
377
	 *  whether the expression contains Arabic or Hebrew words
378
	 *  (if it contains both, the first Arabic or Hebrew letter in the
379
	 *  expression determines which is the governing script) and on
380
	 *  whether the GUI is {@link BidiComplexEnvironment#mirrored mirrored}.
381
	 *
382
	 *  @return the base direction of the last submitted complex
383
	 *          expression. It must be one of the values
384
	 *          {@link BidiComplexFeatures#DIR_LTR} or {@link BidiComplexFeatures#DIR_RTL}.<br>
385
	 *          The {@link #BidiComplexHelper() no-op helper} returns <code>DIR_LTR</code>.
386
	 */
387
	public int getCurDirection() {
388
		if (impl == null)
389
			return BidiComplexFeatures.DIR_LTR;
390
		return impl.getCurDirection();
391
	}
392
393
	/**
394
	 *  Get the current environment under which the <code>BidiComplexHelper</code>
395
	 *  operates.
396
	 *  This environment may have been specified in the constructor or
397
	 *  specified later using {@link #setEnvironment setEnvironment}.<br>
398
	 *
399
	 *  @return the current environment.<br>
400
	 *          The {@link #BidiComplexHelper() no-op helper} returns a {@link BidiComplexEnvironment#DEFAULT DEFAULT}
401
	 *          environment.
402
	 *
403
	 *  @see #setEnvironment setEnvironment
404
	 */
405
	public BidiComplexEnvironment getEnvironment() {
406
		if (impl == null)
407
			return BidiComplexEnvironment.DEFAULT;
408
		return impl.getEnvironment();
409
	}
410
411
	/**
412
	 *  Specify the environment under which the <code>BidiComplexHelper</code>
413
	 *  must operate.
414
	 *  <p>
415
	 *  <b>Note</b> that calling this method causes the processor
416
	 *  associated with this instance of <code>BidiComplexHelper</code>
417
	 *  to re-initialize its features. The effect of a previous call
418
	 *  to {@link #setFeatures(BidiComplexFeatures) setFeatures} is lost.<br>
419
	 *  The {@link #BidiComplexHelper() no-op helper} does nothing.
420
	 *
421
	 *  @see #getEnvironment getEnvironment
422
	 *  @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment
423
	 */
424
	public void setEnvironment(BidiComplexEnvironment environment) {
425
		if (impl != null)
426
			impl.setEnvironment(environment);
427
	}
428
429
	/**
430
	 *  Get the current features of the processor associated with this
431
	 *  <code>BidiComplexHelper</code> instance.
432
	 *
433
	 *  @return the current features.<br>
434
	 *          The {@link #BidiComplexHelper() no-op helper} returns {@link BidiComplexFeatures#DEFAULT DEFAULT}
435
	 *          features.
436
	 *
437
	 *  @see #setFeatures setFeatures
438
	 */
439
	public BidiComplexFeatures getFeatures() {
440
		if (impl == null)
441
			return BidiComplexFeatures.DEFAULT;
442
		return impl.getFeatures();
443
	}
444
445
	/**
446
	 *  Specify the features to be applied to the processor associated with this
447
	 *  <code>BidiComplexHelper</code> instance.
448
	 *  Note that the value of {@link BidiComplexFeatures#specialsCount specialsCount}
449
	 *  cannot be changed (the new value will be ignored).<br>
450
	 *  The {@link #BidiComplexHelper() no-op helper} does nothing.
451
	 *
452
	 *  @see #getFeatures getFeatures
453
	 */
454
	public void setFeatures(BidiComplexFeatures features) {
455
		if (impl != null)
456
			impl.setFeatures(features);
457
	}
458
459
	/**
460
	 *  This method can be called from within
461
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
462
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations
463
	 *  of {@link IBidiComplexProcessor} to retrieve the bidirectional class of
464
	 *  characters in the <i>lean</i> text.
465
	 *
466
	 *  @param index position of the character in the <i>lean</i> text.
467
	 *          It must be a non-negative number smaller than the length
468
	 *          of the <i>lean</i> text.
469
	 *
470
	 *  @return the bidirectional class of the character. It is one of the
471
	 *          values which can be returned by
472
	 *          <code>java.lang.Character#getDirectionality</code>.
473
	 *          However, it is recommended to use <code>getDirProp</code>
474
	 *          rather than <code>java.lang.Character.getDirectionality</code>
475
	 *          since <code>getDirProp</code> manages a cache of character
476
	 *          properties and so can be more efficient than calling the
477
	 *          java.lang.Character method.<br>
478
	 *          The {@link #BidiComplexHelper() no-op helper} returns
479
	 *          <code>Character.DIRECTIONALITY_UNDEFINED</code>.
480
	 */
481
	public byte getDirProp(int index) {
482
		if (impl == null)
483
			return Character.DIRECTIONALITY_UNDEFINED;
484
		return impl.getDirProp(index);
485
	}
486
487
	/**
488
	 *  This method can be called from within
489
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
490
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations
491
	 *  of {@link IBidiComplexProcessor} to set or override the bidirectional
492
	 *  class of characters in the <i>lean</i> text.
493
	 *
494
	 *  @param index position of the character in the <i>lean</i> text.
495
	 *          It must be a non-negative number smaller than the length
496
	 *          of the <i>lean</i> text.
497
	 *
498
	 *  @param  dirProp bidirectional class of the character. It is one of the
499
	 *          values which can be returned by
500
	 *          <code>java.lang.Character.getDirectionality</code>.<br>
501
	 *          The {@link #BidiComplexHelper() no-op helper} does nothing.
502
	 */
503
	public void setDirProp(int index, byte dirProp) {
504
		if (impl != null)
505
			impl.getDirProp(index);
506
	}
507
508
	/**
509
	 *  This method can be called from within
510
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
511
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations
512
	 *  of {@link IBidiComplexProcessor}
513
	 *  to specify that a mark character must be added before the character
514
	 *  at the specified position of the <i>lean</i> text when generating the
515
	 *  <i>full</i> text. The mark character will be LRM for complex expressions
516
	 *  with a LTR base direction, and RLM for complex expressions with RTL
517
	 *  base direction. The mark character is not added physically by this
518
	 *  method, but its position is noted and will be used when generating
519
	 *  the <i>full</i> text.
520
	 *
521
	 *  @param  offset position of the character in the <i>lean</i> text.
522
	 *          It must be a non-negative number smaller than the length
523
	 *          of the <i>lean</i> text.
524
	 *          For the benefit of efficiency, it is better to insert
525
	 *          multiple marks in ascending order of the offsets.<br>
526
	 *          The {@link #BidiComplexHelper() no-op helper} does nothing.
527
	 */
528
	public void insertMark(int offset) {
529
		if (impl != null)
530
			impl.insertMark(offset);
531
	}
532
533
	/**
534
	 *  This method can be called from within
535
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
536
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
537
	 *  implementations of {@link IBidiComplexProcessor} to add a
538
	 *  directional mark before an
539
	 *  operator if needed for correct display, depending on the
540
	 *  base direction of the expression and on the class of the
541
	 *  characters in the <i>lean</i> text preceding and following
542
	 *  the operator itself.<br>
543
	 *  The {@link #BidiComplexHelper() no-op helper} does nothing.
544
	 *
545
	 *  @param  operLocation offset of the operator in the <i>lean</i> text.
546
	 *          It must be a non-negative number smaller than the length
547
	 *          of the <i>lean</i> text.
548
	 */
549
	public void processOperator(int operLocation) {
550
		if (impl != null)
551
			impl.processOperator(operLocation);
552
	}
553
554
	/**
555
	 *  This method can be called from within
556
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
557
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
558
	 *  implementations of {@link IBidiComplexProcessor} to
559
	 *  set the final state which should be used for the next call to
560
	 *  {@link #leanToFullText(java.lang.String, int)}.<br>
561
	 *  The {@link #BidiComplexHelper() no-op helper} does nothing.
562
	 */
563
	public void setFinalState(int newState) {
564
		if (impl != null)
565
			impl.setFinalState(newState);
566
	}
567
568
}
(-)src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java (+195 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import java.lang.ref.SoftReference;
14
import org.eclipse.equinox.bidi.custom.BidiComplexStringProcessor;
15
16
/**
17
 * This class records strings which are complex expressions. Several static
18
 * methods in this class allow to record such strings in a pool, and to find if
19
 * a given string is member of the pool.
20
 * <p>
21
 * Instances of this class are the records which are members of the pool.
22
 * <p>
23
 * The pool is managed as a cyclic list, each new element overrides the oldest
24
 * element in the list.
25
 */
26
public class BidiComplexStringRecord {
27
	/**
28
	 * Number of entries in the pool of recorded strings
29
	 */
30
	public static final int POOLSIZE = 100;
31
32
	// maximum index allowed
33
	private static final int MAXINDEX = POOLSIZE - 1;
34
35
	// index of the last entered record
36
	private static int last = MAXINDEX;
37
38
	// the pool
39
	private static BidiComplexStringRecord[] records = new BidiComplexStringRecord[POOLSIZE];
40
41
	// complex expression types
42
	private static final String[] types = BidiComplexStringProcessor.getKnownTypes();
43
44
	// maximum type index allowed
45
	private static int MAXTYPE = types.length - 1;
46
47
	// reference to the recorded string
48
	private SoftReference strRef;
49
50
	// hash code of the recorded string
51
	private int hash;
52
53
	// reference to the triplets of the recorded string
54
	private SoftReference triRef;
55
56
	/**
57
	 * Constructor.
58
	 * 
59
	 * @param string
60
	 *            the string to record
61
	 * 
62
	 * @param triplets
63
	 *            array of short integers, the number of elements in the array
64
	 *            must be a multiple of 3, so that the array is made of one or
65
	 *            more triplets of short integers.
66
	 *            <p>
67
	 *            The first element in each triplet is the beginning index of a
68
	 *            susbstring of <code>string</code> which is a complex
69
	 *            expression.
70
	 *            <p>
71
	 *            The second element in each triplet is the ending index of a
72
	 *            susbstring of <code>string</code> which is a complex
73
	 *            expression. This index points to one position beyond the last
74
	 *            character of the substring.
75
	 *            <p>
76
	 *            The third element in each triplet is the numeric type of the
77
	 *            complex expression.<br>
78
	 *            The type of a complex expression must be one of the string
79
	 *            values listed in {@link IBidiComplexExpressionTypes}.<br>
80
	 *            The corresponding numeric type must be obtained using the
81
	 *            method {@link #typeStringToShort typeStringToShort}.
82
	 */
83
	public BidiComplexStringRecord(String string, short[] triplets) {
84
		if (string == null || triplets == null || (triplets.length % 3) != 0)
85
			throw new IllegalArgumentException();
86
		for (int i = 2; i < triplets.length; i += 3)
87
			if (triplets[i] < 0 || triplets[i] > MAXTYPE)
88
				throw new IllegalArgumentException();
89
		strRef = new SoftReference(string);
90
		triRef = new SoftReference(triplets);
91
		hash = string.hashCode();
92
	}
93
94
	/**
95
	 * Get the numeric type of a complex expression given its string type.
96
	 * 
97
	 * @param type
98
	 *            type of complex expression as string. It must be one of the
99
	 *            strings listed in {@link IBidiComplexExpressionTypes}.
100
	 * 
101
	 * @return a value which is the corresponding numeric type. If
102
	 *         <code>type</code> is invalid, the method returns <code>-1</code>.
103
	 */
104
	public static short typeStringToShort(String type) {
105
		for (int i = 0; i < types.length; i++)
106
			if (types[i].equals(type))
107
				return (short) i;
108
		return -1;
109
	}
110
111
	/**
112
	 * Get the string type of a complex expression given its numeric type.
113
	 * 
114
	 * @param shType
115
	 *            the numeric type of a complex expression. It should be a value
116
	 *            obtained using {@link #typeStringToShort typeStringToShort}.
117
	 * 
118
	 * @return the corresponding string type. If <code>shType</code> is invalid,
119
	 *         the method returns <code>null</code>.
120
	 */
121
	public static String typeShortToString(short shType) {
122
		if (shType < 0 || shType > MAXTYPE)
123
			return null;
124
		return types[shType];
125
	}
126
127
	/**
128
	 * /** Add a record to the pool.
129
	 * 
130
	 * @param record
131
	 *            a BidiComplexStringRecord instance
132
	 */
133
	public static synchronized void add(BidiComplexStringRecord record) {
134
		if (last < MAXINDEX)
135
			last++;
136
		else
137
			last = 0;
138
		records[last] = record;
139
	}
140
141
	/**
142
	 * Check if a string is recorded and retrieve its triplets.
143
	 * 
144
	 * @param string
145
	 *            the string to check
146
	 * 
147
	 * @return <code>null</code> if the string is not recorded in the pool;
148
	 *         otherwise, return the triplets associated with this string.
149
	 */
150
	public static short[] getTriplets(String string) {
151
		if (records[0] == null) // no records at all
152
			return null;
153
		if (string == null || string.length() < 1)
154
			return null;
155
		BidiComplexStringRecord rec;
156
		String str;
157
		short[] tri;
158
		int myLast = last;
159
		int hash = string.hashCode();
160
		for (int i = myLast; i >= 0; i--) {
161
			rec = records[i];
162
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
163
				return tri;
164
			}
165
		}
166
		if (records[MAXINDEX] == null) // never recorded past myLast
167
			return null;
168
		for (int i = MAXINDEX; i > myLast; i--) {
169
			rec = records[i];
170
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
171
				return tri;
172
			}
173
		}
174
		return null;
175
	}
176
177
	/**
178
	 * Clear the pool. All elements of the pool are erased and any associated
179
	 * memory is freed.
180
	 * 
181
	 */
182
	public static synchronized void clear() {
183
		for (int i = 0; i <= MAXINDEX; i++) {
184
			BidiComplexStringRecord sr = records[i];
185
			if (sr == null)
186
				break;
187
			sr.hash = 0;
188
			sr.strRef.clear();
189
			sr.triRef.clear();
190
			records[i] = null;
191
		}
192
		last = MAXINDEX;
193
	}
194
195
}
(-)src/org/eclipse/equinox/bidi/BidiComplexUtil.java (+315 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
14
15
/**
16
 *  This class provides a number of convenience functions facilitating the
17
 *  processing of complex expressions.
18
 *
19
 *  @noextend This class is not intended to be subclassed by clients.
20
 *  @noinstantiate This class is not intended to be instantiated by clients.
21
 *
22
 *  @author Matitiahu Allouche
23
 */
24
final public class BidiComplexUtil {
25
26
	/**
27
	 *  prevent instantiation
28
	 */
29
	private BidiComplexUtil() {
30
		// empty
31
	}
32
33
	/** This is a convenience method which can add directional marks in a given
34
	 *  text before the characters specified in the given array of offsets,
35
	 *  and can add a prefix and/or a suffix of directional formatting characters.
36
	 *  This can be used for instance after obtaining offsets by calling
37
	 *  {@link BidiComplexHelper#leanBidiCharOffsets() leanBidiCharOffsets} in order to
38
	 *  produce a <i>full</i> text corresponding to the source text.
39
	 *  The directional formatting characters that will be added at the given
40
	 *  offsets will be LRMs for expressions with LTR base direction and
41
	 *  RLMs for expressions with RTL base direction. Leading and
42
	 *  trailing LRE, RLE and PDF which might be needed as prefix or suffix
43
	 *  depending on the orientation of the GUI component used for display
44
	 *  may be added depending on argument <code>affix</code>.
45
	 *
46
	 *  @param  text is the text of the complex expression.
47
	 *
48
	 *  @param  offsets is an array of offsets to characters in <code>text</code>
49
	 *          before which an LRM or RLM will be inserted.
50
	 *          Members of the array must be non-negative numbers smaller
51
	 *          than the length of <code>text</code>.
52
	 *          The array must be sorted in ascending order without duplicates.
53
	 *          This argument may be null if there are no marks to add.
54
	 *
55
	 *  @param  direction specifies the base direction of the complex expression.
56
	 *          It must be one of the values {@link BidiComplexFeatures#DIR_LTR} or
57
	 *          {@link BidiComplexFeatures#DIR_RTL}.
58
	 *
59
	 *  @param  affix specifies if a prefix and a suffix should be added to
60
	 *          the result to make sure that the <code>direction</code>
61
	 *          specified as third argument is honored even if the expression
62
	 *          is displayed in a GUI component with a different orientation.
63
	 *
64
	 *  @return a string corresponding to the source <code>text</code> with
65
	 *          directional marks (LRMs or RLMs) added at the specified offsets,
66
	 *          and directional formatting characters (LRE, RLE, PDF) added
67
	 *          as prefix and suffix if so required.
68
	 */
69
	public static String insertMarks(String text, int[] offsets, int direction, boolean affix) {
70
		int textLen = text.length();
71
		if (textLen == 0)
72
			return ""; //$NON-NLS-1$
73
74
		String curPrefix, curSuffix, full;
75
		char curMark, c;
76
		char[] fullChars;
77
		if (direction == BidiComplexFeatures.DIR_LTR) {
78
			curMark = LRM;
79
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
80
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
81
		} else {
82
			curMark = RLM;
83
			curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$
84
			curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$
85
		}
86
		// add marks at offsets
87
		if ((offsets != null) && (offsets.length > 0)) {
88
			int offLen = offsets.length;
89
			fullChars = new char[textLen + offLen];
90
			int added = 0;
91
			for (int i = 0, j = 0; i < textLen; i++) {
92
				c = text.charAt(i);
93
				if ((j < offLen) && (i == offsets[j])) {
94
					fullChars[i + added] = curMark;
95
					added++;
96
					j++;
97
				}
98
				fullChars[i + added] = c;
99
			}
100
			full = new String(fullChars);
101
		} else {
102
			full = text;
103
		}
104
		if (affix)
105
			return curPrefix + full + curSuffix;
106
		return full;
107
	}
108
109
	/*************************************************************************/
110
	/*                                                                       */
111
	/*  The following code is provided for compatibility with TextProcessor  */
112
	/*                                                                       */
113
	/*************************************************************************/
114
115
	//  The default set of delimiters to use to segment a string.
116
	private static final String defaultDelimiters = ".:/\\"; //$NON-NLS-1$
117
	// left to right mark
118
	private static final char LRM = '\u200e';
119
	// left to right mark
120
	private static final char RLM = '\u200f';
121
	// left to right embedding
122
	private static final char LRE = '\u202a';
123
	// right to left embedding
124
	private static final char RLE = '\u202b';
125
	// pop directional format
126
	private static final char PDF = '\u202c';
127
128
	static boolean isProcessingNeeded() {
129
		if (!BidiComplexEnvironment.isSupportedOS())
130
			return false;
131
		return BidiComplexEnvironment.DEFAULT.isBidi();
132
	}
133
134
	/**
135
	 *  Process the given text and return a string with appropriate
136
	 *  directional formatting characters if the locale is a bidi locale.
137
	 *  This is equivalent to calling
138
	 *  {@link #process(String str, String delimiters)} with the default
139
	 *  set of delimiters (dot, colon, slash, backslash).
140
	 *
141
	 *  @param  str the text to be processed.
142
	 *
143
	 *  @return the processed string.
144
	 */
145
	public static String process(String str) {
146
		return process(str, defaultDelimiters);
147
	}
148
149
	/**
150
	 *  Process a string that has a particular semantic meaning to render
151
	 *  it correctly on bidi locales. This is done by adding directional
152
	 *  formatting characters so that presentation using the Unicode
153
	 *  Bidirectional Algorithm will provide the expected result.
154
	 *  The text is segmented according to the provided delimiters.
155
	 *  Each segment has the Unicode Bidi Algorithm applied to it,
156
	 *  but as a whole, the string is oriented left to right.
157
	 *  <p>
158
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
159
	 *  (where capital letters indicate RTL text) should render as
160
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
161
	 *  <p>
162
	 *  NOTE: this method inserts directional formatting characters into the
163
	 *  text. Methods like <code>String.equals(String)</code> and
164
	 *  <code>String.length()</code> called on the resulting string will not
165
	 *  return the same values as would be returned for the original string.</p>
166
	 *
167
	 *  @param  str the text to process.
168
	 *
169
	 *  @param  delimiters delimiters by which the string will be segmented.
170
	 *          If <code>null</code>, the default delimiters are used
171
	 *          (dot, colon, slash, backslash).
172
	 *
173
	 *  @return the processed string.
174
	 *          If <code>str</code> is <code>null</code>,
175
	 *          or of length 0, or if the current locale is not a bidi one,
176
	 *          return the original string.
177
	 */
178
	public static String process(String str, String delimiters) {
179
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
180
			return str;
181
182
		// do not process a string that has already been processed.
183
		if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF)
184
			return str;
185
186
		// do not process a string if all the following conditions are true:
187
		//  a) it has no RTL characters
188
		//  b) it starts with a LTR character
189
		//  c) it ends with a LTR character or a digit
190
		boolean isStringBidi = false;
191
		int strLength = str.length();
192
		char c;
193
		for (int i = 0; i < strLength; i++) {
194
			c = str.charAt(i);
195
			if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) {
196
				isStringBidi = true;
197
				break;
198
			}
199
		}
200
		while (!isStringBidi) {
201
			if (!Character.isLetter(str.charAt(0)))
202
				break;
203
			c = str.charAt(strLength - 1);
204
			if (!Character.isDigit(c) && !Character.isLetter(c))
205
				break;
206
			return str;
207
		}
208
209
		if (delimiters == null)
210
			delimiters = defaultDelimiters;
211
212
		// make sure that LRE/PDF are added around the string
213
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN);
214
		BidiComplexHelper helper = new BidiComplexHelper(new BidiComplexProcessor(), env);
215
		helper.setFeatures(new BidiComplexFeatures(delimiters, 0, -1, -1, false, false));
216
		return helper.leanToFullText(str);
217
	}
218
219
	/**
220
	 *  Process a string that has a particular semantic meaning to render
221
	 *  it correctly on bidi locales. This is done by adding directional
222
	 *  formatting characters so that presentation using the Unicode
223
	 *  Bidirectional Algorithm will provide the expected result..
224
	 *  The text is segmented according to the syntax specified in the
225
	 *  <code>type</code> argument.
226
	 *  Each segment has the Unicode Bidi Algorithm applied to it, but the
227
	 *  order of the segments is governed by the type of the complex expression.
228
	 *  <p>
229
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
230
	 *  (where capital letters indicate RTL text) should render as
231
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
232
	 *  <p>
233
	 *  NOTE: this method inserts directional formatting characters into the
234
	 *  text. Methods like <code>String.equals(String)</code> and
235
	 *  <code>String.length()</code> called on the resulting string will not
236
	 *  return the same values as would be returned for the original string.</p>
237
	 *
238
	 *  @param  str the text to process.
239
	 *
240
	 *  @param  type specifies the type of the complex expression. It must
241
	 *          be one of the values in {@link IBidiComplexExpressionTypes} or a value.
242
	 *          added by a plug-in extension.
243
	 *
244
	 *  @return the processed string.
245
	 *          If <code>str</code> is <code>null</code>,
246
	 *          or of length 0, or if the current locale is not a bidi one,
247
	 *          return the original string.
248
	 */
249
	public static String processTyped(String str, String type) {
250
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
251
			return str;
252
253
		// do not process a string that has already been processed.
254
		char c = str.charAt(0);
255
		if (((c == LRE) || (c == RLE)) && str.charAt(str.length() - 1) == PDF)
256
			return str;
257
258
		// make sure that LRE/PDF are added around the string
259
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN);
260
		BidiComplexHelper helper = new BidiComplexHelper(type, env);
261
		return helper.leanToFullText(str);
262
	}
263
264
	/**
265
	 *  Remove directional formatting characters in the given string that
266
	 *  were inserted by one of the {@link #process process} methods.
267
	 *
268
	 *  @param  str string with directional characters to remove.
269
	 *
270
	 *  @return string with no directional formatting characters.
271
	 */
272
	public static String deprocess(String str) {
273
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
274
			return str;
275
276
		StringBuffer buf = new StringBuffer();
277
		int strLen = str.length();
278
		for (int i = 0; i < strLen; i++) {
279
			char c = str.charAt(i);
280
			switch (c) {
281
				case LRM :
282
					continue;
283
				case LRE :
284
					continue;
285
				case PDF :
286
					continue;
287
				default :
288
					buf.append(c);
289
			}
290
		}
291
		return buf.toString();
292
	}
293
294
	/**
295
	 *  Remove directional formatting characters in the given string that
296
	 *  were inserted by the {@link #processTyped processTyped} method.
297
	 *
298
	 *  @param  str string with directional characters to remove.
299
	 *
300
	 *  @param  type type of the complex expression as specified when
301
	 *          calling {@link #processTyped processTyped}.
302
	 *
303
	 *  @return string with no directional formatting characters.
304
	 */
305
	public static String deprocess(String str, String type) {
306
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
307
			return str;
308
309
		// make sure that LRE/PDF are added around the string
310
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN);
311
		BidiComplexHelper helper = new BidiComplexHelper(type, env);
312
		return helper.fullToLeanText(str);
313
	}
314
315
}
(-)src/org/eclipse/equinox/bidi/IBidiComplexExpressionTypes.java (+106 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi;
12
13
/**
14
 * Bidirectional processors supplied in this bundle.
15
 *
16
 * @noextend This interface is not intended to be extended by clients.
17
 */
18
public interface IBidiComplexExpressionTypes {
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/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/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/IComplExpProcessor.java (-606 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
/**
15
 *  This interface provides a generic mechanism to handle
16
 *  complex expressions, with as main purpose to ensure that they are
17
 *  correctly presented.
18
 *
19
 *  <p>&nbsp;</p>
20
 *
21
 *  <h2>Code Sample</h2>
22
 *
23
 *  <p>The following code shows how to instantiate a processor adapted for a
24
 *  certain type of complex expression (directory and file paths), and how
25
 *  to obtain the <i>full</i> text corresponding to the <i>lean</i> text
26
 *  of such an expression.
27
 *
28
 *  <pre>
29
 *
30
 *    IComplExpProcessor processor = ComplExpFactory.create(IBiDiProcessor.FILE);
31
 *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
32
 *    String fullText = processor.leanToFullText(leanText);
33
 *    System.out.println("full text = " + fullText);
34
 *  </pre>
35
 *
36
 *  <p>&nbsp;</p>
37
 *
38
 *  @author Matitiahu Allouche
39
 *
40
 */
41
public interface IComplExpProcessor {
42
	/**
43
	 *  Constant to use as <code>type</code> argument when calling
44
	 *  {@link #leanToFullText(java.lang.String, int) leanToFullText} or
45
	 *  {@link #fullToLeanText(java.lang.String, int) fullToLeanText}
46
	 *  to indicate that there is no context of previous lines which
47
	 *  should be initialized before performing the operation.
48
	 */
49
	public static final int STATE_NOTHING_GOING = -1;
50
51
	/**
52
	 *  Constant specifying that the orientation of the GUI component
53
	 *  where a complex expression will be displayed is LTR.
54
	 *  It can appear as argument for {@link #assumeOrientation assumeOrientation}
55
	 *  or return value for {@link #recallOrientation recallOrientation}.
56
	 */
57
	public static final int ORIENT_LTR = 0;
58
59
	/**
60
	 *  Constant specifying that the orientation of the GUI component
61
	 *  where a complex expression will be displayed is RTL.
62
	 *  It can appear as argument for {@link #assumeOrientation assumeOrientation}
63
	 *  or return value for {@link #recallOrientation recallOrientation}.
64
	 */
65
	public static final int ORIENT_RTL = 1;
66
67
	/**
68
	 *  Constant specifying that the orientation of the GUI component
69
	 *  where a complex expression will be displayed is contextual with
70
	 *  a default of LTR (if no strong character appears in the text).
71
	 *  It can appear as argument for {@link #assumeOrientation assumeOrientation}
72
	 *  or return value for {@link #recallOrientation recallOrientation}.
73
	 */
74
	public static final int ORIENT_CONTEXTUAL_LTR = 2;
75
76
	/**
77
	 *  Constant specifying that the orientation of the GUI component
78
	 *  where a complex expression will be displayed is contextual with
79
	 *  a default of RTL (if no strong character appears in the text).
80
	 *  It can appear as argument for {@link #assumeOrientation assumeOrientation}
81
	 *  or return value for {@link #recallOrientation recallOrientation}.
82
	 */
83
	public static final int ORIENT_CONTEXTUAL_RTL = 3;
84
85
	/**
86
	 *  Constant specifying that the orientation of the GUI component
87
	 *  where a complex expression will be displayed is not known.
88
	 *  Directional formatting characters must be added as prefix and
89
	 *  suffix whenever a <i>full</i> text is generated using
90
	 *  {@link #leanToFullText leanToFullText}.
91
	 *  This constant can appear as argument for
92
	 *  {@link #assumeOrientation assumeOrientation}
93
	 *  or return value for {@link #recallOrientation recallOrientation}.
94
	 */
95
	public static final int ORIENT_UNKNOWN = 4;
96
97
	/**
98
	 *  Constant specifying that whatever the orientation of the
99
	 *  GUI component where a complex expression will be displayed, no
100
	 *  directional formatting characters must be added as prefix or
101
	 *  suffix whenever a <i>full</i> text is generated using
102
	 *  {@link #leanToFullText leanToFullText}.
103
	 *  This constant can appear as argument for
104
	 *  {@link #assumeOrientation assumeOrientation}
105
	 *  or return value for {@link #recallOrientation recallOrientation}.
106
	 */
107
	public static final int ORIENT_IGNORE = 5;
108
109
	/**
110
	 *  Constant specifying that the base direction of a complex expression is LTR.
111
	 *  The base direction may depend on whether the GUI is mirrored and may
112
	 *  may be different for Arabic and for Hebrew.
113
	 *  This constant can appear as argument for {@link #setDirection(int) setDirection}
114
	 *  or return value for {@link #getDirection getDirection}.
115
	 *
116
	 *  @see ComplExpUtil#isMirroredDefault()
117
	 */
118
	public static final int DIRECTION_LTR = 0;
119
120
	/**
121
	 *  Constant specifying that the base direction of a complex expression is RTL.
122
	 *  The base direction may depend on whether the GUI is mirrored and may
123
	 *  be different for Arabic and for Hebrew.
124
	 *  This constant can appear as argument for {@link #setDirection(int) setDirection}
125
	 *  or return value for {@link #getDirection getDirection}.
126
	 *
127
	 *  @see ComplExpUtil#isMirroredDefault()
128
	 */
129
	public static final int DIRECTION_RTL = 1;
130
131
	/**
132
	 *  This method specifies whether Arabic letters, Hebrew letters or
133
	 *  both will be considered for processing complex expressions.
134
	 *  If neither is selected, the processor will do nothing (but
135
	 *  some overhead can be expected).
136
	 *  <p>
137
	 *  By default, both Arabic and Hebrew are selected for processing.
138
	 *
139
	 *  @param arabic a <code>true</code> value means that Arabic letters
140
	 *         will be processed.
141
	 *
142
	 *  @param hebrew a <code>true</code> value means that Hebrew letters
143
	 *         will be processed.
144
	 *
145
	 *  @see #handlesArabicScript
146
	 *  @see #handlesHebrewScript
147
	 */
148
	public void selectBidiScript(boolean arabic, boolean hebrew);
149
150
	/**
151
	 *  This method specifies whether Arabic letters
152
	 *  will be considered for processing complex expressions.
153
	 *
154
	 *  @return <code>true</code> if Arabic letters will be processed.
155
	 *
156
	 *  @see #selectBidiScript selectBidiScript
157
	 */
158
	public boolean handlesArabicScript();
159
160
	/**
161
	 *  This method specifies whether Hebrew letters
162
	 *  will be considered for processing complex expressions.
163
	 *
164
	 *  @return <code>true</code> if Hebrew letters will be processed.
165
	 *
166
	 *  @see #selectBidiScript selectBidiScript
167
	 */
168
	public boolean handlesHebrewScript();
169
170
	/** Add directional formatting characters to a complex expression
171
	 *  to ensure correct presentation.
172
	 *
173
	 *  @param text is the text of the complex expression.
174
	 *
175
	 *  @return the complex expression with directional formatting
176
	 *          characters added at proper locations to ensure correct
177
	 *          presentation.
178
	 *
179
	 */
180
	public String leanToFullText(String text);
181
182
	/** Add directional formatting characters to a complex expression
183
	 *  to ensure correct presentation.
184
	 *
185
	 *  @param text is the text of the complex expression.
186
	 *
187
	 *  @param initState specifies that the first parameter is the
188
	 *         continuation of text submitted in a previous call.
189
	 *         The <code>initState</code> of the present call must be
190
	 *         the final state obtained by calling
191
	 *         {@link #getFinalState() getFinalState}
192
	 *         after the previous call.
193
	 *
194
	 *  @return the complex expression with directional formatting
195
	 *          characters added at proper locations to ensure correct
196
	 *          presentation.
197
	 *
198
	 *  @see #getFinalState getFinalState
199
	 */
200
	public String leanToFullText(String text, int initState);
201
202
	/** Given a complex expression, get the offsets of characters before which
203
	 *  directional formatting characters must be added in order to
204
	 *  ensure correct presentation.
205
	 *  Only LRMs (for an expression with LTR base direction) and RLMs (for
206
	 *  an expression with RTL base direction) are considered. Leading and
207
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
208
	 *  depending on the orientation of the GUI component used for display
209
	 *  are not reflected in this method.
210
	 *
211
	 *  @param text is the text of the complex expression.
212
	 *
213
	 *  @return an array of offsets to the characters in the <code>text</code>
214
	 *          before which directional marks must be added to ensure correct
215
	 *          presentation.
216
	 *          The offsets are sorted in ascending order.
217
	 *
218
	 */
219
	public int[] leanBidiCharOffsets(String text);
220
221
	/** Given a complex expression, get the offsets of characters before which
222
	 *  directional formatting characters must be added in order to
223
	 *  ensure correct presentation.
224
	 *  Only LRMs (for an expression with LTR base direction) and RLMs (for
225
	 *  an expression with RTL base direction) are considered. Leading and
226
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
227
	 *  depending on the orientation of the GUI component used for display
228
	 *  are not reflected in this method.
229
	 *
230
	 *  @param text is the text of the complex expression.
231
	 *
232
	 *  @param initState specifies that the first parameter is the
233
	 *         continuation of text submitted in a previous call.
234
	 *         The <code>initState</code> of the present call must be
235
	 *         the final state obtained by calling
236
	 *         {@link #getFinalState() getFinalState}
237
	 *         after the previous call.
238
	 *
239
	 *  @return an array of offsets to the characters in the <code>text</code>
240
	 *          before which directional marks must be added to ensure correct
241
	 *          presentation.
242
	 *          The offsets are sorted in ascending order.
243
	 *
244
	 *  @see #getFinalState getFinalState
245
	 */
246
	public int[] leanBidiCharOffsets(String text, int initState);
247
248
	/** Given a complex expression, get the offsets of characters before which
249
	 *  directional formatting characters must be added in order to
250
	 *  ensure correct presentation.
251
	 *  Only LRMs (for an expression with LTR base direction) and RLMs (for
252
	 *  an expression with RTL base direction) are considered. Leading and
253
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
254
	 *  depending on the orientation of the GUI component used for display
255
	 *  are not reflected in this method.
256
	 *  <p>
257
	 *  This method assumes that a successful call to
258
	 *  {@link #leanToFullText leanToFullText} has been performed, and it
259
	 *  returns the offsets relevant for the last text submitted.
260
	 *
261
	 *  @return an array of offsets to the characters in the last submitted
262
	 *          complex expression before which directional marks must be
263
	 *          added to ensure correct presentation.
264
	 *          The offsets are sorted in ascending order.
265
	 *
266
	 */
267
	public int[] leanBidiCharOffsets();
268
269
	/** Get the offsets of characters in the <i>full</i> text of a
270
	 *  complex expression corresponding to directional formatting
271
	 *  characters which have been added in order to ensure correct presentation.
272
	 *  LRMs (for an expression with LTR base direction), RLMs (for
273
	 *  an expression with RTL base direction) are considered as well as
274
	 *  leading and trailing LRE, RLE and PDF which might be prefixed or suffixed
275
	 *  depending on the orientation of the GUI component used for display.
276
	 *  <p>
277
	 *  This method assumes that a successful call to
278
	 *  {@link #leanToFullText leanToFullText} has been performed, and it
279
	 *  returns the offsets relevant for the last text submitted.
280
	 *
281
	 *  @return an array of offsets to the characters in the <i>full</i>
282
	 *          text of the last submitted complex expression which are
283
	 *          directional formatting characters added to ensure correct
284
	 *          presentation.
285
	 *          The offsets are sorted in ascending order.
286
	 *
287
	 */
288
	public int[] fullBidiCharOffsets();
289
290
	/** Remove directional formatting characters which were added to a
291
	 *  complex expression to ensure correct presentation.
292
	 *
293
	 *  @param text is the text of the complex expression including
294
	 *         directional formatting characters.
295
	 *
296
	 *  @return the complex expression without directional formatting
297
	 *          characters which might have been added by processing it
298
	 *          with {@link #leanToFullText leanToFullText}.
299
	 *
300
	 */
301
	public String fullToLeanText(String text);
302
303
	/** Remove directional formatting characters which were added to a
304
	 *  complex expression to ensure correct presentation.
305
	 *
306
	 *  @param text is the text of the complex expression including
307
	 *         directional formatting characters.
308
	 *
309
	 *  @param initState specifies that the first parameter is the
310
	 *         continuation of text submitted in a previous call.
311
	 *         The <code>initState</code> of the present call must be
312
	 *         the final state obtained by calling
313
	 *         {@link #getFinalState getFinalState} after the previous call.
314
	 *
315
	 *  @return the complex expression without directional formatting
316
	 *          characters which might have been added by processing it
317
	 *          with {@link #leanToFullText leanToFullText}.
318
	 *
319
	 *  @see #getFinalState
320
	 */
321
	public String fullToLeanText(String text, int initState);
322
323
	/** Retrieve the final state achieved in a previous call to
324
	 *  {@link #leanToFullText leanToFullText} or
325
	 *  {@link #fullToLeanText fullToLeanText},
326
	 *  {@link #leanBidiCharOffsets(java.lang.String text)} or
327
	 *  {@link #leanBidiCharOffsets(java.lang.String text, int initState)}.
328
	 *
329
	 *  @return the last final state.
330
	 *
331
	 */
332
	public int getFinalState();
333
334
	/** After transforming a <i>lean</i> string into a <i>full</i> string
335
	 *  using {@link #leanToFullText leanToFullText}, compute the index in the
336
	 *  <i>full</i> string of the character corresponding to the
337
	 *  character with the specified position in the <i>lean</i> string.
338
	 *
339
	 *  @param pos is the index of a character in the <i>lean</i> string.
340
	 *
341
	 *  @return the index of the corresponding character in the
342
	 *          <i>full</i> string.
343
	 *
344
	 */
345
	public int leanToFullPos(int pos);
346
347
	/** After transforming a <i>lean</i> string into a <i>full</i> string
348
	 *  using {@link #leanToFullText leanToFullText}, compute the index in the
349
	 *  <i>lean</i> string of the character corresponding to the
350
	 *  character with the specified position in the <i>full</i> string.
351
	 *
352
	 *  @param pos is the index of a character in the <i>full</i> string.
353
	 *
354
	 *  @return the index of the corresponding character in the
355
	 *          <i>lean</i> string. If there is no corresponding
356
	 *          character in the <i>lean</i> string (because the
357
	 *          specified character is a directional formatting character
358
	 *          added when invoking {@link #leanToFullText leanToFullText}),
359
	 *          the value returned will be that corresponding to the
360
	 *          next character which is not a directional formatting
361
	 *          character.
362
	 *
363
	 */
364
	public int fullToLeanPos(int pos);
365
366
	/** Set the operators which separate a complex expression into tokens.
367
	 *
368
	 *  @param  operators is a string where each character is an operator.
369
	 *  
370
	 *  @see #getOperators
371
	 */
372
	public void setOperators(String operators);
373
374
	/** Get the operators which separate a complex expression into tokens.
375
	 *
376
	 *  @return a string where each character is an operator.
377
	 *
378
	 *  @see #getOperators
379
	 */
380
	public String getOperators();
381
382
	/** Specify whether the GUI where the complex expression will be displayed
383
	 *  is mirrored (is laid out from right to left). The value specified in
384
	 *  this method overrides the default assumed for all complex expressions
385
	 *  as specified by
386
	 *  {@link ComplExpUtil#assumeMirroredDefault assumeMirroredDefault}.
387
	 *
388
	 *  @param  shouldBeMirrored must be specified as <code>false</code> if the GUI
389
	 *          is not mirrored, as <code>true</code> if it is.
390
	 *
391
	 *  @see #isMirrored
392
	 *  @see ComplExpUtil#assumeMirroredDefault assumeMirroredDefault
393
	 */
394
	public void assumeMirrored(boolean shouldBeMirrored);
395
396
	/** Retrieve the value assumed for GUI mirroring for the current
397
	 *  complex expression.
398
	 *
399
	 *  @return the current value assumed for GUI mirroring.
400
	 *
401
	 *  @see #assumeMirrored
402
	 */
403
	public boolean isMirrored();
404
405
	/** Specify the orientation (a.k.a. base direction) of the GUI
406
	 *  component in which the <i>full</i> text of the complex expression will
407
	 *  be displayed. If no orientation was specified, <code>ORIENT_LTR</code>
408
	 *  is assumed.
409
	 *  <p>
410
	 *  When the orientation is <code>ORIENT_RTL</code> and the complex
411
	 *  expression has a LTR base direction, {@link #leanToFullText leanToFullText}
412
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
413
	 *  end.
414
	 *  <p>
415
	 *  When the orientation is <code>ORIENT_LTR</code> and the complex
416
	 *  expression has a RTL base direction, {@link #leanToFullText leanToFullText}
417
	 *  adds RLE+LRM at the head of the <i>full</i> text and RLM+PDF at its
418
	 *  end.
419
	 *  <p>
420
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
421
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
422
	 *  to a RTL orientation while the complex expression has a LTR base
423
	 *  direction, {@link #leanToFullText leanToFullText}
424
	 *  adds LRM at the head of the <i>full</i> text.
425
	 *  <p>
426
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
427
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
428
	 *  to a LTR orientation while the complex expression has a RTL base
429
	 *  direction, {@link #leanToFullText leanToFullText}
430
	 *  adds RLM at the head of the <i>full</i> text.
431
	 *  <p>
432
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
433
	 *  expression has a LTR base direction, {@link #leanToFullText leanToFullText}
434
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
435
	 *  end.
436
	 *  <p>
437
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
438
	 *  expression has a RTL base direction, {@link #leanToFullText leanToFullText}
439
	 *  adds RLE+LRM at the head of the <i>full</i> text and RLM+PDF at its
440
	 *  end.
441
	 *  <p>
442
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
443
	 *  {@link #leanToFullText leanToFullText} does not add any directional
444
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
445
	 *
446
	 *  @param componentOrientation orientation of the GUI component where the
447
	 *         complex expression will be displayed. It must be one of the
448
	 *         values {@link #ORIENT_LTR}, {@link #ORIENT_RTL},
449
	 *         {@link #ORIENT_CONTEXTUAL_LTR}, {@link #ORIENT_CONTEXTUAL_RTL},
450
	 *         {@link #ORIENT_UNKNOWN} or {@link #ORIENT_IGNORE}.
451
	 *
452
	 *  @see #recallOrientation
453
	 */
454
	public void assumeOrientation(int componentOrientation);
455
456
	/** Retrieve the value currently assumed for the orientation.
457
	 *
458
	 *  @return the current value of the orientation. It will be one of the
459
	 *         values {@link #ORIENT_LTR}, {@link #ORIENT_RTL},
460
	 *         {@link #ORIENT_CONTEXTUAL_LTR}, {@link #ORIENT_CONTEXTUAL_RTL},
461
	 *         {@link #ORIENT_UNKNOWN} or {@link #ORIENT_IGNORE}.
462
	 *
463
	 *  @see #assumeOrientation
464
	 */
465
	public int recallOrientation();
466
467
	/** Set the base direction of a complex expression including Arabic words.
468
	 *  It is specified separately for when the GUI is not mirrored and for
469
	 *  when it is mirrored. Each argument must be one of the values
470
	 *  {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
471
	 *  If the values are different for Arabic and Hebrew, the values for
472
	 *  Arabic will be used if an Arabic letter precedes all Hebrew letters
473
	 *  in the expression.
474
	 *
475
	 *  @param  not_mirrored base direction when the GUI is not mirrored.
476
	 *
477
	 *  @param  mirrored base direction when the GUI is mirrored.
478
	 *
479
	 *  @see #setHebrewDirection(int, int)
480
	 *  @see #getDirection
481
	 */
482
	public void setArabicDirection(int not_mirrored, int mirrored);
483
484
	/** Set the base direction of a complex expression including Arabic words.
485
	 *  This direction applies both for when the GUI is not mirrored and for
486
	 *  when it is mirrored.
487
	 *  If the values are different for Arabic and Hebrew, the values for
488
	 *  Arabic will be used if an Arabic letter precedes all Hebrew letters
489
	 *  in the expression.
490
	 *
491
	 *  @param  direction base direction of the expression.
492
	 *          It must be one of the values
493
	 *          {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
494
	 *
495
	 *  @see #setHebrewDirection(int)
496
	 *  @see #getDirection
497
	 */
498
	public void setArabicDirection(int direction);
499
500
	/** Set the base direction of a complex expression including Hebrew words.
501
	 *  It is specified separately for when the GUI is not mirrored and for
502
	 *  when it is mirrored. Each argument must be one of the values
503
	 *  {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
504
	 *  If the values are different for Arabic and Hebrew, the values for
505
	 *  Hebrew will be used if a Hebrew letter precedes all Arabic letters
506
	 *  in the expression.
507
	 *
508
	 *  @param  not_mirrored base direction when the GUI is not mirrored.
509
	 *
510
	 *  @param  mirrored base direction when the GUI is mirrored.
511
	 *
512
	 *  @see #setArabicDirection(int, int)
513
	 *  @see #getDirection
514
	 */
515
	public void setHebrewDirection(int not_mirrored, int mirrored);
516
517
	/** Set the base direction of a complex expression including Hebrew words.
518
	 *  This direction applies both for when the GUI is not mirrored and for
519
	 *  when it is mirrored.
520
	 *  If the values are different for Arabic and Hebrew, the values for
521
	 *  Hebrew will be used if a Hebrew letter precedes all Arabic letters
522
	 *  in the expression.
523
	 *
524
	 *  @param  direction base direction of the expression.
525
	 *          It must be one of the values
526
	 *          {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
527
	 *
528
	 *  @see #setArabicDirection(int)
529
	 *  @see #getDirection
530
	 */
531
	public void setHebrewDirection(int direction);
532
533
	/** Set the base direction of a complex expression.
534
	 *  It is specified separately for when the GUI is not mirrored and for
535
	 *  when it is mirrored. Each argument must be one of the values
536
	 *  {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
537
	 *  The values apply whether the expression contains Arabic or Hebrew
538
	 *  letters, or both.
539
	 *
540
	 *  @param  not_mirrored base direction when the GUI is not mirrored.
541
	 *
542
	 *  @param  mirrored base direction when the GUI is mirrored.
543
	 *
544
	 *  @see #setArabicDirection(int, int)
545
	 *  @see #setHebrewDirection(int, int)
546
	 *  @see #getDirection
547
	 */
548
	public void setDirection(int not_mirrored, int mirrored);
549
550
	/** Set the base direction of a complex expression.
551
	 *  This direction applies both for when the GUI is not mirrored and for
552
	 *  when it is mirrored.
553
	 *  The direction applies whether the expression contains Arabic or Hebrew
554
	 *  letters, or both.
555
	 *
556
	 *  @param  direction base direction of the expression.
557
	 *          It must be one of the values
558
	 *          {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
559
	 *
560
	 *  @see #setArabicDirection(int)
561
	 *  @see #setHebrewDirection(int)
562
	 *  @see #getDirection
563
	 */
564
	public void setDirection(int direction);
565
566
	/** Get the base direction of a complex expression.
567
	 *  Different base directions may have been specified depending on
568
	 *  whether the expression contains Arabic or Hebrew words
569
	 *  (if it contains both, the first Arabic or Hebrew letter in the
570
	 *  expression determines which is the governing script).
571
	 *  Different base directions may also have been specified depending on
572
	 *  whether the GUI is or is not mirrored.
573
	 *  The values for all the possible cases are returned in an array.
574
	 *  Each element of the array must be one of the values
575
	 *  {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
576
	 *
577
	 *  @return a two dimensional array with 2 rows and 2 columns such that
578
	 *  <ul>
579
	 *    <li>element [0][0] represents the base direction for Arabic
580
	 *        when the GUI is not mirrored.
581
	 *    <li>element [0][1] represents the base direction for Arabic
582
	 *        when the GUI is mirrored.
583
	 *    <li>element [1][0] represents the base direction for Hebrew
584
	 *        when the GUI is not mirrored.
585
	 *    <li>element [1][1] represents the base direction for Hebrew
586
	 *        when the GUI is mirrored.
587
	 *  </ul>
588
	 *
589
	 *  @see #setDirection
590
	 */
591
	public int[][] getDirection();
592
593
	/** Get the base direction of the current complex expression.
594
	 *  This base direction may depend on whether the GUI is mirrored and on
595
	 *  whether the expression contains Arabic or Hebrew words
596
	 *  (if it contains both, the first Arabic or Hebrew letter in the
597
	 *  expression determines which is the governing script).
598
	 *
599
	 *  @return the base direction of the current instance of a complex
600
	 *          expression. It must be one of the values
601
	 *  {@link #DIRECTION_LTR} or {@link #DIRECTION_RTL}.
602
	 *
603
	 *  @see #setDirection
604
	 */
605
	public int getCurDirection();
606
}
(-)src/org/eclipse/equinox/bidi/complexp/StringProcessor.java (-31 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
 * The API part for the TextProcessor replacement.
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 {
23
24
	static public String[] getKnownTypes() {
25
		return BiDiTypesCollector.getInstance().getTypes();
26
	}
27
28
	static public IComplExpProcessor getProcessor(String type) {
29
		return BiDiTypesCollector.getInstance().getProcessor(type);
30
	}
31
}
(-)src/org/eclipse/equinox/bidi/complexp/package.html (-158 lines)
Removed 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 an interface and implementing classes for
9
processing complex expressions.
10
11
12
<h2>Introduction to Complex Expressions</h2>
13
<p>
14
Bidirectional text offers interesting challenges to presentation systems.
15
For plain text, the Unicode Bidirectional Algorithm
16
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
17
generally specifies satisfactorily how to reorder Bidirectional text for
18
display. This algorithm is implemented in Java's presentation system.</p>
19
<p>
20
However, all Bidirectional text is not necessarily plain text. There
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
23
has no awareness of these special cases, often gives incorrect results
24
when displaying such structured text.</p>
25
<p>
26
The general idea in handling complex expressions is to add directional
27
formatting characters at proper locations in the text to supplement the
28
standard algorithm, so that the final result is correctly displayed
29
using the UBA.
30
A class which handles complex expressions is thus a transformation
31
engine which receives text without directional formatting characters
32
as input and produces as output the same text with added directional
33
formatting characters, hopefully in the minimum quantity which is
34
sufficient to ensure correct display, considering the type of complex
35
expression involved.</p>
36
<p>
37
In this package, text without directional formatting characters is
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>
40
<p>
41
{@link <a href="IComplExpProcessor.html">IComplExpProcessor</a>} provides
42
an interface for processing complex expressions.  This package also
43
includes several classes which implement <code>IComplExpProcessor</code>,
44
all of them based on class
45
{@link <a href="ComplExpBasic.html">ComplExpBasic</a>}.
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>
62
  <li>property (name=value)</li>
63
  <li>compound name (xxx_yy_zzzz)</li>
64
  <li>comma delimited list</li>
65
  <li>system(user)</li>
66
  <li>directory and file path</li>
67
  <li>e-mail address</li>
68
  <li>URL</li>
69
  <li>regular expression</li>
70
  <li>Xpath</li>
71
  <li>Java code</li>
72
  <li>SQL statements</li>
73
  <li>RTL arithmetic expressions</li>
74
</ul>
75
<p>
76
More types can be supported using the classes provided in the package.
77
It is also possible to develop new classes to handle types of
78
complex expressions which cannot be supported with the existing classes.
79
Using the framework provided by <code>IComplExpProcessor</code> and
80
<code>ComplExpBasic</code> can facilitate
81
considerably the development of such new support.</p>
82
<p>
83
The class {@link <a href="ComplExpUtil.html">ComplExpUtil</a>} provides
84
a number of convenience methods to process some common types of
85
complex expressions. When using methods in this class, there is no need
86
to refer to members of other classes of this package.
87
However, the other classes allow more precise control and possibly better
88
performance.</p>
89
<p>
90
91
<p>&nbsp;</p>
92
93
<h2>Abbreviations used in the documentation of this package</h2>
94
95
<dl>
96
<dt><b>UBA</b><dd>Unicode Bidirectional Algorithm
97
98
<dt><b>Bidi</b><dd>Bidirectional
99
100
<dt><b>GUI</b><dd>Graphical User Interface
101
102
<dt><b>UI</b><dd>User Interface
103
104
<dt><b>LTR</b><dd>Left to Right
105
106
<dt><b>RTL</b><dd>Right to Left
107
108
<dt><b>LRM</b><dd>Left-to-Right Mark
109
110
<dt><b>RLM</b><dd>Right-to-Left Mark
111
112
<dt><b>LRE</b><dd>Left-to-Right Embedding
113
114
<dt><b>RLE</b><dd>Right-to-Left Embedding
115
116
<dt><b>PDF</b><dd>Pop Directional Formatting
117
</dl>
118
119
<p>&nbsp;</p>
120
121
<h2>Known Limitations</h2>
122
123
<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
125
text is displayed. The following related two key points merit special
126
attention:</p>
127
128
<ul>
129
<li>Implementations of the UBA on various platforms (e.g., Windows and
130
Linux) are very similar but nevertheless have known differences. Those
131
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
133
platforms might look different. These differences will surface in Java
134
applications when they use the platform visual components for their UI
135
(e.g., AWT, SWT).</li>
136
137
<li>It is assumed that the presentation engine supports LRE, RLE and
138
PDF directional formatting characters.</li>
139
140
<li>Because some presentation engines are not strictly conformant to the
141
UBA, the implementation of complex expressions in this package adds LRM
142
or RLM characters in association with LRE, RLE or PDF in cases where
143
this would not be needed if the presentation engine was fully conformant
144
to the UBA. Such added marks will not have harmful effects on
145
conformant presentation engines and will help less conformant engines to
146
achieve the desired presentation.</li>
147
</ul>
148
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>
158
</html>
(-)src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java (+98 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.custom;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexImpl;
15
16
/**
17
 *  Generic processor which can be used as superclass (base class)
18
 *  for specific complex expression processors.
19
 *  <p>
20
 *  Here are some guidelines about how to write complex expression
21
 *  processors.
22
 *  <ul>
23
 *    <li>Processor instances may be accessed simultaneously by
24
 *        several threads. They should have no instance variables.</li>
25
 *    <li>Each use of a processor is initialized with the {@link #init init}
26
 *        or the {@link #updateEnvironment updateEnvironment} methods.
27
 *        Both methods have a {@link BidiComplexHelper} argument named <code>caller</code>.
28
 *        All calls to methods of <code>BidiComplexProcessor</code> have a
29
 *        <code>caller</code> argument.
30
 *        If a processor needs to retain some data across invocations, it may
31
 *        access the field {@link BidiComplexImpl#processorData caller.impl.processorData}.
32
 *        It is guaranteed that this field will not be modified by any code
33
 *        except the processor itself.</li>
34
 *    <li>The behavior of a processor is governed by 3 factors:
35
 *        <ul>
36
 *          <li>The {@link BidiComplexFeatures#operators operators} field of its
37
 *              {@link BidiComplexFeatures features} determines how submitted
38
 *              complex expressions are split into tokens.</li>
39
 *          <li>The tokens are displayed one after the other according
40
 *              to the appropriate {@link BidiComplexFeatures#dirArabic direction}.
41
 *          <li>The counter {@link BidiComplexFeatures#specialsCount specialsCount}
42
 *              determines how many special cases need to be handled by
43
 *              code specific to that processor.
44
 *  </ul>
45
 *
46
 *  @author Matitiahu Allouche
47
 */
48
public class BidiComplexProcessor implements IBidiComplexProcessor {
49
50
	/**
51
	 *  In <code>BidiComplexProcessor</code> this method returns a
52
	 *  {@link BidiComplexFeatures#DEFAULT DEFAULT} value which
53
	 *  directs the processor to do nothing.
54
	 */
55
	public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment environment) {
56
		return BidiComplexFeatures.DEFAULT;
57
	}
58
59
	/**
60
	 *  In <code>BidiComplexProcessor</code> this method simply calls the
61
	 *  {@link #init init} method. If this is good enough, i.e.
62
	 *  if the {@link BidiComplexFeatures features} of the processor are
63
	 *  determined identically for initialization and after a
64
	 *  change in the {@link BidiComplexEnvironment environment}, subclasses of
65
	 *  <code>BidiComplexProcessor</code> don't need to override this
66
	 *  method.
67
	 */
68
	public BidiComplexFeatures updateEnvironment(BidiComplexHelper caller, BidiComplexEnvironment environment) {
69
		return init(caller, environment);
70
	}
71
72
	/**
73
	 *  In <code>BidiComplexProcessor</code> this method throws an
74
	 *  <code>IllegalStateException</code>. This is appropriate behavior
75
	 *  (and does not need to be overridden) for processors whose
76
	 *  {@link BidiComplexFeatures#specialsCount specialsCount} is zero, which
77
	 *  means that <code>indexOfSpecial</code> should never be called
78
	 *  for them.
79
	 */
80
	public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex) {
81
		// This method must be overridden by all subclasses with special cases.
82
		throw new IllegalStateException();
83
	}
84
85
	/**
86
	 *  In <code>BidiComplexProcessor</code> this method throws an
87
	 *  <code>IllegalStateException</code>. This is appropriate behavior
88
	 *  (and does not need to be overridden) for processors whose
89
	 *  {@link BidiComplexFeatures#specialsCount specialsCount} is zero, which
90
	 *  means that <code>processSpecial</code> should never be called
91
	 *  for them.
92
	 */
93
	public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation) {
94
		// This method must be overridden by all subclasses with any special case.
95
		throw new IllegalStateException();
96
	}
97
98
}
(-)src/org/eclipse/equinox/bidi/custom/BidiComplexStringProcessor.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.custom;
12
13
import org.eclipse.equinox.bidi.internal.BidiComplexTypesCollector;
14
15
/**
16
 * This class provides access to registered complex expression processors.
17
 */
18
public class BidiComplexStringProcessor {
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 BidiComplexTypesCollector.getInstance().getTypes();
27
	}
28
29
	/**
30
	 *  Get access to a complex expression processor of a given type.
31
	 *
32
	 *  @param type string identifying a type of processor
33
	 *
34
	 *  @return a reference to an instance of a processor of the
35
	 *  required type. If the type is unknown, return <code>null</code>.
36
	 */
37
	static public IBidiComplexProcessor getProcessor(String type) {
38
		return BidiComplexTypesCollector.getInstance().getProcessor(type);
39
	}
40
}
(-)src/org/eclipse/equinox/bidi/custom/IBidiComplexProcessor.java (+150 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.custom;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexImpl;
15
16
/**
17
 *  Interface for all complex expression processors.
18
 *  For guidelines about implementation, see
19
 *  {@link BidiComplexProcessor}.
20
 *
21
 *  @author Matitiahu Allouche
22
 */
23
public interface IBidiComplexProcessor {
24
25
	/**
26
	 *  Do whatever initializations are needed and return the
27
	 *  {@link BidiComplexFeatures} characterizing the processor.
28
	 *
29
	 *  @param env the current environment, which may affect the
30
	 *          initializations.
31
	 *
32
	 *  @param caller <code>BidiComplexHelper</code> instance which called this method.
33
	 *          This allows access to the field
34
	 *          {@link BidiComplexImpl#processorData caller.impl.processorData} where
35
	 *          the processor can keep whatever data it needs.
36
	 *
37
	 *  @return the features in use for this processor.
38
	 */
39
	public abstract BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env);
40
41
	/**
42
	 *  Do whatever renewed initializations are needed after a
43
	 *  change in the environment and return the possibly updated
44
	 *  {@link BidiComplexFeatures} characterizing the processor.
45
	 *
46
	 *  @param env the updated environment, which may affect the
47
	 *          initializations.
48
	 *
49
	 *  @param caller <code>BidiComplexHelper</code> instance which called this method.
50
	 *          This allows access to the field
51
	 *          {@link BidiComplexImpl#processorData caller.impl.processorData} where
52
	 *          the processor can keep whatever data it needs.
53
	 *
54
	 *  @return the features to use for this processor.
55
	 */
56
	public BidiComplexFeatures updateEnvironment(BidiComplexHelper caller, BidiComplexEnvironment env);
57
58
	/**
59
	 *  Locate occurrences of special strings within a complex expression
60
	 *  and return their indexes one after the other in successive calls.
61
	 *  <p>
62
	 *  This method is called repeatedly from the code implementing
63
	 *  {@link BidiComplexHelper#leanToFullText leanToFullText} if the field
64
	 *  {@link BidiComplexFeatures#specialsCount specialsCount} returned when
65
	 *  {@link #init initializing} the processor is greater than zero.
66
	 *  <p>
67
	 *  The code implementing this method may use the following methods
68
	 *  in {@link BidiComplexHelper}:
69
	 *  <ul>
70
	 *    <li>{@link BidiComplexHelper#getDirProp getDirProp}</li>
71
	 *    <li>{@link BidiComplexHelper#setDirProp setDirProp}</li>
72
	 *    <li>{@link BidiComplexHelper#insertMark insertMark}</li>
73
	 *    <li>{@link BidiComplexHelper#processOperator processOperator}</li>
74
	 *    <li>{@link BidiComplexHelper#setFinalState setFinalState}</li>
75
	 *  </ul>
76
	 *
77
	 *  @param  caseNumber number of the special case to locate.
78
	 *          This number varies from zero to <code>specialsCount - 1</code>.
79
	 *          The meaning of this number is internal to the class
80
	 *          implementing <code>indexOfSpecial</code>.
81
	 *
82
	 *  @param  srcText text of the complex expression before addition of any
83
	 *          directional formatting characters.
84
	 *
85
	 *  @param  fromIndex the index within <code>srcText</code> to start
86
	 *          the search from.
87
	 *
88
	 *  @return the position where the start of the special case was located.
89
	 *          The method must return the first occurrence of whatever
90
	 *          identifies the start of the special case starting from
91
	 *          <code>fromIndex</code>. The method does not have to check if
92
	 *          this occurrence appears within the scope of another special
93
	 *          case (e.g. a comment starting delimiter within the scope of
94
	 *          a literal or vice-versa).
95
	 *          <br>If no occurrence is found, the method must return -1.
96
	 */
97
	public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex);
98
99
	/**
100
	 *  This method is called by {@link BidiComplexHelper#leanToFullText leanToFullText}
101
	 *  when a special case occurrence is located by
102
	 *  {@link #indexOfSpecial indexOfSpecial}.
103
	 *  <p>
104
	 *  The code implementing this method may use the following methods
105
	 *  in {@link BidiComplexHelper}:
106
	 *  <ul>
107
	 *    <li>{@link BidiComplexHelper#getDirProp getDirProp}</li>
108
	 *    <li>{@link BidiComplexHelper#setDirProp setDirProp}</li>
109
	 *    <li>{@link BidiComplexHelper#insertMark insertMark}</li>
110
	 *    <li>{@link BidiComplexHelper#processOperator processOperator}</li>
111
	 *    <li>{@link BidiComplexHelper#setFinalState setFinalState}</li>
112
	 *  </ul>
113
	 *  <p>
114
	 *  If a special processing cannot be completed within a current call to
115
	 *  <code>processSpecial</code> (for instance, a comment has been started
116
	 *  in the current line but its end appears in a following line),
117
	 *  <code>processSpecial</code> should specify a final state using
118
	 *  the method {@link BidiComplexHelper#setFinalState setFinalState}.
119
	 *  The meaning of this state is internal to the processor.
120
	 *  On a later call to
121
	 *  {@link BidiComplexHelper#leanToFullText(String text, int initState)}
122
	 *  specifying that state value, <code>processSpecial</code> will be
123
	 *  called with that value for parameter <code>caseNumber</code> and
124
	 *  <code>-1</code> for parameter <code>operLocation</code> and should
125
	 *  perform whatever initializations are required depending on the state.
126
	 *
127
	 *  @param  caseNumber number of the special case to handle.
128
	 *
129
	 *  @param  srcText text of the complex expression.
130
	 *
131
	 *  @param  operLocation the position returned by
132
	 *          {@link #indexOfSpecial indexOfSpecial}. In calls to
133
	 *          {@link BidiComplexHelper#leanToFullText(String text, int initState)} or
134
	 *          {@link BidiComplexHelper#fullToLeanText(String text, int initState)}
135
	 *          specifying an <code>initState</code>
136
	 *          parameter, <code>processSpecial</code> is called when initializing
137
	 *          the processing with the value of <code>caseNumber</code>
138
	 *          equal to <code>initState</code> and the value of
139
	 *          <code>operLocation</code> equal to <code>-1</code>.
140
	 *
141
	 *  @return the position after the scope of the special case ends.
142
	 *          For instance, the position after the end of a comment,
143
	 *          the position after the end of a literal.
144
	 *          <br>A value greater or equal to the length of <code>srcText</code>
145
	 *          means that there is no further occurrence of this case in the
146
	 *          current complex expression.
147
	 */
148
	public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation);
149
150
}
(-)src/org/eclipse/equinox/bidi/custom/package.html (+27 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 an interface and classes for
9
developing complex expressions processors.
10
11
<ul>
12
  <li>{@link <a href="IBidiComplexProcessor.html">IBidiComplexProcessor</a>}
13
      is an interface specifying which methods a processor must provide.</li>
14
  <li>{@link <a href="BidiComplexProcessor.html">BidiComplexProcessor</a>}
15
      is a generic processor which can be used as superclass for specific
16
      processors.</li>
17
  <li>{@link <a href="BidiComplexStringProcessor.html">BidiComplexStringProcessor</a>}
18
      is a class which allows retrieval of the defined processor types and of the
19
      corresponding processors.</li>
20
</ul>
21
22
This package is to be used together with package
23
{@link <a href="..\package-summary.html">
24
org.eclipse.equinox.bidi</a>}.
25
26
</body>
27
</html>
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexActivator.java (+91 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import java.util.Locale;
14
import org.eclipse.osgi.framework.log.FrameworkLog;
15
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
16
import org.eclipse.osgi.service.localization.LocaleProvider;
17
import org.osgi.framework.*;
18
import org.osgi.util.tracker.ServiceTracker;
19
20
public class BidiComplexActivator implements BundleActivator {
21
22
	private ServiceTracker logTracker = null;
23
	private BundleContext bundleContext;
24
	private static BidiComplexActivator instance;
25
26
	public BidiComplexActivator() {
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
	public static BidiComplexActivator getInstance() {
44
		return instance;
45
	}
46
47
	public String getProperty(String key) {
48
		return bundleContext.getProperty(key);
49
	}
50
51
	public Locale getDefaultLocale() {
52
		// use OSGi service
53
		ServiceReference[] references = null;
54
		try {
55
			references = bundleContext.getAllServiceReferences(null, LocaleProvider.class.getName());
56
		} catch (InvalidSyntaxException e) {
57
			// do nothing
58
		}
59
		if (references == null || references.length < 1)
60
			return Locale.getDefault();
61
		Object service = bundleContext.getService(references[0]);
62
		LocaleProvider localeProvider = (LocaleProvider) service;
63
		if (localeProvider != null) {
64
			Locale currentLocale = localeProvider.getLocale();
65
			bundleContext.ungetService(references[0]);
66
			if (currentLocale != null)
67
				return currentLocale;
68
		}
69
		return Locale.getDefault();
70
	}
71
72
	private FrameworkLog getFrameworkLog() {
73
		if (logTracker == null) {
74
			logTracker = new ServiceTracker(bundleContext, FrameworkLog.class.getName(), null);
75
			logTracker.open();
76
		}
77
		return (FrameworkLog) logTracker.getService();
78
	}
79
80
	static public void logError(String message, Exception e) {
81
		FrameworkLog frameworkLog = instance.getFrameworkLog();
82
		if (frameworkLog != null) {
83
			frameworkLog.log(new FrameworkLogEntry("org.eclipse.equinox.bidi", FrameworkLogEntry.ERROR, 1, message, 0, e, null)); //$NON-NLS-1$
84
			return;
85
		}
86
		System.err.println(message);
87
		if (e != null)
88
			e.printStackTrace();
89
	}
90
91
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexDelims.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import org.eclipse.equinox.bidi.BidiComplexHelper;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexDelims</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 BidiComplexDelims extends BidiComplexProcessor {
25
26
	/**
27
	 *  This method locates occurrences of start delimiters.
28
	 */
29
	public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) {
30
		char delim = getDelimiters().charAt(caseNumber * 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(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
38
		helper.processOperator(operLocation);
39
		int loc = operLocation + 1;
40
		char delim = getDelimiters().charAt((caseNumber * 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/BidiComplexDelimsEsc.java (+55 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import org.eclipse.equinox.bidi.BidiComplexHelper;
14
15
/**
16
 *  <code>BidiComplexDelims</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 BidiComplexDelims} 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 BidiComplexDelimsEsc extends BidiComplexDelims {
32
33
	/**
34
	*  This method skips until after the matching end delimiter,
35
	*  ignoring possibly escaped end delimiters.
36
	*/
37
	public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
38
		helper.processOperator(operLocation);
39
		int location = operLocation + 1;
40
		char delim = getDelimiters().charAt((caseNumber * 2) + 1);
41
		while (true) {
42
			location = srcText.indexOf(delim, location);
43
			if (location < 0)
44
				return srcText.length();
45
			int cnt = 0;
46
			for (int i = location - 1; srcText.charAt(i) == '\\'; i--) {
47
				cnt++;
48
			}
49
			location++;
50
			if ((cnt & 1) == 0)
51
				return location;
52
		}
53
	}
54
55
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java (+761 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexImpl</code> provides the code which implements the API in
18
 *  {@link BidiComplexHelper}. All its public methods are shadows of similarly
19
 *  signed methods of <code>BidiComplexHelper</code>, and their documentation
20
 *  is by reference to the methods in <code>BidiComplexHelper</code>.
21
 *
22
 *  @author Matitiahu Allouche
23
 */
24
public class BidiComplexImpl {
25
26
	static final String EMPTY_STRING = ""; //$NON-NLS-1$
27
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
28
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
29
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
30
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
31
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
32
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
33
	static final char LRM = 0x200E;
34
	static final char RLM = 0x200F;
35
	static final char LRE = 0x202A;
36
	static final char RLE = 0x202B;
37
	static final char PDF = 0x202C;
38
	static final char[] MARKS = {LRM, RLM};
39
	static final char[] EMBEDS = {LRE, RLE};
40
	static final byte[] STRONGS = {L, R};
41
	static final int PREFIX_LENGTH = 2;
42
	static final int SUFFIX_LENGTH = 2;
43
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
44
45
	BidiComplexHelper helper;
46
47
	BidiComplexEnvironment environment;
48
49
	IBidiComplexProcessor processor;
50
51
	/**
52
	 *  This field is reserved for use of the complex expression
53
	 *  processor associated with this instance of <code>BidiComplexImpl</code>.
54
	 *  The processor can keep here a reference to an object that it
55
	 *  has sole control of.
56
	 */
57
	public Object processorData;
58
59
	/**
60
	 *  Features of the associated processor.
61
	 *
62
	 */
63
	public BidiComplexFeatures features;
64
65
	int state = BidiComplexHelper.STATE_NOTHING_GOING;
66
67
	// strong bidi class (L or R) for current expression direction
68
	byte curStrong = -1;
69
	// strong character (LRM or RLM) for current expression direction
70
	char curMark;
71
	// strong directional control (LRE or RLE) for current expression direction
72
	char curEmbed;
73
	int prefixLength;
74
	// index of next occurrence for each operator and each special case
75
	int[] locations;
76
	// number of special cases
77
	int specialsCount;
78
	String leanText;
79
	// positions where LRM/RLM must be added
80
	int[] offsets;
81
	// number of LRM/RLM to add
82
	int count;
83
	// For positions where it has been looked up, the entry will receive
84
	// the Character directionality + 2 (so that 0 indicates that the
85
	// the directionality has not been looked up yet.
86
	byte[] dirProps;
87
	// current UI orientation (after resolution if contextual)
88
	int curOrient = -1;
89
	// Current expression base direction (after resolution if depending on
90
	// script and/or on GUI mirroring (0=LTR, 1=RTL))
91
	int curDirection = -1;
92
93
	/**
94
	 *  @see BidiComplexHelper#BidiComplexHelper(IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment)
95
	 */
96
	public BidiComplexImpl(BidiComplexHelper caller, IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment) {
97
		helper = caller;
98
		if (environment == null) {
99
			this.environment = BidiComplexEnvironment.DEFAULT;
100
		} else {
101
			this.environment = environment;
102
		}
103
		processor = myProcessor;
104
		features = processor.init(helper, this.environment);
105
		// keep private copy of specialsCount to avoid later modification
106
		specialsCount = features.specialsCount;
107
		locations = new int[features.operators.length() + specialsCount];
108
	}
109
110
	long computeNextLocation(int curPos) {
111
		int operCount = features.operators.length();
112
		int len = leanText.length();
113
		int nextLocation = len;
114
		int idxLocation = 0;
115
		// Start with special sequences to give them precedence over simple
116
		// operators. This may apply to cases like slash+asterisk versus slash.
117
		for (int i = 0; i < specialsCount; i++) {
118
			int location = locations[operCount + i];
119
			if (location < curPos) {
120
				location = processor.indexOfSpecial(helper, i, leanText, curPos);
121
				if (location < 0)
122
					location = len;
123
				locations[operCount + i] = location;
124
			}
125
			if (location < nextLocation) {
126
				nextLocation = location;
127
				idxLocation = operCount + i;
128
			}
129
		}
130
		for (int i = 0; i < operCount; i++) {
131
			int location = locations[i];
132
			if (location < curPos) {
133
				location = leanText.indexOf(features.operators.charAt(i), curPos);
134
				if (location < 0)
135
					location = len;
136
				locations[i] = location;
137
			}
138
			if (location < nextLocation) {
139
				nextLocation = location;
140
				idxLocation = i;
141
			}
142
		}
143
		return nextLocation + (((long) idxLocation) << 32);
144
	}
145
146
	int getCurOrient() {
147
		if (curOrient >= 0)
148
			return curOrient;
149
150
		if ((environment.orientation & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) {
151
			// absolute orientation
152
			curOrient = environment.orientation;
153
			return curOrient;
154
		}
155
		// contextual orientation
156
		int len = leanText.length();
157
		byte dirProp;
158
		for (int i = 0; i < len; i++) {
159
			// In the following lines, B, L, R and AL represent bidi categories
160
			// as defined in the Unicode Bidirectional Algorithm
161
			// ( http://www.unicode.org/reports/tr9/ ).
162
			// B  represents the category Block Separator.
163
			// L  represents the category Left to Right character.
164
			// R  represents the category Right to Left character.
165
			// AL represents the category Arabic Letter.
166
			dirProp = dirProps[i];
167
			if (dirProp == 0) {
168
				dirProp = Character.getDirectionality(leanText.charAt(i));
169
				if (dirProp == B) // B char resolves to L or R depending on orientation
170
					continue;
171
				dirProps[i] = (byte) (dirProp + 2);
172
			} else {
173
				dirProp -= 2;
174
			}
175
			if (dirProp == L) {
176
				curOrient = BidiComplexEnvironment.ORIENT_LTR;
177
				return curOrient;
178
			}
179
			if (dirProp == R || dirProp == AL) {
180
				curOrient = BidiComplexEnvironment.ORIENT_RTL;
181
				return curOrient;
182
			}
183
		}
184
		curOrient = environment.orientation & 1;
185
		return curOrient;
186
	}
187
188
	/**
189
	 *  @see BidiComplexHelper#getCurDirection
190
	 */
191
	public int getCurDirection() {
192
		if (curDirection >= 0)
193
			return curDirection;
194
195
		curStrong = -1;
196
		// same direction for Arabic and Hebrew?
197
		if (features.dirArabic == features.dirHebrew) {
198
			curDirection = features.dirArabic;
199
			return curDirection;
200
		}
201
		// check if Arabic or Hebrew letter comes first
202
		int len = leanText.length();
203
		byte dirProp;
204
		for (int i = 0; i < len; i++) {
205
			// In the following lines, R and AL represent bidi categories
206
			// as defined in the Unicode Bidirectional Algorithm
207
			// ( http://www.unicode.org/reports/tr9/ ).
208
			// R  represents the category Right to Left character.
209
			// AL represents the category Arabic Letter.
210
			dirProp = getDirProp(i);
211
			if (dirProp == AL) {
212
				curDirection = features.dirArabic;
213
				return curDirection;
214
			}
215
			if (dirProp == R) {
216
				curDirection = features.dirHebrew;
217
				return curDirection;
218
			}
219
		}
220
		// found no Arabic or Hebrew character
221
		curDirection = BidiComplexFeatures.DIR_LTR;
222
		return curDirection;
223
	}
224
225
	void setMarkAndFixes() {
226
		int dir = getCurDirection();
227
		if (curStrong == STRONGS[dir])
228
			return;
229
		curStrong = STRONGS[dir];
230
		curMark = MARKS[dir];
231
		curEmbed = EMBEDS[dir];
232
	}
233
234
	/**
235
	 *  @see BidiComplexHelper#getDirProp(int index)
236
	 */
237
	public byte getDirProp(int index) {
238
		byte dirProp = dirProps[index];
239
		if (dirProp == 0) {
240
			// In the following lines, B, L and R represent bidi categories
241
			// as defined in the Unicode Bidirectional Algorithm
242
			// ( http://www.unicode.org/reports/tr9/ ).
243
			// B  represents the category Block Separator.
244
			// L  represents the category Left to Right character.
245
			// R  represents the category Right to Left character.
246
			dirProp = Character.getDirectionality(leanText.charAt(index));
247
			if (dirProp == B)
248
				dirProp = getCurOrient() == BidiComplexEnvironment.ORIENT_RTL ? R : L;
249
			dirProps[index] = (byte) (dirProp + 2);
250
			return dirProp;
251
		}
252
		return (byte) (dirProp - 2);
253
	}
254
255
	/**
256
	 *  @see BidiComplexHelper#setDirProp(int index, byte dirProp)
257
	 */
258
	public void setDirProp(int index, byte dirProp) {
259
		dirProps[index] = (byte) (dirProp + 2);
260
	}
261
262
	/**
263
	 *  @see BidiComplexHelper#processOperator(int operLocation)
264
	 */
265
	public void processOperator(int operLocation) {
266
		// In this method, L, R, AL, AN and EN represent bidi categories
267
		// as defined in the Unicode Bidirectional Algorithm
268
		// ( http://www.unicode.org/reports/tr9/ ).
269
		// L  represents the category Left to Right character.
270
		// R  represents the category Right to Left character.
271
		// AL represents the category Arabic Letter.
272
		// AN represents the category Arabic Number.
273
		// EN  represents the category European Number.
274
		int len = leanText.length();
275
		boolean doneAN = false;
276
277
		if (getCurDirection() == BidiComplexFeatures.DIR_RTL) {
278
			// the expression base direction is RTL
279
			for (int i = operLocation - 1; i >= 0; i--) {
280
				byte dirProp = getDirProp(i);
281
				if (dirProp == R || dirProp == AL)
282
					return;
283
284
				if (dirProp == L) {
285
					for (int j = operLocation; j < len; j++) {
286
						dirProp = getDirProp(j);
287
						if (dirProp == R || dirProp == AL)
288
							return;
289
						if (dirProp == L || dirProp == EN) {
290
							insertMark(operLocation);
291
							return;
292
						}
293
					}
294
					return;
295
				}
296
			}
297
			return;
298
		}
299
300
		// the expression base direction is LTR
301
		if (features.ignoreArabic) {
302
			if (features.ignoreHebrew) /* process neither Arabic nor Hebrew */
303
				return;
304
			/* process Hebrew, not Arabic */
305
			for (int i = operLocation - 1; i >= 0; i--) {
306
				byte dirProp = getDirProp(i);
307
				if (dirProp == L)
308
					return;
309
				if (dirProp == R) {
310
					for (int j = operLocation; j < len; j++) {
311
						dirProp = getDirProp(j);
312
						if (dirProp == L)
313
							return;
314
						if (dirProp == R || dirProp == EN) {
315
							insertMark(operLocation);
316
							return;
317
						}
318
					}
319
					return;
320
				}
321
			}
322
		} else {
323
			if (features.ignoreHebrew) { /* process Arabic, not Hebrew */
324
				for (int i = operLocation - 1; i >= 0; i--) {
325
					byte dirProp = getDirProp(i);
326
					if (dirProp == L)
327
						return;
328
					if (dirProp == AL) {
329
						for (int j = operLocation; j < len; j++) {
330
							dirProp = getDirProp(j);
331
							if (dirProp == L)
332
								return;
333
							if (dirProp == EN || dirProp == AL || dirProp == AN) {
334
								insertMark(operLocation);
335
								return;
336
							}
337
						}
338
						return;
339
					}
340
					if (dirProp == AN && !doneAN) {
341
						for (int j = operLocation; j < len; j++) {
342
							dirProp = getDirProp(j);
343
							if (dirProp == L)
344
								return;
345
							if (dirProp == AL || dirProp == AN) {
346
								insertMark(operLocation);
347
								return;
348
							}
349
						}
350
						doneAN = true;
351
					}
352
				}
353
			} else { /* process Arabic and Hebrew */
354
				for (int i = operLocation - 1; i >= 0; i--) {
355
					byte dirProp = getDirProp(i);
356
					if (dirProp == L)
357
						return;
358
					if (dirProp == R || dirProp == AL) {
359
						for (int j = operLocation; j < len; j++) {
360
							dirProp = getDirProp(j);
361
							if (dirProp == L)
362
								return;
363
							if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
364
								insertMark(operLocation);
365
								return;
366
							}
367
						}
368
						return;
369
					}
370
					if (dirProp == AN && !doneAN) {
371
						for (int j = operLocation; j < len; j++) {
372
							dirProp = getDirProp(j);
373
							if (dirProp == L)
374
								return;
375
							if (dirProp == AL || dirProp == AN || dirProp == R) {
376
								insertMark(operLocation);
377
								return;
378
							}
379
						}
380
						doneAN = true;
381
					}
382
				}
383
			}
384
		}
385
	}
386
387
	/**
388
	 *  @see BidiComplexHelper#getFinalState()
389
	 */
390
	public int getFinalState() {
391
		return state;
392
	}
393
394
	/**
395
	 *  @see BidiComplexHelper#setFinalState(int newState)
396
	 */
397
	public void setFinalState(int newState) {
398
		state = newState;
399
	}
400
401
	/**
402
	 *  @see BidiComplexHelper#leanToFullText(String text, int initState)
403
	 */
404
	public String leanToFullText(String text, int initState) {
405
		if (text.length() == 0) {
406
			prefixLength = 0;
407
			count = 0;
408
			return text;
409
		}
410
		leanToFullTextNofix(text, initState);
411
		return addMarks(true);
412
	}
413
414
	void leanToFullTextNofix(String text, int initState) {
415
		int operCount = features.operators.length();
416
		// current position
417
		int curPos = 0;
418
		int len = text.length();
419
		// location of next token to handle
420
		int nextLocation;
421
		// index of next token to handle (if < operCount, this is an operator; otherwise a special case
422
		int idxLocation;
423
		leanText = text;
424
		offsets = new int[20];
425
		count = 0;
426
		dirProps = new byte[len];
427
		curOrient = -1;
428
		curDirection = -1;
429
		// initialize locations
430
		int k = locations.length;
431
		for (int i = 0; i < k; i++) {
432
			locations[i] = -1;
433
		}
434
		state = BidiComplexHelper.STATE_NOTHING_GOING;
435
		if (initState != BidiComplexHelper.STATE_NOTHING_GOING)
436
			curPos = processor.processSpecial(helper, initState, leanText, -1);
437
438
		while (true) {
439
			long res = computeNextLocation(curPos);
440
			nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
441
			if (nextLocation >= len)
442
				break;
443
			idxLocation = (int) (res >> 32); /* high word */
444
			if (idxLocation < operCount) {
445
				processOperator(nextLocation);
446
				curPos = nextLocation + 1;
447
			} else {
448
				curPos = processor.processSpecial(helper, idxLocation - operCount, leanText, nextLocation);
449
			}
450
		}
451
	}
452
453
	/**
454
	 *  @see BidiComplexHelper#leanBidiCharOffsets()
455
	 */
456
	public int[] leanBidiCharOffsets() {
457
		int[] result = new int[count];
458
		System.arraycopy(offsets, 0, result, 0, count);
459
		return result;
460
	}
461
462
	/**
463
	 *  @see BidiComplexHelper#fullBidiCharOffsets()
464
	 */
465
	public int[] fullBidiCharOffsets() {
466
		int lim = count;
467
		if (prefixLength > 0) {
468
			if (prefixLength == 1)
469
				lim++;
470
			else
471
				lim += FIXES_LENGTH;
472
		}
473
		int[] fullOffsets = new int[lim];
474
		for (int i = 0; i < prefixLength; i++) {
475
			fullOffsets[i] = i;
476
		}
477
		int added = prefixLength;
478
		for (int i = 0; i < count; i++) {
479
			fullOffsets[prefixLength + i] = offsets[i] + added;
480
			added++;
481
		}
482
		if (prefixLength > 1) {
483
			int len = leanText.length();
484
			fullOffsets[lim - 2] = len + lim - 2;
485
			fullOffsets[lim - 1] = len + lim - 1;
486
		}
487
		return fullOffsets;
488
	}
489
490
	/**
491
	 *  @see BidiComplexHelper#fullToLeanText(String text, int initState)
492
	 */
493
	public String fullToLeanText(String text, int initState) {
494
		int i; // used as loop index
495
		setMarkAndFixes();
496
		// remove any prefix and leading mark
497
		int lenText = text.length();
498
		for (i = 0; i < lenText; i++) {
499
			char c = text.charAt(i);
500
			if (c != curEmbed && c != curMark)
501
				break;
502
		}
503
		if (i > 0) { // found at least one prefix or leading mark
504
			text = text.substring(i);
505
			lenText = text.length();
506
		}
507
		// remove any suffix and trailing mark
508
		for (i = lenText - 1; i >= 0; i--) {
509
			char c = text.charAt(i);
510
			if (c != PDF && c != curMark)
511
				break;
512
		}
513
		if (i < 0) { // only suffix and trailing marks, no real data
514
			leanText = EMPTY_STRING;
515
			prefixLength = 0;
516
			count = 0;
517
			return leanText;
518
		}
519
		if (i < (lenText - 1)) { // found at least one suffix or trailing mark
520
			text = text.substring(0, i + 1);
521
			lenText = text.length();
522
		}
523
		char[] chars = text.toCharArray();
524
		// remove marks from chars
525
		int cnt = 0;
526
		for (i = 0; i < lenText; i++) {
527
			char c = chars[i];
528
			if (c == curMark)
529
				cnt++;
530
			else if (cnt > 0)
531
				chars[i - cnt] = c;
532
		}
533
		String lean = new String(chars, 0, lenText - cnt);
534
		leanToFullTextNofix(lean, initState);
535
		String full = addMarks(false); /* only marks, no prefix/suffix */
536
		if (full.equals(text))
537
			return lean;
538
539
		// There are some marks in full which are not in text and/or vice versa.
540
		// We need to add to lean any mark appearing in text and not in full.
541
		// The completed lean can never be longer than text itself.
542
		char[] newChars = new char[lenText];
543
		char cFull, cText;
544
		int idxFull, idxText, idxLean, markPos, newCharsPos;
545
		int lenFull = full.length();
546
		idxFull = idxText = idxLean = newCharsPos = 0;
547
		while (idxText < lenText && idxFull < lenFull) {
548
			cFull = full.charAt(idxFull);
549
			cText = text.charAt(idxText);
550
			if (cFull == cText) { /* chars are equal, proceed */
551
				idxText++;
552
				idxFull++;
553
				continue;
554
			}
555
			if (cFull == curMark) { /* extra Mark in full text */
556
				idxFull++;
557
				continue;
558
			}
559
			if (cText == curMark) { /* extra Mark in source full text */
560
				idxText++;
561
				// idxText-2 always >= 0 since leading Marks were removed from text
562
				if (text.charAt(idxText - 2) == curMark)
563
					continue; // ignore successive Marks in text after the first one
564
				markPos = fullToLeanPos(idxFull);
565
				// copy from chars (== lean) to newChars until here
566
				for (i = idxLean; i < markPos; i++) {
567
					newChars[newCharsPos++] = chars[i];
568
				}
569
				idxLean = markPos;
570
				newChars[newCharsPos++] = curMark;
571
				continue;
572
			}
573
			// we should never get here (extra char which is not a Mark)
574
			throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$
575
		}
576
		if (idxText < lenText) /* full ended before text - this should never happen */
577
			throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$
578
579
		// copy the last part of chars to newChars
580
		for (i = idxLean; i < lean.length(); i++) {
581
			newChars[newCharsPos++] = chars[i];
582
		}
583
		lean = new String(newChars, 0, newCharsPos);
584
		leanText = lean;
585
		return lean;
586
	}
587
588
	/**
589
	 *  @see BidiComplexHelper#leanToFullPos(int pos)
590
	 */
591
	public int leanToFullPos(int pos) {
592
		int added = prefixLength;
593
		for (int i = 0; i < count; i++) {
594
			if (offsets[i] <= pos)
595
				added++;
596
			else
597
				return pos + added;
598
		}
599
		return pos + added;
600
	}
601
602
	/**
603
	 *  @see BidiComplexHelper#fullToLeanPos(int pos)
604
	 */
605
	public int fullToLeanPos(int pos) {
606
		int len = leanText.length();
607
		int added = 0;
608
		pos -= prefixLength;
609
		for (int i = 0; i < count; i++) {
610
			if ((offsets[i] + added) < pos)
611
				added++;
612
			else
613
				break;
614
		}
615
		pos -= added;
616
		if (pos < 0)
617
			pos = 0;
618
		else if (pos > len)
619
			pos = len;
620
		return pos;
621
	}
622
623
	/**
624
	 *  @see BidiComplexHelper#insertMark(int offset)
625
	 */
626
	public void insertMark(int offset) {
627
		int index = count - 1; // index of greatest member <= offset
628
		// look up after which member the new offset should be inserted
629
		while (index >= 0) {
630
			int wrkOffset = offsets[index];
631
			if (offset > wrkOffset)
632
				break;
633
			if (offset == wrkOffset)
634
				return; // avoid duplicates
635
			index--;
636
		}
637
		index++; // index now points at where to insert
638
		// check if we have an available slot for new member
639
		if (count >= (offsets.length - 1)) {
640
			int[] newOffsets = new int[offsets.length * 2];
641
			System.arraycopy(offsets, 0, newOffsets, 0, count);
642
			offsets = newOffsets;
643
		}
644
645
		int length = count - index; // number of members to move up
646
		if (length > 0) // shift right all members greater than offset
647
			System.arraycopy(offsets, index, offsets, index + 1, length);
648
649
		offsets[index] = offset;
650
		count++;
651
		// if the offset is 0, adding a mark does not change anything
652
		if (offset < 1)
653
			return;
654
655
		byte dirProp = getDirProp(offset);
656
		// if the current char is a strong one or a digit, we change the
657
		//   dirProp of the previous char to account for the inserted mark.
658
		// In the following lines, L, R, AL, AN and EN represent bidi categories
659
		// as defined in the Unicode Bidirectional Algorithm
660
		// ( http://www.unicode.org/reports/tr9/ ).
661
		// L  represents the category Left to Right character.
662
		// R  represents the category Right to Left character.
663
		// AL represents the category Arabic Letter.
664
		// AN represents the category Arabic Number.
665
		// EN  represents the category European Number.
666
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
667
			index = offset - 1;
668
		else
669
			// if the current char is a neutral, we change its own dirProp
670
			index = offset;
671
		setMarkAndFixes();
672
		setDirProp(index, curStrong);
673
	}
674
675
	String addMarks(boolean addFixes) {
676
		// add prefix/suffix only if addFixes is true
677
		if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == BidiComplexEnvironment.ORIENT_IGNORE))) {
678
			prefixLength = 0;
679
			return leanText;
680
		}
681
		int len = leanText.length();
682
		int newLen = len + count;
683
		if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == BidiComplexEnvironment.ORIENT_UNKNOWN))) {
684
			if ((environment.orientation & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) {
685
				prefixLength = PREFIX_LENGTH;
686
				newLen += FIXES_LENGTH;
687
			} else { /* contextual orientation */
688
				prefixLength = 1;
689
				newLen++; /* +1 for a mark char */
690
			}
691
		} else {
692
			prefixLength = 0;
693
		}
694
		char[] fullChars = new char[newLen];
695
		// add a dummy offset as fence
696
		offsets[count] = len;
697
		int added = prefixLength;
698
		// add marks at offsets
699
		setMarkAndFixes();
700
		for (int i = 0, j = 0; i < len; i++) {
701
			char c = leanText.charAt(i);
702
			if (i == offsets[j]) {
703
				fullChars[i + added] = curMark;
704
				added++;
705
				j++;
706
			}
707
			fullChars[i + added] = c;
708
		}
709
		if (prefixLength > 0) { /* add prefix/suffix ? */
710
			if (prefixLength == 1) { /* contextual orientation */
711
				fullChars[0] = curMark;
712
			} else {
713
				// When the orientation is RTL, we need to add EMBED at the
714
				// start of the text and PDF at its end.
715
				// However, because of a bug in Windows' handling of LRE/PDF,
716
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
717
				fullChars[0] = curEmbed;
718
				fullChars[1] = curMark;
719
				fullChars[newLen - 1] = PDF;
720
				fullChars[newLen - 2] = curMark;
721
			}
722
		}
723
		return new String(fullChars);
724
	}
725
726
	/**
727
	 *  @see BidiComplexHelper#getEnvironment()
728
	 */
729
	public BidiComplexEnvironment getEnvironment() {
730
		return environment;
731
	}
732
733
	/**
734
	 *  @see BidiComplexHelper#setEnvironment(BidiComplexEnvironment environment)
735
	 */
736
	public void setEnvironment(BidiComplexEnvironment environment) {
737
		this.environment = environment;
738
		features = processor.updateEnvironment(helper, environment);
739
		specialsCount = features.specialsCount;
740
		if ((features.operators.length() + specialsCount) > locations.length)
741
			locations = new int[features.operators.length() + specialsCount];
742
743
	}
744
745
	/**
746
	 *  @see BidiComplexHelper#getFeatures()
747
	 */
748
	public BidiComplexFeatures getFeatures() {
749
		return features;
750
	}
751
752
	/**
753
	 *  @see BidiComplexHelper#setFeatures(BidiComplexFeatures features)
754
	 */
755
	public void setFeatures(BidiComplexFeatures features) {
756
		if ((features.operators.length() + specialsCount) > locations.length)
757
			locations = new int[features.operators.length() + specialsCount];
758
		this.features = features;
759
	}
760
761
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java (+53 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import org.eclipse.equinox.bidi.BidiComplexFeatures;
14
import org.eclipse.equinox.bidi.BidiComplexHelper;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  <code>BidiComplexSingle</code> is a processor for complex expressions
19
 *  composed of two parts separated by an operator.
20
 *  The first occurrence of the operator delimits the end of the first part
21
 *  and the start of the second part. Further occurrences of the operator,
22
 *  if any, are treated like regular characters of the second text part.
23
 *  The processor makes sure that the expression be presented in the form
24
 *  (assuming that the equal sign is the operator):
25
 *  <pre>
26
 *  part1=part2
27
 *  </pre>
28
 *  The {@link BidiComplexFeatures#operators operators}
29
 *  field in the {@link BidiComplexFeatures features}
30
 *  of this processor should contain exactly one character.
31
 *  Additional characters will be ignored.
32
 *
33
 *  @author Matitiahu Allouche
34
 */
35
public abstract class BidiComplexSingle extends BidiComplexProcessor {
36
37
	/**
38
	 *  This method locates occurrences of the operator.
39
	 */
40
	public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) {
41
		return srcText.indexOf(helper.impl.features.operators.charAt(0), fromIndex);
42
	}
43
44
	/**
45
	 *  This method inserts a mark before the operator if needed and
46
	 *  skips to the end of the source string.
47
	 */
48
	public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
49
		helper.processOperator(operLocation);
50
		return srcText.length();
51
	}
52
53
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexTypesCollector.java (+111 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.equinox.bidi.internal;
12
13
import java.util.HashMap;
14
import java.util.Map;
15
import org.eclipse.core.runtime.*;
16
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
17
18
public class BidiComplexTypesCollector 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 BidiComplexTypesCollector instance = new BidiComplexTypesCollector();
30
31
	private BidiComplexTypesCollector() {
32
		IExtensionRegistry registry = RegistryFactory.getRegistry();
33
		registry.addListener(this, EXT_POINT);
34
	}
35
36
	static public BidiComplexTypesCollector 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 IBidiComplexProcessor getProcessor(String type) {
50
		if (types == null)
51
			read();
52
		Object processor = types.get(type);
53
		if (processor instanceof IBidiComplexProcessor)
54
			return (IBidiComplexProcessor) 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
					BidiComplexActivator.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
					BidiComplexActivator.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/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/ComplExpBasic.java (-989 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.*;
14
15
/**
16
 *  <code>ComplExpBasic</code> is a
17
 *  complex expression processor for simple types of complex expressions.
18
 *  Normally, a group of <q>operators</q> is specified when creating a new
19
 *  instance.
20
 *  <i>Lean</i> text which is submitted to this processor is divided into
21
 *  segments by the operators.  The processor adds directional formatting
22
 *  characters into the lean text to generate a <i>full</i> text where
23
 *  operators and text segments will be presented in left-to-right sequence.
24
 *
25
 *  @see IComplExpProcessor
26
 *
27
 *  @author Matitiahu Allouche
28
 */
29
public class ComplExpBasic implements IComplExpProcessor {
30
31
	final private static String EMPTY_STRING = ""; //$NON-NLS-1$
32
33
	/**
34
	 *  Flag specifying that a specific instance of complex expression should
35
	 *  assume that the GUI is mirrored (globally going from right to left).
36
	 *  This flag overrides the default flag <code>mirroredDefault</code>
37
	 *  for the parent complex expression instance.
38
	 *  @see #assumeMirrored
39
	 *  @see #isMirrored
40
	 *  @see ComplExpUtil#isMirroredDefault()
41
	 */
42
	protected boolean mirrored = ComplExpUtil.isMirroredDefault();
43
44
	/**
45
	 *  Orientation that should be assumed for the text component where the
46
	 *  complex expression will be displayed. It can be specified using
47
	 *  {@link #assumeOrientation}.
48
	 *  It must be one of the values
49
	 *  {@link IComplExpProcessor#ORIENT_LTR ORIENT_LTR},
50
	 *  {@link IComplExpProcessor#ORIENT_LTR ORIENT_RTL},
51
	 *  {@link IComplExpProcessor#ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR} or
52
	 *  {@link IComplExpProcessor#ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL}.
53
	 *  {@link IComplExpProcessor#ORIENT_UNKNOWN ORIENT_UNKNOWN}.
54
	 *  {@link IComplExpProcessor#ORIENT_IGNORE ORIENT_IGNORE}.
55
	 *  The default is <code>ORIENT_LTR</code>.
56
	 *  <p>
57
	 *  The orientation affects the addition of directional formatting
58
	 *  characters as prefix and/or suffix when generating the <i>full</i>
59
	 *  text of the complex expression.
60
	 *
61
	 *  @see #assumeOrientation
62
	 *  @see #recallOrientation
63
	 *  @see #leanToFullText
64
	 */
65
	protected int orientation;
66
67
	/**
68
	 *  Type of the complex expression processor specified when calling
69
	 *  {@link ComplExpFactory#create(String)}.
70
	 */
71
	protected String type;
72
73
	/**
74
	 *  Base direction of the complex expression. This is an array such that
75
	 *  <ul>
76
	 *    <li><code>direction[0][0]</code> represents the base direction
77
	 *        for Arabic when the GUI is not mirrored.
78
	 *    <li><code>direction[0][1]</code> represents the base direction
79
	 *        for Arabic when the GUI is mirrored.
80
	 *    <li><code>direction[1][0]</code> represents the base direction
81
	 *        for Hebrew when the GUI is not mirrored.
82
	 *    <li><code>direction[1][1]</code> represents the base direction
83
	 *        for Hebrew when the GUI is mirrored.
84
	 *  </ul>
85
	 *  Each of the elements in the array must be one of the values
86
	 *  {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_LTR},
87
	 *  {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_RTL}.
88
	 *  The default is <code>DIRECTION_LTR</code>.
89
	 *
90
	 *  @see #setDirection(int) setDirection
91
	 *  @see #getDirection getDirection
92
	 */
93
	protected int[][] direction = new int[2][2];
94
95
	/**
96
	 *  This field represents the final state achieved in a previous call to
97
	 *  {@link IComplExpProcessor#leanToFullText leanToFullText} or
98
	 *  {@link IComplExpProcessor#fullToLeanText fullToLeanText},
99
	 *  {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text)} or
100
	 *  {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text, int initState)}.
101
	 *  The <code>state</code> is an opaque value which makes sense only
102
	 *  within calls to a same complex expression processor.
103
	 *  The only externalized value is
104
	 *  {@link IComplExpProcessor#STATE_NOTHING_GOING} which means that
105
	 *  there is nothing to remember from the last call.
106
	 *  <p>
107
	 *  <code>state</code> should be used only for complex expressions
108
	 *  which span more than one line, when the user makes a separate call to
109
	 *  <code>leanToFullText</code>, <code>fullToLeanText</code> or
110
	 *  <code>leanBidiCharOffsets</code> for each
111
	 *  line in the expression. The final state value retrieved after the
112
	 *  call for one line should be used as the initial state in the call
113
	 *  which processes the next line.
114
	 *  <p>
115
	 *  If a line within a complex expression has already been processed by
116
	 *  <code>leanToFullText</code> and the <i>lean</i> version of that line has
117
	 *  not changed, and its initial state has not changed either, the user
118
	 *  can be sure that the <i>full</i> version of that line is also
119
	 *  identical to the result of the previous processing.
120
	 *
121
	 *  @see IComplExpProcessor#getFinalState
122
	 *  @see IComplExpProcessor#leanToFullText(String text, int initState)
123
	 *  @see IComplExpProcessor#fullToLeanText(String text, int initState)
124
	 *  @see IComplExpProcessor#leanBidiCharOffsets(String text, int initState)
125
	 */
126
	protected int state = STATE_NOTHING_GOING;
127
128
	private boolean ignoreArabic, ignoreHebrew;
129
130
	public static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
131
	public static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
132
	public static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
133
	public static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
134
	public static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
135
	public static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
136
	public static final char LRM = 0x200E;
137
	public static final char RLM = 0x200F;
138
	public static final char LRE = 0x202A;
139
	public static final char RLE = 0x202B;
140
	public static final char PDF = 0x202C;
141
	public static final char[] MARKS = {LRM, RLM};
142
	public static final char[] EMBEDS = {LRE, RLE};
143
	public static final byte[] STRONGS = {L, R};
144
	public static final int PREFIX_LENGTH = 2;
145
	public static final int SUFFIX_LENGTH = 2;
146
	public static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
147
148
	private byte curStrong = -1;
149
	private char curMark;
150
	private char curEmbed;
151
	private int prefixLength;
152
	char[] operators;
153
	int[] locations;
154
	int specialsCount;
155
	private String leanText;
156
	private int[] offsets;
157
	private int count;
158
	// For positions where it has been looked up, the entry will receive
159
	// the Character directionality + 2 (so that 0 indicates that the
160
	// the directionality has not been looked up yet.
161
	private byte[] dirProps;
162
	// current UI orientation (after resolution if contextual)
163
	private int curOrient = -1;
164
	// Current expression base direction (after resolution if depending on
165
	// script and/or on GUI mirroring (0=LTR, 1=RTL))
166
	private int curDirection = -1;
167
168
	/**
169
	 *  Constructor specifying operators. The processor will add directional
170
	 *  formatting characters to <i>lean</i> text to generate a <i>full</i>
171
	 *  text so that the operators and the segments of text between operators
172
	 *  are displayed from left to right, while each segment is displayed
173
	 *  according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>.
174
	 *
175
	 *  @param operators string grouping one-character operators which
176
	 *         separate the text of the complex expression into segments.
177
	 */
178
	public ComplExpBasic(String operators) {
179
		this.operators = operators.toCharArray();
180
		locations = new int[this.operators.length];
181
	}
182
183
	public void setOperators(String operators) {
184
		this.operators = operators.toCharArray();
185
		locations = new int[this.operators.length + specialsCount];
186
	}
187
188
	public String getOperators() {
189
		return new String(operators);
190
	}
191
192
	/**
193
	 *  Constructor specifying operators and a number of special cases.
194
	 *  In <code>ComplExpBasic</code> the special cases are implemented as
195
	 *  doing nothing. Subclasses of <code>ComplExpBasic</code> may override
196
	 *  methods <code>indexOfSpecial</code> and <code>processSpecial</code>
197
	 *  to provide specific handling for the special cases.
198
	 *  Examples of special cases are comments, literals, or anything which
199
	 *  is not identified by a one-character operator.
200
	 *  <p>
201
	 *  Independently of the special cases, the processor will add directional
202
	 *  formatting characters to <i>lean</i> text to generate a <i>full</i>
203
	 *  text so that the operators and the segments of text between operators
204
	 *  are displayed from left to right, while each segment is displayed
205
	 *  according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>.
206
	 *
207
	 *  @param operators string grouping one-character operators which
208
	 *         separate the text of the complex expression into segments.
209
	 *
210
	 *  @param specialsCount number of special cases supported by this
211
	 *         class. Handling of the special cases is implemented with
212
	 *         methods <code>indexOfSpecial</code> and
213
	 *         <code>processSpecial</code>.
214
	 *
215
	 *  @see #indexOfSpecial indexOfSpecial
216
	 *  @see #processSpecial processSpecial
217
	 */
218
	public ComplExpBasic(String operators, int specialsCount) {
219
		this.operators = operators.toCharArray();
220
		this.specialsCount = specialsCount;
221
		locations = new int[this.operators.length + specialsCount];
222
	}
223
224
	public void selectBidiScript(boolean arabic, boolean hebrew) {
225
		ignoreArabic = !arabic;
226
		ignoreHebrew = !hebrew;
227
	}
228
229
	public boolean handlesArabicScript() {
230
		return !ignoreArabic;
231
	}
232
233
	public boolean handlesHebrewScript() {
234
		return !ignoreHebrew;
235
	}
236
237
	long computeNextLocation(int curPos) {
238
		int operCount = operators.length;
239
		int len = leanText.length();
240
		int nextLocation = len;
241
		int idxLocation = 0;
242
		// Start with special sequences to give them precedence over simple
243
		// operators. This may apply to cases like slash+asterisk versus slash.
244
		for (int i = 0; i < specialsCount; i++) {
245
			int loc = locations[operCount + i];
246
			if (loc < curPos) {
247
				loc = indexOfSpecial(i, leanText, curPos);
248
				if (loc < 0)
249
					loc = len;
250
				locations[operCount + i] = loc;
251
			}
252
			if (loc < nextLocation) {
253
				nextLocation = loc;
254
				idxLocation = operCount + i;
255
			}
256
		}
257
		for (int i = 0; i < operCount; i++) {
258
			int loc = locations[i];
259
			if (loc < curPos) {
260
				loc = leanText.indexOf(operators[i], curPos);
261
				if (loc < 0)
262
					loc = len;
263
				locations[i] = loc;
264
			}
265
			if (loc < nextLocation) {
266
				nextLocation = loc;
267
				idxLocation = i;
268
			}
269
		}
270
		return nextLocation + (((long) idxLocation) << 32);
271
	}
272
273
	/**
274
	 *  This method is called repeatedly by <code>leanToFullText</code> to
275
	 *  locate all special cases specified in the constructor
276
	 *  (see {@link #ComplExpBasic(String operators, int specialsCount)}),
277
	 *  varying <code>whichSpecial</code> from zero to
278
	 *  <code>specialsCount - 1</code>. It is meant to be overridden in
279
	 *  subclasses of <code>ComplExpBasic</code>.
280
	 *  Those subclasses may use methods
281
	 *  {@link #getDirProp getDirProp},
282
	 *  {@link #setDirProp setDirProp} and
283
	 *  {@link #insertMark insertMark} within <code>indexOfSpecial</code>.
284
	 *
285
	 *  @param  whichSpecial number of the special case to locate. The meaning
286
	 *          of this number is internal to the class implementing
287
	 *          <code>indexOfSpecial</code>.
288
	 *
289
	 *  @param  srcText text of the complex expression before addition of any
290
	 *          directional formatting characters.
291
	 *
292
	 *  @param  fromIndex the index within <code>srcText</code> to start
293
	 *          the search from.
294
	 *
295
	 *  @return the position where the start of the special case was located.
296
	 *          The method must return the first occurrence of whatever
297
	 *          identifies the start of the special case after
298
	 *          <code>fromIndex</code>. The method does not have to check if
299
	 *          this occurrence appears within the scope of another special
300
	 *          case (e.g. a comment starting delimiter within the scope of
301
	 *          a literal or vice-versa).
302
	 *          If no occurrence is found, the method must return -1.
303
	 *  <p>
304
	 *          In <code>ComplExpBasic</code> this method always returns -1.
305
	 *
306
	 */
307
	protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) {
308
		// This method must be overridden by all subclasses with special cases.
309
		return -1;
310
	}
311
312
	/**
313
	 *  This method is called by <code>leanToFullText</code>
314
	 *  when a special case occurrence is located by
315
	 *  {@link #indexOfSpecial indexOfSpecial}.
316
	 *  It is meant to be overridden in subclasses of <code>ComplExpBasic</code>.
317
	 *  Those subclasses may use methods
318
	 *  {@link #getDirProp getDirProp},
319
	 *  {@link #setDirProp setDirProp} and
320
	 *  {@link #insertMark insertMark} within <code>processSpecial</code>.
321
	 *  <p>
322
	 *  If a special processing cannot be completed within a current call to
323
	 *  <code>processSpecial</code> (for instance, a comment has been started
324
	 *  in the current line but its end appears in a following line),
325
	 *  <code>processSpecial</code> should put in the {@link #state}
326
	 *  member of the class instance a number which characterizes this
327
	 *  situation. On a later call to
328
	 *  {@link IComplExpProcessor#leanToFullText(String text, int initState)}
329
	 *  specifying that state value, <code>processSpecial</code> will be
330
	 *  called with that value for parameter <code>whichSpecial</code> and
331
	 *  <code>-1</code> for parameter <code>operLocation</code> and should
332
	 *  perform whatever initializations are required depending on the state.
333
	 *
334
	 *  @param  whichSpecial number of the special case to handle.
335
	 *
336
	 *  @param  srcText text of the complex expression.
337
	 *
338
	 *  @param  operLocation the position returned by <code>indexOfSpecial</code>.
339
	 *          In calls to <code>leanToFullText</code> or
340
	 *          <code>fullToLeanText</code> specifying an <code>initState</code>
341
	 *          parameter, <code>processSpecial</code> is called when initializing
342
	 *          the processing with the value of <code>whichSpecial</code>
343
	 *          equal to <code>initState</code> and the value of
344
	 *          <code>operLocation</code> equal to <code>-1</code>.
345
	 *
346
	 *  @return the position after the scope of the special case ends.
347
	 *          For instance, the position after the end of a comment,
348
	 *          the position after the end of a literal.
349
	 *  <p>
350
	 *          In <code>ComplExpBasic</code> this method always returns
351
	 *          <code>operLocation + 1</code> (but it should never be called).
352
	 *
353
	 */
354
	protected int processSpecial(int whichSpecial, String srcText, int operLocation) {
355
		// This method must be overridden by all subclasses with any special case.
356
		return operLocation + 1;
357
	}
358
359
	private int getCurOrient() {
360
		if (curOrient >= 0)
361
			return curOrient;
362
363
		if ((orientation & ORIENT_CONTEXTUAL_LTR) == 0) {
364
			// absolute orientation
365
			curOrient = orientation;
366
			return curOrient;
367
		}
368
		// contextual orientation
369
		int len = leanText.length();
370
		byte dirProp;
371
		for (int i = 0; i < len; i++) {
372
			dirProp = dirProps[i];
373
			if (dirProp == 0) {
374
				dirProp = Character.getDirectionality(leanText.charAt(i));
375
				if (dirProp == B) // B char resolves to L or R depending on orientation
376
					continue;
377
				dirProps[i] = (byte) (dirProp + 2);
378
			} else {
379
				dirProp -= 2;
380
			}
381
			if (dirProp == L) {
382
				curOrient = ORIENT_LTR;
383
				return curOrient;
384
			}
385
			if (dirProp == R || dirProp == AL) {
386
				curOrient = ORIENT_RTL;
387
				return curOrient;
388
			}
389
		}
390
		curOrient = orientation & 1;
391
		return curOrient;
392
	}
393
394
	public int getCurDirection() {
395
		if (curDirection >= 0)
396
			return curDirection;
397
398
		curStrong = -1;
399
		int idx2 = mirrored ? 1 : 0;
400
		// same direction for Arabic and Hebrew?
401
		if (direction[0][idx2] == direction[1][idx2]) {
402
			curDirection = direction[0][idx2];
403
			return curDirection;
404
		}
405
		// check if Arabic or Hebrew letter comes first
406
		int len = leanText.length();
407
		byte dirProp;
408
		for (int i = 0; i < len; i++) {
409
			dirProp = getDirProp(i);
410
			if (dirProp == AL) {
411
				curDirection = direction[0][idx2];
412
				return curDirection;
413
			}
414
			if (dirProp == R) {
415
				curDirection = direction[1][idx2];
416
				return curDirection;
417
			}
418
		}
419
		// found no Arabic or Hebrew character
420
		curDirection = DIRECTION_LTR;
421
		return curDirection;
422
	}
423
424
	private void setMarkAndFixes() {
425
		int dir = getCurDirection();
426
		if (curStrong == STRONGS[dir])
427
			return;
428
		curStrong = STRONGS[dir];
429
		curMark = MARKS[dir];
430
		curEmbed = EMBEDS[dir];
431
	}
432
433
	/**
434
	 *  This method can be called from within {@link #indexOfSpecial indexOfSpecial}
435
	 *  or {@link #processSpecial processSpecial} in subclasses of
436
	 *  <code>ComplExpBasic</code> to retrieve the bidirectional class of
437
	 *  characters in <code>leanText</code>.
438
	 *
439
	 *  @param index position of the character in <code>leanText</code>.
440
	 *
441
	 *  @return the bidirectional class of the character. It is one of the
442
	 *          values which can be returned by
443
	 *          <code>java.lang.Character#getDirectionality</code>.
444
	 *          However, it is recommended to use <code>getDirProp</code>
445
	 *          rather than <code>java.lang.Character.getDirectionality</code>
446
	 *          since <code>getDirProp</code> manages a cache of character
447
	 *          properties and so can be more efficient than calling the
448
	 *          java.lang.Character method.
449
	 *
450
	 */
451
	protected byte getDirProp(int index) {
452
		byte dirProp = dirProps[index];
453
		if (dirProp == 0) {
454
			dirProp = Character.getDirectionality(leanText.charAt(index));
455
			if (dirProp == B)
456
				dirProp = getCurOrient() == ORIENT_RTL ? R : L;
457
			dirProps[index] = (byte) (dirProp + 2);
458
			return dirProp;
459
		}
460
		return (byte) (dirProp - 2);
461
	}
462
463
	/**
464
	 *  This method can be called from within {@link #indexOfSpecial indexOfSpecial}
465
	 *  or {@link #processSpecial processSpecial} in subclasses of
466
	 *  <code>ComplExpBasic</code> to set or override the bidirectional
467
	 *  class of characters in <code>leanText</code>.
468
	 *
469
	 *  @param index position of the character in <code>leanText</code>.
470
	 *
471
	 *  @param dirProp bidirectional class of the character. It is one of the
472
	 *         values which can be returned by
473
	 *         <code>java.lang.Character.getDirectionality</code>.
474
	 *
475
	 */
476
	protected void setDirProp(int index, byte dirProp) {
477
		dirProps[index] = (byte) (dirProp + 2);
478
	}
479
480
	/**
481
	 *  This method can be called from within
482
	 *  {@link #processSpecial processSpecial} in subclasses of
483
	 *  <code>ComplExpBasic</code> to add a directional mark before an
484
	 *  operator if needed for correct display, depending on the
485
	 *  base direction of the expression and on the class of the
486
	 *  characters in <code>leanText</code> preceding and following
487
	 *  the operator itself.
488
	 *
489
	 *  @param  operLocation offset of the operator in <code>leanText</code>.
490
	 *
491
	 */
492
	protected void processOperator(int operLocation) {
493
		int len = leanText.length();
494
		boolean doneAN = false;
495
496
		if (getCurDirection() == DIRECTION_RTL) {
497
			// the expression base direction is RTL
498
			for (int i = operLocation - 1; i >= 0; i--) {
499
				byte dirProp = getDirProp(i);
500
				if (dirProp == R || dirProp == AL)
501
					return;
502
503
				if (dirProp == L) {
504
					for (int j = operLocation; j < len; j++) {
505
						dirProp = getDirProp(j);
506
						if (dirProp == R || dirProp == AL)
507
							return;
508
						if (dirProp == L || dirProp == EN) {
509
							insertMark(operLocation);
510
							return;
511
						}
512
					}
513
					return;
514
				}
515
			}
516
			return;
517
		}
518
519
		// the expression base direction is LTR
520
		if (ignoreArabic) {
521
			if (ignoreHebrew) /* process neither Arabic nor Hebrew */
522
				return;
523
			/* process Hebrew, not Arabic */
524
			for (int i = operLocation - 1; i >= 0; i--) {
525
				byte dirProp = getDirProp(i);
526
				if (dirProp == L)
527
					return;
528
				if (dirProp == R) {
529
					for (int j = operLocation; j < len; j++) {
530
						dirProp = getDirProp(j);
531
						if (dirProp == L)
532
							return;
533
						if (dirProp == R || dirProp == EN) {
534
							insertMark(operLocation);
535
							return;
536
						}
537
					}
538
					return;
539
				}
540
			}
541
		} else {
542
			if (ignoreHebrew) { /* process Arabic, not Hebrew */
543
				for (int i = operLocation - 1; i >= 0; i--) {
544
					byte dirProp = getDirProp(i);
545
					if (dirProp == L)
546
						return;
547
					if (dirProp == AL) {
548
						for (int j = operLocation; j < len; j++) {
549
							dirProp = getDirProp(j);
550
							if (dirProp == L)
551
								return;
552
							if (dirProp == EN || dirProp == AL || dirProp == AN) {
553
								insertMark(operLocation);
554
								return;
555
							}
556
						}
557
						return;
558
					}
559
					if (dirProp == AN && !doneAN) {
560
						for (int j = operLocation; j < len; j++) {
561
							dirProp = getDirProp(j);
562
							if (dirProp == L)
563
								return;
564
							if (dirProp == AL || dirProp == AN) {
565
								insertMark(operLocation);
566
								return;
567
							}
568
						}
569
						doneAN = true;
570
					}
571
				}
572
			} else { /* process Arabic and Hebrew */
573
				for (int i = operLocation - 1; i >= 0; i--) {
574
					byte dirProp = getDirProp(i);
575
					if (dirProp == L)
576
						return;
577
					if (dirProp == R || dirProp == AL) {
578
						for (int j = operLocation; j < len; j++) {
579
							dirProp = getDirProp(j);
580
							if (dirProp == L)
581
								return;
582
							if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) {
583
								insertMark(operLocation);
584
								return;
585
							}
586
						}
587
						return;
588
					}
589
					if (dirProp == AN && !doneAN) {
590
						for (int j = operLocation; j < len; j++) {
591
							dirProp = getDirProp(j);
592
							if (dirProp == L)
593
								return;
594
							if (dirProp == AL || dirProp == AN || dirProp == R) {
595
								insertMark(operLocation);
596
								return;
597
							}
598
						}
599
						doneAN = true;
600
					}
601
				}
602
			}
603
		}
604
	}
605
606
	public int getFinalState() {
607
		return state;
608
	}
609
610
	public String leanToFullText(String text) {
611
		return leanToFullText(text, STATE_NOTHING_GOING);
612
	}
613
614
	public String leanToFullText(String text, int initState) {
615
		if (text.length() == 0) {
616
			prefixLength = 0;
617
			count = 0;
618
			return text;
619
		}
620
		leanToFullTextNofix(text, initState);
621
		return addMarks(true);
622
	}
623
624
	void leanToFullTextNofix(String text, int initState) {
625
		int operCount = operators.length;
626
		int curPos = 0;
627
		int len = text.length();
628
		int nextLocation, idxLocation;
629
		leanText = text;
630
		offsets = new int[20];
631
		count = 0;
632
		dirProps = new byte[len];
633
		curOrient = -1;
634
		curDirection = -1;
635
		// initialize locations
636
		int k = locations.length;
637
		for (int i = 0; i < k; i++) {
638
			locations[i] = -1;
639
		}
640
		state = STATE_NOTHING_GOING;
641
		if (initState != STATE_NOTHING_GOING)
642
			curPos = processSpecial(initState, leanText, -1);
643
644
		while (true) {
645
			long res = computeNextLocation(curPos);
646
			nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
647
			if (nextLocation >= len)
648
				break;
649
			idxLocation = (int) (res >> 32); /* high word */
650
			if (idxLocation < operCount) {
651
				processOperator(nextLocation);
652
				curPos = nextLocation + 1;
653
			} else {
654
				curPos = processSpecial(idxLocation - operCount, leanText, nextLocation);
655
			}
656
		}
657
	}
658
659
	public int[] leanBidiCharOffsets(String text) {
660
		return leanBidiCharOffsets(text, STATE_NOTHING_GOING);
661
	}
662
663
	public int[] leanBidiCharOffsets(String text, int initState) {
664
		leanToFullTextNofix(text, initState);
665
		return leanBidiCharOffsets();
666
	}
667
668
	public int[] leanBidiCharOffsets() {
669
		int[] result = new int[count];
670
		System.arraycopy(offsets, 0, result, 0, count);
671
		return result;
672
	}
673
674
	public int[] fullBidiCharOffsets() {
675
		int lim = count;
676
		if (prefixLength > 0) {
677
			if (prefixLength == 1)
678
				lim++;
679
			else
680
				lim += FIXES_LENGTH;
681
		}
682
		int[] fullOffsets = new int[lim];
683
		for (int i = 0; i < prefixLength; i++) {
684
			fullOffsets[i] = i;
685
		}
686
		int added = prefixLength;
687
		for (int i = 0; i < count; i++) {
688
			fullOffsets[prefixLength + i] = offsets[i] + added;
689
			added++;
690
		}
691
		if (prefixLength > 1) {
692
			int len = leanText.length();
693
			fullOffsets[lim - 2] = len + lim - 2;
694
			fullOffsets[lim - 1] = len + lim - 1;
695
		}
696
		return fullOffsets;
697
	}
698
699
	public String fullToLeanText(String text) {
700
		return fullToLeanText(text, STATE_NOTHING_GOING);
701
	}
702
703
	public String fullToLeanText(String text, int initState) {
704
		int i; // TBD this variable is used for multiple unrelated tasks
705
		setMarkAndFixes();
706
		// remove any prefix and leading mark
707
		int lenText = text.length();
708
		for (i = 0; i < lenText; i++) {
709
			char c = text.charAt(i);
710
			if (c != curEmbed && c != curMark)
711
				break;
712
		}
713
		if (i > 0) {
714
			text = text.substring(i);
715
			lenText = text.length();
716
		}
717
		// remove any suffix and trailing mark
718
		for (i = lenText - 1; i >= 0; i--) {
719
			char c = text.charAt(i);
720
			if (c != PDF && c != curMark)
721
				break;
722
		}
723
		if (i < 0) {
724
			leanText = EMPTY_STRING;
725
			prefixLength = 0;
726
			count = 0;
727
			return leanText;
728
		}
729
		if (i < (lenText - 1)) {
730
			text = text.substring(0, i + 1);
731
			lenText = text.length();
732
		}
733
		char[] chars = text.toCharArray();
734
		// remove marks from chars
735
		int cnt = 0;
736
		for (i = 0; i < lenText; i++) {
737
			char c = chars[i];
738
			if (c == curMark)
739
				cnt++;
740
			else if (cnt > 0)
741
				chars[i - cnt] = c;
742
		}
743
		String lean = new String(chars, 0, lenText - cnt);
744
		leanToFullTextNofix(lean, initState);
745
		String full = addMarks(false); /* only marks, no prefix/suffix */
746
		if (full.equals(text))
747
			return lean;
748
749
		// There are some marks in full which are not in text and/or vice versa.
750
		// We need to add to lean any mark appearing in text and not in full.
751
		// The completed lean can never be longer than text itself.
752
		char[] newChars = new char[lenText];
753
		char cFull, cText;
754
		int idxFull, idxText, idxLean, markPos, newCharsPos;
755
		int lenFull = full.length();
756
		idxFull = idxText = idxLean = newCharsPos = 0;
757
		while (idxText < lenText && idxFull < lenFull) {
758
			cFull = full.charAt(idxFull);
759
			cText = text.charAt(idxText);
760
			if (cFull == cText) { /* chars are equal, proceed */
761
				idxText++;
762
				idxFull++;
763
				continue;
764
			}
765
			if (cFull == curMark) { /* extra Mark in full text */
766
				idxFull++;
767
				continue;
768
			}
769
			if (cText == curMark) { /* extra Mark in source full text */
770
				idxText++;
771
				// idxText-2 always >= 0 since leading Marks were removed from text
772
				if (text.charAt(idxText - 2) == curMark)
773
					continue; // ignore successive Marks in text after the first one
774
				markPos = fullToLeanPos(idxFull);
775
				// copy from chars (== lean) to newChars until here
776
				for (i = idxLean; i < markPos; i++) {
777
					newChars[newCharsPos++] = chars[i];
778
				}
779
				idxLean = markPos;
780
				newChars[newCharsPos++] = curMark;
781
				continue;
782
			}
783
			// we should never get here (extra char which is not a Mark)
784
			throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$
785
		}
786
		if (idxText < lenText) /* full ended before text - this should never happen */
787
			throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$
788
789
		// copy the last part of chars to newChars
790
		for (i = idxLean; i < lean.length(); i++) {
791
			newChars[newCharsPos++] = chars[i];
792
		}
793
		lean = new String(newChars, 0, newCharsPos);
794
		leanText = lean;
795
		return lean;
796
	}
797
798
	public int leanToFullPos(int pos) {
799
		int added = prefixLength;
800
		for (int i = 0; i < count; i++) {
801
			if (offsets[i] <= pos)
802
				added++;
803
			else
804
				return pos + added;
805
		}
806
		return pos + added;
807
	}
808
809
	public int fullToLeanPos(int pos) {
810
		int len = leanText.length();
811
		int added = 0;
812
		pos -= prefixLength;
813
		for (int i = 0; i < count; i++) {
814
			if ((offsets[i] + added) < pos)
815
				added++;
816
			else
817
				break;
818
		}
819
		pos -= added;
820
		if (pos < 0)
821
			pos = 0;
822
		else if (pos > len)
823
			pos = len;
824
		return pos;
825
	}
826
827
	/**
828
	 *  This method can be called from within {@link #indexOfSpecial} or
829
	 *  {@link #processSpecial} in subclasses of <code>ComplExpBasic</code>
830
	 *  to specify that a mark character must be added before the character
831
	 *  at the specified position of the <i>lean</i> text when generating the
832
	 *  <i>full</i> text. The mark character will be LRM for complex expressions
833
	 *  with a LTR base direction, and RLM for complex expressions with RTL
834
	 *  base direction. The mark character is not added physically by this
835
	 *  method, but its position is noted and will be used when generating
836
	 *  the <i>full</i> text.
837
	 *
838
	 *  @param  offset position of the character in <code>leanText</code>.
839
	 *          It must be a non-negative number smaller than the length
840
	 *          of the <i>lean</i> text.
841
	 *          For the benefit of efficiency, it is better to insert
842
	 *          multiple marks in ascending order of the offsets.
843
	 *
844
	 */
845
	protected void insertMark(int offset) {
846
		int index = count - 1; // index of greatest member <= offset
847
		// look up after which member the new offset should be inserted
848
		while (index >= 0) {
849
			int wrkOffset = offsets[index];
850
			if (offset > wrkOffset)
851
				break;
852
			if (offset == wrkOffset)
853
				return; // avoid duplicates
854
			index--;
855
		}
856
		index++; // index now points at where to insert
857
		// check if we have an available slot for new member
858
		if (count >= (offsets.length - 1)) {
859
			int[] newOffsets = new int[offsets.length * 2];
860
			System.arraycopy(offsets, 0, newOffsets, 0, count);
861
			offsets = newOffsets;
862
		}
863
864
		int length = count - index; // number of members to move up
865
		if (length > 0) // shift right all members greater than offset
866
			System.arraycopy(offsets, index, offsets, index + 1, length);
867
868
		offsets[index] = offset;
869
		count++;
870
		// if the offset is 0, adding a mark does not change anything
871
		if (offset < 1)
872
			return;
873
874
		byte dirProp = getDirProp(offset);
875
		// if the current char is a strong one or a digit, we change the
876
		//   dirProp of the previous char to account for the inserted mark
877
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
878
			index = offset - 1;
879
		else
880
			// if the current char is a neutral, we change its own dirProp
881
			index = offset;
882
		setMarkAndFixes();
883
		setDirProp(index, curStrong);
884
	}
885
886
	private String addMarks(boolean addFixes) {
887
		// add prefix/suffix only if addFixes is true
888
		if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == ORIENT_IGNORE))) {
889
			prefixLength = 0;
890
			return leanText;
891
		}
892
		int len = leanText.length();
893
		int newLen = len + count;
894
		if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == ORIENT_UNKNOWN))) {
895
			if ((orientation & ORIENT_CONTEXTUAL_LTR) == 0) {
896
				prefixLength = PREFIX_LENGTH;
897
				newLen += FIXES_LENGTH;
898
			} else { /* contextual orientation */
899
				prefixLength = 1;
900
				newLen++; /* +1 for a mark char */
901
			}
902
		} else {
903
			prefixLength = 0;
904
		}
905
		char[] fullChars = new char[newLen];
906
		// add a dummy offset as fence
907
		offsets[count] = len;
908
		int added = prefixLength;
909
		// add marks at offsets
910
		setMarkAndFixes();
911
		for (int i = 0, j = 0; i < len; i++) {
912
			char c = leanText.charAt(i);
913
			if (i == offsets[j]) {
914
				fullChars[i + added] = curMark;
915
				added++;
916
				j++;
917
			}
918
			fullChars[i + added] = c;
919
		}
920
		if (prefixLength > 0) { /* add prefix/suffix ? */
921
			if (prefixLength == 1) { /* contextual orientation */
922
				fullChars[0] = curMark;
923
			} else {
924
				// When the orientation is RTL, we need to add EMBED at the
925
				// start of the text and PDF at its end.
926
				// However, because of a bug in Windows' handling of LRE/PDF,
927
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
928
				fullChars[0] = curEmbed;
929
				fullChars[1] = curMark;
930
				fullChars[newLen - 1] = PDF;
931
				fullChars[newLen - 2] = curMark;
932
			}
933
		}
934
		return new String(fullChars);
935
	}
936
937
	public void assumeMirrored(boolean shouldBeMirrored) {
938
		mirrored = shouldBeMirrored;
939
		curDirection = -1;
940
	}
941
942
	public boolean isMirrored() {
943
		return mirrored;
944
	}
945
946
	public void assumeOrientation(int componentOrientation) {
947
		if (componentOrientation < ORIENT_LTR || componentOrientation > ORIENT_IGNORE)
948
			orientation = ORIENT_UNKNOWN; // TBD should throw new IllegalArgumentException()?
949
		else
950
			orientation = componentOrientation;
951
	}
952
953
	public int recallOrientation() {
954
		return orientation;
955
	}
956
957
	public void setArabicDirection(int not_mirrored, int mirrored) {
958
		direction[0][0] = not_mirrored & 1;
959
		direction[0][1] = mirrored & 1;
960
		curDirection = -1;
961
	}
962
963
	public void setArabicDirection(int direction) {
964
		setArabicDirection(direction, direction);
965
	}
966
967
	public void setHebrewDirection(int not_mirrored, int mirrored) {
968
		direction[1][0] = not_mirrored & 1;
969
		direction[1][1] = mirrored & 1;
970
		curDirection = -1;
971
	}
972
973
	public void setHebrewDirection(int direction) {
974
		setHebrewDirection(direction, direction);
975
	}
976
977
	public void setDirection(int not_mirrored, int mirrored) {
978
		setArabicDirection(not_mirrored, mirrored);
979
		setHebrewDirection(not_mirrored, mirrored);
980
	}
981
982
	public void setDirection(int direction) {
983
		setDirection(direction, direction);
984
	}
985
986
	public int[][] getDirection() {
987
		return direction;
988
	}
989
}
(-)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/ComplExpDoNothing.java (-265 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
 *  This class is a minimal processor which implements the
17
 *  <code>IComplExpProcessor</code> interface but does no real processing.
18
 *  Since it is optimized for minimal overhead, it can
19
 *  be used as a low-cost default processor when no complex expression is
20
 *  involved and no processing is needed, but a general framework of
21
 *  handling complex expressions must be preserved.
22
 *
23
 *  @author Matitiahu Allouche
24
 */
25
// TBD is this needed?
26
public class ComplExpDoNothing implements IComplExpProcessor {
27
28
	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
29
	private static final int[] EMPTY_INT_ARRAY = new int[0];
30
	private static final int[][] ALL_LTR = new int[][] { {DIRECTION_LTR, DIRECTION_LTR}, {DIRECTION_LTR, DIRECTION_LTR}};
31
32
	/**
33
	 *  Allocate a <code>ComplExpDoNothing</code> processor instance.
34
	 *  Such a processor does not modify text submitted to it, and can be
35
	 *  used as a place holder when the text to process is not a known
36
	 *  complex expression.
37
	 */
38
	public ComplExpDoNothing() {
39
		return;
40
	}
41
42
	/**
43
	 *  For class <code>ComplExpDoNothing</code>
44
	 *  this method does nothing.
45
	 */
46
	public void setOperators(String operators) {
47
		// empty
48
	}
49
50
	/**
51
	 *  For class <code>ComplExpDoNothing</code>
52
	 *  this method returns a zero-length string.
53
	 */
54
	public String getOperators() {
55
		return EMPTY_STRING;
56
	}
57
58
	/**
59
	 *  For class <code>ComplExpDoNothing</code>
60
	 *  this method does nothing.
61
	 */
62
	public void selectBidiScript(boolean arabic, boolean hebrew) {
63
		// empty
64
	}
65
66
	/**
67
	 *  For class <code>ComplExpDoNothing</code>
68
	 *  this method always returns <code>false</code>.
69
	 */
70
	public boolean handlesArabicScript() {
71
		return false;
72
	}
73
74
	/**
75
	 *  For class <code>ComplExpDoNothing</code>
76
	 *  this method always returns <code>false</code>.
77
	 */
78
	public boolean handlesHebrewScript() {
79
		return false;
80
	}
81
82
	/**
83
	 *  For class <code>ComplExpDoNothing</code> this method
84
	 *  returns a string identical to the <code>text</code> parameter.
85
	 */
86
	public String leanToFullText(String text) {
87
		return text;
88
	}
89
90
	/**
91
	 *  For class <code>ComplExpDoNothing</code> this method
92
	 *  returns a string identical to the <code>text</code> parameter.
93
	 */
94
	public String leanToFullText(String text, int initState) {
95
		return text;
96
	}
97
98
	/**
99
	 *  For class <code>ComplExpDoNothing</code> this method
100
	 *  returns a zero length array.
101
	 */
102
	public int[] leanBidiCharOffsets(String text) {
103
		return EMPTY_INT_ARRAY;
104
	}
105
106
	/**
107
	 *  For class <code>ComplExpDoNothing</code> this method
108
	 *  returns a zero length array.
109
	 */
110
	public int[] leanBidiCharOffsets(String text, int initState) {
111
		return EMPTY_INT_ARRAY;
112
	}
113
114
	/**
115
	 *  For class <code>ComplExpDoNothing</code> this method
116
	 *  returns a zero length array.
117
	 */
118
	public int[] leanBidiCharOffsets() {
119
		return EMPTY_INT_ARRAY;
120
	}
121
122
	/**
123
	 *  For class <code>ComplExpDoNothing</code> this method
124
	 *  returns a zero length array.
125
	 */
126
	public int[] fullBidiCharOffsets() {
127
		return EMPTY_INT_ARRAY;
128
	}
129
130
	/**
131
	 *  For class <code>ComplExpDoNothing</code> this method
132
	 *  returns a string identical to the <code>text</code> parameter.
133
	 */
134
	public String fullToLeanText(String text) {
135
		return text;
136
	}
137
138
	/**
139
	 *  For class <code>ComplExpDoNothing</code> this method
140
	 *  returns a string identical to the <code>text</code> parameter.
141
	 */
142
	public String fullToLeanText(String text, int initState) {
143
		return text;
144
	}
145
146
	/**
147
	 *  For class <code>ComplExpDoNothing</code> this method
148
	 *  returns value {@link #STATE_NOTHING_GOING}.
149
	 */
150
	public int getFinalState() {
151
		return STATE_NOTHING_GOING;
152
	}
153
154
	/**
155
	 *  For class <code>ComplExpDoNothing</code> this method
156
	 *  returns an index identical to the <code>pos</code> parameter.
157
	 */
158
	public int leanToFullPos(int pos) {
159
		return pos;
160
	}
161
162
	/**
163
	 *  For class <code>ComplExpDoNothing</code> this method
164
	 *  returns an index identical to the <code>pos</code> parameter.
165
	 */
166
	public int fullToLeanPos(int pos) {
167
		return pos;
168
	}
169
170
	/**
171
	 *  For class <code>ComplExpDoNothing</code> this method
172
	 *  does nothing.
173
	 */
174
	public void assumeMirrored(boolean mirrored) {
175
		// empty
176
	}
177
178
	/**
179
	 *  For class <code>ComplExpDoNothing</code> this method
180
	 *  always returns <code>false</code>.
181
	 */
182
	public boolean isMirrored() {
183
		return false;
184
	}
185
186
	/**
187
	 *  For class <code>ComplExpDoNothing</code> this method
188
	 *  does nothing.
189
	 */
190
	public void assumeOrientation(int orientation) {
191
		// empty
192
	}
193
194
	/**
195
	 *  For class <code>ComplExpDoNothing</code> this method
196
	 *  always returns <code>ORIENT_LTR</code>.
197
	 */
198
	public int recallOrientation() {
199
		return ORIENT_LTR;
200
	}
201
202
	/**
203
	 *  For class <code>ComplExpDoNothing</code> this method
204
	 *  does nothing.
205
	 */
206
	public void setArabicDirection(int not_mirrored, int mirrored) {
207
		// empty
208
	}
209
210
	/**
211
	 *  For class <code>ComplExpDoNothing</code> this method
212
	 *  does nothing.
213
	 */
214
	public void setArabicDirection(int direction) {
215
		// empty
216
	}
217
218
	/**
219
	 *  For class <code>ComplExpDoNothing</code> this method
220
	 *  does nothing.
221
	 */
222
	public void setHebrewDirection(int not_mirrored, int mirrored) {
223
		// empty
224
	}
225
226
	/**
227
	 *  For class <code>ComplExpDoNothing</code> this method
228
	 *  does nothing.
229
	 */
230
	public void setHebrewDirection(int direction) {
231
		// empty
232
	}
233
234
	/**
235
	 *  For class <code>ComplExpDoNothing</code> this method
236
	 *  does nothing.
237
	 */
238
	public void setDirection(int not_mirrored, int mirrored) {
239
		// empty
240
	}
241
242
	/**
243
	 *  For class <code>ComplExpDoNothing</code> this method
244
	 *  does nothing.
245
	 */
246
	public void setDirection(int direction) {
247
		// empty
248
	}
249
250
	/**
251
	 *  For class <code>ComplExpDoNothing</code> this method
252
	 *  returns all directions as <code>DIRECTION_LTR</code>.
253
	 */
254
	public int[][] getDirection() {
255
		return ALL_LTR;
256
	}
257
258
	/**
259
	 *  For class <code>ComplExpDoNothing</code> this method
260
	 *  returns <code>DIRECTION_LTR</code>.
261
	 */
262
	public int getCurDirection() {
263
		return DIRECTION_LTR;
264
	}
265
}
(-)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/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/consumable/BidiComplexComma.java (+35 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 * Processor adapted to processing comma-delimited lists, such as:
18
 * <pre>
19
 *  part1,part2,part3
20
 * </pre>
21
 */
22
public class BidiComplexComma extends BidiComplexProcessor {
23
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(",", 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 (comma), no special cases,
29
	 *          LTR direction for Arabic and Hebrew, and support for both.
30
	 */
31
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
32
		return FEATURES;
33
	}
34
35
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java (+45 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexDelimsEsc;
15
16
/**
17
 * Processor adapted to processing e-mail addresses.
18
 */
19
public class BidiComplexEmail extends BidiComplexDelimsEsc {
20
	static final int LTR = BidiComplexFeatures.DIR_LTR;
21
	static final int RTL = BidiComplexFeatures.DIR_RTL;
22
	static final BidiComplexFeatures MIRRORED = new BidiComplexFeatures("<>.:,;@", 2, RTL, LTR, false, false); //$NON-NLS-1$
23
	static final BidiComplexFeatures NOT_MIRRORED = new BidiComplexFeatures("<>.:,;@", 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 BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment 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/consumable/BidiComplexFile.java (+32 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 * Processor adapted to processing directory and file paths.
18
 */
19
public class BidiComplexFile extends BidiComplexProcessor {
20
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":/\\.", 0, -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 ":/\.", no special cases,
26
	 *          LTR direction for Arabic and Hebrew, and support for both.
27
	 */
28
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
29
		return FEATURES;
30
	}
31
32
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java (+128 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexJava</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 BidiComplexHelper#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 BidiComplexHelper#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 BidiComplexHelper
31
 *
32
 *  @author Matitiahu Allouche
33
 */
34
public class BidiComplexJava extends BidiComplexProcessor {
35
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
36
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("[](){}.+-<>=~!&*/%^|?:,;\t", 4, -1, -1, false, false); //$NON-NLS-1$
37
	static final String lineSep = BidiComplexEnvironment.getLineSep();
38
39
	/**
40
	 *  This method retrieves the features specific to this processor.
41
	 *
42
	 *  @return features with operators "[](){}.+-<>=~!&/*%^|?:,;\t",
43
	 *          4 special cases, LTR direction for Arabic and Hebrew,
44
	 *          and support for both.
45
	 */
46
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
47
		return FEATURES;
48
	}
49
50
	/**
51
	     *  This method looks for occurrences of 4 special strings:
52
	     *  <ol>
53
	     *    <li>spaces</li>
54
	     *    <li>literals starting with quotation mark</li>
55
	     *    <li>comments starting with slash-asterisk</li>
56
	     *    <li>comments starting with slash-slash</li>
57
	     *  </ol>
58
	     */
59
	public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) {
60
		switch (caseNumber) {
61
			case 0 : /* space */
62
				return srcText.indexOf(' ', fromIndex);
63
			case 1 : /* literal */
64
				return srcText.indexOf('"', fromIndex);
65
			case 2 : /* slash-aster comment */
66
				return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
67
			case 3 : /* slash-slash comment */
68
				return srcText.indexOf("//", fromIndex); //$NON-NLS-1$
69
		}
70
		// we should never get here
71
		return -1;
72
	}
73
74
	/**
75
	 *  This method processes the 4 special cases as follows.
76
	     *  <ol>
77
	     *    <li>skip the run of spaces</li>
78
	     *    <li>look for a matching quotation mark and skip until after it</li>
79
	     *    <li>skip until after the closing asterisk-slash</li>
80
	     *    <li>skip until after a line separator</li>
81
	     *  </ol>
82
	 */
83
	public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
84
		int location, counter, i;
85
86
		helper.processOperator(operLocation);
87
		switch (caseNumber) {
88
			case 0 : /* space */
89
				operLocation++;
90
				while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
91
					helper.setDirProp(operLocation, WS);
92
					operLocation++;
93
				}
94
				return operLocation;
95
			case 1 : /* literal */
96
				location = operLocation + 1;
97
				while (true) {
98
					location = srcText.indexOf('"', location);
99
					if (location < 0)
100
						return srcText.length();
101
					for (counter = 0, i = location - 1; srcText.charAt(i) == '\\'; i--) {
102
						counter++;
103
					}
104
					location++;
105
					if ((counter & 1) == 0)
106
						return location;
107
				}
108
			case 2 : /* slash-aster comment */
109
				if (operLocation < 0)
110
					location = 0; // initial state from previous line
111
				else
112
					location = operLocation + 2; // skip the opening slash-aster
113
				location = srcText.indexOf("*/", location); //$NON-NLS-1$
114
				if (location < 0) {
115
					helper.setFinalState(2);
116
					return srcText.length();
117
				}
118
				return location + 2;
119
			case 3 : /* slash-slash comment */
120
				location = srcText.indexOf(lineSep, operLocation + 2);
121
				if (location < 0)
122
					return srcText.length();
123
				return location + lineSep.length();
124
		}
125
		// we should never get here
126
		return srcText.length();
127
	}
128
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 * Processor adapted to processing arithmetic expressions with right-to-left
18
 * base direction.
19
 */
20
public class BidiComplexMath extends BidiComplexProcessor {
21
	static final int RTL = BidiComplexFeatures.DIR_RTL;
22
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("+-/*()=", 0, RTL, RTL, false, false); //$NON-NLS-1$
23
24
	/**
25
	 *  This method retrieves the features specific to this processor.
26
	 *
27
	 *  @return features with operators "+-/*()=", no special cases,
28
	 *          RTL direction for Arabic and Hebrew, and support for both.
29
	 */
30
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
31
		return FEATURES;
32
	}
33
34
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java (+36 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexSingle;
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 BidiComplexProperty extends BidiComplexSingle {
24
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("=", 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 BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
33
		return FEATURES;
34
	}
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java (+216 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexRegex</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 BidiComplexHelper#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 BidiComplexHelper#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 BidiComplexHelper
30
 *
31
 *  @author Matitiahu Allouche
32
 */
33
public class BidiComplexRegex extends BidiComplexProcessor {
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
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(null, maxSpecial, -1, -1, false, false);
58
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
59
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
60
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
61
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
62
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
63
64
	/**
65
	 *  This method retrieves the features specific to this processor.
66
	 *
67
	 *  @return features with no operators , special cases for each kind of
68
	 *          regular expression syntactic string,
69
	 *          LTR direction for Arabic and Hebrew, and support for both.
70
	 */
71
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
72
		return FEATURES;
73
	}
74
75
	/**
76
	 *  This method locates occurrences of the syntactic strings and of
77
	 *  R, AL, EN, AN characters.
78
	 */
79
	public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) {
80
		// In this method, L, R, AL, AN and EN represent bidi categories
81
		// as defined in the Unicode Bidirectional Algorithm
82
		// ( http://www.unicode.org/reports/tr9/ ).
83
		// L  represents the category Left to Right character.
84
		// R  represents the category Right to Left character.
85
		// AL represents the category Arabic Letter.
86
		// AN represents the category Arabic Number.
87
		// EN  represents the category European Number.
88
		byte dirProp;
89
90
		if (caseNumber < numberOfStrings) {
91
			/*  0 *//* comment (?#...) */
92
			/*  1 *//* named group (?<name> */
93
			/*  2 *//* named group (?'name' */
94
			/*  3 *//* conditional named back reference (?(name) */
95
			/*  4 *//* conditional named back reference (?(<name>) */
96
			/*  5 *//* conditional named back reference (?('name') */
97
			/*  6 *//* named parentheses reference (?&name) */
98
			/*  7 *//* named group (?P<name> */
99
			/*  8 *//* named back reference \k<name> */
100
			/*  9 *//* named back reference \k'name' */
101
			/* 10 *//* named back reference \k{name} */
102
			/* 11 *//* named back reference (?P=name) */
103
			/* 12 *//* named back reference \g{name} */
104
			/* 13 *//* subroutine call \g<name> */
105
			/* 14 *//* subroutine call \g'name' */
106
			/* 15 *//* named back reference recursion (?(R&name) */
107
			/* 16 *//* quoted sequence \Q...\E */
108
			return srcText.indexOf(startStrings[caseNumber], fromIndex);
109
		}
110
		// there never is a need for a mark before the first char
111
		if (fromIndex <= 0)
112
			fromIndex = 1;
113
		// look for R, AL, AN, EN which are potentially needing a mark
114
		for (; fromIndex < srcText.length(); fromIndex++) {
115
			dirProp = helper.getDirProp(fromIndex);
116
			// R and AL will always be examined using processOperator()
117
			if (dirProp == R || dirProp == AL)
118
				return fromIndex;
119
120
			if (dirProp == EN || dirProp == AN) {
121
				// no need for a mark after the first digit in a number
122
				if (helper.getDirProp(fromIndex - 1) == dirProp)
123
					continue;
124
125
				for (int i = fromIndex - 1; i >= 0; i--) {
126
					dirProp = helper.getDirProp(i);
127
					// after a L char, no need for a mark
128
					if (dirProp == L)
129
						continue;
130
131
					// digit after R or AL or AN need a mark, except for EN
132
					//   following AN, but this is a contrived case, so we
133
					//   don't check for it (and calling processOperator()
134
					//   for it will do no harm)
135
					if (dirProp == R || dirProp == AL || dirProp == AN)
136
						return fromIndex;
137
				}
138
				continue;
139
			}
140
		}
141
		return -1;
142
	}
143
144
	/**
145
	 *  This method process the special cases.
146
	 */
147
	public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
148
		int location;
149
150
		switch (caseNumber) {
151
			case 0 : /* comment (?#...) */
152
				if (operLocation < 0) {
153
					// initial state from previous line
154
					location = 0;
155
				} else {
156
					helper.processOperator(operLocation);
157
					// skip the opening "(?#"
158
					location = operLocation + 3;
159
				}
160
				location = srcText.indexOf(')', location);
161
				if (location < 0) {
162
					helper.setFinalState(caseNumber);
163
					return srcText.length();
164
				}
165
				return location + 1;
166
			case 1 : /* named group (?<name> */
167
			case 2 : /* named group (?'name' */
168
			case 3 : /* conditional named back reference (?(name) */
169
			case 4 : /* conditional named back reference (?(<name>) */
170
			case 5 : /* conditional named back reference (?('name') */
171
			case 6 : /* named parentheses reference (?&name) */
172
				helper.processOperator(operLocation);
173
				// no need for calling processOperator() for the following cases
174
				//   since the starting string contains a L char
175
			case 7 : /* named group (?P<name> */
176
			case 8 : /* named back reference \k<name> */
177
			case 9 : /* named back reference \k'name' */
178
			case 10 : /* named back reference \k{name} */
179
			case 11 : /* named back reference (?P=name) */
180
			case 12 : /* named back reference \g{name} */
181
			case 13 : /* subroutine call \g<name> */
182
			case 14 : /* subroutine call \g'name' */
183
			case 15 : /* named back reference recursion (?(R&name) */
184
				// skip the opening string
185
				location = operLocation + startStrings[caseNumber].length();
186
				// look for ending character
187
				location = srcText.indexOf(endChars[caseNumber], location);
188
				if (location < 0)
189
					return srcText.length();
190
				return location + 1;
191
			case 16 : /* quoted sequence \Q...\E */
192
				if (operLocation < 0) {
193
					// initial state from previous line
194
					location = 0;
195
				} else {
196
					helper.processOperator(operLocation);
197
					// skip the opening "\Q"
198
					location = operLocation + 2;
199
				}
200
				location = srcText.indexOf("\\E", location); //$NON-NLS-1$
201
				if (location < 0) {
202
					helper.setFinalState(caseNumber);
203
					return srcText.length();
204
				}
205
				// set the dirProp for the "E" to L (Left to Right character)
206
				helper.setDirProp(location + 1, L);
207
				return location + 2;
208
			case 17 : /* R, AL, AN, EN */
209
				helper.processOperator(operLocation);
210
				return operLocation + 1;
211
212
		}
213
		// we should never get here
214
		return srcText.length();
215
	}
216
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java (+149 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexSql</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 BidiComplexHelper#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 BidiComplexHelper#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 BidiComplexHelper
31
 *
32
 *  @author Matitiahu Allouche
33
 */
34
public class BidiComplexSql extends BidiComplexProcessor {
35
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
36
	static final String operators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$
37
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(operators, 5, -1, -1, false, false);
38
	static final String lineSep = BidiComplexEnvironment.getLineSep();
39
40
	/**
41
	 *  This method retrieves the features specific to this processor.
42
	 *
43
	 *  @return features with operators "\t!#%&()*+,-./:;<=>?|[]{}", 5 special cases,
44
	 *          LTR direction for Arabic and Hebrew, and support for both.
45
	 */
46
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
47
		return FEATURES;
48
	}
49
50
	/**
51
	  *  This method looks for occurrences of 5 special strings:
52
	  *  <ol>
53
	  *    <li>spaces</li>
54
	  *    <li>literals starting with apostrophe</li>
55
	  *    <li>identifiers starting with quotation mark</li>
56
	  *    <li>comments starting with slash-asterisk</li>
57
	  *    <li>comments starting with hyphen-hyphen</li>
58
	  *  </ol>
59
	  */
60
	public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) {
61
		switch (caseNumber) {
62
			case 0 : /* space */
63
				return srcText.indexOf(" ", fromIndex); //$NON-NLS-1$
64
			case 1 : /* literal */
65
				return srcText.indexOf('\'', fromIndex);
66
			case 2 : /* delimited identifier */
67
				return srcText.indexOf('"', fromIndex);
68
			case 3 : /* slash-aster comment */
69
				return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$
70
			case 4 : /* hyphen-hyphen comment */
71
				return srcText.indexOf("--", fromIndex); //$NON-NLS-1$
72
		}
73
		// we should never get here
74
		return -1;
75
	}
76
77
	/**
78
	 *  This method processes the 5 special cases as follows.
79
	     *  <ol>
80
	     *    <li>skip the run of spaces</li>
81
	     *    <li>look for a matching apostrophe and skip until after it</li>
82
	     *    <li>look for a matching quotation mark and skip until after it</li>
83
	     *    <li>skip until after the closing asterisk-slash</li>
84
	     *    <li>skip until after a line separator</li>
85
	     *  </ol>
86
	 */
87
	public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) {
88
		int location;
89
90
		helper.processOperator(operLocation);
91
		switch (caseNumber) {
92
			case 0 : /* space */
93
				operLocation++;
94
				while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') {
95
					helper.setDirProp(operLocation, WS);
96
					operLocation++;
97
				}
98
				return operLocation;
99
			case 1 : /* literal */
100
				location = operLocation + 1;
101
				while (true) {
102
					location = srcText.indexOf('\'', location);
103
					if (location < 0) {
104
						helper.setFinalState(caseNumber);
105
						return srcText.length();
106
					}
107
					if ((location + 1) < srcText.length() && srcText.charAt(location + 1) == '\'') {
108
						location += 2;
109
						continue;
110
					}
111
					return location + 1;
112
				}
113
			case 2 : /* delimited identifier */
114
				location = operLocation + 1;
115
				while (true) {
116
					location = srcText.indexOf('"', location);
117
					if (location < 0)
118
						return srcText.length();
119
120
					if ((location + 1) < srcText.length() && srcText.charAt(location + 1) == '"') {
121
						location += 2;
122
						continue;
123
					}
124
					return location + 1;
125
				}
126
			case 3 : /* slash-aster comment */
127
				if (operLocation < 0)
128
					location = 0; // initial state from previous line
129
				else
130
					location = operLocation + 2; // skip the opening slash-aster
131
				location = srcText.indexOf("*/", location); //$NON-NLS-1$
132
				if (location < 0) {
133
					helper.setFinalState(caseNumber);
134
					return srcText.length();
135
				}
136
				// we need to call processOperator since text may follow the
137
				//  end of comment immediately without even a space
138
				helper.processOperator(location);
139
				return location + 2;
140
			case 4 : /* hyphen-hyphen comment */
141
				location = srcText.indexOf(lineSep, operLocation + 2);
142
				if (location < 0)
143
					return srcText.length();
144
				return location + lineSep.length();
145
		}
146
		// we should never get here
147
		return srcText.length();
148
	}
149
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java (+35 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexSingle;
15
16
/**
17
 * Processor adapted to processing expressions with the following string format:
18
 * <pre>
19
 *  system(user)
20
 * </pre>
21
 */
22
public class BidiComplexSystem extends BidiComplexSingle {
23
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("(", 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 BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
33
		return FEATURES;
34
	}
35
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 * Processor adapted to processing URLs.
18
 */
19
public class BidiComplexURL extends BidiComplexProcessor {
20
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":?#/@.[]", 0, -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
	 *          no special cases, LTR direction for Arabic and Hebrew,
27
	 *          and support for both.
28
	 */
29
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
30
		return FEATURES;
31
	}
32
33
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java (+37 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 * Processor adapted to processing compound names.
18
 * This type covers names made of one or more parts, separated by underscores:
19
 * <pre>
20
 *  part1_part2_part3
21
 * </pre>
22
 */
23
public class BidiComplexUnderscore extends BidiComplexProcessor {
24
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("_", 0, -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 (underscore),
30
	 *          no special cases, LTR direction for Arabic and Hebrew,
31
	 *          and support for both.
32
	 */
33
	public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) {
34
		return FEATURES;
35
	}
36
37
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java (+40 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.consumable;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.internal.BidiComplexDelims;
15
16
/**
17
 * Processor adapted to processing XPath expressions.
18
 */
19
public class BidiComplexXPath extends BidiComplexDelims {
20
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(" /[]<>=!:@.|()+-*", 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 BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment 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/package.html (+180 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 interfaces and classes for
9
processing complex expressions.
10
11
12
<h2>Introduction to Complex Expressions</h2>
13
<p>
14
Bidirectional text offers interesting challenges to presentation systems.
15
For plain text, the Unicode Bidirectional Algorithm
16
(<a href="http://www.unicode.org/reports/tr9/">UBA</a>)
17
generally specifies satisfactorily how to reorder bidirectional text for
18
display. This algorithm is implemented in Java's presentation system.</p>
19
<p>
20
However, all bidirectional text is not necessarily plain text. There
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
23
has no awareness of these special cases, often gives incorrect results
24
when displaying such structured text.</p>
25
<p>
26
The general idea in handling complex expressions is to add directional
27
formatting characters at proper locations in the text to supplement the
28
standard algorithm, so that the final result is correctly displayed
29
using the UBA.
30
A class which handles complex expressions is thus essentially a
31
transformation engine which receives text without directional formatting
32
characters as input and produces as output the same text with added
33
directional formatting characters, hopefully in the minimum quantity
34
which is sufficient to ensure correct display, considering the type of
35
complex expression involved.</p>
36
<p>
37
In this package, text without directional formatting characters is
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>
40
<p>
41
The class {@link
42
<a href="BidiComplexHelper.html"><b>BidiComplexHelper</b></a>}
43
is the main tool for processing complex expressions.  It facilitates
44
handling several types of complex expressions, each type being handled
45
by a specific
46
{@link <a href="custom\IBidiComplexProcessor.html"><b><i>processor</i></b></a>} :</p>
47
<ul>
48
  <li>property (name=value)</li>
49
  <li>compound name (xxx_yy_zzzz)</li>
50
  <li>comma delimited list</li>
51
  <li>system(user)</li>
52
  <li>directory and file path</li>
53
  <li>e-mail address</li>
54
  <li>URL</li>
55
  <li>regular expression</li>
56
  <li>Xpath</li>
57
  <li>Java code</li>
58
  <li>SQL statements</li>
59
  <li>RTL arithmetic expressions</li>
60
</ul>
61
<p>
62
Other classes and one interface in this package may be used to
63
complement and facilitate the action of
64
{@link <a href="BidiComplexHelper.html">BidiComplexHelper</a>}:
65
<ul>
66
  <li>{@link <a href="BidiComplexEnvironment.html">BidiComplexEnvironment</a>}
67
  which regroups details about the environment</li>
68
  <li>{@link <a href="BidiComplexFeatures.html">BidiComplexFeatures</a>}
69
      which allows viewing and manipulating some factors which affect
70
      a complex expression processor's behavior</li>
71
  <li>{@link <a href="BidiComplexUtil.html">BidiComplexUtil</a>}
72
      provides a number of convenience methods to process some common types of
73
      complex expressions.  When using methods in this class, there is no need
74
      to use other classes of this package.  However, the other classes allow
75
      more precise control and possibly better performance.</li>
76
  <li>{@link <a href="IBidiComplexExpressionTypes.html">IBidiComplexExpressionTypes</a>}
77
      is an interface which contains only literals identifying the various types
78
      of complex expressions currently supported.</li>
79
  <li>{@link <a href="BidiComplexStringRecord.html">BidiComplexStringRecord</a>}
80
      which allows to record strings which are complex expressions with their
81
      type, so that another module can check if a given string has been recorded
82
      as a complex expression and retrieve its type.</li>
83
</ul>
84
<p>
85
{@link <a href="BidiComplexHelper.html">BidiComplexHelper</a>} and the
86
other classes and interface mentioned above are intended for users who
87
need to process complex expressions for which there already exist
88
processors.
89
<p>
90
Developers who want to develop new processors to support types of complex
91
expressions not currently supported can use the following components of the
92
package {@link <a href="custom\package-summary.html">
93
org.eclipse.equinox.bidi.custom</a>}:
94
<ul>
95
  <li>{@link <a href="custom\IBidiComplexProcessor.html">IBidiComplexProcessor</a>}
96
      is an interface specifying which methods a processor must provide.</li>
97
  <li>{@link <a href="custom\BidiComplexProcessor.html">BidiComplexProcessor</a>}
98
      is a generic processor which can be used as superclass for specific
99
      processors.</li>
100
  <li>{@link <a href="custom\BidiComplexStringProcessor.html">BidiComplexStringProcessor</a>}
101
      is a class which allows retrieval of the defined processor types and of the
102
      corresponding processors.</li>
103
</ul>
104
<p>
105
There are two other packages associated with the current one:
106
<ul>
107
  <li>{@link <a href="internal\package-summary.html">
108
      org.eclipse.equinox.bidi.internal</a>}</li>
109
  <li>{@link <a href="internal\consumable\package-summary.html">
110
       org.eclipse.equinox.bidi.internal.consumable</a>}</li>
111
</ul>
112
The tools in the first package can serve as example of how to develop
113
processors for currently unsupported types of complex expressions.<br>
114
The latter package contains classes for the processors implementing
115
the currently supported types of complex expressions.
116
<p>
117
However, users wishing to process the currently supported types of
118
complex expressions typically don't need to interact with these
119
two packages.
120
121
<p>&nbsp;</p>
122
123
<h2>Abbreviations used in the documentation of this package</h2>
124
125
<dl>
126
<dt><b>UBA</b><dd>Unicode Bidirectional Algorithm
127
128
<dt><b>Bidi</b><dd>Bidirectional
129
130
<dt><b>GUI</b><dd>Graphical User Interface
131
132
<dt><b>UI</b><dd>User Interface
133
134
<dt><b>LTR</b><dd>Left to Right
135
136
<dt><b>RTL</b><dd>Right to Left
137
138
<dt><b>LRM</b><dd>Left-to-Right Mark
139
140
<dt><b>RLM</b><dd>Right-to-Left Mark
141
142
<dt><b>LRE</b><dd>Left-to-Right Embedding
143
144
<dt><b>RLE</b><dd>Right-to-Left Embedding
145
146
<dt><b>PDF</b><dd>Pop Directional Formatting
147
</dl>
148
149
<p>&nbsp;</p>
150
151
<h2>Known Limitations</h2>
152
153
<p>The proposed solution is making extensive usage of LRM, RLM, LRE, RLE
154
and PDF directional controls which are invisible but affect the way bidi
155
text is displayed. The following related key points merit special
156
attention:</p>
157
158
<ul>
159
<li>Implementations of the UBA on various platforms (e.g., Windows and
160
Linux) are very similar but nevertheless have known differences. Those
161
differences are minor and will not have a visible effect in most cases.
162
However there might be cases in which the same bidi text on two
163
platforms might look different. These differences will surface in Java
164
applications when they use the platform visual components for their UI
165
(e.g., AWT, SWT).</li>
166
167
<li>It is assumed that the presentation engine supports LRE, RLE and
168
PDF directional formatting characters.</li>
169
170
<li>Because some presentation engines are not strictly conformant to the
171
UBA, the implementation of complex expressions in this package adds LRM
172
or RLM characters in association with LRE, RLE or PDF in cases where
173
this would not be needed if the presentation engine was fully conformant
174
to the UBA. Such added marks will not have harmful effects on
175
conformant presentation engines and will help less conformant engines to
176
achieve the desired presentation.</li>
177
</ul>
178
179
</body>
180
</html>
(-).settings/org.eclipse.jdt.core.prefs (-1 / +344 lines)
Lines 1-7 Link Here
1
#Wed Feb 03 11:32:36 EST 2010
1
#Wed Feb 09 14:41:33 EST 2011
2
eclipse.preferences.version=1
2
eclipse.preferences.version=1
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
5
org.eclipse.jdt.core.builder.invalidClasspath=abort
6
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
7
org.eclipse.jdt.core.circularClasspath=error
8
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
9
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
10
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
3
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
11
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
12
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
4
org.eclipse.jdt.core.compiler.compliance=1.4
13
org.eclipse.jdt.core.compiler.compliance=1.4
14
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
15
org.eclipse.jdt.core.compiler.debug.localVariable=generate
16
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
17
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
18
org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
19
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
20
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
21
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
22
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
23
org.eclipse.jdt.core.compiler.problem.deadCode=warning
24
org.eclipse.jdt.core.compiler.problem.deprecation=warning
25
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
26
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
27
org.eclipse.jdt.core.compiler.problem.discouragedReference=error
28
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
6
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
29
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
30
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
31
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
32
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
33
org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
34
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
35
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
36
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
37
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
38
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
39
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
40
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
41
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
42
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
43
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
44
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
45
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
46
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error
47
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
48
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
49
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
50
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
51
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
52
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
53
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
54
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
55
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
56
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
57
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
58
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
59
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
60
org.eclipse.jdt.core.compiler.problem.nullReference=warning
61
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
62
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
63
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
64
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
65
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
66
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
67
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
68
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
69
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
70
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
71
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
72
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
73
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
74
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
75
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
76
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
77
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
78
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
79
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
80
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
81
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
82
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
83
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
84
org.eclipse.jdt.core.compiler.problem.unusedImport=error
85
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
86
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
87
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
88
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
89
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
90
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
91
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
92
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
93
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
94
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
7
org.eclipse.jdt.core.compiler.source=1.3
95
org.eclipse.jdt.core.compiler.source=1.3
96
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
97
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
98
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
99
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
100
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
101
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
102
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
103
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
104
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
105
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
106
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
107
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
108
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
109
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
110
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
111
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
112
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
113
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
114
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
115
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
116
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
117
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
118
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
119
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
120
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
121
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
122
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
123
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
124
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
125
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
126
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
127
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
128
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
129
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
130
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
131
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
132
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
133
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
134
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
135
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
136
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
137
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
138
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
139
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
140
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
141
org.eclipse.jdt.core.formatter.comment.format_block_comments=false
142
org.eclipse.jdt.core.formatter.comment.format_header=false
143
org.eclipse.jdt.core.formatter.comment.format_html=true
144
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
145
org.eclipse.jdt.core.formatter.comment.format_line_comments=false
146
org.eclipse.jdt.core.formatter.comment.format_source_code=true
147
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
148
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
149
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
150
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
151
org.eclipse.jdt.core.formatter.comment.line_length=80
152
org.eclipse.jdt.core.formatter.compact_else_if=true
153
org.eclipse.jdt.core.formatter.continuation_indentation=2
154
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
155
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
156
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
157
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
158
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
159
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
160
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
161
org.eclipse.jdt.core.formatter.indent_empty_lines=false
162
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
163
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
164
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
165
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
166
org.eclipse.jdt.core.formatter.indentation.size=4
167
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
168
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
169
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
170
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
171
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
172
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
173
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
174
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
175
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
176
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
177
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
178
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
179
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
180
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
181
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
182
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
183
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
184
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
185
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
186
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
187
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
188
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
189
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
190
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
191
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
192
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
193
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
194
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
195
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
196
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
197
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
198
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
199
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
200
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
201
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
202
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
203
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
204
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
205
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
206
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
207
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
208
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
209
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
210
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
211
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
212
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
213
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
214
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
215
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
216
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
217
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
218
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
219
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
220
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
221
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
222
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
223
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
224
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
225
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
226
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
227
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
228
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
229
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
230
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
231
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
232
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
233
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
234
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
235
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
236
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
237
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
238
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
239
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
240
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
241
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
242
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
243
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
244
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
245
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
246
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
247
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
248
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
249
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
250
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
251
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
252
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
253
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
254
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
255
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
256
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
257
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
258
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
259
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
260
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
261
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
262
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
263
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
264
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert
265
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
266
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert
267
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
268
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
269
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
270
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
271
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
272
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
273
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
274
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
275
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
276
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
277
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
278
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
279
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
280
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
281
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
282
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
283
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
284
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
285
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
286
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
287
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
288
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
289
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
290
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
291
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
292
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
293
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
294
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
295
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
296
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
297
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
298
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
299
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
300
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
301
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
302
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
303
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
304
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
305
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
306
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
307
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
308
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
309
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
310
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
311
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
312
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
313
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
314
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
315
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
316
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
317
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
318
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
319
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
320
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
321
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
322
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
323
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
324
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
325
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
326
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
327
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
328
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
329
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
330
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
331
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
332
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
333
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
334
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
335
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
336
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
337
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
338
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
339
org.eclipse.jdt.core.formatter.lineSplit=800
340
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
341
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
342
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
343
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
344
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
345
org.eclipse.jdt.core.formatter.tabulation.char=tab
346
org.eclipse.jdt.core.formatter.tabulation.size=4
347
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
348
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
349
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
350
org.eclipse.jdt.core.incompleteClasspath=error
(-).settings/org.eclipse.jdt.ui.prefs (+58 lines)
Added Link Here
1
#Tue Aug 21 11:27:48 CDT 2007
2
eclipse.preferences.version=1
3
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
4
formatter_profile=_core
5
formatter_settings_version=11
6
internal.default.compliance=user
7
org.eclipse.jdt.ui.ignorelowercasenames=true
8
org.eclipse.jdt.ui.importorder=;
9
org.eclipse.jdt.ui.ondemandthreshold=3
10
org.eclipse.jdt.ui.staticondemandthreshold=99
11
sp_cleanup.add_default_serial_version_id=true
12
sp_cleanup.add_generated_serial_version_id=false
13
sp_cleanup.add_missing_annotations=true
14
sp_cleanup.add_missing_deprecated_annotations=true
15
sp_cleanup.add_missing_nls_tags=false
16
sp_cleanup.add_missing_override_annotations=true
17
sp_cleanup.add_serial_version_id=false
18
sp_cleanup.always_use_blocks=true
19
sp_cleanup.always_use_parentheses_in_expressions=false
20
sp_cleanup.always_use_this_for_non_static_field_access=false
21
sp_cleanup.always_use_this_for_non_static_method_access=false
22
sp_cleanup.convert_to_enhanced_for_loop=false
23
sp_cleanup.correct_indentation=false
24
sp_cleanup.format_source_code=true
25
sp_cleanup.make_local_variable_final=false
26
sp_cleanup.make_parameters_final=false
27
sp_cleanup.make_private_fields_final=true
28
sp_cleanup.make_variable_declarations_final=true
29
sp_cleanup.never_use_blocks=false
30
sp_cleanup.never_use_parentheses_in_expressions=true
31
sp_cleanup.on_save_use_additional_actions=false
32
sp_cleanup.organize_imports=true
33
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
34
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
35
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
36
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
37
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
38
sp_cleanup.remove_private_constructors=true
39
sp_cleanup.remove_trailing_whitespaces=false
40
sp_cleanup.remove_trailing_whitespaces_all=true
41
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
42
sp_cleanup.remove_unnecessary_casts=true
43
sp_cleanup.remove_unnecessary_nls_tags=false
44
sp_cleanup.remove_unused_imports=false
45
sp_cleanup.remove_unused_local_variables=false
46
sp_cleanup.remove_unused_private_fields=true
47
sp_cleanup.remove_unused_private_members=false
48
sp_cleanup.remove_unused_private_methods=true
49
sp_cleanup.remove_unused_private_types=true
50
sp_cleanup.sort_members=false
51
sp_cleanup.sort_members_all=false
52
sp_cleanup.use_blocks=false
53
sp_cleanup.use_blocks_only_for_return_and_throw=false
54
sp_cleanup.use_parentheses_in_expressions=false
55
sp_cleanup.use_this_for_non_static_field_access=false
56
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
57
sp_cleanup.use_this_for_non_static_method_access=false
58
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
(-)plugin.xml (-1 / +1 lines)
Lines 5-11 Link Here
5
         id="id2"
5
         id="id2"
6
         point="org.eclipse.equinox.bidi.bidiTypes">
6
         point="org.eclipse.equinox.bidi.bidiTypes">
7
      <typeDescription
7
      <typeDescription
8
            class="org.eclipse.equinox.bidi.internal.tests.ComplExpTest"
8
            class="org.eclipse.equinox.bidi.internal.tests.BidiComplexTest"
9
            description="Test"
9
            description="Test"
10
            type="test">
10
            type="test">
11
      </typeDescription>
11
      </typeDescription>
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexExtensibilityTest.java (+65 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.BidiComplexHelper;
15
import org.eclipse.equinox.bidi.custom.BidiComplexStringProcessor;
16
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
17
18
/**
19
 * Tests contribution of BiDi processors.
20
 */
21
public class BidiComplexExtensibilityTest extends BidiComplexTestBase {
22
23
	public void testBaseContributions() {
24
		String[] types = BidiComplexStringProcessor.getKnownTypes();
25
		assertNotNull(types);
26
		assertTrue(types.length > 0);
27
28
		// check one of the types that we know should be there
29
		assertTrue(isTypePresent(types, "regex"));
30
31
		IBidiComplexProcessor processor = BidiComplexStringProcessor.getProcessor("regex");
32
		assertNotNull(processor);
33
	}
34
35
	public void testOtherContributions() {
36
		String[] types = BidiComplexStringProcessor.getKnownTypes();
37
		assertNotNull(types);
38
		assertTrue(types.length > 0);
39
40
		// check the type added by the test bundle
41
		assertTrue(isTypePresent(types, "test"));
42
43
		IBidiComplexProcessor processor = BidiComplexStringProcessor.getProcessor("test");
44
		assertNotNull(processor);
45
46
		processor = BidiComplexStringProcessor.getProcessor("badtest");
47
		assertNull(processor);
48
49
		BidiComplexHelper helper = new BidiComplexHelper("test");
50
		String data, lean, full, model;
51
		data = "ABC.DEF:HOST-COM=HELLO";
52
		lean = toUT16(data);
53
		full = helper.leanToFullText(lean);
54
		model = "ABC@.DEF@:HOST@-COM@=HELLO";
55
		assertEquals("Test 'test' plugin", model, toPseudo(full));
56
	}
57
58
	private boolean isTypePresent(String[] types, String type) {
59
		for (int i = 0; i < types.length; i++) {
60
			if (type.equalsIgnoreCase(types[i]))
61
				return true;
62
		}
63
		return false;
64
	}
65
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexExtensionsTest.java (+186 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
16
/**
17
 * Tests all plug-in extensions
18
 */
19
20
public class BidiComplexExtensionsTest extends BidiComplexTestBase {
21
22
	static int state = BidiComplexHelper.STATE_NOTHING_GOING;
23
24
	private void doTest1(BidiComplexHelper complexp, String label, String data, String result) {
25
		String full;
26
		full = complexp.leanToFullText(toUT16(data), state);
27
		state = complexp.getFinalState();
28
		assertEquals(label + " data = " + data, result, toPseudo(full));
29
	}
30
31
	private void doTest2(BidiComplexHelper complexp, String label, String data, String result) {
32
		String full;
33
		full = complexp.leanToFullText(data, state);
34
		state = complexp.getFinalState();
35
		assertEquals(label + " data = " + data, result, toPseudo(full));
36
	}
37
38
	public void testExtensions() {
39
40
		BidiComplexHelper helper;
41
42
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
43
		assertNotNull(helper);
44
		state = BidiComplexHelper.STATE_NOTHING_GOING;
45
		doTest1(helper, "Comma #1", "ab,cd, AB, CD, EFG", "ab,cd, AB@, CD@, EFG");
46
47
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.EMAIL);
48
		assertNotNull(helper);
49
		state = BidiComplexHelper.STATE_NOTHING_GOING;
50
		doTest1(helper, "Email #1", "abc.DEF:GHI", "abc.DEF@:GHI");
51
		doTest1(helper, "Email #2", "DEF.GHI \"A.B\":JK ", "DEF@.GHI @\"A.B\"@:JK ");
52
		doTest1(helper, "Email #3", "DEF,GHI (A,B);JK ", "DEF@,GHI @(A,B)@;JK ");
53
		doTest1(helper, "Email #4", "DEF.GHI (A.B :JK ", "DEF@.GHI @(A.B :JK ");
54
55
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE);
56
		assertNotNull(helper);
57
		state = BidiComplexHelper.STATE_NOTHING_GOING;
58
		doTest1(helper, "File #1", "c:\\A\\B\\FILE.EXT", "c:\\A@\\B@\\FILE@.EXT");
59
60
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.JAVA);
61
		assertNotNull(helper);
62
		state = BidiComplexHelper.STATE_NOTHING_GOING;
63
		doTest1(helper, "Java #1", "A = B + C;", "A@ = B@ + C;");
64
		doTest1(helper, "Java #2", "A   = B + C;", "A@   = B@ + C;");
65
		doTest1(helper, "Java #3", "A = \"B+C\"+D;", "A@ = \"B+C\"@+D;");
66
		doTest1(helper, "Java #4", "A = \"B+C+D;", "A@ = \"B+C+D;");
67
		doTest1(helper, "Java #5", "A = \"B\\\"C\"+D;", "A@ = \"B\\\"C\"@+D;");
68
		doTest1(helper, "Java #6", "A = /*B+C*/ D;", "A@ = /*B+C*/@ D;");
69
		doTest1(helper, "Java #7", "A = /*B+C* D;", "A@ = /*B+C* D;");
70
		doTest1(helper, "Java #8", "X+Y+Z */ B;  ", "X+Y+Z */@ B;  ");
71
		doTest1(helper, "Java #9", "A = //B+C* D;", "A@ = //B+C* D;");
72
		doTest1(helper, "Java #10", "A = //B+C`|D+E;", "A@ = //B+C`|D@+E;");
73
74
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.PROPERTY);
75
		assertNotNull(helper);
76
		state = BidiComplexHelper.STATE_NOTHING_GOING;
77
		doTest1(helper, "Property #0", "NAME,VAL1,VAL2", "NAME,VAL1,VAL2");
78
		doTest1(helper, "Property #1", "NAME=VAL1,VAL2", "NAME@=VAL1,VAL2");
79
		doTest1(helper, "Property #2", "NAME=VAL1,VAL2=VAL3", "NAME@=VAL1,VAL2=VAL3");
80
81
		String data;
82
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.REGEXP);
83
		assertNotNull(helper);
84
		state = BidiComplexHelper.STATE_NOTHING_GOING;
85
		data = toUT16("ABC(?") + "#" + toUT16("DEF)GHI");
86
		doTest2(helper, "Regex #0.0", data, "A@B@C@(?#DEF)@G@H@I");
87
		data = toUT16("ABC(?") + "#" + toUT16("DEF");
88
		doTest2(helper, "Regex #0.1", data, "A@B@C@(?#DEF");
89
		doTest1(helper, "Regex #0.2", "GHI)JKL", "GHI)@J@K@L");
90
		data = toUT16("ABC(?") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
91
		doTest2(helper, "Regex #1", data, "A@B@C@(?<DEF>@G@H@I");
92
		doTest1(helper, "Regex #2.0", "ABC(?'DEF'GHI", "A@B@C@(?'DEF'@G@H@I");
93
		doTest1(helper, "Regex #2.1", "ABC(?'DEFGHI", "A@B@C@(?'DEFGHI");
94
		data = toUT16("ABC(?(") + "<" + toUT16("DEF") + ">" + toUT16(")GHI");
95
		doTest2(helper, "Regex #3", data, "A@B@C@(?(<DEF>)@G@H@I");
96
		doTest1(helper, "Regex #4", "ABC(?('DEF')GHI", "A@B@C@(?('DEF')@G@H@I");
97
		doTest1(helper, "Regex #5", "ABC(?(DEF)GHI", "A@B@C@(?(DEF)@G@H@I");
98
		data = toUT16("ABC(?") + "&" + toUT16("DEF)GHI");
99
		doTest2(helper, "Regex #6", data, "A@B@C@(?&DEF)@G@H@I");
100
		data = toUT16("ABC(?") + "P<" + toUT16("DEF") + ">" + toUT16("GHI");
101
		doTest2(helper, "Regex #7", data, "A@B@C(?p<DEF>@G@H@I");
102
		data = toUT16("ABC\\k") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
103
		doTest2(helper, "Regex #8", data, "A@B@C\\k<DEF>@G@H@I");
104
		doTest1(helper, "Regex #9", "ABC\\k'DEF'GHI", "A@B@C\\k'DEF'@G@H@I");
105
		doTest1(helper, "Regex #10", "ABC\\k{DEF}GHI", "A@B@C\\k{DEF}@G@H@I");
106
		data = toUT16("ABC(?") + "P=" + toUT16("DEF)GHI");
107
		doTest2(helper, "Regex #11", data, "A@B@C(?p=DEF)@G@H@I");
108
		doTest1(helper, "Regex #12", "ABC\\g{DEF}GHI", "A@B@C\\g{DEF}@G@H@I");
109
		data = toUT16("ABC\\g") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
110
		doTest2(helper, "Regex #13", data, "A@B@C\\g<DEF>@G@H@I");
111
		doTest1(helper, "Regex #14", "ABC\\g'DEF'GHI", "A@B@C\\g'DEF'@G@H@I");
112
		data = toUT16("ABC(?(") + "R&" + toUT16("DEF)GHI");
113
		doTest2(helper, "Regex #15", data, "A@B@C(?(r&DEF)@G@H@I");
114
		data = toUT16("ABC") + "\\Q" + toUT16("DEF") + "\\E" + toUT16("GHI");
115
		doTest2(helper, "Regex #16.0", data, "A@B@C\\qDEF\\eG@H@I");
116
		data = toUT16("ABC") + "\\Q" + toUT16("DEF");
117
		doTest2(helper, "Regex #16.1", data, "A@B@C\\qDEF");
118
		data = toUT16("GHI") + "\\E" + toUT16("JKL");
119
		doTest2(helper, "Regex #16.2", data, "GHI\\eJ@K@L");
120
		doTest1(helper, "Regex #17.0", "abc[d-h]ijk", "abc[d-h]ijk");
121
		doTest1(helper, "Regex #17.1", "aBc[d-H]iJk", "aBc[d-H]iJk");
122
		doTest1(helper, "Regex #17.2", "aB*[!-H]iJ2", "aB*[!-@H]iJ@2");
123
		doTest1(helper, "Regex #17.3", "aB*[1-2]J3", "aB*[@1-2]J@3");
124
		doTest1(helper, "Regex #17.4", "aB*[5-6]J3", "aB*[@5-@6]@J@3");
125
		doTest1(helper, "Regex #17.5", "a*[5-6]J3", "a*[5-@6]@J@3");
126
		doTest1(helper, "Regex #17.6", "aB*123", "aB*@123");
127
		doTest1(helper, "Regex #17.7", "aB*567", "aB*@567");
128
129
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.SQL);
130
		assertNotNull(helper);
131
		state = BidiComplexHelper.STATE_NOTHING_GOING;
132
		doTest1(helper, "SQL #0", "abc GHI", "abc GHI");
133
		doTest1(helper, "SQL #1", "abc DEF   GHI", "abc DEF@   GHI");
134
		doTest1(helper, "SQL #2", "ABC, DEF,   GHI", "ABC@, DEF@,   GHI");
135
		doTest1(helper, "SQL #3", "ABC'DEF GHI' JKL,MN", "ABC@'DEF GHI'@ JKL@,MN");
136
		doTest1(helper, "SQL #4.0", "ABC'DEF GHI JKL", "ABC@'DEF GHI JKL");
137
		doTest1(helper, "SQL #4.1", "MNO PQ' RS,TUV", "MNO PQ'@ RS@,TUV");
138
		doTest1(helper, "SQL #5", "ABC\"DEF GHI\" JKL,MN", "ABC@\"DEF GHI\"@ JKL@,MN");
139
		doTest1(helper, "SQL #6", "ABC\"DEF GHI JKL", "ABC@\"DEF GHI JKL");
140
		doTest1(helper, "SQL #7", "ABC/*DEF GHI*/ JKL,MN", "ABC@/*DEF GHI@*/ JKL@,MN");
141
		doTest1(helper, "SQL #8.0", "ABC/*DEF GHI JKL", "ABC@/*DEF GHI JKL");
142
		doTest1(helper, "SQL #8.1", "MNO PQ*/RS,TUV", "MNO PQ@*/RS@,TUV");
143
		doTest1(helper, "SQL #9", "ABC--DEF GHI JKL", "ABC@--DEF GHI JKL");
144
		doTest1(helper, "SQL #10", "ABC--DEF--GHI,JKL", "ABC@--DEF--GHI,JKL");
145
		doTest1(helper, "SQL #11", "ABC'DEF '' G I' JKL,MN", "ABC@'DEF '' G I'@ JKL@,MN");
146
		doTest1(helper, "SQL #12", "ABC\"DEF \"\" G I\" JKL,MN", "ABC@\"DEF \"\" G I\"@ JKL@,MN");
147
		doTest1(helper, "SQL #13", "ABC--DEF GHI`|JKL MN", "ABC@--DEF GHI`|JKL@ MN");
148
149
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.SYSTEM_USER);
150
		assertNotNull(helper);
151
		state = BidiComplexHelper.STATE_NOTHING_GOING;
152
		doTest1(helper, "System #1", "HOST(JACK)", "HOST@(JACK)");
153
154
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.UNDERSCORE);
155
		assertNotNull(helper);
156
		state = BidiComplexHelper.STATE_NOTHING_GOING;
157
		doTest1(helper, "Underscore #1", "A_B_C_d_e_F_G", "A@_B@_C_d_e_F@_G");
158
159
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.URL);
160
		assertNotNull(helper);
161
		state = BidiComplexHelper.STATE_NOTHING_GOING;
162
		doTest1(helper, "URL #1", "WWW.DOMAIN.COM/DIR1/DIR2/dir3/DIR4", "WWW@.DOMAIN@.COM@/DIR1@/DIR2/dir3/DIR4");
163
164
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.XPATH);
165
		assertNotNull(helper);
166
		state = BidiComplexHelper.STATE_NOTHING_GOING;
167
		doTest1(helper, "Xpath #1", "abc(DEF)GHI", "abc(DEF@)GHI");
168
		doTest1(helper, "Xpath #2", "DEF.GHI \"A.B\":JK ", "DEF@.GHI@ \"A.B\"@:JK ");
169
		doTest1(helper, "Xpath #3", "DEF!GHI 'A!B'=JK ", "DEF@!GHI@ 'A!B'@=JK ");
170
		doTest1(helper, "Xpath #4", "DEF.GHI 'A.B :JK ", "DEF@.GHI@ 'A.B :JK ");
171
172
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.EMAIL);
173
		state = BidiComplexHelper.STATE_NOTHING_GOING;
174
		BidiComplexFeatures f1 = helper.getFeatures();
175
		assertEquals("<>.:,;@", f1.operators);
176
		BidiComplexFeatures f2 = new BidiComplexFeatures("+-*/", f1.specialsCount, f1.dirArabic, f1.dirHebrew, f1.ignoreArabic, f1.ignoreHebrew);
177
		helper.setFeatures(f2);
178
		doTest1(helper, "DelimsEsc #1", "abc+DEF-GHI", "abc+DEF@-GHI");
179
		doTest1(helper, "DelimsEsc #2", "DEF-GHI (A*B)/JK ", "DEF@-GHI @(A*B)@/JK ");
180
		doTest1(helper, "DelimsEsc #3", "DEF-GHI (A*B)/JK ", "DEF@-GHI @(A*B)@/JK ");
181
		doTest1(helper, "DelimsEsc #4", "DEF-GHI (A*B\\)*C) /JK ", "DEF@-GHI @(A*B\\)*C) @/JK ");
182
		doTest1(helper, "DelimsEsc #5", "DEF-GHI (A\\\\\\)*C) /JK ", "DEF@-GHI @(A\\\\\\)*C) @/JK ");
183
		doTest1(helper, "DelimsEsc #6", "DEF-GHI (A\\\\)*C /JK ", "DEF@-GHI @(A\\\\)@*C @/JK ");
184
		doTest1(helper, "DelimsEsc #7", "DEF-GHI (A\\)*C /JK ", "DEF@-GHI @(A\\)*C /JK ");
185
	}
186
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexFullToLeanTest.java (+160 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
16
/**
17
 * Tests fullToLean method
18
 */
19
20
public class BidiComplexFullToLeanTest extends BidiComplexTestBase {
21
22
	static final BidiComplexEnvironment envLTR = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_LTR);
23
24
	static final BidiComplexEnvironment envRTL = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_RTL);
25
26
	private BidiComplexHelper helper;
27
28
	protected void setUp() throws Exception {
29
		super.setUp();
30
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
31
	}
32
33
	static int[] getpos(BidiComplexHelper complexp, boolean leanToFull) {
34
		int[] pos = new int[5];
35
36
		if (leanToFull) {
37
			pos[0] = complexp.leanToFullPos(0);
38
			pos[1] = complexp.leanToFullPos(4);
39
			pos[2] = complexp.leanToFullPos(7);
40
			pos[3] = complexp.leanToFullPos(10);
41
			pos[4] = complexp.leanToFullPos(30);
42
		} else {
43
			pos[0] = complexp.fullToLeanPos(0);
44
			pos[1] = complexp.fullToLeanPos(4);
45
			pos[2] = complexp.fullToLeanPos(7);
46
			pos[3] = complexp.fullToLeanPos(10);
47
			pos[4] = complexp.fullToLeanPos(30);
48
		}
49
		return pos;
50
	}
51
52
	private void doTest1(String msg, String data, String leanLTR, String fullLTR, int[] l2fPosLTR, int[] f2lPosLTR, String leanRTL, String fullRTL, int[] l2fPosRTL, int[] f2lPosRTL) {
53
		String text, full, lean, label;
54
		int[] pos;
55
56
		text = toUT16(data);
57
		helper.setEnvironment(envLTR);
58
		lean = helper.fullToLeanText(text);
59
		assertEquals(msg + "LTR lean", leanLTR, toPseudo(lean));
60
		full = helper.leanToFullText(lean);
61
		assertEquals(msg + "LTR full", fullLTR, toPseudo(full));
62
		pos = getpos(helper, true);
63
		label = msg + "leanToFullPos() LTR, expected=" + array_display(l2fPosLTR) + " result=" + array_display(pos);
64
		assertTrue(label, arrays_equal(l2fPosLTR, pos));
65
		pos = getpos(helper, false);
66
		label = msg + "fullToLeanPos() LTR, expected=" + array_display(f2lPosLTR) + " result=" + array_display(pos);
67
		assertTrue(label, arrays_equal(f2lPosLTR, pos));
68
		helper.setEnvironment(envRTL);
69
		lean = helper.fullToLeanText(text);
70
		assertEquals(msg + "RTL lean", leanRTL, toPseudo(lean));
71
		full = helper.leanToFullText(lean);
72
		assertEquals(msg + "RTL full", fullRTL, toPseudo(full));
73
		pos = getpos(helper, true);
74
		label = msg + "leanToFullPos() RTL, expected=" + array_display(l2fPosRTL) + " result=" + array_display(pos);
75
		assertTrue(label, arrays_equal(l2fPosRTL, pos));
76
		pos = getpos(helper, false);
77
		label = msg + "fullToLeanPos() RTL, expected=" + array_display(f2lPosRTL) + " result=" + array_display(pos);
78
		assertTrue(label, arrays_equal(f2lPosRTL, pos));
79
	}
80
81
	private void doTest2(String msg) {
82
		String text, data, full, lean, model;
83
		int state, state2, state3;
84
85
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.SQL);
86
		helper.setEnvironment(envLTR);
87
		data = "update \"AB_CDE\" set \"COL1\"@='01', \"COL2\"@='02' /* GH IJK";
88
		text = toUT16(data);
89
		lean = helper.fullToLeanText(text);
90
		state = helper.getFinalState();
91
		model = "update \"AB_CDE\" set \"COL1\"='01', \"COL2\"='02' /* GH IJK";
92
		assertEquals(msg + "LTR lean", model, toPseudo(lean));
93
		full = helper.leanToFullText(lean);
94
		assertEquals(msg + "LTR full", data, toPseudo(full));
95
		assertEquals(msg + "state from leanToFullText", helper.getFinalState(), state);
96
		data = "THIS IS A COMMENT LINE";
97
		text = toUT16(data);
98
		lean = helper.fullToLeanText(text, state);
99
		state2 = helper.getFinalState();
100
		model = "THIS IS A COMMENT LINE";
101
		assertEquals(msg + "LTR lean2", model, toPseudo(lean));
102
		full = helper.leanToFullText(lean, state);
103
		assertEquals(msg + "LTR full2", data, toPseudo(full));
104
		assertEquals(msg + "state from leanToFullText2", helper.getFinalState(), state2);
105
		data = "SOME MORE */ where \"COL3\"@=123";
106
		text = toUT16(data);
107
		lean = helper.fullToLeanText(text, state2);
108
		state3 = helper.getFinalState();
109
		model = "SOME MORE */ where \"COL3\"=123";
110
		assertEquals(msg + "LTR lean3", model, toPseudo(lean));
111
		full = helper.leanToFullText(lean, state2);
112
		assertEquals(msg + "LTR full3", data, toPseudo(full));
113
		assertEquals(msg + "state from leanToFullText3", helper.getFinalState(), state3);
114
	}
115
116
	public void testFullToLean() {
117
118
		doTest1("testFullToLean #1 - ", "", "", "", new int[] {0, 4, 7, 10, 30}, new int[] {0, 0, 0, 0, 0}, "", "", new int[] {0, 4, 7, 10, 30}, new int[] {0, 0, 0, 0, 0});
119
		doTest1("testFullToLean #01 - ", "1.abc", "1.abc", "1.abc", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 5, 5, 5}, "1.abc", ">@1.abc@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 5, 5});
120
		doTest1("testFullToLean #02 - ", "2.abc,def", "2.abc,def", "2.abc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "2.abc,def", ">@2.abc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
121
		doTest1("testFullToLean #03 - ", "@a.3.bc,def", "a.3.bc,def", "a.3.bc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 10}, "a.3.bc,def", ">@a.3.bc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 10});
122
		doTest1("testFullToLean #04 - ", "@@a.4.bc,def", "a.4.bc,def", "a.4.bc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 10}, "a.4.bc,def", ">@a.4.bc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 10});
123
		doTest1("testFullToLean #05 - ", "@5.abc,def", "5.abc,def", "5.abc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "5.abc,def", ">@5.abc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
124
		doTest1("testFullToLean #06 - ", "@@6.abc,def", "6.abc,def", "6.abc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "6.abc,def", ">@6.abc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
125
		doTest1("testFullToLean #07 - ", "7abc,@def", "7abc,@def", "7abc,@def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "7abc,@def", ">@7abc,@def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
126
		doTest1("testFullToLean #08 - ", "8abc,@@def", "8abc,@def", "8abc,@def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "8abc,@def", ">@8abc,@def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
127
		doTest1("testFullToLean #09 - ", "9abc,def@", "9abc,def", "9abc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 8, 8}, "9abc,def", ">@9abc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 8});
128
		doTest1("testFullToLean #10 - ", "10abc,def@@", "10abc,def", "10abc,def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "10abc,def", ">@10abc,def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
129
		doTest1("testFullToLean #11 - ", "@a.11.bc,@def@", "a.11.bc,@def", "a.11.bc,@def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 12}, "a.11.bc,@def", ">@a.11.bc,@def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 12});
130
		doTest1("testFullToLean #12 - ", "@@a.12.bc,@@def@@", "a.12.bc,@def", "a.12.bc,@def", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 12}, "a.12.bc,@def", ">@a.12.bc,@def@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 12});
131
		doTest1("testFullToLean #13 - ", "13ABC", "13ABC", "13ABC", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 5, 5, 5}, "13ABC", ">@13ABC@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 5, 5});
132
		doTest1("testFullToLean #14 - ", "14ABC,DE", "14ABC,DE", "14ABC@,DE", new int[] {0, 4, 8, 11, 31}, new int[] {0, 4, 6, 8, 8}, "14ABC,DE", ">@14ABC@,DE@^", new int[] {2, 6, 10, 13, 33}, new int[] {0, 2, 5, 7, 8});
133
		doTest1("testFullToLean #15 - ", "15ABC@,DE", "15ABC,DE", "15ABC@,DE", new int[] {0, 4, 8, 11, 31}, new int[] {0, 4, 6, 8, 8}, "15ABC,DE", ">@15ABC@,DE@^", new int[] {2, 6, 10, 13, 33}, new int[] {0, 2, 5, 7, 8});
134
		doTest1("testFullToLean #16 - ", "16ABC@@,DE", "16ABC,DE", "16ABC@,DE", new int[] {0, 4, 8, 11, 31}, new int[] {0, 4, 6, 8, 8}, "16ABC,DE", ">@16ABC@,DE@^", new int[] {2, 6, 10, 13, 33}, new int[] {0, 2, 5, 7, 8});
135
		doTest1("testFullToLean #17 - ", "17ABC,@@DE", "17ABC,@DE", "17ABC,@DE", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 9, 9}, "17ABC,@DE", ">@17ABC,@DE@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 9});
136
		doTest1("testFullToLean #18 - ", "18ABC,DE,FGH", "18ABC,DE,FGH", "18ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "18ABC,DE,FGH", ">@18ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
137
		doTest1("testFullToLean #19 - ", "19ABC@,DE@,FGH", "19ABC,DE,FGH", "19ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "19ABC,DE,FGH", ">@19ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
138
		doTest1("testFullToLean #20 - ", "20ABC,@DE,@FGH", "20ABC,@DE,@FGH", "20ABC,@DE,@FGH", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 14}, "20ABC,@DE,@FGH", ">@20ABC,@DE,@FGH@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 14});
139
		doTest1("testFullToLean #21 - ", "21ABC@@,DE@@,FGH", "21ABC,DE,FGH", "21ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "21ABC,DE,FGH", ">@21ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
140
		doTest1("testFullToLean #22 - ", "22ABC,@@DE,@@FGH", "22ABC,@DE,@FGH", "22ABC,@DE,@FGH", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 14}, "22ABC,@DE,@FGH", ">@22ABC,@DE,@FGH@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 14});
141
		doTest1("testFullToLean #23 - ", ">@23abc@^", "23abc", "23abc", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 5, 5, 5}, "23abc", ">@23abc@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 5, 5});
142
		doTest1("testFullToLean #24 - ", "24abc@^", "24abc", "24abc", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 5, 5, 5}, "24abc", ">@24abc@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 5, 5});
143
		doTest1("testFullToLean #25 - ", ">@25abc", "25abc", "25abc", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 5, 5, 5}, "25abc", ">@25abc@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 5, 5});
144
		doTest1("testFullToLean #26 - ", "26AB,CD@EF,GHI", "26AB,CD@EF,GHI", "26AB@,CD@EF@,GHI", new int[] {0, 5, 8, 12, 32}, new int[] {0, 4, 6, 9, 14}, "26AB,CD@EF,GHI", ">@26AB@,CD@EF@,GHI@^", new int[] {2, 7, 10, 14, 34}, new int[] {0, 2, 4, 7, 14});
145
		doTest1("testFullToLean #27 - ", "27AB,CD@123ef,GHI", "27AB,CD@123ef,GHI", "27AB@,CD@123ef,GHI", new int[] {0, 5, 8, 11, 31}, new int[] {0, 4, 6, 9, 17}, "27AB,CD@123ef,GHI", ">@27AB@,CD@123ef,GHI@^", new int[] {2, 7, 10, 13, 33}, new int[] {0, 2, 4, 7, 17});
146
		doTest1("testFullToLean #28 - ", ">28ABC@,DE@,FGH^", "28ABC,DE,FGH", "28ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "28ABC,DE,FGH", ">@28ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
147
		doTest1("testFullToLean #29 - ", ">>29ABC@,DE@,FGH^^", "29ABC,DE,FGH", "29ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "29ABC,DE,FGH", ">@29ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
148
		doTest1("testFullToLean #30 - ", ">30AB>C^@,DE@,FGH^", "30AB>C^,DE,FGH", "30AB>C^@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 7, 9, 14}, "30AB>C^,DE,FGH", ">@30AB>C^@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 14});
149
		doTest1("testFullToLean #31 - ", ">31AB>C@,DE@,FGH^^", "31AB>C,DE,FGH", "31AB>C@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 9, 13}, "31AB>C,DE,FGH", ">@31AB>C@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 13});
150
		doTest1("testFullToLean #32 - ", ">@32ABC@,DE@,FGH@^", "32ABC,DE,FGH", "32ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "32ABC,DE,FGH", ">@32ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
151
		doTest1("testFullToLean #33 - ", "@33ABC@,DE@,FGH@^", "33ABC,DE,FGH", "33ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "33ABC,DE,FGH", ">@33ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
152
		doTest1("testFullToLean #34 - ", ">@34ABC@,DE@,FGH@", "34ABC,DE,FGH", "34ABC@,DE@,FGH", new int[] {0, 4, 8, 12, 32}, new int[] {0, 4, 6, 8, 12}, "34ABC,DE,FGH", ">@34ABC@,DE@,FGH@^", new int[] {2, 6, 10, 14, 34}, new int[] {0, 2, 5, 7, 12});
153
		doTest1("testFullToLean #35 - ", "35ABC@@DE@@@GH@", "35ABC@DE@GH", "35ABC@DE@GH", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 10, 11}, "35ABC@DE@GH", ">@35ABC@DE@GH@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 11});
154
		doTest1("testFullToLean #36 - ", "36ABC@@DE@@@@@@", "36ABC@DE", "36ABC@DE", new int[] {0, 4, 7, 10, 30}, new int[] {0, 4, 7, 8, 8}, "36ABC@DE", ">@36ABC@DE@^", new int[] {2, 6, 9, 12, 32}, new int[] {0, 2, 5, 8, 8});
155
		doTest1("testFullToLean #37 - ", ">>>@@@@@^^^", "", "", new int[] {0, 4, 7, 10, 30}, new int[] {0, 0, 0, 0, 0}, "", "", new int[] {0, 4, 7, 10, 30}, new int[] {0, 0, 0, 0, 0});
156
157
		// test fullToLeanText with initial state
158
		doTest2("testFullToLean #38 - ");
159
	}
160
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexMathTest.java (+55 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
16
/**
17
 * Tests RTL arithmetic
18
 */
19
public class BidiComplexMathTest extends BidiComplexTestBase {
20
21
	static final BidiComplexEnvironment envLTR = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_LTR);
22
23
	static final BidiComplexEnvironment envRTL = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_RTL);
24
25
	private BidiComplexHelper helper;
26
27
	protected void setUp() throws Exception {
28
		super.setUp();
29
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.RTL_ARITHMETIC);
30
	}
31
32
	private void verifyOneLine(String msg, String data, String resLTR, String resRTL) {
33
		String lean = toUT16(data);
34
		helper.setEnvironment(envLTR);
35
		String fullLTR = helper.leanToFullText(lean);
36
		assertEquals(msg + " LTR - ", resLTR, toPseudo(fullLTR));
37
38
		helper.setEnvironment(envRTL);
39
		String fullRTL = helper.leanToFullText(lean);
40
		assertEquals(msg + " RTL - ", resRTL, toPseudo(fullRTL));
41
	}
42
43
	public void testRTLarithmetic() {
44
		verifyOneLine("Math #0", "", "", "");
45
		verifyOneLine("Math #1", "1+abc", "<&1+abc&^", "1+abc");
46
		verifyOneLine("Math #2", "2+abc-def", "<&2+abc&-def&^", "2+abc&-def");
47
		verifyOneLine("Math #3", "a+3*bc/def", "<&a&+3*bc&/def&^", "a&+3*bc&/def");
48
		verifyOneLine("Math #4", "4+abc/def", "<&4+abc&/def&^", "4+abc&/def");
49
		verifyOneLine("Math #5", "13ABC", "<&13ABC&^", "13ABC");
50
		verifyOneLine("Math #6", "14ABC-DE", "<&14ABC-DE&^", "14ABC-DE");
51
		verifyOneLine("Math #7", "15ABC+DE", "<&15ABC+DE&^", "15ABC+DE");
52
		verifyOneLine("Math #8", "16ABC*DE", "<&16ABC*DE&^", "16ABC*DE");
53
		verifyOneLine("Math #9", "17ABC/DE", "<&17ABC/DE&^", "17ABC/DE");
54
	}
55
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexMethodsTest.java (+366 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
16
/**
17
 * Tests most public methods of BidiComplexHelper
18
 */
19
20
public class BidiComplexMethodsTest extends BidiComplexTestBase {
21
22
	final static int LTR = BidiComplexFeatures.DIR_LTR;
23
24
	final static int RTL = BidiComplexFeatures.DIR_RTL;
25
26
	final static BidiComplexEnvironment envLTR = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_LTR);
27
28
	final static BidiComplexEnvironment envRTL = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_RTL);
29
30
	final static BidiComplexEnvironment envRTLMIR = new BidiComplexEnvironment(null, true, BidiComplexEnvironment.ORIENT_RTL);
31
32
	final static BidiComplexEnvironment envIGN = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_IGNORE);
33
34
	final static BidiComplexEnvironment envCLR = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR);
35
36
	final static BidiComplexEnvironment envCRL = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_CONTEXTUAL_RTL);
37
38
	final static BidiComplexEnvironment envERR = new BidiComplexEnvironment(null, false, 9999);
39
40
	BidiComplexHelper helper;
41
42
	private void doTestTools() {
43
44
		// This method tests utility methods used by the JUnits
45
		String data = "56789ABCDEFGHIJKLMNOPQRSTUVWXYZ~#@&><^|`";
46
		String text = toUT16(data);
47
		String dat2 = toPseudo(text);
48
		assertEquals(data, dat2);
49
50
		text = toPseudo(data);
51
		assertEquals("56789abcdefghijklmnopqrstuvwxyz~#@&><^|`", text);
52
53
		int[] arrayA = new int[] {1, 2};
54
		int[] arrayB = new int[] {3, 4, 5};
55
		assertFalse(arrays_equal(arrayA, arrayB));
56
57
		assertTrue(arrays_equal(arrayA, arrayA));
58
59
		arrayB = new int[] {3, 4};
60
		assertFalse(arrays_equal(arrayA, arrayB));
61
62
		text = array_display(null);
63
		assertEquals("null", text);
64
	}
65
66
	private void doTestState() {
67
		String data, lean, full, model;
68
		int state;
69
70
		data = "A=B+C;/* D=E+F;";
71
		lean = toUT16(data);
72
		full = helper.leanToFullText(lean);
73
		model = "A@=B@+C@;/* D=E+F;";
74
		assertEquals("full1", model, toPseudo(full));
75
		state = helper.getFinalState();
76
		data = "A=B+C; D=E+F;";
77
		lean = toUT16(data);
78
		full = helper.leanToFullText(lean, state);
79
		model = "A=B+C; D=E+F;";
80
		assertEquals("full2", model, toPseudo(full));
81
		state = helper.getFinalState();
82
		data = "A=B+C;*/ D=E+F;";
83
		lean = toUT16(data);
84
		full = helper.leanToFullText(lean, state);
85
		model = "A=B+C;*/@ D@=E@+F;";
86
		assertEquals("full3", model, toPseudo(full));
87
	}
88
89
	private void doTestOrientation() {
90
		int orient;
91
92
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
93
		orient = helper.getEnvironment().orientation;
94
		assertEquals("orient #1", BidiComplexEnvironment.ORIENT_LTR, orient);
95
96
		helper.setEnvironment(envIGN);
97
		orient = helper.getEnvironment().orientation;
98
		assertEquals("orient #2", BidiComplexEnvironment.ORIENT_IGNORE, orient);
99
100
		helper.setEnvironment(envCRL);
101
		orient = helper.getEnvironment().orientation;
102
		helper.leanToFullText("--!**");
103
		assertEquals("orient #3", BidiComplexEnvironment.ORIENT_CONTEXTUAL_RTL, orient);
104
105
		helper.setEnvironment(envERR);
106
		orient = helper.getEnvironment().orientation;
107
		helper.leanToFullText("--!**");
108
		assertEquals("orient #4", BidiComplexEnvironment.ORIENT_UNKNOWN, orient);
109
	}
110
111
	private void doTestOrient(BidiComplexFeatures f, String label, String data, String resLTR, String resRTL, String resCon) {
112
		String full, lean;
113
114
		lean = toUT16(data);
115
		helper.setEnvironment(envLTR);
116
		helper.setFeatures(f);
117
		full = helper.leanToFullText(lean);
118
		assertEquals(label + "LTR full", resLTR, toPseudo(full));
119
		helper.setEnvironment(envRTL);
120
		helper.setFeatures(f);
121
		full = helper.leanToFullText(lean);
122
		assertEquals("label + RTL full", resRTL, toPseudo(full));
123
		helper.setEnvironment(envCRL);
124
		helper.setFeatures(f);
125
		full = helper.leanToFullText(lean);
126
		assertEquals(label + "CON full", resCon, toPseudo(full));
127
	}
128
129
	private void doTestScripts() {
130
		BidiComplexFeatures f2, f1 = helper.getFeatures();
131
		boolean flag;
132
		flag = f1.ignoreArabic;
133
		assertFalse("Ignores Arabic 1", flag);
134
		flag = f1.ignoreHebrew;
135
		assertFalse("Ignores Hebrew 1", flag);
136
137
		f2 = new BidiComplexFeatures(f1.operators, 0, -1, -1, true, true);
138
		flag = f2.ignoreArabic;
139
		assertTrue("Ignores Arabic 2", flag);
140
		flag = f2.ignoreHebrew;
141
		assertTrue("Ignores Hebrew 2", flag);
142
		doTestOrient(f2, "Scripts #1 ", "BCD,EF", "BCD,EF", ">@BCD,EF@^", "@BCD,EF");
143
		f2 = new BidiComplexFeatures(f1.operators, 0, -1, -1, false, true);
144
		flag = f2.ignoreArabic;
145
		assertFalse("Ignores Arabic 3", flag);
146
		flag = f2.ignoreHebrew;
147
		assertTrue("Ignores Hebrew 3", flag);
148
		doTestOrient(f2, "Scripts #2 ", "d,EF", "d,EF", ">@d,EF@^", "d,EF");
149
		doTestOrient(f2, "Scripts #3 ", "#,eF", "#,eF", ">@#,eF@^", "@#,eF");
150
		doTestOrient(f2, "Scripts #4 ", "#,12", "#@,12", ">@#@,12@^", "@#@,12");
151
		doTestOrient(f2, "Scripts #5 ", "#,##", "#@,##", ">@#@,##@^", "@#@,##");
152
		doTestOrient(f2, "Scripts #6 ", "#,89", "#@,89", ">@#@,89@^", "@#@,89");
153
		doTestOrient(f2, "Scripts #7 ", "#,ef", "#,ef", ">@#,ef@^", "@#,ef");
154
		doTestOrient(f2, "Scripts #8 ", "#,", "#,", ">@#,@^", "@#,");
155
		doTestOrient(f2, "Scripts #9 ", "9,ef", "9,ef", ">@9,ef@^", "9,ef");
156
		doTestOrient(f2, "Scripts #10 ", "9,##", "9@,##", ">@9@,##@^", "9@,##");
157
		doTestOrient(f2, "Scripts #11 ", "7,89", "7@,89", ">@7@,89@^", "7@,89");
158
		doTestOrient(f2, "Scripts #12 ", "7,EF", "7,EF", ">@7,EF@^", "@7,EF");
159
		doTestOrient(f2, "Scripts #13 ", "BCD,EF", "BCD,EF", ">@BCD,EF@^", "@BCD,EF");
160
161
		f2 = new BidiComplexFeatures(f1.operators, 0, -1, -1, true, false);
162
		flag = f2.ignoreArabic;
163
		assertTrue("Ignores Arabic 4", flag);
164
		flag = f2.ignoreHebrew;
165
		assertFalse("Ignores Hebrew 4", flag);
166
		doTestOrient(f2, "Scripts #14 ", "BCd,EF", "BCd,EF", ">@BCd,EF@^", "@BCd,EF");
167
		doTestOrient(f2, "Scripts #15 ", "BCD,eF", "BCD,eF", ">@BCD,eF@^", "@BCD,eF");
168
		doTestOrient(f2, "Scripts #16 ", "BCD,EF", "BCD@,EF", ">@BCD@,EF@^", "@BCD@,EF");
169
		doTestOrient(f2, "Scripts #17 ", "BCD,12", "BCD@,12", ">@BCD@,12@^", "@BCD@,12");
170
		doTestOrient(f2, "Scripts #18 ", "BCD,", "BCD,", ">@BCD,@^", "@BCD,");
171
172
		f2 = new BidiComplexFeatures(f1.operators, 0, -1, -1, false, false);
173
		doTestOrient(f2, "Scripts #19 ", "123,45|67", "123,45|67", ">@123,45|67@^", "@123,45|67");
174
		doTestOrient(f2, "Scripts #20 ", "5,e", "5,e", ">@5,e@^", "5,e");
175
		doTestOrient(f2, "Scripts #21 ", "5,#", "5@,#", ">@5@,#@^", "5@,#");
176
		doTestOrient(f2, "Scripts #22 ", "5,6", "5@,6", ">@5@,6@^", "5@,6");
177
		doTestOrient(f2, "Scripts #23 ", "5,D", "5@,D", ">@5@,D@^", "5@,D");
178
		doTestOrient(f2, "Scripts #24 ", "5,--", "5,--", ">@5,--@^", "@5,--");
179
	}
180
181
	private void doTestLeanOffsets() {
182
		String lean, data, label;
183
		int state;
184
		int[] offsets;
185
		int[] model;
186
187
		data = "A=B+C;/* D=E+F;";
188
		lean = toUT16(data);
189
		helper.leanToFullText(lean);
190
		offsets = helper.leanBidiCharOffsets();
191
		model = new int[] {1, 3, 5};
192
		label = "leanBidiCharOffsets() #1 expected=" + array_display(model) + " result=" + array_display(offsets);
193
		assertTrue(label, arrays_equal(model, offsets));
194
		state = helper.getFinalState();
195
		data = "A=B+C;*/ D=E+F;";
196
		lean = toUT16(data);
197
		helper.leanToFullText(lean, state);
198
		offsets = helper.leanBidiCharOffsets();
199
		model = new int[] {8, 10, 12};
200
		label = "leanBidiCharOffsets() #2 expected=" + array_display(model) + " result=" + array_display(offsets);
201
		assertTrue(label, arrays_equal(model, offsets));
202
		offsets = helper.leanBidiCharOffsets();
203
		model = new int[] {8, 10, 12};
204
		label = "leanBidiCharOffsets() #3 expected=" + array_display(model) + " result=" + array_display(offsets);
205
		assertTrue(label, arrays_equal(model, offsets));
206
	}
207
208
	private void doTestFullOffsets(String label, String data, int[] resLTR, int[] resRTL, int[] resCon) {
209
		String full, lean, msg;
210
		int[] offsets;
211
212
		lean = toUT16(data);
213
		helper.setEnvironment(envLTR);
214
		full = helper.leanToFullText(lean);
215
		// the following line avoids a compiler warning about full never being
216
		// read
217
		full += "";
218
		offsets = helper.fullBidiCharOffsets();
219
		msg = label + "LTR expected=" + array_display(resLTR) + " result=" + array_display(offsets);
220
		assertTrue(msg, arrays_equal(resLTR, offsets));
221
		helper.setEnvironment(envRTL);
222
		full = helper.leanToFullText(lean);
223
		offsets = helper.fullBidiCharOffsets();
224
		msg = label + "RTL expected=" + array_display(resRTL) + " result=" + array_display(offsets);
225
		assertTrue(msg, arrays_equal(resRTL, offsets));
226
		helper.setEnvironment(envCLR);
227
		full = helper.leanToFullText(lean);
228
		offsets = helper.fullBidiCharOffsets();
229
		msg = label + "CON expected=" + array_display(resCon) + " result=" + array_display(offsets);
230
		assertTrue(msg, arrays_equal(resCon, offsets));
231
	}
232
233
	private void doTestMirrored() {
234
		boolean mirrored;
235
236
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
237
		mirrored = helper.getEnvironment().mirrored;
238
		assertFalse("mirrored #1", mirrored);
239
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, true, BidiComplexEnvironment.ORIENT_LTR);
240
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED, env);
241
		mirrored = helper.getEnvironment().mirrored;
242
		assertTrue("mirrored #2", mirrored);
243
	}
244
245
	private void doTestDirection() {
246
		String data, lean, full, model, msg;
247
248
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
249
		BidiComplexFeatures f1 = helper.getFeatures();
250
		msg = "TestDirection #1";
251
		assertTrue(msg, f1.dirArabic == LTR && f1.dirHebrew == LTR);
252
253
		BidiComplexFeatures f2 = new BidiComplexFeatures(f1.operators, 0, RTL, RTL, false, false);
254
		helper.setFeatures(f2);
255
		f1 = helper.getFeatures();
256
		msg = "TestDirection #2";
257
		assertTrue(msg, f1.dirArabic == RTL && f1.dirHebrew == RTL);
258
259
		BidiComplexEnvironment environment = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_LTR);
260
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.EMAIL, environment);
261
		f1 = helper.getFeatures();
262
		msg = "TestDirection #3";
263
		assertTrue(msg, f1.dirArabic == LTR && f1.dirHebrew == LTR);
264
		data = "#ABC.#DEF:HOST.com";
265
		lean = toUT16(data);
266
		full = helper.leanToFullText(lean);
267
		model = "#ABC@.#DEF@:HOST.com";
268
		assertEquals("TestDirection #9 full", model, toPseudo(full));
269
270
		data = "ABC.DEF:HOST.com";
271
		lean = toUT16(data);
272
		full = helper.leanToFullText(lean);
273
		model = "ABC@.DEF@:HOST.com";
274
		assertEquals("TestDirection #10 full", model, toPseudo(full));
275
276
		environment = new BidiComplexEnvironment(null, true, BidiComplexEnvironment.ORIENT_LTR);
277
		helper.setEnvironment(environment);
278
		f1 = helper.getFeatures();
279
		msg = "TestDirection #10.5";
280
		assertTrue(msg, f1.dirArabic == RTL && f1.dirHebrew == LTR);
281
		data = "#ABC.#DEF:HOST.com";
282
		lean = toUT16(data);
283
		full = helper.leanToFullText(lean);
284
		model = "<&#ABC.#DEF:HOST.com&^";
285
		assertEquals("TestDirection #11 full", model, toPseudo(full));
286
287
		data = "#ABc.#DEF:HOSt.COM";
288
		lean = toUT16(data);
289
		full = helper.leanToFullText(lean);
290
		model = "<&#ABc.#DEF:HOSt.COM&^";
291
		assertEquals("TestDirection #12 full", model, toPseudo(full));
292
293
		data = "#ABc.#DEF:HOSt.";
294
		lean = toUT16(data);
295
		full = helper.leanToFullText(lean);
296
		model = "<&#ABc.#DEF:HOSt.&^";
297
		assertEquals("TestDirection #13 full", model, toPseudo(full));
298
299
		data = "ABC.DEF:HOST.com";
300
		lean = toUT16(data);
301
		full = helper.leanToFullText(lean);
302
		model = "ABC@.DEF@:HOST.com";
303
		assertEquals("TestDirection #14 full", model, toPseudo(full));
304
305
		data = "--.---:----";
306
		lean = toUT16(data);
307
		full = helper.leanToFullText(lean);
308
		model = "--.---:----";
309
		assertEquals("TestDirection #15 full", model, toPseudo(full));
310
311
		data = "ABC.|DEF:HOST.com";
312
		lean = toUT16(data);
313
		full = helper.leanToFullText(lean);
314
		model = "ABC.|DEF@:HOST.com";
315
		assertEquals("TestDirection #16 full", model, toPseudo(full));
316
317
		helper.setEnvironment(envRTLMIR);
318
		data = "#ABc.|#DEF:HOST.com";
319
		lean = toUT16(data);
320
		full = helper.leanToFullText(lean);
321
		model = "#ABc.|#DEF:HOST.com";
322
		assertEquals("TestDirection #17 full", model, toPseudo(full));
323
		assertEquals("Test curDirection", RTL, helper.getCurDirection());
324
	}
325
326
	public void testMethods() {
327
328
		doTestTools();
329
330
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.JAVA);
331
		doTestState();
332
333
		doTestOrientation();
334
335
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
336
		BidiComplexFeatures f2 = helper.getFeatures();
337
		doTestOrient(f2, "Methods #1 ", "", "", "", "");
338
		doTestOrient(f2, "Methods #2 ", "abc", "abc", ">@abc@^", "abc");
339
		doTestOrient(f2, "Methods #3 ", "ABC", "ABC", ">@ABC@^", "@ABC");
340
		doTestOrient(f2, "Methods #4 ", "bcd,ef", "bcd,ef", ">@bcd,ef@^", "bcd,ef");
341
		doTestOrient(f2, "Methods #5 ", "BCD,EF", "BCD@,EF", ">@BCD@,EF@^", "@BCD@,EF");
342
		doTestOrient(f2, "Methods #6 ", "cde,FG", "cde,FG", ">@cde,FG@^", "cde,FG");
343
		doTestOrient(f2, "Methods #7 ", "CDE,fg", "CDE,fg", ">@CDE,fg@^", "@CDE,fg");
344
		doTestOrient(f2, "Methods #8 ", "12..def,GH", "12..def,GH", ">@12..def,GH@^", "12..def,GH");
345
		doTestOrient(f2, "Methods #9 ", "34..DEF,gh", "34..DEF,gh", ">@34..DEF,gh@^", "@34..DEF,gh");
346
347
		doTestScripts();
348
349
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.JAVA);
350
		doTestLeanOffsets();
351
352
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
353
		doTestFullOffsets("TestFullOffsets ", "BCD,EF,G", new int[] {3, 7}, new int[] {0, 1, 5, 9, 12, 13}, new int[] {0, 4, 8});
354
355
		doTestMirrored();
356
357
		doTestDirection();
358
359
		helper = new BidiComplexHelper(IBidiComplexExpressionTypes.COMMA_DELIMITED);
360
		String data = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
361
		String lean = toUT16(data);
362
		String full = helper.leanToFullText(lean);
363
		String model = "A@,B@,C@,D@,E@,F@,G@,H@,I@,J@,K@,L@,M@,N@,O@,P@,Q@,R@,S@,T@,U@,V@,W@,X@,Y@,Z";
364
		assertEquals("many inserts", model, toPseudo(full));
365
	}
366
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexNullProcessorTest.java (+59 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
16
/**
17
 * Tests RTL arithmetic
18
 */
19
public class BidiComplexNullProcessorTest extends BidiComplexTestBase {
20
21
	static final int[] EMPTY_INT_ARRAY = new int[0];
22
23
	private BidiComplexHelper helper;
24
25
	protected void setUp() throws Exception {
26
		super.setUp();
27
		helper = new BidiComplexHelper();
28
	}
29
30
	public void testNullProcessor() {
31
		String full = helper.leanToFullText("abc");
32
		assertEquals("leanToFullText", "abc", full);
33
		full = helper.leanToFullText("abc", 3);
34
		assertEquals("leanToFullText with state", "abc", full);
35
		int[] offsets = helper.leanBidiCharOffsets();
36
		assertTrue("leanBidiCharOffsets", arrays_equal(offsets, EMPTY_INT_ARRAY));
37
		offsets = helper.fullBidiCharOffsets();
38
		assertTrue("fullBidiCharOffsets", arrays_equal(offsets, EMPTY_INT_ARRAY));
39
		String lean = helper.fullToLeanText("abc");
40
		assertEquals("fullToLeanText", "abc", lean);
41
		lean = helper.fullToLeanText("abc", 3);
42
		assertEquals("fullToLeanText with state", "abc", lean);
43
		int state = helper.getFinalState();
44
		assertEquals("getFinalState", BidiComplexHelper.STATE_NOTHING_GOING, state);
45
		int pos = helper.leanToFullPos(13);
46
		assertEquals("leanToFullPos", 13, pos);
47
		pos = helper.fullToLeanPos(15);
48
		assertEquals("fullToLeanPos", 15, pos);
49
		assertEquals("getDirProp", Character.DIRECTIONALITY_UNDEFINED, helper.getDirProp(123));
50
		int direction = helper.getCurDirection();
51
		assertEquals("getCurDirection", BidiComplexFeatures.DIR_LTR, direction);
52
		BidiComplexEnvironment env = helper.getEnvironment();
53
		assertEquals("getEnvironment", BidiComplexEnvironment.DEFAULT, env);
54
		helper.setEnvironment(env);
55
		BidiComplexFeatures features = helper.getFeatures();
56
		assertEquals("getFeatures", BidiComplexFeatures.DEFAULT, features);
57
		helper.setFeatures(features);
58
	}
59
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexSomeMoreTest.java (+100 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.*;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
17
18
/**
19
 * Tests some weird cases
20
 */
21
22
public class BidiComplexSomeMoreTest extends BidiComplexTestBase {
23
24
	final static BidiComplexEnvironment env1 = new BidiComplexEnvironment("en_US", false, BidiComplexEnvironment.ORIENT_LTR);
25
26
	final static BidiComplexEnvironment env2 = new BidiComplexEnvironment("he", false, BidiComplexEnvironment.ORIENT_LTR);
27
28
	final static BidiComplexFeatures features = new BidiComplexFeatures(null, 1, -1, -1, false, false);
29
30
	BidiComplexHelper helper;
31
32
	class Processor1 extends BidiComplexProcessor {
33
34
		public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env) {
35
			return features;
36
		}
37
38
		public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex) {
39
			return fromIndex;
40
		}
41
42
		public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation) {
43
			int len = srcText.length();
44
			for (int i = len - 1; i >= 0; i--) {
45
				caller.insertMark(i);
46
				caller.insertMark(i);
47
			}
48
			return len;
49
		}
50
	}
51
52
	class Processor2 extends BidiComplexProcessor {
53
54
		public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env) {
55
			return features;
56
		}
57
	}
58
59
	class Processor3 extends BidiComplexProcessor {
60
61
		public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env) {
62
			return features;
63
		}
64
65
		public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex) {
66
			return 0;
67
		}
68
	}
69
70
	public void testSomeMore() {
71
		assertFalse(env1.isBidi());
72
		assertTrue(env2.isBidi());
73
74
		IBidiComplexProcessor processor = new Processor1();
75
		helper = new BidiComplexHelper(processor, env1);
76
		String full = toPseudo(helper.leanToFullText("abcd"));
77
		assertEquals("@a@b@c@d", full);
78
79
		processor = new Processor2();
80
		helper = new BidiComplexHelper(processor, env1);
81
		boolean catchFlag = false;
82
		try {
83
			full = toPseudo(helper.leanToFullText("abcd"));
84
		} catch (IllegalStateException e) {
85
			catchFlag = true;
86
		}
87
		assertTrue("Catch missing indexOfSpecial", catchFlag);
88
89
		processor = new Processor3();
90
		helper = new BidiComplexHelper(processor, env1);
91
		catchFlag = false;
92
		try {
93
			full = toPseudo(helper.leanToFullText("abcd"));
94
		} catch (IllegalStateException e) {
95
			catchFlag = true;
96
		}
97
		assertTrue("Catch missing processSpecial", catchFlag);
98
	}
99
100
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexTest.java (+36 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
package org.eclipse.equinox.bidi.internal.tests;
12
13
import org.eclipse.equinox.bidi.*;
14
import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor;
15
16
public class BidiComplexTest implements IBidiComplexProcessor {
17
18
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("-=.:", 0, -1, -1, false, false);
19
20
	public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env) {
21
		return FEATURES;
22
	}
23
24
	public BidiComplexFeatures updateEnvironment(BidiComplexHelper caller, BidiComplexEnvironment env) {
25
		return FEATURES;
26
	}
27
28
	public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex) {
29
		throw new IllegalStateException();
30
	}
31
32
	public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation) {
33
		throw new IllegalStateException();
34
	}
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexTestBase.java (+123 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import junit.framework.TestCase;
15
16
/**
17
 * Base functionality for the processor tests.
18
 */
19
public class BidiComplexTestBase extends TestCase {
20
21
	static final private char LRM = 0x200E;
22
23
	static final private char RLM = 0x200F;
24
25
	static final private char LRE = 0x202A;
26
27
	static final private char RLE = 0x202B;
28
29
	static final private char PDF = 0x202C;
30
31
	public static String toPseudo(String text) {
32
		char[] chars = text.toCharArray();
33
		int len = chars.length;
34
35
		for (int i = 0; i < len; i++) {
36
			char c = chars[i];
37
			if (c >= 'A' && c <= 'Z')
38
				chars[i] = (char) (c + 'a' - 'A');
39
			else if (c >= 0x05D0 && c < 0x05EA)
40
				chars[i] = (char) (c + 'A' - 0x05D0);
41
			else if (c == 0x05EA)
42
				chars[i] = '~';
43
			else if (c == 0x0644)
44
				chars[i] = '#';
45
			else if (c >= 0x0665 && c <= 0x0669)
46
				chars[i] = (char) (c + '5' - 0x0665);
47
			else if (c == LRM)
48
				chars[i] = '@';
49
			else if (c == RLM)
50
				chars[i] = '&';
51
			else if (c == LRE)
52
				chars[i] = '>';
53
			else if (c == RLE)
54
				chars[i] = '<';
55
			else if (c == PDF)
56
				chars[i] = '^';
57
			else if (c == '\n')
58
				chars[i] = '|';
59
			else if (c == '\r')
60
				chars[i] = '`';
61
		}
62
		return new String(chars);
63
	}
64
65
	public static String toUT16(String text) {
66
		char[] chars = text.toCharArray();
67
		int len = chars.length;
68
69
		for (int i = 0; i < len; i++) {
70
			char c = chars[i];
71
			if (c >= '5' && c <= '9')
72
				chars[i] = (char) (0x0665 + c - '5');
73
			else if (c >= 'A' && c <= 'Z')
74
				chars[i] = (char) (0x05D0 + c - 'A');
75
			else if (c == '~')
76
				chars[i] = (char) (0x05EA);
77
			else if (c == '#')
78
				chars[i] = (char) (0x0644);
79
			else if (c == '@')
80
				chars[i] = LRM;
81
			else if (c == '&')
82
				chars[i] = RLM;
83
			else if (c == '>')
84
				chars[i] = LRE;
85
			else if (c == '<')
86
				chars[i] = RLE;
87
			else if (c == '^')
88
				chars[i] = PDF;
89
			else if (c == '|')
90
				chars[i] = '\n';
91
			else if (c == '`')
92
				chars[i] = '\r';
93
		}
94
		return new String(chars);
95
	}
96
97
	static String array_display(int[] array) {
98
		if (array == null) {
99
			return "null";
100
		}
101
		StringBuffer sb = new StringBuffer(50);
102
		int len = array.length;
103
		for (int i = 0; i < len; i++) {
104
			sb.append(array[i]);
105
			sb.append(' ');
106
		}
107
		return sb.toString();
108
	}
109
110
	static boolean arrays_equal(int[] one, int[] two) {
111
		int len = one.length;
112
		if (len != two.length) {
113
			return false;
114
		}
115
		for (int i = 0; i < len; i++) {
116
			if (one[i] != two[i]) {
117
				return false;
118
			}
119
		}
120
		return true;
121
	}
122
123
}
(-)src/org/eclipse/equinox/bidi/internal/tests/BidiComplexUtilTest.java (+138 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import java.util.Locale;
15
import org.eclipse.equinox.bidi.BidiComplexUtil;
16
import org.eclipse.equinox.bidi.IBidiComplexExpressionTypes;
17
18
/**
19
 * Tests methods in BidiComplexUtil
20
 */
21
22
public class BidiComplexUtilTest extends BidiComplexTestBase {
23
24
	private static final String HEBREW = "iw";
25
26
	private static final String HEBREW2 = "he";
27
28
	private static final String ARABIC = "ar";
29
30
	private static final String FARSI = "fa";
31
32
	private static final String URDU = "ur";
33
34
	private Locale locale;
35
36
	protected void setUp() throws Exception {
37
		super.setUp();
38
		locale = Locale.getDefault();
39
	}
40
41
	protected void tearDown() {
42
		Locale.setDefault(locale);
43
	}
44
45
	private void doTest1(String data, String result) {
46
		Locale.setDefault(Locale.ENGLISH);
47
		String full = BidiComplexUtil.process(toUT16(data));
48
		assertEquals("Util #1 full EN - ", data, toPseudo(full));
49
		Locale.setDefault(new Locale(HEBREW2));
50
		full = BidiComplexUtil.process(toUT16(data));
51
		assertEquals("Util #1 full HE - ", result, toPseudo(full));
52
		Locale.setDefault(new Locale(ARABIC));
53
		full = BidiComplexUtil.process(toUT16(data));
54
		assertEquals("Util #1 full AR - ", result, toPseudo(full));
55
		Locale.setDefault(new Locale(FARSI));
56
		full = BidiComplexUtil.process(toUT16(data));
57
		assertEquals("Util #1 full FA - ", result, toPseudo(full));
58
		Locale.setDefault(new Locale(URDU));
59
		full = BidiComplexUtil.process(toUT16(data));
60
		assertEquals("Util #1 full UR - ", result, toPseudo(full));
61
		Locale.setDefault(new Locale(HEBREW));
62
		full = BidiComplexUtil.process(toUT16(data));
63
		String ful2 = BidiComplexUtil.process(toUT16(data), null);
64
		assertEquals("Util #1 full - ", result, toPseudo(full));
65
		assertEquals("Util #1 ful2 - ", result, toPseudo(ful2));
66
		String lean = BidiComplexUtil.deprocess(full);
67
		assertEquals("Util #1 lean - ", data, toPseudo(lean));
68
	}
69
70
	private void doTest2(String msg, String data, String result) {
71
		doTest2(msg, data, result, data);
72
	}
73
74
	private void doTest2(String msg, String data, String result, String resLean) {
75
		String full = BidiComplexUtil.process(toUT16(data), "*");
76
		assertEquals(msg + "full", result, toPseudo(full));
77
		String lean = BidiComplexUtil.deprocess(full);
78
		assertEquals(msg + "lean", resLean, toPseudo(lean));
79
	}
80
81
	private void doTest3(String msg, String data, String result) {
82
		doTest3(msg, data, result, data);
83
	}
84
85
	private void doTest3(String msg, String data, String result, String resLean) {
86
		String full = BidiComplexUtil.processTyped(toUT16(data), IBidiComplexExpressionTypes.COMMA_DELIMITED);
87
		assertEquals(msg + "full", result, toPseudo(full));
88
		String lean = BidiComplexUtil.deprocess(full, IBidiComplexExpressionTypes.COMMA_DELIMITED);
89
		assertEquals(msg + "lean", resLean, toPseudo(lean));
90
	}
91
92
	private void doTest4(String msg, String data, int[] offsets, int direction, boolean affix, String result) {
93
		String txt = msg + "text=" + data + "\n    offsets=" + array_display(offsets) + "\n    direction=" + direction + "\n    affix=" + affix;
94
		String lean = toUT16(data);
95
		String full = BidiComplexUtil.insertMarks(lean, offsets, direction, affix);
96
		assertEquals(txt, result, toPseudo(full));
97
	}
98
99
	public void testBidiComplexUtil() {
100
101
		// Test process() and deprocess() with default delimiters
102
		doTest1("ABC/DEF/G", ">@ABC@/DEF@/G@^");
103
		// Test process() and deprocess() with specified delimiters
104
		doTest2("Util #2.1 - ", "", "");
105
		doTest2("Util #2.2 - ", ">@ABC@^", ">@ABC@^", "ABC");
106
		doTest2("Util #2.3 - ", "abc", "abc");
107
		doTest2("Util #2.4 - ", "!abc", ">@!abc@^");
108
		doTest2("Util #2.5 - ", "abc!", ">@abc!@^");
109
		doTest2("Util #2.6 - ", "ABC*DEF*G", ">@ABC@*DEF@*G@^");
110
		// Test process() and deprocess() with specified expression type
111
		doTest3("Util #3.1 - ", "ABC,DEF,G", ">@ABC@,DEF@,G@^");
112
		doTest3("Util #3.2 - ", "", "");
113
		doTest3("Util #3.3 - ", ">@DEF@^", ">@DEF@^", "DEF");
114
		boolean catchFlag = false;
115
		try {
116
			BidiComplexUtil.deprocess(toUT16("ABC,DE"), "wrong_type");
117
		} catch (IllegalArgumentException e) {
118
			catchFlag = true;
119
		}
120
		assertTrue("Catch invalid type on deprocess", catchFlag);
121
		catchFlag = false;
122
		try {
123
			BidiComplexUtil.processTyped("abc", "wrong_type");
124
		} catch (IllegalArgumentException e) {
125
			catchFlag = true;
126
		}
127
		assertTrue("Catch invalid type on process", catchFlag);
128
		// Test insertMarks()
129
		doTest4("Util #4.1 - ", "ABCDEFG", new int[] {3, 6}, 0, false, "ABC@DEF@G");
130
		doTest4("Util #4.2 - ", "ABCDEFG", new int[] {3, 6}, 0, true, ">@ABC@DEF@G@^");
131
		doTest4("Util #4.3 - ", "ABCDEFG", new int[] {3, 6}, 1, false, "ABC&DEF&G");
132
		doTest4("Util #4.4 - ", "ABCDEFG", new int[] {3, 6}, 1, true, "<&ABC&DEF&G&^");
133
		doTest4("Util #4.5 - ", "", new int[] {3, 6}, 0, false, "");
134
		doTest4("Util #4.6 - ", "", new int[] {3, 6}, 0, true, "");
135
		doTest4("Util #4.7 - ", "ABCDEFG", null, 1, false, "ABCDEFG");
136
		doTest4("Util #4.8 - ", "ABCDEFG", null, 1, true, "<&ABCDEFG&^");
137
	}
138
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ComplExpMathTest.java (-55 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.complexp.IBiDiProcessor;
15
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
16
import org.eclipse.equinox.bidi.complexp.StringProcessor;
17
18
/**
19
 * Tests RTL arithmetic
20
 */
21
public class ComplExpMathTest extends ComplExpTestBase {
22
23
	private IComplExpProcessor processor;
24
25
	protected void setUp() throws Exception {
26
		super.setUp();
27
		processor = StringProcessor.getProcessor(IBiDiProcessor.RTL_ARITHMETIC);
28
	}
29
30
	private void verifyOneLine(String msg, String data, String resLTR,
31
			String resRTL) {
32
		String lean = toUT16(data);
33
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
34
		String fullLTR = processor.leanToFullText(lean);
35
		assertEquals(msg + " LTR - ", resLTR, toPseudo(fullLTR));
36
37
		processor.assumeOrientation(IComplExpProcessor.ORIENT_RTL);
38
		String fullRTL = processor.leanToFullText(lean);
39
		assertEquals(msg + " RTL - ", resRTL, toPseudo(fullRTL));
40
	}
41
42
	public void testRTLarithmetic() {
43
		verifyOneLine("Math #0", "", "", "");
44
		verifyOneLine("Math #1", "1+abc", "<&1+abc&^", "1+abc");
45
		verifyOneLine("Math #2", "2+abc-def", "<&2+abc&-def&^", "2+abc&-def");
46
		verifyOneLine("Math #3", "a+3*bc/def", "<&a&+3*bc&/def&^",
47
				"a&+3*bc&/def");
48
		verifyOneLine("Math #4", "4+abc/def", "<&4+abc&/def&^", "4+abc&/def");
49
		verifyOneLine("Math #5", "13ABC", "<&13ABC&^", "13ABC");
50
		verifyOneLine("Math #6", "14ABC-DE", "<&14ABC-DE&^", "14ABC-DE");
51
		verifyOneLine("Math #7", "15ABC+DE", "<&15ABC+DE&^", "15ABC+DE");
52
		verifyOneLine("Math #8", "16ABC*DE", "<&16ABC*DE&^", "16ABC*DE");
53
		verifyOneLine("Math #9", "17ABC/DE", "<&17ABC/DE&^", "17ABC/DE");
54
	}
55
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ComplExpTest.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.tests;
12
13
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
14
15
public class ComplExpTest implements IComplExpProcessor {
16
17
	private static final int[] EMPTY_INT_ARRAY = new int[0];
18
	private static final int[][] ALL_LTR = new int[][] {
19
			{ DIRECTION_LTR, DIRECTION_LTR }, { DIRECTION_LTR, DIRECTION_LTR } };
20
21
	public ComplExpTest() {
22
		return;
23
	}
24
25
	public void setOperators(String operators) {
26
		// empty
27
	}
28
29
	public String getOperators() {
30
		return "";
31
	}
32
33
	public void selectBidiScript(boolean arabic, boolean hebrew) {
34
		// empty
35
	}
36
37
	public boolean handlesArabicScript() {
38
		return false;
39
	}
40
41
	public boolean handlesHebrewScript() {
42
		return false;
43
	}
44
45
	public String leanToFullText(String text) {
46
		return text;
47
	}
48
49
	public String leanToFullText(String text, int initState) {
50
		return text;
51
	}
52
53
	public int[] leanBidiCharOffsets(String text) {
54
		return EMPTY_INT_ARRAY;
55
	}
56
57
	public int[] leanBidiCharOffsets(String text, int initState) {
58
		return EMPTY_INT_ARRAY;
59
	}
60
61
	public int[] leanBidiCharOffsets() {
62
		return EMPTY_INT_ARRAY;
63
	}
64
65
	public int[] fullBidiCharOffsets() {
66
		return EMPTY_INT_ARRAY;
67
	}
68
69
	public String fullToLeanText(String text) {
70
		return text;
71
	}
72
73
	public String fullToLeanText(String text, int initState) {
74
		return text;
75
	}
76
77
	public int getFinalState() {
78
		return STATE_NOTHING_GOING;
79
	}
80
81
	public int leanToFullPos(int pos) {
82
		return pos;
83
	}
84
85
	public int fullToLeanPos(int pos) {
86
		return pos;
87
	}
88
89
	public void assumeMirrored(boolean mirrored) {
90
		// empty
91
	}
92
93
	public boolean isMirrored() {
94
		return false;
95
	}
96
97
	public void assumeOrientation(int orientation) {
98
		// empty
99
	}
100
101
	public int recallOrientation() {
102
		return ORIENT_LTR;
103
	}
104
105
	public void setArabicDirection(int not_mirrored, int mirrored) {
106
		// empty
107
	}
108
109
	public void setArabicDirection(int direction) {
110
		// empty
111
	}
112
113
	public void setHebrewDirection(int not_mirrored, int mirrored) {
114
		// empty
115
	}
116
117
	public void setHebrewDirection(int direction) {
118
		// empty
119
	}
120
121
	public void setDirection(int not_mirrored, int mirrored) {
122
		// empty
123
	}
124
125
	public void setDirection(int direction) {
126
		// empty
127
	}
128
129
	public int[][] getDirection() {
130
		return ALL_LTR;
131
	}
132
133
	public int getCurDirection() {
134
		return DIRECTION_LTR;
135
	}
136
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ComplExpTestBase.java (-156 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import junit.framework.TestCase;
15
16
/**
17
 * Base functionality for the processor tests.
18
 */
19
public class ComplExpTestBase extends TestCase {
20
21
	static final private char LRM = 0x200E;
22
	static final private char RLM = 0x200F;
23
	static final private char LRE = 0x202A;
24
	static final private char RLE = 0x202B;
25
	static final private char PDF = 0x202C;
26
27
	protected String toPseudo(String text) {
28
		char[] chars = text.toCharArray();
29
		int len = chars.length;
30
31
		for (int i = 0; i < len; i++) {
32
			char c = chars[i];
33
			if (c >= 'A' && c <= 'Z')
34
				chars[i] = (char) (c + 'a' - 'A');
35
			else if (c >= 0x05D0 && c < 0x05EA)
36
				chars[i] = (char) (c + 'A' - 0x05D0);
37
			else if (c == 0x05EA)
38
				chars[i] = '~';
39
			else if (c == 0x0644)
40
				chars[i] = '#';
41
			else if (c >= 0x0665 && c <= 0x0669)
42
				chars[i] = (char) (c + '5' - 0x0665);
43
			else if (c == LRM)
44
				chars[i] = '@';
45
			else if (c == RLM)
46
				chars[i] = '&';
47
			else if (c == LRE)
48
				chars[i] = '>';
49
			else if (c == RLE)
50
				chars[i] = '<';
51
			else if (c == PDF)
52
				chars[i] = '^';
53
			else if (c == '\n')
54
				chars[i] = '|';
55
			else if (c == '\r')
56
				chars[i] = '`';
57
		}
58
		return new String(chars);
59
	}
60
61
	protected String toUT16(String text) {
62
		char[] chars = text.toCharArray();
63
		int len = chars.length;
64
65
		for (int i = 0; i < len; i++) {
66
			char c = chars[i];
67
			if (c >= '5' && c <= '9')
68
				chars[i] = (char) (0x0665 + c - '5');
69
			else if (c >= 'A' && c <= 'Z')
70
				chars[i] = (char) (0x05D0 + c - 'A');
71
			else if (c == '~')
72
				chars[i] = (char) (0x05EA);
73
			else if (c == '#')
74
				chars[i] = (char) (0x0644);
75
			else if (c == '@')
76
				chars[i] = LRM;
77
			else if (c == '&')
78
				chars[i] = RLM;
79
			else if (c == '>')
80
				chars[i] = LRE;
81
			else if (c == '<')
82
				chars[i] = RLE;
83
			else if (c == '^')
84
				chars[i] = PDF;
85
			else if (c == '|')
86
				chars[i] = '\n';
87
			else if (c == '`')
88
				chars[i] = '\r';
89
		}
90
		return new String(chars);
91
	}
92
93
	static String array_display(int[] array) {
94
		if (array == null) {
95
			return "null";
96
		}
97
		StringBuffer sb = new StringBuffer(50);
98
		int len = array.length;
99
		for (int i = 0; i < len; i++) {
100
			sb.append(array[i]);
101
			sb.append(' ');
102
		}
103
		return sb.toString();
104
	}
105
106
	static boolean arrays_equal(int[] one, int[] two) {
107
		int len = one.length;
108
		if (len != two.length) {
109
			return false;
110
		}
111
		for (int i = 0; i < len; i++) {
112
			if (one[i] != two[i]) {
113
				return false;
114
			}
115
		}
116
		return true;
117
	}
118
119
	static boolean arrays2_equal(int[][] one, int[][] two) {
120
		int dim1, dim2;
121
		dim1 = one.length;
122
		if (dim1 != two.length) {
123
			return false;
124
		}
125
		for (int i = 0; i < dim1; i++) {
126
			dim2 = one[i].length;
127
			if (dim2 != two[i].length) {
128
				return false;
129
			}
130
			for (int j = 0; j < dim2; j++) {
131
				if (one[i][j] != two[i][j]) {
132
					return false;
133
				}
134
			}
135
		}
136
		return true;
137
	}
138
139
	static String array2_display(int[][] array) {
140
		int dim1, dim2;
141
		if (array == null) {
142
			return "null";
143
		}
144
		StringBuffer sb = new StringBuffer(50);
145
		dim1 = array.length;
146
		for (int i = 0; i < dim1; i++) {
147
			dim2 = array[i].length;
148
			for (int j = 0; j < dim2; j++) {
149
				sb.append(array[i][j]);
150
				sb.append(' ');
151
			}
152
		}
153
		return sb.toString();
154
	}
155
156
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ComplExpUtilTest.java (-131 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.complexp.*;
15
import java.util.Locale;
16
17
/**
18
 * Tests methods in ComplExpUtil
19
 */
20
21
public class ComplExpUtilTest extends ComplExpTestBase {
22
23
	private static final String HEBREW = "iw";
24
	private static final String HEBREW2 = "he";
25
	private static final String ARABIC = "ar";
26
	private static final String FARSI = "fa";
27
	private static final String URDU = "ur";
28
	private Locale locale;
29
30
	protected void setUp() throws Exception {
31
		super.setUp();
32
		locale = Locale.getDefault();
33
	}
34
35
	protected void tearDown() {
36
		Locale.setDefault(locale);
37
	}
38
39
	private void doTest1(String data, String result) {
40
		Locale.setDefault(Locale.ENGLISH);
41
		String full = ComplExpUtil.process(toUT16(data));
42
		assertEquals("Util #1 full EN - ", data, toPseudo(full));
43
		Locale.setDefault(new Locale(HEBREW2));
44
		full = ComplExpUtil.process(toUT16(data));
45
		assertEquals("Util #1 full HE - ", result, toPseudo(full));
46
		Locale.setDefault(new Locale(ARABIC));
47
		full = ComplExpUtil.process(toUT16(data));
48
		assertEquals("Util #1 full AR - ", result, toPseudo(full));
49
		Locale.setDefault(new Locale(FARSI));
50
		full = ComplExpUtil.process(toUT16(data));
51
		assertEquals("Util #1 full FA - ", result, toPseudo(full));
52
		Locale.setDefault(new Locale(URDU));
53
		full = ComplExpUtil.process(toUT16(data));
54
		assertEquals("Util #1 full UR - ", result, toPseudo(full));
55
		Locale.setDefault(new Locale(HEBREW));
56
		full = ComplExpUtil.process(toUT16(data));
57
		String ful2 = ComplExpUtil.process(toUT16(data), null);
58
		assertEquals("Util #1 full - ", result, toPseudo(full));
59
		assertEquals("Util #1 ful2 - ", result, toPseudo(ful2));
60
		String lean = ComplExpUtil.deprocess(full);
61
		assertEquals("Util #1 lean - ", data, toPseudo(lean));
62
	}
63
64
	private void doTest2(String msg, String data, String result) {
65
		doTest2(msg, data, result, data);
66
	}
67
68
	private void doTest2(String msg, String data, String result, String resLean) {
69
		String full = ComplExpUtil.process(toUT16(data), "*");
70
		assertEquals(msg + "full", result, toPseudo(full));
71
		String lean = ComplExpUtil.deprocess(full);
72
		assertEquals(msg + "lean", resLean, toPseudo(lean));
73
	}
74
75
	private void doTest3(String msg, String data, String result) {
76
		doTest3(msg, data, result, data);
77
	}
78
79
	private void doTest3(String msg, String data, String result, String resLean) {
80
		String full = ComplExpUtil.processTyped(toUT16(data),
81
				IBiDiProcessor.COMMA_DELIMITED);
82
		assertEquals(msg + "full", result, toPseudo(full));
83
		String lean = ComplExpUtil.deprocess(full,
84
				IBiDiProcessor.COMMA_DELIMITED);
85
		assertEquals(msg + "lean", resLean, toPseudo(lean));
86
	}
87
88
	private void doTest4(String msg, String data, int[] offsets, int direction,
89
			boolean affix, String result) {
90
		String txt = msg + "text=" + data + "\n    offsets="
91
				+ array_display(offsets) + "\n    direction=" + direction
92
				+ "\n    affix=" + affix;
93
		String lean = toUT16(data);
94
		String full = ComplExpUtil.insertMarks(lean, offsets, direction, affix);
95
		assertEquals(txt, result, toPseudo(full));
96
	}
97
98
	public void testComplExpUtil() {
99
100
		// Test process() and deprocess() with default delimiters
101
		doTest1("ABC/DEF/G", ">@ABC@/DEF@/G@^");
102
		// Test process() and deprocess() with specified delimiters
103
		doTest2("Util #2.1 - ", "", "");
104
		doTest2("Util #2.2 - ", ">@ABC@^", ">@ABC@^", "ABC");
105
		doTest2("Util #2.3 - ", "abc", "abc");
106
		doTest2("Util #2.4 - ", "!abc", ">@!abc@^");
107
		doTest2("Util #2.5 - ", "abc!", ">@abc!@^");
108
		doTest2("Util #2.6 - ", "ABC*DEF*G", ">@ABC@*DEF@*G@^");
109
		// Test process() and deprocess() with specified expression type
110
		doTest3("Util #3.1 - ", "ABC,DEF,G", ">@ABC@,DEF@,G@^");
111
		doTest3("Util #3.2 - ", "", "");
112
		doTest3("Util #3.3 - ", ">@DEF@^", ">@DEF@^", "DEF");
113
		String str = ComplExpUtil.deprocess(toUT16("ABC,DE"), "wrong_type");
114
		assertEquals("deprocess(9999)", "ABC,DE", toPseudo(str));
115
		str = ComplExpUtil.process("abc", "wrong_type");
116
		assertEquals("invalid type", "abc", toPseudo(str));
117
		// Test insertMarks()
118
		doTest4("Util #4.1 - ", "ABCDEFG", new int[] { 3, 6 }, 0, false,
119
				"ABC@DEF@G");
120
		doTest4("Util #4.2 - ", "ABCDEFG", new int[] { 3, 6 }, 0, true,
121
				">@ABC@DEF@G@^");
122
		doTest4("Util #4.3 - ", "ABCDEFG", new int[] { 3, 6 }, 1, false,
123
				"ABC&DEF&G");
124
		doTest4("Util #4.4 - ", "ABCDEFG", new int[] { 3, 6 }, 1, true,
125
				"<&ABC&DEF&G&^");
126
		doTest4("Util #4.5 - ", "", new int[] { 3, 6 }, 0, false, "");
127
		doTest4("Util #4.6 - ", "", new int[] { 3, 6 }, 0, true, "");
128
		doTest4("Util #4.7 - ", "ABCDEFG", null, 1, false, "ABCDEFG");
129
		doTest4("Util #4.8 - ", "ABCDEFG", null, 1, true, "<&ABCDEFG&^");
130
	}
131
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ExtensibilityTest.java (-55 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import junit.framework.TestCase;
15
16
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
17
import org.eclipse.equinox.bidi.complexp.StringProcessor;
18
19
/**
20
 * Tests contribution of BiDi processors.
21
 */
22
public class ExtensibilityTest extends TestCase {
23
24
	public void testBaseContributions() {
25
		String[] types = StringProcessor.getKnownTypes();
26
		assertNotNull(types);
27
		assertTrue(types.length > 0);
28
29
		// check one of the types that we know should be there
30
		assertTrue(isTypePresent(types, "regex"));
31
32
		IComplExpProcessor processor = StringProcessor.getProcessor("regex");
33
		assertNotNull(processor);
34
	}
35
36
	public void testOtherContributions() {
37
		String[] types = StringProcessor.getKnownTypes();
38
		assertNotNull(types);
39
		assertTrue(types.length > 0);
40
41
		// check the type added by the test bundle
42
		assertTrue(isTypePresent(types, "test"));
43
44
		IComplExpProcessor processor = StringProcessor.getProcessor("test");
45
		assertNotNull(processor);
46
	}
47
48
	private boolean isTypePresent(String[] types, String type) {
49
		for (int i = 0; i < types.length; i++) {
50
			if (type.equalsIgnoreCase(types[i]))
51
				return true;
52
		}
53
		return false;
54
	}
55
}
(-)src/org/eclipse/equinox/bidi/internal/tests/ExtensionsTest.java (-210 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
15
import org.eclipse.equinox.bidi.complexp.StringProcessor;
16
import org.eclipse.equinox.bidi.complexp.IBiDiProcessor;
17
18
/**
19
 * Tests all plug-in extensions
20
 */
21
22
public class ExtensionsTest extends ComplExpTestBase {
23
24
	static int state = IComplExpProcessor.STATE_NOTHING_GOING;
25
26
	private void doTest1(IComplExpProcessor complexp, String label,
27
			String data, String result) {
28
		String full;
29
		full = complexp.leanToFullText(toUT16(data), state);
30
		state = complexp.getFinalState();
31
		assertEquals(label + " data = " + data, result, toPseudo(full));
32
	}
33
34
	private void doTest2(IComplExpProcessor complexp, String label,
35
			String data, String result) {
36
		String full;
37
		full = complexp.leanToFullText(data, state);
38
		state = complexp.getFinalState();
39
		assertEquals(label + " data = " + data, result, toPseudo(full));
40
	}
41
42
	public void testExtensions() {
43
44
		IComplExpProcessor ce;
45
46
		ce = StringProcessor.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
47
		assertNotNull(ce);
48
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
49
		state = IComplExpProcessor.STATE_NOTHING_GOING;
50
		doTest1(ce, "Comma #1", "ab,cd, AB, CD, EFG", "ab,cd, AB@, CD@, EFG");
51
52
		ce = StringProcessor.getProcessor(IBiDiProcessor.EMAIL);
53
		assertNotNull(ce);
54
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
55
		state = IComplExpProcessor.STATE_NOTHING_GOING;
56
		doTest1(ce, "Email #1", "abc.DEF:GHI", "abc.DEF@:GHI");
57
		doTest1(ce, "Email #2", "DEF.GHI \"A.B\":JK ", "DEF@.GHI @\"A.B\"@:JK ");
58
		doTest1(ce, "Email #3", "DEF,GHI (A,B);JK ", "DEF@,GHI @(A,B)@;JK ");
59
		doTest1(ce, "Email #4", "DEF.GHI (A.B :JK ", "DEF@.GHI @(A.B :JK ");
60
61
		ce = StringProcessor.getProcessor(IBiDiProcessor.FILE);
62
		assertNotNull(ce);
63
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
64
		state = IComplExpProcessor.STATE_NOTHING_GOING;
65
		doTest1(ce, "File #1", "c:\\A\\B\\FILE.EXT", "c:\\A@\\B@\\FILE@.EXT");
66
67
		ce = StringProcessor.getProcessor(IBiDiProcessor.JAVA);
68
		assertNotNull(ce);
69
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
70
		state = IComplExpProcessor.STATE_NOTHING_GOING;
71
		doTest1(ce, "Java #1", "A = B + C;", "A@ = B@ + C;");
72
		doTest1(ce, "Java #2", "A   = B + C;", "A@   = B@ + C;");
73
		doTest1(ce, "Java #3", "A = \"B+C\"+D;", "A@ = \"B+C\"@+D;");
74
		doTest1(ce, "Java #4", "A = \"B+C+D;", "A@ = \"B+C+D;");
75
		doTest1(ce, "Java #5", "A = \"B\\\"C\"+D;", "A@ = \"B\\\"C\"@+D;");
76
		doTest1(ce, "Java #6", "A = /*B+C*/ D;", "A@ = /*B+C*/@ D;");
77
		doTest1(ce, "Java #7", "A = /*B+C* D;", "A@ = /*B+C* D;");
78
		doTest1(ce, "Java #8", "X+Y+Z */ B;  ", "X+Y+Z */@ B;  ");
79
		doTest1(ce, "Java #9", "A = //B+C* D;", "A@ = //B+C* D;");
80
		doTest1(ce, "Java #10", "A = //B+C`|D+E;", "A@ = //B+C`|D@+E;");
81
82
		ce = StringProcessor.getProcessor(IBiDiProcessor.PROPERTY);
83
		assertNotNull(ce);
84
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
85
		state = IComplExpProcessor.STATE_NOTHING_GOING;
86
		doTest1(ce, "Property #0", "NAME,VAL1,VAL2", "NAME,VAL1,VAL2");
87
		doTest1(ce, "Property #1", "NAME=VAL1,VAL2", "NAME@=VAL1,VAL2");
88
		doTest1(ce, "Property #2", "NAME=VAL1,VAL2=VAL3",
89
				"NAME@=VAL1,VAL2=VAL3");
90
91
		String data;
92
		ce = StringProcessor.getProcessor(IBiDiProcessor.REGEXP);
93
		assertNotNull(ce);
94
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
95
		state = IComplExpProcessor.STATE_NOTHING_GOING;
96
		data = toUT16("ABC(?") + "#" + toUT16("DEF)GHI");
97
		doTest2(ce, "Regex #0.0", data, "A@B@C@(?#DEF)@G@H@I");
98
		data = toUT16("ABC(?") + "#" + toUT16("DEF");
99
		doTest2(ce, "Regex #0.1", data, "A@B@C@(?#DEF");
100
		doTest1(ce, "Regex #0.2", "GHI)JKL", "GHI)@J@K@L");
101
		data = toUT16("ABC(?") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
102
		doTest2(ce, "Regex #1", data, "A@B@C@(?<DEF>@G@H@I");
103
		doTest1(ce, "Regex #2.0", "ABC(?'DEF'GHI", "A@B@C@(?'DEF'@G@H@I");
104
		doTest1(ce, "Regex #2.1", "ABC(?'DEFGHI", "A@B@C@(?'DEFGHI");
105
		data = toUT16("ABC(?(") + "<" + toUT16("DEF") + ">" + toUT16(")GHI");
106
		doTest2(ce, "Regex #3", data, "A@B@C@(?(<DEF>)@G@H@I");
107
		doTest1(ce, "Regex #4", "ABC(?('DEF')GHI", "A@B@C@(?('DEF')@G@H@I");
108
		doTest1(ce, "Regex #5", "ABC(?(DEF)GHI", "A@B@C@(?(DEF)@G@H@I");
109
		data = toUT16("ABC(?") + "&" + toUT16("DEF)GHI");
110
		doTest2(ce, "Regex #6", data, "A@B@C@(?&DEF)@G@H@I");
111
		data = toUT16("ABC(?") + "P<" + toUT16("DEF") + ">" + toUT16("GHI");
112
		doTest2(ce, "Regex #7", data, "A@B@C(?p<DEF>@G@H@I");
113
		data = toUT16("ABC\\k") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
114
		doTest2(ce, "Regex #8", data, "A@B@C\\k<DEF>@G@H@I");
115
		doTest1(ce, "Regex #9", "ABC\\k'DEF'GHI", "A@B@C\\k'DEF'@G@H@I");
116
		doTest1(ce, "Regex #10", "ABC\\k{DEF}GHI", "A@B@C\\k{DEF}@G@H@I");
117
		data = toUT16("ABC(?") + "P=" + toUT16("DEF)GHI");
118
		doTest2(ce, "Regex #11", data, "A@B@C(?p=DEF)@G@H@I");
119
		doTest1(ce, "Regex #12", "ABC\\g{DEF}GHI", "A@B@C\\g{DEF}@G@H@I");
120
		data = toUT16("ABC\\g") + "<" + toUT16("DEF") + ">" + toUT16("GHI");
121
		doTest2(ce, "Regex #13", data, "A@B@C\\g<DEF>@G@H@I");
122
		doTest1(ce, "Regex #14", "ABC\\g'DEF'GHI", "A@B@C\\g'DEF'@G@H@I");
123
		data = toUT16("ABC(?(") + "R&" + toUT16("DEF)GHI");
124
		doTest2(ce, "Regex #15", data, "A@B@C(?(r&DEF)@G@H@I");
125
		data = toUT16("ABC") + "\\Q" + toUT16("DEF") + "\\E" + toUT16("GHI");
126
		doTest2(ce, "Regex #16.0", data, "A@B@C\\qDEF\\eG@H@I");
127
		data = toUT16("ABC") + "\\Q" + toUT16("DEF");
128
		doTest2(ce, "Regex #16.1", data, "A@B@C\\qDEF");
129
		data = toUT16("GHI") + "\\E" + toUT16("JKL");
130
		doTest2(ce, "Regex #16.2", data, "GHI\\eJ@K@L");
131
		doTest1(ce, "Regex #17.0", "abc[d-h]ijk", "abc[d-h]ijk");
132
		doTest1(ce, "Regex #17.1", "aBc[d-H]iJk", "aBc[d-H]iJk");
133
		doTest1(ce, "Regex #17.2", "aB*[!-H]iJ2", "aB*[!-@H]iJ@2");
134
		doTest1(ce, "Regex #17.3", "aB*[1-2]J3", "aB*[@1-2]J@3");
135
		doTest1(ce, "Regex #17.4", "aB*[5-6]J3", "aB*[@5-@6]@J@3");
136
		doTest1(ce, "Regex #17.5", "a*[5-6]J3", "a*[5-@6]@J@3");
137
		doTest1(ce, "Regex #17.6", "aB*123", "aB*@123");
138
		doTest1(ce, "Regex #17.7", "aB*567", "aB*@567");
139
140
		ce = StringProcessor.getProcessor(IBiDiProcessor.SQL);
141
		assertNotNull(ce);
142
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
143
		state = IComplExpProcessor.STATE_NOTHING_GOING;
144
		doTest1(ce, "SQL #0", "abc GHI", "abc GHI");
145
		doTest1(ce, "SQL #1", "abc DEF   GHI", "abc DEF@   GHI");
146
		doTest1(ce, "SQL #2", "ABC, DEF,   GHI", "ABC@, DEF@,   GHI");
147
		doTest1(ce, "SQL #3", "ABC'DEF GHI' JKL,MN", "ABC@'DEF GHI'@ JKL@,MN");
148
		doTest1(ce, "SQL #4.0", "ABC'DEF GHI JKL", "ABC@'DEF GHI JKL");
149
		doTest1(ce, "SQL #4.1", "MNO PQ' RS,TUV", "MNO PQ'@ RS@,TUV");
150
		doTest1(ce, "SQL #5", "ABC\"DEF GHI\" JKL,MN",
151
				"ABC@\"DEF GHI\"@ JKL@,MN");
152
		doTest1(ce, "SQL #6", "ABC\"DEF GHI JKL", "ABC@\"DEF GHI JKL");
153
		doTest1(ce, "SQL #7", "ABC/*DEF GHI*/ JKL,MN",
154
				"ABC@/*DEF GHI@*/ JKL@,MN");
155
		doTest1(ce, "SQL #8.0", "ABC/*DEF GHI JKL", "ABC@/*DEF GHI JKL");
156
		doTest1(ce, "SQL #8.1", "MNO PQ*/RS,TUV", "MNO PQ@*/RS@,TUV");
157
		doTest1(ce, "SQL #9", "ABC--DEF GHI JKL", "ABC@--DEF GHI JKL");
158
		doTest1(ce, "SQL #10", "ABC--DEF--GHI,JKL", "ABC@--DEF--GHI,JKL");
159
		doTest1(ce, "SQL #11", "ABC'DEF '' G I' JKL,MN",
160
				"ABC@'DEF '' G I'@ JKL@,MN");
161
		doTest1(ce, "SQL #12", "ABC\"DEF \"\" G I\" JKL,MN",
162
				"ABC@\"DEF \"\" G I\"@ JKL@,MN");
163
		doTest1(ce, "SQL #13", "ABC--DEF GHI`|JKL MN", "ABC@--DEF GHI`|JKL@ MN");
164
165
		ce = StringProcessor.getProcessor(IBiDiProcessor.SYSTEM_USER);
166
		assertNotNull(ce);
167
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
168
		state = IComplExpProcessor.STATE_NOTHING_GOING;
169
		doTest1(ce, "System #1", "HOST(JACK)", "HOST@(JACK)");
170
171
		ce = StringProcessor.getProcessor(IBiDiProcessor.UNDERSCORE);
172
		assertNotNull(ce);
173
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
174
		state = IComplExpProcessor.STATE_NOTHING_GOING;
175
		doTest1(ce, "Underscore #1", "A_B_C_d_e_F_G", "A@_B@_C_d_e_F@_G");
176
177
		ce = StringProcessor.getProcessor(IBiDiProcessor.URL);
178
		assertNotNull(ce);
179
		state = IComplExpProcessor.STATE_NOTHING_GOING;
180
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
181
		doTest1(ce, "URL #1", "WWW.DOMAIN.COM/DIR1/DIR2/dir3/DIR4",
182
				"WWW@.DOMAIN@.COM@/DIR1@/DIR2/dir3/DIR4");
183
184
		ce = StringProcessor.getProcessor(IBiDiProcessor.XPATH);
185
		assertNotNull(ce);
186
		ce.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
187
		state = IComplExpProcessor.STATE_NOTHING_GOING;
188
		doTest1(ce, "Xpath #1", "abc(DEF)GHI", "abc(DEF@)GHI");
189
		doTest1(ce, "Xpath #2", "DEF.GHI \"A.B\":JK ", "DEF@.GHI@ \"A.B\"@:JK ");
190
		doTest1(ce, "Xpath #3", "DEF!GHI 'A!B'=JK ", "DEF@!GHI@ 'A!B'@=JK ");
191
		doTest1(ce, "Xpath #4", "DEF.GHI 'A.B :JK ", "DEF@.GHI@ 'A.B :JK ");
192
193
		ce = StringProcessor.getProcessor(IBiDiProcessor.EMAIL);
194
		state = IComplExpProcessor.STATE_NOTHING_GOING;
195
		String operators = ce.getOperators();
196
		assertEquals("<>.:,;@", operators);
197
		ce.setOperators("+-*/");
198
		doTest1(ce, "DelimsEsc #1", "abc+DEF-GHI", "abc+DEF@-GHI");
199
		doTest1(ce, "DelimsEsc #2", "DEF-GHI (A*B)/JK ", "DEF@-GHI @(A*B)@/JK ");
200
		doTest1(ce, "DelimsEsc #3", "DEF-GHI (A*B)/JK ", "DEF@-GHI @(A*B)@/JK ");
201
		doTest1(ce, "DelimsEsc #4", "DEF-GHI (A*B\\)*C) /JK ",
202
				"DEF@-GHI @(A*B\\)*C) @/JK ");
203
		doTest1(ce, "DelimsEsc #5", "DEF-GHI (A\\\\\\)*C) /JK ",
204
				"DEF@-GHI @(A\\\\\\)*C) @/JK ");
205
		doTest1(ce, "DelimsEsc #6", "DEF-GHI (A\\\\)*C /JK ",
206
				"DEF@-GHI @(A\\\\)@*C @/JK ");
207
		doTest1(ce, "DelimsEsc #7", "DEF-GHI (A\\)*C /JK ",
208
				"DEF@-GHI @(A\\)*C /JK ");
209
	}
210
}
(-)src/org/eclipse/equinox/bidi/internal/tests/FullToLeanTest.java (-284 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
15
import org.eclipse.equinox.bidi.complexp.StringProcessor;
16
import org.eclipse.equinox.bidi.complexp.IBiDiProcessor;
17
18
/**
19
 * Tests fullToLean method
20
 */
21
22
public class FullToLeanTest extends ComplExpTestBase {
23
24
	private IComplExpProcessor processor;
25
26
	protected void setUp() throws Exception {
27
		super.setUp();
28
		processor = StringProcessor
29
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
30
	}
31
32
	static int[] getpos(IComplExpProcessor complexp, boolean leanToFull) {
33
		int[] pos = new int[5];
34
35
		if (leanToFull) {
36
			pos[0] = complexp.leanToFullPos(0);
37
			pos[1] = complexp.leanToFullPos(4);
38
			pos[2] = complexp.leanToFullPos(7);
39
			pos[3] = complexp.leanToFullPos(10);
40
			pos[4] = complexp.leanToFullPos(30);
41
		} else {
42
			pos[0] = complexp.fullToLeanPos(0);
43
			pos[1] = complexp.fullToLeanPos(4);
44
			pos[2] = complexp.fullToLeanPos(7);
45
			pos[3] = complexp.fullToLeanPos(10);
46
			pos[4] = complexp.fullToLeanPos(30);
47
		}
48
		return pos;
49
	}
50
51
	private void doTest1(String msg, String data, String leanLTR,
52
			String fullLTR, int[] l2fPosLTR, int[] f2lPosLTR, String leanRTL,
53
			String fullRTL, int[] l2fPosRTL, int[] f2lPosRTL) {
54
		String text, full, lean, label;
55
		int[] pos;
56
57
		text = toUT16(data);
58
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
59
		lean = processor.fullToLeanText(text);
60
		assertEquals(msg + "LTR lean", leanLTR, toPseudo(lean));
61
		full = processor.leanToFullText(lean);
62
		assertEquals(msg + "LTR full", fullLTR, toPseudo(full));
63
		pos = getpos(processor, true);
64
		label = msg + "leanToFullPos() LTR, expected="
65
				+ array_display(l2fPosLTR) + " result=" + array_display(pos);
66
		assertTrue(label, arrays_equal(l2fPosLTR, pos));
67
		pos = getpos(processor, false);
68
		label = msg + "fullToLeanPos() LTR, expected="
69
				+ array_display(f2lPosLTR) + " result=" + array_display(pos);
70
		assertTrue(label, arrays_equal(f2lPosLTR, pos));
71
		processor.assumeOrientation(IComplExpProcessor.ORIENT_RTL);
72
		lean = processor.fullToLeanText(text);
73
		assertEquals(msg + "RTL lean", leanRTL, toPseudo(lean));
74
		full = processor.leanToFullText(lean);
75
		assertEquals(msg + "RTL full", fullRTL, toPseudo(full));
76
		pos = getpos(processor, true);
77
		label = msg + "leanToFullPos() RTL, expected="
78
				+ array_display(l2fPosRTL) + " result=" + array_display(pos);
79
		assertTrue(label, arrays_equal(l2fPosRTL, pos));
80
		pos = getpos(processor, false);
81
		label = msg + "fullToLeanPos() RTL, expected="
82
				+ array_display(f2lPosRTL) + " result=" + array_display(pos);
83
		assertTrue(label, arrays_equal(f2lPosRTL, pos));
84
	}
85
86
	private void doTest2(String msg) {
87
		String text, data, full, lean, model;
88
		int state, state2, state3;
89
90
		processor = StringProcessor.getProcessor(IBiDiProcessor.SQL);
91
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
92
		data = "update \"AB_CDE\" set \"COL1\"@='01', \"COL2\"@='02' /* GH IJK";
93
		text = toUT16(data);
94
		lean = processor.fullToLeanText(text);
95
		state = processor.getFinalState();
96
		model = "update \"AB_CDE\" set \"COL1\"='01', \"COL2\"='02' /* GH IJK";
97
		assertEquals(msg + "LTR lean", model, toPseudo(lean));
98
		full = processor.leanToFullText(lean);
99
		assertEquals(msg + "LTR full", data, toPseudo(full));
100
		assertEquals(msg + "state from leanToFullText", processor
101
				.getFinalState(), state);
102
		data = "THIS IS A COMMENT LINE";
103
		text = toUT16(data);
104
		lean = processor.fullToLeanText(text, state);
105
		state2 = processor.getFinalState();
106
		model = "THIS IS A COMMENT LINE";
107
		assertEquals(msg + "LTR lean2", model, toPseudo(lean));
108
		full = processor.leanToFullText(lean, state);
109
		assertEquals(msg + "LTR full2", data, toPseudo(full));
110
		assertEquals(msg + "state from leanToFullText2", processor
111
				.getFinalState(), state2);
112
		data = "SOME MORE */ where \"COL3\"@=123";
113
		text = toUT16(data);
114
		lean = processor.fullToLeanText(text, state2);
115
		state3 = processor.getFinalState();
116
		model = "SOME MORE */ where \"COL3\"=123";
117
		assertEquals(msg + "LTR lean3", model, toPseudo(lean));
118
		full = processor.leanToFullText(lean, state2);
119
		assertEquals(msg + "LTR full3", data, toPseudo(full));
120
		assertEquals(msg + "state from leanToFullText3", processor
121
				.getFinalState(), state3);
122
	}
123
124
	public void testFullToLean() {
125
126
		doTest1("testFullToLean #1 - ", "", "", "",
127
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 0, 0, 0, 0 }, "",
128
				"", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 0, 0, 0, 0 });
129
		doTest1("testFullToLean #01 - ", "1.abc", "1.abc", "1.abc", new int[] {
130
				0, 4, 7, 10, 30 }, new int[] { 0, 4, 5, 5, 5 }, "1.abc",
131
				">@1.abc@^", new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2,
132
						5, 5, 5 });
133
		doTest1("testFullToLean #02 - ", "2.abc,def", "2.abc,def", "2.abc,def",
134
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 7, 9, 9 },
135
				"2.abc,def", ">@2.abc,def@^", new int[] { 2, 6, 9, 12, 32 },
136
				new int[] { 0, 2, 5, 8, 9 });
137
		doTest1("testFullToLean #03 - ", "@a.3.bc,def", "a.3.bc,def",
138
				"a.3.bc,def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
139
						7, 10, 10 }, "a.3.bc,def", ">@a.3.bc,def@^", new int[] {
140
						2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 10 });
141
		doTest1("testFullToLean #04 - ", "@@a.4.bc,def", "a.4.bc,def",
142
				"a.4.bc,def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
143
						7, 10, 10 }, "a.4.bc,def", ">@a.4.bc,def@^", new int[] {
144
						2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 10 });
145
		doTest1("testFullToLean #05 - ", "@5.abc,def", "5.abc,def",
146
				"5.abc,def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
147
						7, 9, 9 }, "5.abc,def", ">@5.abc,def@^", new int[] { 2,
148
						6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 9 });
149
		doTest1("testFullToLean #06 - ", "@@6.abc,def", "6.abc,def",
150
				"6.abc,def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
151
						7, 9, 9 }, "6.abc,def", ">@6.abc,def@^", new int[] { 2,
152
						6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 9 });
153
		doTest1("testFullToLean #07 - ", "7abc,@def", "7abc,@def", "7abc,@def",
154
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 7, 9, 9 },
155
				"7abc,@def", ">@7abc,@def@^", new int[] { 2, 6, 9, 12, 32 },
156
				new int[] { 0, 2, 5, 8, 9 });
157
		doTest1("testFullToLean #08 - ", "8abc,@@def", "8abc,@def",
158
				"8abc,@def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
159
						7, 9, 9 }, "8abc,@def", ">@8abc,@def@^", new int[] { 2,
160
						6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 9 });
161
		doTest1("testFullToLean #09 - ", "9abc,def@", "9abc,def", "9abc,def",
162
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 7, 8, 8 },
163
				"9abc,def", ">@9abc,def@^", new int[] { 2, 6, 9, 12, 32 },
164
				new int[] { 0, 2, 5, 8, 8 });
165
		doTest1("testFullToLean #10 - ", "10abc,def@@", "10abc,def",
166
				"10abc,def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
167
						7, 9, 9 }, "10abc,def", ">@10abc,def@^", new int[] { 2,
168
						6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 9 });
169
		doTest1("testFullToLean #11 - ", "@a.11.bc,@def@", "a.11.bc,@def",
170
				"a.11.bc,@def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0,
171
						4, 7, 10, 12 }, "a.11.bc,@def", ">@a.11.bc,@def@^",
172
				new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 12 });
173
		doTest1("testFullToLean #12 - ", "@@a.12.bc,@@def@@", "a.12.bc,@def",
174
				"a.12.bc,@def", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0,
175
						4, 7, 10, 12 }, "a.12.bc,@def", ">@a.12.bc,@def@^",
176
				new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 12 });
177
		doTest1("testFullToLean #13 - ", "13ABC", "13ABC", "13ABC", new int[] {
178
				0, 4, 7, 10, 30 }, new int[] { 0, 4, 5, 5, 5 }, "13ABC",
179
				">@13ABC@^", new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2,
180
						5, 5, 5 });
181
		doTest1("testFullToLean #14 - ", "14ABC,DE", "14ABC,DE", "14ABC@,DE",
182
				new int[] { 0, 4, 8, 11, 31 }, new int[] { 0, 4, 6, 8, 8 },
183
				"14ABC,DE", ">@14ABC@,DE@^", new int[] { 2, 6, 10, 13, 33 },
184
				new int[] { 0, 2, 5, 7, 8 });
185
		doTest1("testFullToLean #15 - ", "15ABC@,DE", "15ABC,DE", "15ABC@,DE",
186
				new int[] { 0, 4, 8, 11, 31 }, new int[] { 0, 4, 6, 8, 8 },
187
				"15ABC,DE", ">@15ABC@,DE@^", new int[] { 2, 6, 10, 13, 33 },
188
				new int[] { 0, 2, 5, 7, 8 });
189
		doTest1("testFullToLean #16 - ", "16ABC@@,DE", "16ABC,DE", "16ABC@,DE",
190
				new int[] { 0, 4, 8, 11, 31 }, new int[] { 0, 4, 6, 8, 8 },
191
				"16ABC,DE", ">@16ABC@,DE@^", new int[] { 2, 6, 10, 13, 33 },
192
				new int[] { 0, 2, 5, 7, 8 });
193
		doTest1("testFullToLean #17 - ", "17ABC,@@DE", "17ABC,@DE",
194
				"17ABC,@DE", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
195
						7, 9, 9 }, "17ABC,@DE", ">@17ABC,@DE@^", new int[] { 2,
196
						6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 9 });
197
		doTest1("testFullToLean #18 - ", "18ABC,DE,FGH", "18ABC,DE,FGH",
198
				"18ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
199
						4, 6, 8, 12 }, "18ABC,DE,FGH", ">@18ABC@,DE@,FGH@^",
200
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
201
		doTest1("testFullToLean #19 - ", "19ABC@,DE@,FGH", "19ABC,DE,FGH",
202
				"19ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
203
						4, 6, 8, 12 }, "19ABC,DE,FGH", ">@19ABC@,DE@,FGH@^",
204
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
205
		doTest1("testFullToLean #20 - ", "20ABC,@DE,@FGH", "20ABC,@DE,@FGH",
206
				"20ABC,@DE,@FGH", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0,
207
						4, 7, 10, 14 }, "20ABC,@DE,@FGH", ">@20ABC,@DE,@FGH@^",
208
				new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 14 });
209
		doTest1("testFullToLean #21 - ", "21ABC@@,DE@@,FGH", "21ABC,DE,FGH",
210
				"21ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
211
						4, 6, 8, 12 }, "21ABC,DE,FGH", ">@21ABC@,DE@,FGH@^",
212
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
213
		doTest1("testFullToLean #22 - ", "22ABC,@@DE,@@FGH", "22ABC,@DE,@FGH",
214
				"22ABC,@DE,@FGH", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0,
215
						4, 7, 10, 14 }, "22ABC,@DE,@FGH", ">@22ABC,@DE,@FGH@^",
216
				new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 14 });
217
		doTest1("testFullToLean #23 - ", ">@23abc@^", "23abc", "23abc",
218
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 5, 5, 5 },
219
				"23abc", ">@23abc@^", new int[] { 2, 6, 9, 12, 32 }, new int[] {
220
						0, 2, 5, 5, 5 });
221
		doTest1("testFullToLean #24 - ", "24abc@^", "24abc", "24abc",
222
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 5, 5, 5 },
223
				"24abc", ">@24abc@^", new int[] { 2, 6, 9, 12, 32 }, new int[] {
224
						0, 2, 5, 5, 5 });
225
		doTest1("testFullToLean #25 - ", ">@25abc", "25abc", "25abc",
226
				new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 5, 5, 5 },
227
				"25abc", ">@25abc@^", new int[] { 2, 6, 9, 12, 32 }, new int[] {
228
						0, 2, 5, 5, 5 });
229
		doTest1("testFullToLean #26 - ", "26AB,CD@EF,GHI", "26AB,CD@EF,GHI",
230
				"26AB@,CD@EF@,GHI", new int[] { 0, 5, 8, 12, 32 }, new int[] {
231
						0, 4, 6, 9, 14 }, "26AB,CD@EF,GHI",
232
				">@26AB@,CD@EF@,GHI@^", new int[] { 2, 7, 10, 14, 34 },
233
				new int[] { 0, 2, 4, 7, 14 });
234
		doTest1("testFullToLean #27 - ", "27AB,CD@123ef,GHI",
235
				"27AB,CD@123ef,GHI", "27AB@,CD@123ef,GHI", new int[] { 0, 5, 8,
236
						11, 31 }, new int[] { 0, 4, 6, 9, 17 },
237
				"27AB,CD@123ef,GHI", ">@27AB@,CD@123ef,GHI@^", new int[] { 2,
238
						7, 10, 13, 33 }, new int[] { 0, 2, 4, 7, 17 });
239
		doTest1("testFullToLean #28 - ", ">28ABC@,DE@,FGH^", "28ABC,DE,FGH",
240
				"28ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
241
						4, 6, 8, 12 }, "28ABC,DE,FGH", ">@28ABC@,DE@,FGH@^",
242
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
243
		doTest1("testFullToLean #29 - ", ">>29ABC@,DE@,FGH^^", "29ABC,DE,FGH",
244
				"29ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
245
						4, 6, 8, 12 }, "29ABC,DE,FGH", ">@29ABC@,DE@,FGH@^",
246
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
247
		doTest1("testFullToLean #30 - ", ">30AB>C^@,DE@,FGH^",
248
				"30AB>C^,DE,FGH", "30AB>C^@,DE@,FGH", new int[] { 0, 4, 8, 12,
249
						32 }, new int[] { 0, 4, 7, 9, 14 }, "30AB>C^,DE,FGH",
250
				">@30AB>C^@,DE@,FGH@^", new int[] { 2, 6, 10, 14, 34 },
251
				new int[] { 0, 2, 5, 7, 14 });
252
		doTest1("testFullToLean #31 - ", ">31AB>C@,DE@,FGH^^", "31AB>C,DE,FGH",
253
				"31AB>C@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] {
254
						0, 4, 6, 9, 13 }, "31AB>C,DE,FGH",
255
				">@31AB>C@,DE@,FGH@^", new int[] { 2, 6, 10, 14, 34 },
256
				new int[] { 0, 2, 5, 7, 13 });
257
		doTest1("testFullToLean #32 - ", ">@32ABC@,DE@,FGH@^", "32ABC,DE,FGH",
258
				"32ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
259
						4, 6, 8, 12 }, "32ABC,DE,FGH", ">@32ABC@,DE@,FGH@^",
260
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
261
		doTest1("testFullToLean #33 - ", "@33ABC@,DE@,FGH@^", "33ABC,DE,FGH",
262
				"33ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
263
						4, 6, 8, 12 }, "33ABC,DE,FGH", ">@33ABC@,DE@,FGH@^",
264
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
265
		doTest1("testFullToLean #34 - ", ">@34ABC@,DE@,FGH@", "34ABC,DE,FGH",
266
				"34ABC@,DE@,FGH", new int[] { 0, 4, 8, 12, 32 }, new int[] { 0,
267
						4, 6, 8, 12 }, "34ABC,DE,FGH", ">@34ABC@,DE@,FGH@^",
268
				new int[] { 2, 6, 10, 14, 34 }, new int[] { 0, 2, 5, 7, 12 });
269
		doTest1("testFullToLean #35 - ", "35ABC@@DE@@@GH@", "35ABC@DE@GH",
270
				"35ABC@DE@GH", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4,
271
						7, 10, 11 }, "35ABC@DE@GH", ">@35ABC@DE@GH@^",
272
				new int[] { 2, 6, 9, 12, 32 }, new int[] { 0, 2, 5, 8, 11 });
273
		doTest1("testFullToLean #36 - ", "36ABC@@DE@@@@@@", "36ABC@DE",
274
				"36ABC@DE", new int[] { 0, 4, 7, 10, 30 }, new int[] { 0, 4, 7,
275
						8, 8 }, "36ABC@DE", ">@36ABC@DE@^", new int[] { 2, 6,
276
						9, 12, 32 }, new int[] { 0, 2, 5, 8, 8 });
277
		doTest1("testFullToLean #37 - ", ">>>@@@@@^^^", "", "", new int[] { 0,
278
				4, 7, 10, 30 }, new int[] { 0, 0, 0, 0, 0 }, "", "", new int[] {
279
				0, 4, 7, 10, 30 }, new int[] { 0, 0, 0, 0, 0 });
280
281
		// test fullToLeanText with initial state
282
		doTest2("testFullToLean #38 - ");
283
	}
284
}
(-)src/org/eclipse/equinox/bidi/internal/tests/MethodsTest.java (-438 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
12
package org.eclipse.equinox.bidi.internal.tests;
13
14
import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
15
import org.eclipse.equinox.bidi.complexp.IBiDiProcessor;
16
import org.eclipse.equinox.bidi.complexp.StringProcessor;
17
import org.eclipse.equinox.bidi.complexp.ComplExpUtil;
18
19
/**
20
 * Tests most public methods of ComplExpBasic
21
 */
22
23
public class MethodsTest extends ComplExpTestBase {
24
25
	final static int LTR = IComplExpProcessor.DIRECTION_LTR;
26
	final static int RTL = IComplExpProcessor.DIRECTION_RTL;
27
28
	IComplExpProcessor processor;
29
30
	private void doTestTools() {
31
32
		// This method tests utility methods used by the JUnits
33
		String data = "56789ABCDEFGHIJKLMNOPQRSTUVWXYZ~#@&><^|`";
34
		String text = toUT16(data);
35
		String dat2 = toPseudo(text);
36
		assertEquals(data, dat2);
37
38
		text = toPseudo(data);
39
		assertEquals("56789abcdefghijklmnopqrstuvwxyz~#@&><^|`", text);
40
41
		int[] arA = new int[] { 1, 2 };
42
		int[] arB = new int[] { 3, 4, 5 };
43
		assertFalse(arrays_equal(arA, arB));
44
45
		assertTrue(arrays_equal(arA, arA));
46
47
		arB = new int[] { 3, 4 };
48
		assertFalse(arrays_equal(arA, arB));
49
50
		int[][] ar2A = new int[][] { { 1 }, { 1, 2 }, { 1, 2, 3 } };
51
		int[][] ar2B = new int[][] { { 1 }, { 1, 2 } };
52
		assertTrue(arrays2_equal(ar2A, ar2A));
53
54
		assertFalse(arrays2_equal(ar2A, ar2B));
55
56
		ar2B = new int[][] { { 1 }, { 1, 2 }, { 1, 2, 3, 4 } };
57
		assertFalse(arrays2_equal(ar2A, ar2B));
58
59
		ar2B = new int[][] { { 1 }, { 1, 2 }, { 1, 2, 4 } };
60
		assertFalse(arrays2_equal(ar2A, ar2B));
61
62
		text = array_display(null);
63
		assertEquals("null", text);
64
65
		text = array2_display(null);
66
		assertEquals("null", text);
67
	}
68
69
	private void doTestState() {
70
		String data, lean, full, model;
71
		int state;
72
73
		data = "A=B+C;/* D=E+F;";
74
		lean = toUT16(data);
75
		full = processor.leanToFullText(lean);
76
		model = "A@=B@+C@;/* D=E+F;";
77
		assertEquals("full1", model, toPseudo(full));
78
		state = processor.getFinalState();
79
		data = "A=B+C; D=E+F;";
80
		lean = toUT16(data);
81
		full = processor.leanToFullText(lean, state);
82
		model = "A=B+C; D=E+F;";
83
		assertEquals("full2", model, toPseudo(full));
84
		state = processor.getFinalState();
85
		data = "A=B+C;*/ D=E+F;";
86
		lean = toUT16(data);
87
		full = processor.leanToFullText(lean, state);
88
		model = "A=B+C;*/@ D@=E@+F;";
89
		assertEquals("full3", model, toPseudo(full));
90
	}
91
92
	private void doTestOrientation() {
93
		int orient;
94
95
		processor = StringProcessor
96
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
97
		orient = processor.recallOrientation();
98
		// TBD: the following test cannot succeed with the current
99
		// implementation.
100
		// it will need allocating separate data for each processor use.
101
		// assertEquals("orient #1", IComplExpProcessor.ORIENT_LTR, orient);
102
103
		processor.assumeOrientation(IComplExpProcessor.ORIENT_IGNORE);
104
		orient = processor.recallOrientation();
105
		assertEquals("orient #2", IComplExpProcessor.ORIENT_IGNORE, orient);
106
107
		processor.assumeOrientation(IComplExpProcessor.ORIENT_CONTEXTUAL_RTL);
108
		orient = processor.recallOrientation();
109
		processor.leanToFullText("--!**");
110
		assertEquals("orient #3", IComplExpProcessor.ORIENT_CONTEXTUAL_RTL,
111
				orient);
112
113
		processor.assumeOrientation(9999);
114
		orient = processor.recallOrientation();
115
		processor.leanToFullText("--!**");
116
		assertEquals("orient #4", IComplExpProcessor.ORIENT_UNKNOWN, orient);
117
	}
118
119
	private void doTestOrient(String label, String data, String resLTR,
120
			String resRTL, String resCon) {
121
		String full, lean;
122
123
		lean = toUT16(data);
124
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
125
		full = processor.leanToFullText(lean);
126
		assertEquals(label + "LTR full", resLTR, toPseudo(full));
127
		processor.assumeOrientation(IComplExpProcessor.ORIENT_RTL);
128
		full = processor.leanToFullText(lean);
129
		assertEquals("label + RTL full", resRTL, toPseudo(full));
130
		processor.assumeOrientation(IComplExpProcessor.ORIENT_CONTEXTUAL_RTL);
131
		full = processor.leanToFullText(lean);
132
		assertEquals(label + "CON full", resCon, toPseudo(full));
133
	}
134
135
	private void doTestScripts() {
136
		boolean flag;
137
		flag = processor.handlesArabicScript();
138
		assertTrue("Handles Arabic 1", flag);
139
		flag = processor.handlesHebrewScript();
140
		assertTrue("Handles Hebrew 1", flag);
141
142
		processor.selectBidiScript(false, false);
143
		flag = processor.handlesArabicScript();
144
		assertFalse("Handles Arabic 2", flag);
145
		flag = processor.handlesHebrewScript();
146
		assertFalse("Handles Hebrew 2", flag);
147
		doTestOrient("Scripts #1 ", "BCD,EF", "BCD,EF", ">@BCD,EF@^", "@BCD,EF");
148
		processor.selectBidiScript(true, false);
149
		flag = processor.handlesArabicScript();
150
		assertTrue("Handles Arabic 3", flag);
151
		flag = processor.handlesHebrewScript();
152
		assertFalse("Handles Hebrew 3", flag);
153
		doTestOrient("Scripts #2 ", "d,EF", "d,EF", ">@d,EF@^", "d,EF");
154
		doTestOrient("Scripts #3 ", "#,eF", "#,eF", ">@#,eF@^", "@#,eF");
155
		doTestOrient("Scripts #4 ", "#,12", "#@,12", ">@#@,12@^", "@#@,12");
156
		doTestOrient("Scripts #5 ", "#,##", "#@,##", ">@#@,##@^", "@#@,##");
157
		doTestOrient("Scripts #6 ", "#,89", "#@,89", ">@#@,89@^", "@#@,89");
158
		doTestOrient("Scripts #7 ", "#,ef", "#,ef", ">@#,ef@^", "@#,ef");
159
		doTestOrient("Scripts #8 ", "#,", "#,", ">@#,@^", "@#,");
160
		doTestOrient("Scripts #9 ", "9,ef", "9,ef", ">@9,ef@^", "9,ef");
161
		doTestOrient("Scripts #10 ", "9,##", "9@,##", ">@9@,##@^", "9@,##");
162
		doTestOrient("Scripts #11 ", "7,89", "7@,89", ">@7@,89@^", "7@,89");
163
		doTestOrient("Scripts #12 ", "7,EF", "7,EF", ">@7,EF@^", "@7,EF");
164
		doTestOrient("Scripts #13 ", "BCD,EF", "BCD,EF", ">@BCD,EF@^",
165
				"@BCD,EF");
166
167
		processor.selectBidiScript(false, true);
168
		flag = processor.handlesArabicScript();
169
		assertFalse("Handles Arabic 4", flag);
170
		flag = processor.handlesHebrewScript();
171
		assertTrue("Handles Hebrew 4", flag);
172
		doTestOrient("Scripts #14 ", "BCd,EF", "BCd,EF", ">@BCd,EF@^",
173
				"@BCd,EF");
174
		doTestOrient("Scripts #15 ", "BCD,eF", "BCD,eF", ">@BCD,eF@^",
175
				"@BCD,eF");
176
		doTestOrient("Scripts #16 ", "BCD,EF", "BCD@,EF", ">@BCD@,EF@^",
177
				"@BCD@,EF");
178
		doTestOrient("Scripts #17 ", "BCD,12", "BCD@,12", ">@BCD@,12@^",
179
				"@BCD@,12");
180
		doTestOrient("Scripts #18 ", "BCD,", "BCD,", ">@BCD,@^", "@BCD,");
181
182
		processor.selectBidiScript(true, true);
183
		doTestOrient("Scripts #19 ", "123,45|67", "123,45|67", ">@123,45|67@^",
184
				"@123,45|67");
185
		doTestOrient("Scripts #20 ", "5,e", "5,e", ">@5,e@^", "5,e");
186
		doTestOrient("Scripts #21 ", "5,#", "5@,#", ">@5@,#@^", "5@,#");
187
		doTestOrient("Scripts #22 ", "5,6", "5@,6", ">@5@,6@^", "5@,6");
188
		doTestOrient("Scripts #23 ", "5,D", "5@,D", ">@5@,D@^", "5@,D");
189
		doTestOrient("Scripts #24 ", "5,--", "5,--", ">@5,--@^", "@5,--");
190
	}
191
192
	private void doTestLeanOffsets() {
193
		String lean, data, label;
194
		int state;
195
		int[] offsets;
196
		int[] model;
197
198
		data = "A=B+C;/* D=E+F;";
199
		lean = toUT16(data);
200
		offsets = processor.leanBidiCharOffsets(lean);
201
		model = new int[] { 1, 3, 5 };
202
		label = "leanBidiCharOffsets() #1 expected=" + array_display(model)
203
				+ " result=" + array_display(offsets);
204
		assertTrue(label, arrays_equal(model, offsets));
205
		state = processor.getFinalState();
206
		data = "A=B+C;*/ D=E+F;";
207
		lean = toUT16(data);
208
		offsets = processor.leanBidiCharOffsets(lean, state);
209
		model = new int[] { 8, 10, 12 };
210
		label = "leanBidiCharOffsets() #2 expected=" + array_display(model)
211
				+ " result=" + array_display(offsets);
212
		assertTrue(label, arrays_equal(model, offsets));
213
		offsets = processor.leanBidiCharOffsets();
214
		model = new int[] { 8, 10, 12 };
215
		label = "leanBidiCharOffsets() #3 expected=" + array_display(model)
216
				+ " result=" + array_display(offsets);
217
		assertTrue(label, arrays_equal(model, offsets));
218
	}
219
220
	private void doTestFullOffsets(String label, String data, int[] resLTR,
221
			int[] resRTL, int[] resCon) {
222
		String full, lean, msg;
223
		int[] offsets;
224
225
		lean = toUT16(data);
226
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
227
		full = processor.leanToFullText(lean);
228
		// the following line avoids a compiler warning about full never being
229
		// read
230
		full += "";
231
		offsets = processor.fullBidiCharOffsets();
232
		msg = label + "LTR expected=" + array_display(resLTR) + " result="
233
				+ array_display(offsets);
234
		assertTrue(msg, arrays_equal(resLTR, offsets));
235
		processor.assumeOrientation(IComplExpProcessor.ORIENT_RTL);
236
		full = processor.leanToFullText(lean);
237
		offsets = processor.fullBidiCharOffsets();
238
		msg = label + "RTL expected=" + array_display(resRTL) + " result="
239
				+ array_display(offsets);
240
		assertTrue(msg, arrays_equal(resRTL, offsets));
241
		processor.assumeOrientation(IComplExpProcessor.ORIENT_CONTEXTUAL_LTR);
242
		full = processor.leanToFullText(lean);
243
		offsets = processor.fullBidiCharOffsets();
244
		msg = label + "CON expected=" + array_display(resCon) + " result="
245
				+ array_display(offsets);
246
		assertTrue(msg, arrays_equal(resCon, offsets));
247
	}
248
249
	private void doTestMirrored() {
250
		boolean mirrored;
251
252
		mirrored = ComplExpUtil.isMirroredDefault();
253
		assertFalse("mirrored #1", mirrored);
254
		processor = StringProcessor
255
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
256
		mirrored = processor.isMirrored();
257
		assertFalse("mirrored #2", mirrored);
258
		ComplExpUtil.assumeMirroredDefault(true);
259
		mirrored = ComplExpUtil.isMirroredDefault();
260
		assertTrue("mirrored #3", mirrored);
261
		processor = StringProcessor
262
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
263
		mirrored = processor.isMirrored();
264
		// TBD: the following test cannot succeed with the current
265
		// implementation.
266
		// it will need allocating separate data for each processor use.
267
		// assertTrue("mirrored #4", mirrored);
268
		processor.assumeMirrored(false);
269
		mirrored = processor.isMirrored();
270
		assertFalse("mirrored #5", mirrored);
271
	}
272
273
	private void doTestDirection() {
274
		int[][] dir;
275
		int[][] modir;
276
		String data, lean, full, model, msg;
277
278
		processor = StringProcessor
279
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
280
		dir = processor.getDirection();
281
		modir = new int[][] { { LTR, LTR }, { LTR, LTR } };
282
		msg = "TestDirection #1 expected=" + array2_display(modir) + " result="
283
				+ array2_display(dir);
284
		assertTrue(msg, arrays2_equal(modir, dir));
285
286
		processor.setDirection(RTL);
287
		dir = processor.getDirection();
288
		modir = new int[][] { { RTL, RTL }, { RTL, RTL } };
289
		msg = "TestDirection #2 expected=" + array2_display(modir) + " result="
290
				+ array2_display(dir);
291
		assertTrue(msg, arrays2_equal(modir, dir));
292
293
		processor.setDirection(LTR, RTL);
294
		dir = processor.getDirection();
295
		modir = new int[][] { { LTR, RTL }, { LTR, RTL } };
296
		msg = "TestDirection #3 expected=" + array2_display(modir) + " result="
297
				+ array2_display(dir);
298
		assertTrue(msg, arrays2_equal(modir, dir));
299
300
		processor.setArabicDirection(RTL);
301
		dir = processor.getDirection();
302
		modir = new int[][] { { RTL, RTL }, { LTR, RTL } };
303
		msg = "TestDirection #4 expected=" + array2_display(modir) + " result="
304
				+ array2_display(dir);
305
		assertTrue(msg, arrays2_equal(modir, dir));
306
307
		processor.setArabicDirection(RTL, LTR);
308
		dir = processor.getDirection();
309
		modir = new int[][] { { RTL, LTR }, { LTR, RTL } };
310
		msg = "TestDirection #5 expected=" + array2_display(modir) + " result="
311
				+ array2_display(dir);
312
		assertTrue(msg, arrays2_equal(modir, dir));
313
314
		processor.setHebrewDirection(RTL);
315
		dir = processor.getDirection();
316
		modir = new int[][] { { RTL, LTR }, { RTL, RTL } };
317
		msg = "TestDirection #6 expected=" + array2_display(modir) + " result="
318
				+ array2_display(dir);
319
		assertTrue(msg, arrays2_equal(modir, dir));
320
321
		processor.setHebrewDirection(RTL, LTR);
322
		dir = processor.getDirection();
323
		modir = new int[][] { { RTL, LTR }, { RTL, LTR } };
324
		msg = "TestDirection #7 expected=" + array2_display(modir) + " result="
325
				+ array2_display(dir);
326
		assertTrue(msg, arrays2_equal(modir, dir));
327
328
		processor = StringProcessor.getProcessor(IBiDiProcessor.EMAIL);
329
		processor.assumeMirrored(false);
330
		processor.setArabicDirection(LTR, RTL);
331
		processor.setHebrewDirection(LTR, LTR);
332
		data = "#ABC.#DEF:HOST.com";
333
		lean = toUT16(data);
334
		full = processor.leanToFullText(lean);
335
		model = "#ABC@.#DEF@:HOST.com";
336
		assertEquals("TestDirection #9 full", model, toPseudo(full));
337
338
		data = "ABC.DEF:HOST.com";
339
		lean = toUT16(data);
340
		full = processor.leanToFullText(lean);
341
		model = "ABC@.DEF@:HOST.com";
342
		assertEquals("TestDirection #10 full", model, toPseudo(full));
343
344
		processor.assumeMirrored(true);
345
		data = "#ABC.#DEF:HOST.com";
346
		lean = toUT16(data);
347
		full = processor.leanToFullText(lean);
348
		model = "<&#ABC.#DEF:HOST.com&^";
349
		assertEquals("TestDirection #11 full", model, toPseudo(full));
350
351
		data = "#ABc.#DEF:HOSt.COM";
352
		lean = toUT16(data);
353
		full = processor.leanToFullText(lean);
354
		model = "<&#ABc.#DEF:HOSt.COM&^";
355
		assertEquals("TestDirection #12 full", model, toPseudo(full));
356
357
		data = "#ABc.#DEF:HOSt.";
358
		lean = toUT16(data);
359
		full = processor.leanToFullText(lean);
360
		model = "<&#ABc.#DEF:HOSt.&^";
361
		assertEquals("TestDirection #13 full", model, toPseudo(full));
362
363
		data = "ABC.DEF:HOST.com";
364
		lean = toUT16(data);
365
		full = processor.leanToFullText(lean);
366
		model = "ABC@.DEF@:HOST.com";
367
		assertEquals("TestDirection #14 full", model, toPseudo(full));
368
369
		data = "--.---:----";
370
		lean = toUT16(data);
371
		full = processor.leanToFullText(lean);
372
		model = "--.---:----";
373
		assertEquals("TestDirection #15 full", model, toPseudo(full));
374
375
		data = "ABC.|DEF:HOST.com";
376
		lean = toUT16(data);
377
		full = processor.leanToFullText(lean);
378
		model = "ABC.|DEF@:HOST.com";
379
		assertEquals("TestDirection #16 full", model, toPseudo(full));
380
381
		processor.assumeOrientation(IComplExpProcessor.ORIENT_RTL);
382
		data = "#ABc.|#DEF:HOST.com";
383
		lean = toUT16(data);
384
		full = processor.leanToFullText(lean);
385
		model = "#ABc.|#DEF:HOST.com";
386
		assertEquals("TestDirection #17 full", model, toPseudo(full));
387
	}
388
389
	public void testMethods() {
390
391
		doTestTools();
392
393
		processor = StringProcessor.getProcessor(IBiDiProcessor.JAVA);
394
		doTestState();
395
396
		doTestOrientation();
397
398
		processor = StringProcessor
399
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
400
		doTestOrient("Methods #1 ", "", "", "", "");
401
		doTestOrient("Methods #2 ", "abc", "abc", ">@abc@^", "abc");
402
		doTestOrient("Methods #3 ", "ABC", "ABC", ">@ABC@^", "@ABC");
403
		doTestOrient("Methods #4 ", "bcd,ef", "bcd,ef", ">@bcd,ef@^", "bcd,ef");
404
		doTestOrient("Methods #5 ", "BCD,EF", "BCD@,EF", ">@BCD@,EF@^",
405
				"@BCD@,EF");
406
		doTestOrient("Methods #6 ", "cde,FG", "cde,FG", ">@cde,FG@^", "cde,FG");
407
		doTestOrient("Methods #7 ", "CDE,fg", "CDE,fg", ">@CDE,fg@^", "@CDE,fg");
408
		doTestOrient("Methods #8 ", "12..def,GH", "12..def,GH",
409
				">@12..def,GH@^", "12..def,GH");
410
		doTestOrient("Methods #9 ", "34..DEF,gh", "34..DEF,gh",
411
				">@34..DEF,gh@^", "@34..DEF,gh");
412
413
		doTestScripts();
414
415
		processor = StringProcessor.getProcessor(IBiDiProcessor.JAVA);
416
		doTestLeanOffsets();
417
418
		processor = StringProcessor
419
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
420
		doTestFullOffsets("TestFullOffsets ", "BCD,EF,G", new int[] { 3, 7 },
421
				new int[] { 0, 1, 5, 9, 12, 13 }, new int[] { 0, 4, 8 });
422
423
		doTestMirrored();
424
425
		doTestDirection();
426
427
		processor = StringProcessor
428
				.getProcessor(IBiDiProcessor.COMMA_DELIMITED);
429
		processor.assumeOrientation(IComplExpProcessor.ORIENT_LTR);
430
		processor.setDirection(LTR);
431
		String data = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
432
		String lean = toUT16(data);
433
		String full = processor.leanToFullText(lean);
434
		String model = "A@,B@,C@,D@,E@,F@,G@,H@,I@,J@,K@,L@,M@,N@,O@,P@,Q@,R@,S@,T@,U@,V@,W@,X@,Y@,Z";
435
		assertEquals("many inserts", model, toPseudo(full));
436
437
	}
438
}
(-)src/org/eclipse/equinox/bidi/tests/BiDiTestSuite.java (-34 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
12
package org.eclipse.equinox.bidi.tests;
13
14
import org.eclipse.equinox.bidi.internal.tests.*;
15
16
import junit.framework.Test;
17
import junit.framework.TestSuite;
18
19
public class BiDiTestSuite extends TestSuite {
20
	public static Test suite() {
21
		return new BiDiTestSuite();
22
	}
23
24
	public BiDiTestSuite() {
25
		addTestSuite(ExtensibilityTest.class);
26
		addTestSuite(MethodsTest.class);
27
		// addTestSuite(TestDoNothing.class);
28
		addTestSuite(FullToLeanTest.class);
29
		addTestSuite(ComplExpMathTest.class);
30
		// TBD: TestSubclass
31
		addTestSuite(ExtensionsTest.class);
32
		addTestSuite(ComplExpUtilTest.class);
33
	}
34
}
(-)src/org/eclipse/equinox/bidi/tests/BidiComplexTestSuite.java (+33 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.equinox.bidi.tests;
13
14
import junit.framework.Test;
15
import junit.framework.TestSuite;
16
import org.eclipse.equinox.bidi.internal.tests.*;
17
18
public class BidiComplexTestSuite extends TestSuite {
19
	public static Test suite() {
20
		return new BidiComplexTestSuite();
21
	}
22
23
	public BidiComplexTestSuite() {
24
		addTestSuite(BidiComplexExtensibilityTest.class);
25
		addTestSuite(BidiComplexMethodsTest.class);
26
		addTestSuite(BidiComplexNullProcessorTest.class);
27
		addTestSuite(BidiComplexFullToLeanTest.class);
28
		addTestSuite(BidiComplexExtensionsTest.class);
29
		addTestSuite(BidiComplexMathTest.class);
30
		addTestSuite(BidiComplexSomeMoreTest.class);
31
		addTestSuite(BidiComplexUtilTest.class);
32
	}
33
}

Return to bug 183164