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

Collapse All | Expand All

(-)META-INF/MANIFEST.MF (-1 / +1 lines)
Lines 18-21 Link Here
18
 org.eclipse.osgi.util;version="1.1.0",
18
 org.eclipse.osgi.util;version="1.1.0",
19
 org.osgi.framework;version="1.5.0",
19
 org.osgi.framework;version="1.5.0",
20
 org.osgi.util.tracker;version="1.4.0"
20
 org.osgi.util.tracker;version="1.4.0"
21
Bundle-Activator: org.eclipse.equinox.bidi.internal.BidiComplexActivator
21
Bundle-Activator: org.eclipse.equinox.bidi.internal.STextActivator
(-)plugin.properties (-3 / +3 lines)
Lines 10-18 Link Here
10
###############################################################################
10
###############################################################################
11
pluginName = Bidirectional Text Support
11
pluginName = Bidirectional Text Support
12
providerName = Eclipse.org - Equinox
12
providerName = Eclipse.org - Equinox
13
bidiExpressionPointName = Add new complex expression type
13
bidiExpressionPointName = Add new structured text type
14
bidiExtensionName = Default bi-directional processors
14
bidiExtensionName = Default bidirectional processors
15
sqlProcessorName = Processor for SQL expressions
15
sqlProcessorName = Processor for SQL statements
16
regexProcessorName = Processor for regular expressions
16
regexProcessorName = Processor for regular expressions
17
javaProcessorName = Processor for Java statements
17
javaProcessorName = Processor for Java statements
18
commaProcessorName = Processor for comma-separated lists
18
commaProcessorName = Processor for comma-separated lists
(-)plugin.xml (-13 / +13 lines)
Lines 1-68 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
1
<?xml version="1.0" encoding="UTF-8"?>
2
<?eclipse version="3.2"?>
2
<?eclipse version="3.2"?>
3
<plugin>
3
<plugin>
4
   <extension-point id="bidiTypes" name="%bidiExpressionPointName" schema="schema/BiDiExpressionType.exsd"/>
4
   <extension-point id="bidiTypes" name="%bidiExpressionPointName" schema="schema/STextType.exsd"/>
5
   <extension
5
   <extension
6
         id="bidi"
6
         id="bidi"
7
         name="%bidiExtensionName"
7
         name="%bidiExtensionName"
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.consumable.BidiComplexSql"
11
            class="org.eclipse.equinox.bidi.internal.consumable.STextSql"
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.consumable.BidiComplexRegex"
16
            class="org.eclipse.equinox.bidi.internal.consumable.STextRegex"
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.consumable.BidiComplexJava"
21
            class="org.eclipse.equinox.bidi.internal.consumable.STextJava"
22
            type="java">
22
            type="java">
23
      </typeDescription>
23
      </typeDescription>
24
      <typeDescription
24
      <typeDescription
25
            class="org.eclipse.equinox.bidi.internal.consumable.BidiComplexComma"
25
            class="org.eclipse.equinox.bidi.internal.consumable.STextComma"
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.consumable.BidiComplexEmail"
30
            class="org.eclipse.equinox.bidi.internal.consumable.STextEmail"
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.consumable.BidiComplexFile"
35
            class="org.eclipse.equinox.bidi.internal.consumable.STextFile"
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.consumable.BidiComplexMath"
40
            class="org.eclipse.equinox.bidi.internal.consumable.STextMath"
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.consumable.BidiComplexProperty"
45
            class="org.eclipse.equinox.bidi.internal.consumable.STextProperty"
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.consumable.BidiComplexSystem"
50
            class="org.eclipse.equinox.bidi.internal.consumable.STextSystem"
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.consumable.BidiComplexUnderscore"
55
            class="org.eclipse.equinox.bidi.internal.consumable.STextUnderscore"
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.consumable.BidiComplexURL"
60
            class="org.eclipse.equinox.bidi.internal.consumable.STextURL"
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.consumable.BidiComplexXPath"
65
            class="org.eclipse.equinox.bidi.internal.consumable.STextXPath"
66
            description="%xpathProcessorName"
66
            description="%xpathProcessorName"
67
            type="xpath">
67
            type="xpath">
68
      </typeDescription>
68
      </typeDescription>
(-)schema/BiDiExpressionType.exsd (-146 lines)
Removed Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.equinox.bidi" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.equinox.bidi" id="org.eclipse.equinox.bidi.bidiTypes" name="String types that need special bi-directinal handling"/>
7
      </appInfo>
8
      <documentation>
9
         Use this extension point to describe processing for strings that need special Bi-directional handling, such as file paths, SQL expressions, or Java code.
10
11
      </documentation>
12
   </annotation>
13
14
   <element name="extension">
15
      <annotation>
16
         <appInfo>
17
            <meta.element />
18
         </appInfo>
19
      </annotation>
20
      <complexType>
21
         <sequence>
22
            <element ref="typeDescription" minOccurs="1" maxOccurs="unbounded"/>
23
         </sequence>
24
         <attribute name="point" type="string" use="required">
25
            <annotation>
26
               <documentation>
27
                  
28
               </documentation>
29
            </annotation>
30
         </attribute>
31
         <attribute name="id" type="string" use="required">
32
            <annotation>
33
               <documentation>
34
                  Unique identifier of this extension
35
               </documentation>
36
            </annotation>
37
         </attribute>
38
         <attribute name="name" type="string">
39
            <annotation>
40
               <documentation>
41
                  
42
               </documentation>
43
               <appInfo>
44
                  <meta.attribute translatable="true"/>
45
               </appInfo>
46
            </annotation>
47
         </attribute>
48
      </complexType>
49
   </element>
50
51
   <element name="typeDescription">
52
      <complexType>
53
         <attribute name="type" type="string" use="required">
54
            <annotation>
55
               <documentation>
56
                  Type of the expression that this processor will work on.
57
               </documentation>
58
            </annotation>
59
         </attribute>
60
         <attribute name="class" type="string">
61
            <annotation>
62
               <documentation>
63
                  The processor that provides specialized bi-directional handling for this type of strings.
64
               </documentation>
65
               <appInfo>
66
                  <meta.attribute kind="java" basedOn=":org.eclipse.equinox.bidi.custom.IBidiComplexProcessor"/>
67
               </appInfo>
68
            </annotation>
69
         </attribute>
70
         <attribute name="description" type="string">
71
            <annotation>
72
               <documentation>
73
                  The description of the string type.
74
               </documentation>
75
               <appInfo>
76
                  <meta.attribute translatable="true"/>
77
               </appInfo>
78
            </annotation>
79
         </attribute>
80
      </complexType>
81
   </element>
82
83
   <annotation>
84
      <appInfo>
85
         <meta.section type="since"/>
86
      </appInfo>
87
      <documentation>
88
         1.0
89
      </documentation>
90
   </annotation>
91
92
   <annotation>
93
      <appInfo>
94
         <meta.section type="examples"/>
95
      </appInfo>
96
      <documentation>
97
         A processor for the complex expressions that support &quot;minus&quot; delimiters can be described as:
98
99
&lt;pre&gt;
100
public class ComplExpSepMinus extends ComplExpBasic
101
{
102
    public ComplExpSepMinus()
103
    {
104
        super(&quot;-&quot;);
105
    }
106
}
107
&lt;/pre&gt;
108
109
      </documentation>
110
   </annotation>
111
112
   <annotation>
113
      <appInfo>
114
         <meta.section type="apiinfo"/>
115
      </appInfo>
116
      <documentation>
117
         TBD
118
      </documentation>
119
   </annotation>
120
121
   <annotation>
122
      <appInfo>
123
         <meta.section type="implementation"/>
124
      </appInfo>
125
      <documentation>
126
         All the classes mentioned as Examples
127
      </documentation>
128
   </annotation>
129
130
   <annotation>
131
      <appInfo>
132
         <meta.section type="copyright"/>
133
      </appInfo>
134
      <documentation>
135
         Copyright (c) 2010 IBM Corporation and others.&lt;br&gt;
136
All rights reserved. This program and the accompanying materials are made 
137
available under the terms of the Eclipse Public License v1.0 which 
138
accompanies 
139
this distribution, and is available at 
140
&lt;a 
141
href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
142
143
      </documentation>
144
   </annotation>
145
146
</schema>
(-)schema/STextType.exsd (+142 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.equinox.bidi" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.equinox.bidi" id="org.eclipse.equinox.bidi.bidiTypes" name="String types that need special bidirectional handling"/>
7
      </appInfo>
8
      <documentation>
9
         Use this extension point to describe processing for strings that need special bidirectional handling, such as file paths, SQL statements, or Java code.
10
      </documentation>
11
   </annotation>
12
13
   <element name="extension">
14
      <annotation>
15
         <appInfo>
16
            <meta.element />
17
         </appInfo>
18
      </annotation>
19
      <complexType>
20
         <sequence>
21
            <element ref="typeDescription" minOccurs="1" maxOccurs="unbounded"/>
22
         </sequence>
23
         <attribute name="point" type="string" use="required">
24
            <annotation>
25
               <documentation>
26
                  
27
               </documentation>
28
            </annotation>
29
         </attribute>
30
         <attribute name="id" type="string" use="required">
31
            <annotation>
32
               <documentation>
33
                  Unique identifier of this extension
34
               </documentation>
35
            </annotation>
36
         </attribute>
37
         <attribute name="name" type="string">
38
            <annotation>
39
               <documentation>
40
                  
41
               </documentation>
42
               <appInfo>
43
                  <meta.attribute translatable="true"/>
44
               </appInfo>
45
            </annotation>
46
         </attribute>
47
      </complexType>
48
   </element>
49
50
   <element name="typeDescription">
51
      <complexType>
52
         <attribute name="type" type="string" use="required">
53
            <annotation>
54
               <documentation>
55
                  Type of the structured text that this processor will work on.
56
               </documentation>
57
            </annotation>
58
         </attribute>
59
         <attribute name="class" type="string">
60
            <annotation>
61
               <documentation>
62
                  The processor that provides specialized bidirectional handling for this type of strings.
63
               </documentation>
64
               <appInfo>
65
                  <meta.attribute kind="java" basedOn=":org.eclipse.equinox.bidi.custom.ISTextProcessor"/>
66
               </appInfo>
67
            </annotation>
68
         </attribute>
69
         <attribute name="description" type="string">
70
            <annotation>
71
               <documentation>
72
                  The description of the string type.
73
               </documentation>
74
               <appInfo>
75
                  <meta.attribute translatable="true"/>
76
               </appInfo>
77
            </annotation>
78
         </attribute>
79
      </complexType>
80
   </element>
81
82
   <annotation>
83
      <appInfo>
84
         <meta.section type="since"/>
85
      </appInfo>
86
      <documentation>
87
         1.0
88
      </documentation>
89
   </annotation>
90
91
   <annotation>
92
      <appInfo>
93
         <meta.section type="examples"/>
94
      </appInfo>
95
      <documentation>
96
         A processor for the structured text strings that support &quot;minus&quot; delimiters can be described as:
97
98
&lt;pre&gt;
99
public class STextSepMinus extends STextProcessor
100
{
101
    public STextSepMinus()
102
    {
103
        super(&quot;-&quot;);
104
    }
105
}
106
&lt;/pre&gt;
107
      </documentation>
108
   </annotation>
109
110
   <annotation>
111
      <appInfo>
112
         <meta.section type="apiinfo"/>
113
      </appInfo>
114
      <documentation>
115
         TBD
116
      </documentation>
117
   </annotation>
118
119
   <annotation>
120
      <appInfo>
121
         <meta.section type="implementation"/>
122
      </appInfo>
123
      <documentation>
124
         All the classes mentioned as Examples
125
      </documentation>
126
   </annotation>
127
128
   <annotation>
129
      <appInfo>
130
         <meta.section type="copyright"/>
131
      </appInfo>
132
      <documentation>
133
         Copyright (c) 2011 IBM Corporation and others.&lt;br&gt;
134
All rights reserved. This program and the accompanying materials are made 
135
available under the terms of the Eclipse Public License v1.0 which 
136
accompanies this distribution, and is available at 
137
&lt;a 
138
href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
139
      </documentation>
140
   </annotation>
141
142
</schema>
(-)src/org/eclipse/equinox/bidi/BidiComplexEngine.java (-496 lines)
Removed 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.BidiComplexFeatures;
14
import org.eclipse.equinox.bidi.internal.BidiComplexImpl;
15
16
/**
17
 *  This class acts as a mediator between applications and complex
18
 *  expression processors.
19
 *  The purpose of complex expression processors is to add directional
20
 *  formatting characters to ensure correct display.
21
 *  This class shields applications from the
22
 *  intricacies of complex expression processors.
23
 *  <p>
24
 *  For a general introduction to complex expressions, see
25
 *  {@link <a href="package-summary.html">
26
 *  the package documentation</a>}.
27
 *
28
 *  <h2><a name="processor">How to Specify a Processor</a></h2>
29
 *
30
 *  <p>All the methods in this class have a first argument which
31
 *  designates a type of processor.
32
 *
33
 *  <p>It can be specified as a string (usually one of the
34
 *  literals to be found in {@link IBidiComplexExpressionTypes}
35
 *  or as an instance of {@link custom.IBidiComplexProcessor}.
36
 *
37
 *  <p>Such an instance can be obtained using the
38
 *  {@link custom.BidiComplexStringProcessor#getProcessor getProcessor}
39
 *  method for the registered processors, or by instantiating a private processor.
40
 *
41
 *  <p>When the same processor is used in multiple calls, it may be
42
 *  beneficial to obtain a reference to the processor and to use it
43
 *  in following calls, rather than to specify the processor by its
44
 *  type expressed as a string, which necessitates a registry search
45
 *  for each call.
46
 *
47
 *  <p>A processor reference is also the only way to examine the
48
 *  features of a processor by calling its
49
 *  {@link custom.IBidiComplexProcessor#getFeatures getFeatures} method.
50
 *
51
 *  <p>Specifying <code>null</code> for the processor as first argument
52
 *  of a method causes this method to behave as a no-op.
53
 *
54
 *  <h2><a name="state">State</a></h2>
55
 *
56
 *  <p>Most of the methods in this class have a <code>text</code>
57
 *  argument which may be just a part of a larger body of text.
58
 *  When it is the case that the text is submitted in parts with
59
 *  repeated calls, there may be a need to pass information from
60
 *  one invocation to the next one. For instance, one invocation
61
 *  may detect that a comment or a literal has been started but
62
 *  has not been completed. In such cases, a <code>state</code>
63
 *  argument must be used.
64
 *
65
 *  <p>The <code>state</code> argument must be an array of integers
66
 *  with at least one element. Only the first element is used by
67
 *  the methods of this class.
68
 *
69
 *  <p>When submitting the initial part of the text, the first element
70
 *  of <code>state</code> must contain the value {@link #STATE_INITIAL}
71
 *  or any value <= 0.
72
 *
73
 *  <p>After calling a method with a non-null <code>state</code> argument,
74
 *  a value is returned in the first element of <code>state</code>. This
75
 *  value should be passed unmodified to the method when calling it again
76
 *  with the text which is the continuation of the text submitted in the
77
 *  last call.
78
 *
79
 *  <p>When the text submitted to a method is not a continuation and is not
80
 *  expected to have a continuation , e.g. it is processed all by itself,
81
 *  the <code>state</code> argument should be specified as <code>null</code>.
82
 *
83
 *  <h2>Code Samples</h2>
84
 *
85
 *  <p>The following code shows how to transform a certain type of complex
86
 *  expression (directory and file paths) in order to obtain the <i>full</i>
87
 *  text corresponding to the <i>lean</i> text of such an expression.
88
 *
89
 *  <pre>
90
 *
91
 *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
92
 *    String fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.FILE, null, null, leanText, null);
93
 *    System.out.println("full text = " + fullText);
94
 *
95
 *  </pre>
96
 *
97
 *  <p>The following code shows how to transform successive lines of Java
98
 *  code in order to obtain the <i>full</i>
99
 *  text corresponding to the <i>lean</i> text of each line.
100
 *
101
 *  <pre>
102
 *
103
 *    int[] state = new int[1];
104
 *    state[0] = BidiComplexEngine.STATE_INITIAL;
105
 *    String leanText = "int i = 3; // first Java statement";
106
 *    String fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.JAVA, null, null, leanText, state);
107
 *    System.out.println("full text = " + fullText);
108
 *    leanText = "i += 4; // next Java statement";
109
 *    fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.JAVA, null, null, leanText, state);
110
 *    System.out.println("full text = " + fullText);
111
 *
112
 *  </pre>
113
 *
114
 *  <p>This class provides a user-oriented API but does not provide
115
 *  an actual implementation. The real work is done by the class
116
 *  {@link BidiComplexImpl}. Users of the API need not be concerned by, and
117
 *  should not depend upon, details of the implementation in
118
 *  <code>BidiComplexImpl</code>.
119
 *
120
 *  @author Matitiahu Allouche
121
 *
122
 */
123
public class BidiComplexEngine {
124
	/**
125
	 *  Constant to use in the first element of the <code>state</code>
126
	 *  argument when calling most methods of this class
127
	 *  to indicate that there is no context of previous lines which
128
	 *  should be initialized before performing the operation.
129
	 */
130
	public static final int STATE_INITIAL = 0;
131
132
	private static final int[] EMPTY_INT_ARRAY = new int[0];
133
134
	/**
135
	 *  Prevent creation of a BidiComplexEngine instance
136
	 */
137
	private BidiComplexEngine() {
138
		// nothing to do
139
	}
140
141
	/** Add directional formatting characters to a complex expression
142
	 *  to ensure correct presentation.
143
	 *
144
	 *  @param  processor designates one of the registered processors.
145
	 *          It can be a string containing a keyword according to
146
	 *          the processor type, or a processor reference.
147
	 *          For more details, see above <a href="#processor">
148
	 *          How to Specify a Processor</a>.
149
	 *          <p>If this argument is <code>null</code>, this method
150
	 *          returns the <code>text</code> string.
151
	 *
152
	 *  @param  features specifies features that affect the processor's
153
	 *          behavior.
154
	 *          <p>This argument may be specified as <code>null</code>,
155
	 *          in which case the processor will use its standard features
156
	 *          (as returned by the processor
157
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
158
	 *          method).
159
	 *
160
	 *  @param  environment specifies an environment whose characteristics
161
	 *          may affect the processor's behavior.
162
	 *          <p>This argument may be specified as <code>null</code>,
163
	 *          in which case the processor will assume a standard
164
	 *          environment as specified in
165
	 *          {@link BidiComplexEnvironment#DEFAULT}.
166
	 *
167
	 *  @param text is the text of the complex expression.
168
	 *
169
	 *  @param  state can be used to specify that the <code>text</code>
170
	 *          argument is the continuation of text submitted in a
171
	 *          previous call and/or to receive information to pass to
172
	 *          continuation calls.
173
	 *          For more details, see <a href="#state">State</a> above.
174
	 *          <p>If all calls to this method are independent from one another,
175
	 *          this argument should be specified as <code>null</code>.
176
	 *
177
	 *  @return the complex expression with directional formatting
178
	 *          characters added at proper locations to ensure correct
179
	 *          presentation.
180
	 */
181
	public static String leanToFullText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
182
		if (processor == null)
183
			return text;
184
		return BidiComplexImpl.leanToFullText(processor, features, environment, text, state);
185
	}
186
187
	/**
188
	 *  Given a <i>lean</i> string, compute the positions of each of its
189
	 *  characters within the corresponding <i>full</i> string.
190
	 *
191
	 *  @param  processor designates one of the registered processors.
192
	 *          It can be a string containing a keyword according to
193
	 *          the processor type, or a processor reference.
194
	 *          For more details, see above <a href="#processor">
195
	 *          How to Specify a Processor</a>.
196
	 *          <p>If this argument is <code>null</code>, this method
197
	 *          returns an identity map.
198
	 *
199
	 *  @param  features specifies features that affect the processor's
200
	 *          behavior.
201
	 *          <p>This argument may be specified as <code>null</code>,
202
	 *          in which case the processor will use its standard features
203
	 *          (as returned by the processor
204
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
205
	 *          method).
206
	 *
207
	 *  @param  environment specifies an environment whose characteristics
208
	 *          may affect the processor's behavior.
209
	 *          <p>This argument may be specified as <code>null</code>,
210
	 *          in which case the processor will assume a standard
211
	 *          environment as specified in
212
	 *          {@link BidiComplexEnvironment#DEFAULT}.
213
	 *
214
	 *  @param text is the text of the complex expression.
215
	 *
216
	 *  @param  state can be used to specify that the <code>text</code>
217
	 *          argument is the continuation of text submitted in a
218
	 *          previous call and/or to receive information to pass to
219
	 *          continuation calls.
220
	 *          For more details, see <a href="#state">State</a> above.
221
	 *          <p>If all calls to this method are independent from one another,
222
	 *          this argument should be specified as <code>null</code>.
223
	 *
224
	 *  @return an array of integers with one element for each of the characters
225
	 *          in the <code>text</code> argument, equal to the offset of the
226
	 *          corresponding character in the <i>full</i> string.
227
	 */
228
	public static int[] leanToFullMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
229
		if (processor == null) {
230
			int[] map = new int[text.length()];
231
			for (int i = 0; i < map.length; i++)
232
				map[i] = i;
233
			return map;
234
		}
235
		return BidiComplexImpl.leanToFullMap(processor, features, environment, text, state);
236
	}
237
238
	/**
239
	 *  Given a <i>lean</i> string, compute the offsets of characters
240
	 *  before which directional formatting characters must be added
241
	 *  in order to ensure correct presentation.
242
	 *
243
	 *  <p>Only LRMs (for an expression with LTR base direction) and RLMs (for
244
	 *  an expression with RTL base direction) are considered. Leading and
245
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
246
	 *  depending on the {@link BidiComplexEnvironment#getOrientation orientation} of the
247
	 *  GUI component used for display are not reflected in this method.
248
	 *
249
	 *  @param  processor designates one of the registered processors.
250
	 *          It can be a string containing a keyword according to
251
	 *          the processor type, or a processor reference.
252
	 *          For more details, see above <a href="#processor">
253
	 *          How to Specify a Processor</a>.
254
	 *          <p>If this argument is <code>null</code>, this method
255
	 *          returns an empty array.
256
	 *
257
	 *  @param  features specifies features that affect the processor's
258
	 *          behavior.
259
	 *          <p>This argument may be specified as <code>null</code>,
260
	 *          in which case the processor will use its standard features
261
	 *          (as returned by the processor
262
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
263
	 *          method).
264
	 *
265
	 *  @param  environment specifies an environment whose characteristics
266
	 *          may affect the processor's behavior.
267
	 *          <p>This argument may be specified as <code>null</code>,
268
	 *          in which case the processor will assume a standard
269
	 *          environment as specified in
270
	 *          {@link BidiComplexEnvironment#DEFAULT}.
271
	 *
272
	 *  @param text is the text of the complex expression.
273
	 *
274
	 *  @param  state can be used to specify that the <code>text</code>
275
	 *          argument is the continuation of text submitted in a
276
	 *          previous call and/or to receive information to pass to
277
	 *          continuation calls.
278
	 *          For more details, see <a href="#state">State</a> above.
279
	 *          <p>If all calls to this method are independent from one another,
280
	 *          this argument should be specified as <code>null</code>.
281
	 *
282
	 *  @return an array of offsets to the characters in the <code>text</code>
283
	 *          argument before which directional marks must be
284
	 *          added to ensure correct presentation.
285
	 *          The offsets are sorted in ascending order.
286
	 */
287
	public static int[] leanBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
288
		if (processor == null)
289
			return EMPTY_INT_ARRAY;
290
		return BidiComplexImpl.leanBidiCharOffsets(processor, features, environment, text, state);
291
	}
292
293
	/**
294
	 *  Remove directional formatting characters which were added to a
295
	 *  complex expression to ensure correct presentation.
296
	 *
297
	 *  @param  processor designates one of the registered processors.
298
	 *          It can be a string containing a keyword according to
299
	 *          the processor type, or a processor reference.
300
	 *          For more details, see above <a href="#processor">
301
	 *          How to Specify a Processor</a>.
302
	 *          <p>If this argument is <code>null</code>, this method
303
	 *          returns the <code>text</code> string.
304
	 *
305
	 *  @param  features specifies features that affect the processor's
306
	 *          behavior.
307
	 *          <p>This argument may be specified as <code>null</code>,
308
	 *          in which case the processor will use its standard features
309
	 *          (as returned by the processor
310
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
311
	 *          method).
312
	 *
313
	 *  @param  environment specifies an environment whose characteristics
314
	 *          may affect the processor's behavior.
315
	 *          <p>This argument may be specified as <code>null</code>,
316
	 *          in which case the processor will assume a standard
317
	 *          environment as specified in
318
	 *          {@link BidiComplexEnvironment#DEFAULT}.
319
	 *
320
	 *  @param text is the text of the complex expression including
321
	 *         directional formatting characters.
322
	 *
323
	 *  @param  state can be used to specify that the <code>text</code>
324
	 *          argument is the continuation of text submitted in a
325
	 *          previous call and/or to receive information to pass to
326
	 *          continuation calls.
327
	 *          For more details, see <a href="#state">State</a> above.
328
	 *          <p>If all calls to this method are independent from one another,
329
	 *          this argument should be specified as <code>null</code>.
330
	 *
331
	 *  @return the complex expression without directional formatting
332
	 *          characters which might have been added by processing it
333
	 *          with {@link #leanToFullText leanToFullText}.
334
	 *
335
	 */
336
	public static String fullToLeanText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
337
		if (processor == null)
338
			return text;
339
		return BidiComplexImpl.fullToLeanText(processor, features, environment, text, state);
340
	}
341
342
	/**
343
	 *  Given a <i>full</i> string, compute the positions of each of its
344
	 *  characters within the corresponding <i>lean</i> string.
345
	 *
346
	 *  @param  processor designates one of the registered processors.
347
	 *          It can be a string containing a keyword according to
348
	 *          the processor type, or a processor reference.
349
	 *          For more details, see above <a href="#processor">
350
	 *          How to Specify a Processor</a>.
351
	 *          <p>If this argument is <code>null</code>, this method
352
	 *          returns an identity map.
353
	 *
354
	 *  @param  features specifies features that affect the processor's
355
	 *          behavior.
356
	 *          <p>This argument may be specified as <code>null</code>,
357
	 *          in which case the processor will use its standard features
358
	 *          (as returned by the processor
359
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
360
	 *          method).
361
	 *
362
	 *  @param  environment specifies an environment whose characteristics
363
	 *          may affect the processor's behavior.
364
	 *          <p>This argument may be specified as <code>null</code>,
365
	 *          in which case the processor will assume a standard
366
	 *          environment as specified in
367
	 *          {@link BidiComplexEnvironment#DEFAULT}.
368
	 *
369
	 *  @param  text is the text of the complex expression including
370
	 *          directional formatting characters.
371
	 *
372
	 *  @param  state can be used to specify that the <code>text</code>
373
	 *          argument is the continuation of text submitted in a
374
	 *          previous call and/or to receive information to pass to
375
	 *          continuation calls.
376
	 *          For more details, see <a href="#state">State</a> above.
377
	 *          <p>If all calls to this method are independent from one another,
378
	 *          this argument should be specified as <code>null</code>.
379
	 *
380
	 *  @return an array of integers with one element for each of the characters
381
	 *          in the <code>text</code> argument, equal to the offset of the
382
	 *          corresponding character in the <i>lean</i> string.
383
	 *          If there is no corresponding
384
	 *          character in the <i>lean</i> string (because the
385
	 *          specified character is a directional formatting character
386
	 *          added when invoking {@link #leanToFullText leanToFullText}),
387
	 *          the value returned for this character is -1.
388
	 */
389
	public static int[] fullToLeanMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
390
		if (processor == null) {
391
			int[] map = new int[text.length()];
392
			for (int i = 0; i < map.length; i++)
393
				map[i] = i;
394
			return map;
395
		}
396
		return BidiComplexImpl.fullToLeanMap(processor, features, environment, text, state);
397
	}
398
399
	/**
400
	 *  Given a <i>full</i> string, return the offsets of characters
401
	 *  which are directional formatting characters that have been added
402
	 *  in order to ensure correct presentation.
403
	 *
404
	 *  <p>LRMs (for an expression with LTR base direction), RLMs (for
405
	 *  an expression with RTL base direction) are considered as well as
406
	 *  leading and trailing LRE, RLE and PDF which might be prefixed or suffixed
407
	 *  depending on the {@link BidiComplexEnvironment#getOrientation orientation}
408
	 *  of the GUI component used for display.
409
	 *
410
	 *  @param  processor designates one of the registered processors.
411
	 *          It can be a string containing a keyword according to
412
	 *          the processor type, or a processor reference.
413
	 *          For more details, see above <a href="#processor">
414
	 *          How to Specify a Processor</a>.
415
	 *          <p>If this argument is <code>null</code>, this method
416
	 *          returns an empty array.
417
	 *
418
	 *  @param  features specifies features that affect the processor's
419
	 *          behavior.
420
	 *          <p>This argument may be specified as <code>null</code>,
421
	 *          in which case the processor will use its standard features
422
	 *          (as returned by the processor
423
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
424
	 *          method).
425
	 *
426
	 *  @param  environment specifies an environment whose characteristics
427
	 *          may affect the processor's behavior.
428
	 *          <p>This argument may be specified as <code>null</code>,
429
	 *          in which case the processor will assume a standard
430
	 *          environment as specified in
431
	 *          {@link BidiComplexEnvironment#DEFAULT}.
432
	 *
433
	 *  @param  text is the text of the complex expression including
434
	 *          directional formatting characters.
435
	 *
436
	 *  @param  state can be used to specify that the <code>text</code>
437
	 *          argument is the continuation of text submitted in a
438
	 *          previous call and/or to receive information to pass to
439
	 *          continuation calls.
440
	 *          For more details, see <a href="#state">State</a> above.
441
	 *          <p>If all calls to this method are independent from one another,
442
	 *          this argument should be specified as <code>null</code>.
443
	 *
444
	 *  @return an array of offsets to the characters in the <code>text</code>
445
	 *          argument which are directional formatting characters
446
	 *          added to ensure correct presentation.
447
	 *          The offsets are sorted in ascending order.
448
	 */
449
	public static int[] fullBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
450
		if (processor == null)
451
			return EMPTY_INT_ARRAY;
452
		return BidiComplexImpl.fullBidiCharOffsets(processor, features, environment, text, state);
453
	}
454
455
	/**
456
	 *  Get the base direction of a complex expression.
457
	 *  This base direction may depend on
458
	 *  whether the expression contains Arabic or Hebrew words
459
	 *  (if it contains both, the first Arabic or Hebrew letter in the
460
	 *  expression determines which is the governing script) and on
461
	 *  whether the GUI is {@link BidiComplexEnvironment#getMirrored mirrored}.
462
	 *
463
	 *  @param  processor designates one of the registered processors.
464
	 *          It can be a string containing a keyword according to
465
	 *          the processor type, or a processor reference.
466
	 *          For more details, see above <a href="#processor">
467
	 *          How to Specify a Processor</a>.
468
	 *          <p>If this argument is <code>null</code>, this method
469
	 *          returns {@link BidiComplexFeatures#DIR_LTR}.
470
	 *
471
	 *  @param  features specifies features that affect the processor's
472
	 *          behavior.
473
	 *          <p>This argument may be specified as <code>null</code>,
474
	 *          in which case the processor will use its standard features
475
	 *          (as returned by the processor
476
	 *          {@link custom.IBidiComplexProcessor#getFeatures getFeatures}
477
	 *          method).
478
	 *
479
	 *  @param  environment specifies an environment whose characteristics
480
	 *          may affect the processor's behavior.
481
	 *          <p>This argument may be specified as <code>null</code>,
482
	 *          in which case the processor will assume a standard
483
	 *          environment as specified in
484
	 *          {@link BidiComplexEnvironment#DEFAULT}.
485
	 *
486
	 *  @param  text is the text of the complex expression.
487
	 *
488
	 *  @return the base direction of the complex expression.
489
	 *          It is one of the values {@link BidiComplexFeatures#DIR_LTR}
490
	 *          or {@link BidiComplexFeatures#DIR_RTL}.
491
	 */
492
	public static int getCurDirection(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text) {
493
		return BidiComplexImpl.getCurDirection(processor, features, environment, text, null);
494
	}
495
496
}
(-)src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java (-326 lines)
Removed 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
 *  All methods in {@link BidiComplexEngine} have a BidiComplexEnvironment
25
 *  argument. If this argument is specified as <code>null</code>, the
26
 *  {@link #DEFAULT} environment is used.
27
 *
28
 *  <h2>Code Samples</h2>
29
 *  <p>Example (set all environment parameters)
30
 *  <pre>
31
 *
32
 *    BidiComplexEnvironment myEnv = new BidiComplexEnvironment("he_IL", true, BidiComplexEnvironment.ORIENT_RTL);
33
 *
34
 *  </pre>
35
 *  <p>
36
 *  This class also provides a number of convenience methods related to the environment.
37
 *  <p>&nbsp;</p>
38
 *  @see IBidiComplexProcessor#getFeatures
39
 *
40
 *  @author Matitiahu Allouche
41
 */
42
public class BidiComplexEnvironment {
43
44
	/**
45
	 *  Constant specifying that the orientation of the GUI component
46
	 *  where a complex expression will be displayed is LTR.
47
	 *  It can appear as <code>orientation</code> argument for the
48
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
49
	 *  and as value returned by {@link #getOrientation}.
50
	 */
51
	public static final int ORIENT_LTR = 0;
52
53
	/**
54
	 *  Constant specifying that the orientation of the GUI component
55
	 *  where a complex expression will be displayed is RTL.
56
	 *  It can appear as <code>orientation</code> argument for the
57
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
58
	 *  and as value returned by {@link #getOrientation}.
59
	 */
60
	public static final int ORIENT_RTL = 1;
61
62
	/**
63
	 *  Constant specifying that the orientation of the GUI component
64
	 *  where a complex expression will be displayed is contextual with
65
	 *  a default of LTR (if no strong character appears in the text).
66
	 *  It can appear as <code>orientation</code> argument for the
67
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
68
	 *  and as value returned by {@link #getOrientation}.
69
	 */
70
	public static final int ORIENT_CONTEXTUAL_LTR = 2;
71
72
	/**
73
	 *  Constant specifying that the orientation of the GUI component
74
	 *  where a complex expression will be displayed is contextual with
75
	 *  a default of RTL (if no strong character appears in the text).
76
	 *  It can appear as <code>orientation</code> argument for the
77
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
78
	 *  and as value returned by {@link #getOrientation}.
79
	 */
80
	public static final int ORIENT_CONTEXTUAL_RTL = 3;
81
82
	/**
83
	 *  Constant specifying that the orientation of the GUI component
84
	 *  where a complex expression will be displayed is not known.
85
	 *  Directional formatting characters must be added as prefix and
86
	 *  suffix whenever a <i>full</i> text is generated using
87
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}.
88
	 *  It can appear as <code>orientation</code> argument for the
89
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
90
	 *  and as value returned by {@link #getOrientation}.
91
	 */
92
	public static final int ORIENT_UNKNOWN = 4;
93
94
	/**
95
	 *  Constant specifying that whatever the orientation of the
96
	 *  GUI component where a complex expression will be displayed, no
97
	 *  directional formatting characters must be added as prefix or
98
	 *  suffix when a <i>full</i> text is generated using
99
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}.
100
	 *  It can appear as <code>orientation</code> argument for the
101
	 *  {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor}
102
	 *  and as value returned by {@link #getOrientation}.
103
	 */
104
	public static final int ORIENT_IGNORE = 5;
105
106
	/**
107
	 *  Pre-defined <code>BidiComplexEnvironment</code> instance with values
108
	 *  for a non-mirrored GUI and a Left-to-Right presentation component.<br>
109
	 *  The language is set to <code>null</code>, which defaults to the language
110
	 *  of the current default locale.
111
	 */
112
	public static final BidiComplexEnvironment DEFAULT = new BidiComplexEnvironment(null, false, ORIENT_LTR);
113
114
	/**
115
	 *  This string is a 2-letters code representing a language as defined by
116
	 *  ISO-639. If left as <code>null</code>, it defaults to the language
117
	 *  of the current default locale.
118
	 */
119
	final String language;
120
121
	/**
122
	 *  Flag specifying that complex expressions processed under this environment
123
	 *  should assume that the GUI is mirrored (globally going from right to left).
124
	 */
125
	final boolean mirrored;
126
127
	/** Specify the orientation (a.k.a. base direction) of the GUI
128
	 *  component in which the <i>full</i> text of the complex expression will
129
	 *  be displayed.
130
	 */
131
	final int orientation;
132
133
	static Locale defaultLocale;
134
	static String defaultLanguage;
135
	static boolean defaultBidi;
136
	boolean bidiFlag;
137
138
	/**
139
	 *  Constructor
140
	 *
141
	 *  @param lang represents the language to be used in this environment.
142
	 *          It should be specified as a 2-letters code as defined by
143
	 *          ISO-639.<br>
144
	 *          If longer than 2 letters, the extra letters are ignored.<br>
145
	 *          If set to <code>null</code>, it defaults to the language
146
	 *          of the default locale.
147
	 *  @see #getLanguage
148
	 *
149
	 *  @param mirrored specifies if the GUI is mirrored.
150
	 *  @see #getMirrored
151
	 *
152
	 *  @param orientation specifies the orientation of the component
153
	 *          which is to display the complex expression. It must be
154
	 *          one of the values
155
	 *          {@link #ORIENT_LTR ORIENT_LTR},
156
	 *          {@link #ORIENT_LTR ORIENT_RTL},
157
	 *          {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
158
	 *          {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
159
	 *          {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
160
	 *          {@link #ORIENT_IGNORE ORIENT_IGNORE}.<br>
161
	 *          If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}.
162
	 *  @see #getOrientation
163
	 */
164
	public BidiComplexEnvironment(String lang, boolean mirrored, int orientation) {
165
		if (lang == null) {
166
			language = null;
167
		} else {
168
			if (lang.length() > 2)
169
				language = lang.substring(0, 2);
170
			else
171
				language = lang;
172
			bidiFlag = isBidiLanguage(language);
173
		}
174
		this.mirrored = mirrored;
175
		this.orientation = orientation >= ORIENT_LTR && orientation <= ORIENT_IGNORE ? orientation : ORIENT_UNKNOWN;
176
	}
177
178
	/**
179
	 *  Return a 2-letters code representing a language as defined by
180
	 *  ISO-639. If equal to <code>null</code>, it defaults to the language
181
	 *  of the current default locale.
182
	 */
183
	public String getLanguage() {
184
		return language;
185
	}
186
187
	/**
188
	 *  Return a flag indicating that complex expressions processed
189
	 *  within this environment should assume that the GUI is mirrored
190
	 * (globally going from right to left).
191
	 */
192
	public boolean getMirrored() {
193
		return mirrored;
194
	}
195
196
	/** Return the orientation (a.k.a. base direction) of the GUI
197
	 *  component in which the <i>full</i> text of the complex expression
198
	 *  will be displayed.<br>
199
	 *  The orientation must have one of the values
200
	 *  {@link #ORIENT_LTR ORIENT_LTR},
201
	 *  {@link #ORIENT_LTR ORIENT_RTL},
202
	 *  {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
203
	 *  {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
204
	 *  {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
205
	 *  {@link #ORIENT_IGNORE ORIENT_IGNORE}.
206
	  *  <p>
207
	 *  When the orientation is <code>ORIENT_LTR</code> and the complex
208
	 *  expression has a RTL base direction,
209
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
210
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
211
	 *  end.
212
	 *  <p>
213
	 *  When the orientation is <code>ORIENT_RTL</code> and the complex
214
	 *  expression has a LTR base direction,
215
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
216
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
217
	 *  end.
218
	 *  <p>
219
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
220
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
221
	 *  to a RTL orientation while the complex expression has a LTR base
222
	 *  direction, {@link BidiComplexEngine#leanToFullText leanToFullText}
223
	 *  adds LRM at the head of the <i>full</i> text.
224
	 *  <p>
225
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
226
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
227
	 *  to a LTR orientation while the complex expression has a RTL base
228
	 *  direction, {@link BidiComplexEngine#leanToFullText leanToFullText}
229
	 *  adds RLM at the head of the <i>full</i> text.
230
	 *  <p>
231
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
232
	 *  expression has a LTR base direction,
233
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
234
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
235
	 *  end.
236
	 *  <p>
237
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the complex
238
	 *  expression has a RTL base direction,
239
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
240
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
241
	 *  end.
242
	 *  <p>
243
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
244
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText} does not add any directional
245
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
246
	 *  <p>
247
	 */
248
	public int getOrientation() {
249
		return orientation;
250
	}
251
252
	/**
253
	 *  Check whether the current language uses a
254
	 *  bidi script (Arabic, Hebrew, Farsi or Urdu).
255
	 *
256
	 *  @return <code>true</code> if the current language uses a bidi script.
257
	 *          The language may have been set explicitly when creating the
258
	 *          <code>BidiComplexEnvironment</code> instance, or it may have
259
	 *          defaulted to the language of the current default locale.
260
	 *  @see #getLanguage
261
	 */
262
	public boolean isBidi() {
263
		if (defaultLanguage != null && defaultLocale.equals(getDefaultLocale()))
264
			return defaultBidi;
265
266
		if (language == null) {
267
			defaultLocale = getDefaultLocale();
268
			defaultLanguage = defaultLocale.getLanguage();
269
			defaultBidi = isBidiLanguage(defaultLanguage);
270
			return defaultBidi;
271
		}
272
273
		return bidiFlag;
274
	}
275
276
	static boolean isBidiLanguage(String lang) {
277
		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$
278
	}
279
280
	static String lineSep;
281
282
	/**
283
	 *  Retrieve the string which represents a line separator in this environment.
284
	 *
285
	 *  @return the string which is used as line separator (e.g. CRLF).
286
	 */
287
	public static String getLineSep() {
288
		// use bundle properties
289
		if (lineSep == null) {
290
			//          lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
291
			lineSep = getProperty("line.separator"); //$NON-NLS-1$/
292
		}
293
		return lineSep;
294
	}
295
296
	static String osName;
297
	static boolean flagOS;
298
299
	private static String getProperty(String key) {
300
		// use bundle properties
301
		//      osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
302
		BidiComplexActivator bidiComplexActivator = BidiComplexActivator.getInstance();
303
		return bidiComplexActivator.getProperty(key);
304
	}
305
306
	private Locale getDefaultLocale() {
307
		BidiComplexActivator bidiComplexActivator = BidiComplexActivator.getInstance();
308
		return bidiComplexActivator.getDefaultLocale();
309
	}
310
311
	/**
312
	 *  Check if the current OS is supported by the complex expression packages.
313
	 *
314
	 *  @return <code>true</code> if the current OS is supported.
315
	 */
316
	public static boolean isSupportedOS() {
317
		if (osName == null) {
318
			// use bundle properties
319
			// osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
320
			osName = getProperty("os.name").toLowerCase(); //$NON-NLS-1$/
321
			flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$
322
		}
323
		return flagOS;
324
	}
325
326
}
(-)src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java (-193 lines)
Removed 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. When the pool is full,
24
 *  each new element overrides the oldest 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 the string to record
60
	 *
61
	 *  @param  triplets
62
	 *          array of short integers, the number of elements in the array
63
	 *          must be a multiple of 3, so that the array is made of one or
64
	 *          more triplets of short integers.
65
	 *          <p>
66
	 *          The first element in each triplet is the beginning offset of a
67
	 *          susbstring of <code>string</code> which is a complex
68
	 *          expression.
69
	 *          <p>
70
	 *          The second element in each triplet is the ending offset of a
71
	 *          susbstring of <code>string</code> which is a complex
72
	 *          expression. This offset points to one position beyond the last
73
	 *          character of the substring.
74
	 *          <p>
75
	 *          The third element in each triplet is the numeric type of the
76
	 *          complex expression.<br>
77
	 *          The type of a complex expression must be one of the string
78
	 *          values listed in {@link IBidiComplexExpressionTypes}.<br>
79
	 *          The corresponding numeric type must be obtained using the
80
	 *          method {@link #typeStringToShort typeStringToShort}.
81
	 */
82
	public BidiComplexStringRecord(String string, short[] triplets) {
83
		if (string == null || triplets == null)
84
			throw new IllegalArgumentException("The string and triplets argument must not be null!"); //$NON-NLS-1$
85
		if ((triplets.length % 3) != 0)
86
			throw new IllegalArgumentException("The number of elements in triplets must be a multiple of 3!"); //$NON-NLS-1$
87
		for (int i = 2; i < triplets.length; i += 3)
88
			if (triplets[i] < 0 || triplets[i] > MAXTYPE)
89
				throw new IllegalArgumentException("Illegal type value in element" + i);
90
		strRef = new SoftReference(string);
91
		triRef = new SoftReference(triplets);
92
		hash = string.hashCode();
93
	}
94
95
	/**
96
	 *  Get the numeric type of a complex expression given its string type.
97
	 *
98
	 *  @param  type type of complex expression as string. It must be one
99
	 *          of the 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 a BidiComplexStringRecord instance
131
	 */
132
	public static synchronized void add(BidiComplexStringRecord record) {
133
		if (last < MAXINDEX)
134
			last++;
135
		else
136
			last = 0;
137
		records[last] = record;
138
	}
139
140
	/**
141
	 *  Check if a string is recorded and retrieve its triplets.
142
	 *
143
	 *  @param  string the string to check
144
	 *
145
	 *  @return <code>null</code> if the string is not recorded in the pool;
146
	 *          otherwise, return the triplets associated with this string.
147
	 */
148
	public static short[] getTriplets(String string) {
149
		if (records[0] == null) // no records at all
150
			return null;
151
		if (string == null || string.length() < 1)
152
			return null;
153
		BidiComplexStringRecord rec;
154
		String str;
155
		short[] tri;
156
		int myLast = last;
157
		int hash = string.hashCode();
158
		for (int i = myLast; i >= 0; i--) {
159
			rec = records[i];
160
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
161
				return tri;
162
			}
163
		}
164
		if (records[MAXINDEX] == null) // never recorded past myLast
165
			return null;
166
		for (int i = MAXINDEX; i > myLast; i--) {
167
			rec = records[i];
168
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
169
				return tri;
170
			}
171
		}
172
		return null;
173
	}
174
175
	/**
176
	 *  Clear the pool. All elements of the pool are erased and any associated
177
	 *  memory is freed.
178
	 *
179
	 */
180
	public static synchronized void clear() {
181
		for (int i = 0; i <= MAXINDEX; i++) {
182
			BidiComplexStringRecord sr = records[i];
183
			if (sr == null)
184
				break;
185
			sr.hash = 0;
186
			sr.strRef.clear();
187
			sr.triRef.clear();
188
			records[i] = null;
189
		}
190
		last = MAXINDEX;
191
	}
192
193
}
(-)src/org/eclipse/equinox/bidi/BidiComplexUtil.java (-313 lines)
Removed 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.BidiComplexFeatures;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
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 BidiComplexUtil {
26
27
	/**
28
	 *  prevent instantiation
29
	 */
30
	private BidiComplexUtil() {
31
		// empty
32
	}
33
34
	/** This is a convenience method which can add directional marks in a given
35
	 *  text before the characters specified in the given array of offsets,
36
	 *  and can add a prefix and/or a suffix of directional formatting characters.
37
	 *  This can be used for instance after obtaining offsets by calling
38
	 *  {@link BidiComplexEngine#leanBidiCharOffsets leanBidiCharOffsets} in order to
39
	 *  produce a <i>full</i> text corresponding to the source text.
40
	 *  The directional formatting characters that will be added at the given
41
	 *  offsets will be LRMs for expressions with LTR base direction and
42
	 *  RLMs for expressions with RTL base direction. Leading and
43
	 *  trailing LRE, RLE and PDF which might be needed as prefix or suffix
44
	 *  depending on the orientation of the GUI component used for display
45
	 *  may be added depending on argument <code>affix</code>.
46
	 *
47
	 *  @param  text is the text of the complex expression.
48
	 *
49
	 *  @param  offsets is an array of offsets to characters in <code>text</code>
50
	 *          before which an LRM or RLM will be inserted.
51
	 *          Members of the array must be non-negative numbers smaller
52
	 *          than the length of <code>text</code>.
53
	 *          The array must be sorted in ascending order without duplicates.
54
	 *          This argument may be null if there are no marks to add.
55
	 *
56
	 *  @param  direction specifies the base direction of the complex expression.
57
	 *          It must be one of the values {@link BidiComplexFeatures#DIR_LTR} or
58
	 *          {@link BidiComplexFeatures#DIR_RTL}.
59
	 *
60
	 *  @param  affix specifies if a prefix and a suffix should be added to
61
	 *          the result to make sure that the <code>direction</code>
62
	 *          specified as third argument is honored even if the expression
63
	 *          is displayed in a GUI component with a different orientation.
64
	 *
65
	 *  @return a string corresponding to the source <code>text</code> with
66
	 *          directional marks (LRMs or RLMs) added at the specified offsets,
67
	 *          and directional formatting characters (LRE, RLE, PDF) added
68
	 *          as prefix and suffix if so required.
69
	 */
70
	public static String insertMarks(String text, int[] offsets, int direction, boolean affix) {
71
		int textLen = text.length();
72
		if (textLen == 0)
73
			return ""; //$NON-NLS-1$
74
75
		String curPrefix, curSuffix, full;
76
		char curMark, c;
77
		char[] fullChars;
78
		if (direction == BidiComplexFeatures.DIR_LTR) {
79
			curMark = LRM;
80
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
81
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
82
		} else {
83
			curMark = RLM;
84
			curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$
85
			curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$
86
		}
87
		// add marks at offsets
88
		if ((offsets != null) && (offsets.length > 0)) {
89
			int offLen = offsets.length;
90
			fullChars = new char[textLen + offLen];
91
			int added = 0;
92
			for (int i = 0, j = 0; i < textLen; i++) {
93
				c = text.charAt(i);
94
				if ((j < offLen) && (i == offsets[j])) {
95
					fullChars[i + added] = curMark;
96
					added++;
97
					j++;
98
				}
99
				fullChars[i + added] = c;
100
			}
101
			full = new String(fullChars);
102
		} else {
103
			full = text;
104
		}
105
		if (affix)
106
			return curPrefix + full + curSuffix;
107
		return full;
108
	}
109
110
	/*************************************************************************/
111
	/*                                                                       */
112
	/*  The following code is provided for compatibility with TextProcessor  */
113
	/*                                                                       */
114
	/*************************************************************************/
115
116
	//  The default set of separators to use to segment a string.
117
	private static final String defaultSeparators = ".:/\\"; //$NON-NLS-1$
118
	// left to right mark
119
	private static final char LRM = '\u200e';
120
	// left to right mark
121
	private static final char RLM = '\u200f';
122
	// left to right embedding
123
	private static final char LRE = '\u202a';
124
	// right to left embedding
125
	private static final char RLE = '\u202b';
126
	// pop directional format
127
	private static final char PDF = '\u202c';
128
129
	static boolean isProcessingNeeded() {
130
		if (!BidiComplexEnvironment.isSupportedOS())
131
			return false;
132
		return BidiComplexEnvironment.DEFAULT.isBidi();
133
	}
134
135
	/**
136
	 *  Process the given text and return a string with appropriate
137
	 *  directional formatting characters if the locale is a bidi locale.
138
	 *  This is equivalent to calling
139
	 *  {@link #process(String str, String separators)} with the default
140
	 *  set of separators (dot, colon, slash, backslash).
141
	 *
142
	 *  @param  str the text to be processed.
143
	 *
144
	 *  @return the processed string.
145
	 */
146
	public static String process(String str) {
147
		return process(str, defaultSeparators);
148
	}
149
150
	/**
151
	 *  Process a string that has a particular semantic meaning to render
152
	 *  it correctly on bidi locales. This is done by adding directional
153
	 *  formatting characters so that presentation using the Unicode
154
	 *  Bidirectional Algorithm will provide the expected result.
155
	 *  The text is segmented according to the provided separators.
156
	 *  Each segment has the Unicode Bidi Algorithm applied to it,
157
	 *  but as a whole, the string is oriented left to right.
158
	 *  <p>
159
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
160
	 *  (where capital letters indicate RTL text) should render as
161
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
162
	 *  <p>
163
	 *  NOTE: this method inserts directional formatting characters into the
164
	 *  text. Methods like <code>String.equals(String)</code> and
165
	 *  <code>String.length()</code> called on the resulting string will not
166
	 *  return the same values as would be returned for the original string.</p>
167
	 *
168
	 *  @param  str the text to process.
169
	 *
170
	 *  @param  separators separators by which the string will be segmented.
171
	 *          If <code>null</code>, the default separators are used
172
	 *          (dot, colon, slash, backslash).
173
	 *
174
	 *  @return the processed string.
175
	 *          If <code>str</code> is <code>null</code>,
176
	 *          or of length 0, or if the current locale is not a bidi one,
177
	 *          return the original string.
178
	 */
179
	public static String process(String str, String separators) {
180
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
181
			return str;
182
183
		// do not process a string that has already been processed.
184
		if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF)
185
			return str;
186
187
		// do not process a string if all the following conditions are true:
188
		//  a) it has no RTL characters
189
		//  b) it starts with a LTR character
190
		//  c) it ends with a LTR character or a digit
191
		boolean isStringBidi = false;
192
		int strLength = str.length();
193
		char c;
194
		for (int i = 0; i < strLength; i++) {
195
			c = str.charAt(i);
196
			if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) {
197
				isStringBidi = true;
198
				break;
199
			}
200
		}
201
		while (!isStringBidi) {
202
			if (!Character.isLetter(str.charAt(0)))
203
				break;
204
			c = str.charAt(strLength - 1);
205
			if (!Character.isDigit(c) && !Character.isLetter(c))
206
				break;
207
			return str;
208
		}
209
210
		if (separators == null)
211
			separators = defaultSeparators;
212
213
		// make sure that LRE/PDF are added around the string
214
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN);
215
		BidiComplexFeatures features = new BidiComplexFeatures(separators, 0, -1, -1, false, false);
216
		return BidiComplexEngine.leanToFullText(new BidiComplexProcessor(), features, env, str, null);
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
		return BidiComplexEngine.leanToFullText(type, null, env, str, null);
261
	}
262
263
	/**
264
	 *  Remove directional formatting characters in the given string that
265
	 *  were inserted by one of the {@link #process process} methods.
266
	 *
267
	 *  @param  str string with directional characters to remove.
268
	 *
269
	 *  @return string with no directional formatting characters.
270
	 */
271
	public static String deprocess(String str) {
272
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
273
			return str;
274
275
		StringBuffer buf = new StringBuffer();
276
		int strLen = str.length();
277
		for (int i = 0; i < strLen; i++) {
278
			char c = str.charAt(i);
279
			switch (c) {
280
				case LRM :
281
					continue;
282
				case LRE :
283
					continue;
284
				case PDF :
285
					continue;
286
				default :
287
					buf.append(c);
288
			}
289
		}
290
		return buf.toString();
291
	}
292
293
	/**
294
	 *  Remove directional formatting characters in the given string that
295
	 *  were inserted by the {@link #processTyped processTyped} method.
296
	 *
297
	 *  @param  str string with directional characters to remove.
298
	 *
299
	 *  @param  type type of the complex expression as specified when
300
	 *          calling {@link #processTyped processTyped}.
301
	 *
302
	 *  @return string with no directional formatting characters.
303
	 */
304
	public static String deprocess(String str, String type) {
305
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
306
			return str;
307
308
		// make sure that LRE/PDF are added around the string
309
		BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN);
310
		return BidiComplexEngine.fullToLeanText(type, null, env, str, null);
311
	}
312
313
}
(-)src/org/eclipse/equinox/bidi/IBidiComplexExpressionTypes.java (-106 lines)
Removed 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/ISTextTypes.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 ISTextTypes {
19
20
	/**
21
	 * Constant indicating a type of structured text 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 structured text 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 structured text 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 structured text processor adapted
51
	 * to processing strings with the following 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 structured text 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 structured text 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 structured text processor adapted
72
	 *  to processing URLs.
73
	 */
74
	public String URL = "url"; //$NON-NLS-1$
75
76
	/**
77
	 *  Constant indicating a type of structured text 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 structured text processor adapted
85
	 *  to processing XPath expressions.
86
	 */
87
	public String XPATH = "xpath"; //$NON-NLS-1$
88
89
	/**
90
	 *  Constant indicating a type of structured text 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 structured text 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 structured text 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/STextEngine.java (+497 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.ISTextProcessor;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.internal.STextImpl;
16
17
/**
18
 *  This class acts as a mediator between applications and structured text
19
 *  processors.
20
 *  The purpose of structured text processors is to add directional
21
 *  formatting characters to ensure correct display.
22
 *  This class shields applications from the
23
 *  intricacies of structured text processors.
24
 *  <p>
25
 *  For a general introduction to structured text, see
26
 *  {@link <a href="package-summary.html">
27
 *  the package documentation</a>}.
28
 *
29
 *  <h2><a name="processor">How to Specify a Processor</a></h2>
30
 *
31
 *  <p>All the methods in this class have a first argument which
32
 *  designates a type of processor.
33
 *
34
 *  <p>It can be specified as a string (usually one of the
35
 *  literals to be found in {@link ISTextTypes}
36
 *  or as an instance of {@link ISTextProcessor}.
37
 *
38
 *  <p>Such an instance can be obtained using the
39
 *  {@link org.eclipse.equinox.bidi.custom.STextStringProcessor#getProcessor getProcessor}
40
 *  method for the registered processors, or by instantiating a private processor.
41
 *
42
 *  <p>When the same processor is used in multiple calls, it may be
43
 *  beneficial to obtain a reference to the processor and to use it
44
 *  in following calls, rather than to specify the processor by its
45
 *  type expressed as a string, which necessitates a registry search
46
 *  for each call.
47
 *
48
 *  <p>A processor reference is also the only way to examine the
49
 *  features of a processor by calling its
50
 *  {@link ISTextProcessor#getFeatures getFeatures} method.
51
 *
52
 *  <p>Specifying <code>null</code> for the processor as first argument
53
 *  of a method causes this method to behave as a no-op.
54
 *
55
 *  <h2><a name="state">State</a></h2>
56
 *
57
 *  <p>Most of the methods in this class have a <code>text</code>
58
 *  argument which may be just a part of a larger body of text.
59
 *  When it is the case that the text is submitted in parts with
60
 *  repeated calls, there may be a need to pass information from
61
 *  one invocation to the next one. For instance, one invocation
62
 *  may detect that a comment or a literal has been started but
63
 *  has not been completed. In such cases, a <code>state</code>
64
 *  argument must be used.
65
 *
66
 *  <p>The <code>state</code> argument must be an array of integers
67
 *  with at least one element. Only the first element is used by
68
 *  the methods of this class.
69
 *
70
 *  <p>When submitting the initial part of the text, the first element
71
 *  of <code>state</code> must contain the value {@link #STATE_INITIAL}
72
 *  or any value <= 0.
73
 *
74
 *  <p>After calling a method with a non-null <code>state</code> argument,
75
 *  a value is returned in the first element of <code>state</code>. This
76
 *  value should be passed unmodified to the method when calling it again
77
 *  with the text which is the continuation of the text submitted in the
78
 *  last call.
79
 *
80
 *  <p>When the text submitted to a method is not a continuation and is not
81
 *  expected to have a continuation , e.g. it is processed all by itself,
82
 *  the <code>state</code> argument should be specified as <code>null</code>.
83
 *
84
 *  <h2>Code Samples</h2>
85
 *
86
 *  <p>The following code shows how to transform a certain type of structured text
87
 *  (directory and file paths) in order to obtain the <i>full</i>
88
 *  text corresponding to the given <i>lean</i> text.
89
 *
90
 *  <pre>
91
 *
92
 *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
93
 *    String fullText = STextEngine.leanToFullText(ISTextTypes.FILE, null, null, leanText, null);
94
 *    System.out.println("full text = " + fullText);
95
 *
96
 *  </pre>
97
 *
98
 *  <p>The following code shows how to transform successive lines of Java
99
 *  code in order to obtain the <i>full</i>
100
 *  text corresponding to the <i>lean</i> text of each line.
101
 *
102
 *  <pre>
103
 *
104
 *    int[] state = new int[1];
105
 *    state[0] = STextEngine.STATE_INITIAL;
106
 *    String leanText = "int i = 3; // first Java statement";
107
 *    String fullText = STextEngine.leanToFullText(ISTextTypes.JAVA, null, null, leanText, state);
108
 *    System.out.println("full text = " + fullText);
109
 *    leanText = "i += 4; // next Java statement";
110
 *    fullText = STextEngine.leanToFullText(ISTextTypes.JAVA, null, null, leanText, state);
111
 *    System.out.println("full text = " + fullText);
112
 *
113
 *  </pre>
114
 *
115
 *  <p>This class provides a user-oriented API but does not provide
116
 *  an actual implementation. The real work is done by the class
117
 *  {@link STextImpl}. Users of the API need not be concerned by, and
118
 *  should not depend upon, details of the implementation in
119
 *  <code>STextImpl</code>.
120
 *
121
 *  @author Matitiahu Allouche
122
 *
123
 */
124
public class STextEngine {
125
	/**
126
	 *  Constant to use in the first element of the <code>state</code>
127
	 *  argument when calling most methods of this class
128
	 *  to indicate that there is no context of previous lines which
129
	 *  should be initialized before performing the operation.
130
	 */
131
	public static final int STATE_INITIAL = 0;
132
133
	private static final int[] EMPTY_INT_ARRAY = new int[0];
134
135
	/**
136
	 *  Prevent creation of a STextEngine instance
137
	 */
138
	private STextEngine() {
139
		// nothing to do
140
	}
141
142
	/** Add directional formatting characters to a structured text
143
	 *  to ensure correct presentation.
144
	 *
145
	 *  @param  processor designates one of the registered processors.
146
	 *          It can be a string containing a keyword according to
147
	 *          the processor type, or a processor reference.
148
	 *          For more details, see above <a href="#processor">
149
	 *          How to Specify a Processor</a>.
150
	 *          <p>If this argument is <code>null</code>, this method
151
	 *          returns the <code>text</code> string.
152
	 *
153
	 *  @param  features specifies features that affect the processor's
154
	 *          behavior.
155
	 *          <p>This argument may be specified as <code>null</code>,
156
	 *          in which case the processor will use its standard features
157
	 *          (as returned by the processor
158
	 *          {@link ISTextProcessor#getFeatures getFeatures}
159
	 *          method).
160
	 *
161
	 *  @param  environment specifies an environment whose characteristics
162
	 *          may affect the processor's behavior.
163
	 *          <p>This argument may be specified as <code>null</code>,
164
	 *          in which case the processor will assume a standard
165
	 *          environment as specified in
166
	 *          {@link STextEnvironment#DEFAULT}.
167
	 *
168
	 *  @param text is the structured text string.
169
	 *
170
	 *  @param  state can be used to specify that the <code>text</code>
171
	 *          argument is the continuation of text submitted in a
172
	 *          previous call and/or to receive information to pass to
173
	 *          continuation calls.
174
	 *          For more details, see <a href="#state">State</a> above.
175
	 *          <p>If all calls to this method are independent from one another,
176
	 *          this argument should be specified as <code>null</code>.
177
	 *
178
	 *  @return the structured text with directional formatting
179
	 *          characters added at proper locations to ensure correct
180
	 *          presentation.
181
	 */
182
	public static String leanToFullText(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
183
		if (processor == null)
184
			return text;
185
		return STextImpl.leanToFullText(processor, features, environment, text, state);
186
	}
187
188
	/**
189
	 *  Given a <i>lean</i> string, compute the positions of each of its
190
	 *  characters within the corresponding <i>full</i> string.
191
	 *
192
	 *  @param  processor designates one of the registered processors.
193
	 *          It can be a string containing a keyword according to
194
	 *          the processor type, or a processor reference.
195
	 *          For more details, see above <a href="#processor">
196
	 *          How to Specify a Processor</a>.
197
	 *          <p>If this argument is <code>null</code>, this method
198
	 *          returns an identity map.
199
	 *
200
	 *  @param  features specifies features that affect the processor's
201
	 *          behavior.
202
	 *          <p>This argument may be specified as <code>null</code>,
203
	 *          in which case the processor will use its standard features
204
	 *          (as returned by the processor
205
	 *          {@link ISTextProcessor#getFeatures getFeatures}
206
	 *          method).
207
	 *
208
	 *  @param  environment specifies an environment whose characteristics
209
	 *          may affect the processor's behavior.
210
	 *          <p>This argument may be specified as <code>null</code>,
211
	 *          in which case the processor will assume a standard
212
	 *          environment as specified in
213
	 *          {@link STextEnvironment#DEFAULT}.
214
	 *
215
	 *  @param text is the structured text string.
216
	 *
217
	 *  @param  state can be used to specify that the <code>text</code>
218
	 *          argument is the continuation of text submitted in a
219
	 *          previous call and/or to receive information to pass to
220
	 *          continuation calls.
221
	 *          For more details, see <a href="#state">State</a> above.
222
	 *          <p>If all calls to this method are independent from one another,
223
	 *          this argument should be specified as <code>null</code>.
224
	 *
225
	 *  @return an array of integers with one element for each of the characters
226
	 *          in the <code>text</code> argument, equal to the offset of the
227
	 *          corresponding character in the <i>full</i> string.
228
	 */
229
	public static int[] leanToFullMap(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
230
		if (processor == null) {
231
			int[] map = new int[text.length()];
232
			for (int i = 0; i < map.length; i++)
233
				map[i] = i;
234
			return map;
235
		}
236
		return STextImpl.leanToFullMap(processor, features, environment, text, state);
237
	}
238
239
	/**
240
	 *  Given a <i>lean</i> string, compute the offsets of characters
241
	 *  before which directional formatting characters must be added
242
	 *  in order to ensure correct presentation.
243
	 *
244
	 *  <p>Only LRMs (for a string with LTR base direction) and RLMs (for
245
	 *  a string with RTL base direction) are considered. Leading and
246
	 *  trailing LRE, RLE and PDF which might be prefixed or suffixed
247
	 *  depending on the {@link STextEnvironment#getOrientation orientation} of the
248
	 *  GUI component used for display are not reflected in this method.
249
	 *
250
	 *  @param  processor designates one of the registered processors.
251
	 *          It can be a string containing a keyword according to
252
	 *          the processor type, or a processor reference.
253
	 *          For more details, see above <a href="#processor">
254
	 *          How to Specify a Processor</a>.
255
	 *          <p>If this argument is <code>null</code>, this method
256
	 *          returns an empty array.
257
	 *
258
	 *  @param  features specifies features that affect the processor's
259
	 *          behavior.
260
	 *          <p>This argument may be specified as <code>null</code>,
261
	 *          in which case the processor will use its standard features
262
	 *          (as returned by the processor
263
	 *          {@link ISTextProcessor#getFeatures getFeatures}
264
	 *          method).
265
	 *
266
	 *  @param  environment specifies an environment whose characteristics
267
	 *          may affect the processor's behavior.
268
	 *          <p>This argument may be specified as <code>null</code>,
269
	 *          in which case the processor will assume a standard
270
	 *          environment as specified in
271
	 *          {@link STextEnvironment#DEFAULT}.
272
	 *
273
	 *  @param text is the structured text string.
274
	 *
275
	 *  @param  state can be used to specify that the <code>text</code>
276
	 *          argument is the continuation of text submitted in a
277
	 *          previous call and/or to receive information to pass to
278
	 *          continuation calls.
279
	 *          For more details, see <a href="#state">State</a> above.
280
	 *          <p>If all calls to this method are independent from one another,
281
	 *          this argument should be specified as <code>null</code>.
282
	 *
283
	 *  @return an array of offsets to the characters in the <code>text</code>
284
	 *          argument before which directional marks must be
285
	 *          added to ensure correct presentation.
286
	 *          The offsets are sorted in ascending order.
287
	 */
288
	public static int[] leanBidiCharOffsets(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
289
		if (processor == null)
290
			return EMPTY_INT_ARRAY;
291
		return STextImpl.leanBidiCharOffsets(processor, features, environment, text, state);
292
	}
293
294
	/**
295
	 *  Remove directional formatting characters which were added to a
296
	 *  structured text string to ensure correct presentation.
297
	 *
298
	 *  @param  processor designates one of the registered processors.
299
	 *          It can be a string containing a keyword according to
300
	 *          the processor type, or a processor reference.
301
	 *          For more details, see above <a href="#processor">
302
	 *          How to Specify a Processor</a>.
303
	 *          <p>If this argument is <code>null</code>, this method
304
	 *          returns the <code>text</code> string.
305
	 *
306
	 *  @param  features specifies features that affect the processor's
307
	 *          behavior.
308
	 *          <p>This argument may be specified as <code>null</code>,
309
	 *          in which case the processor will use its standard features
310
	 *          (as returned by the processor
311
	 *          {@link ISTextProcessor#getFeatures getFeatures}
312
	 *          method).
313
	 *
314
	 *  @param  environment specifies an environment whose characteristics
315
	 *          may affect the processor's behavior.
316
	 *          <p>This argument may be specified as <code>null</code>,
317
	 *          in which case the processor will assume a standard
318
	 *          environment as specified in
319
	 *          {@link STextEnvironment#DEFAULT}.
320
	 *
321
	 *  @param text is the structured text string including
322
	 *         directional formatting characters.
323
	 *
324
	 *  @param  state can be used to specify that the <code>text</code>
325
	 *          argument is the continuation of text submitted in a
326
	 *          previous call and/or to receive information to pass to
327
	 *          continuation calls.
328
	 *          For more details, see <a href="#state">State</a> above.
329
	 *          <p>If all calls to this method are independent from one another,
330
	 *          this argument should be specified as <code>null</code>.
331
	 *
332
	 *  @return the structured text string without directional formatting
333
	 *          characters which might have been added by processing it
334
	 *          with {@link #leanToFullText leanToFullText}.
335
	 *
336
	 */
337
	public static String fullToLeanText(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
338
		if (processor == null)
339
			return text;
340
		return STextImpl.fullToLeanText(processor, features, environment, text, state);
341
	}
342
343
	/**
344
	 *  Given a <i>full</i> string, compute the positions of each of its
345
	 *  characters within the corresponding <i>lean</i> string.
346
	 *
347
	 *  @param  processor designates one of the registered processors.
348
	 *          It can be a string containing a keyword according to
349
	 *          the processor type, or a processor reference.
350
	 *          For more details, see above <a href="#processor">
351
	 *          How to Specify a Processor</a>.
352
	 *          <p>If this argument is <code>null</code>, this method
353
	 *          returns an identity map.
354
	 *
355
	 *  @param  features specifies features that affect the processor's
356
	 *          behavior.
357
	 *          <p>This argument may be specified as <code>null</code>,
358
	 *          in which case the processor will use its standard features
359
	 *          (as returned by the processor
360
	 *          {@link ISTextProcessor#getFeatures getFeatures}
361
	 *          method).
362
	 *
363
	 *  @param  environment specifies an environment whose characteristics
364
	 *          may affect the processor's behavior.
365
	 *          <p>This argument may be specified as <code>null</code>,
366
	 *          in which case the processor will assume a standard
367
	 *          environment as specified in
368
	 *          {@link STextEnvironment#DEFAULT}.
369
	 *
370
	 *  @param  text is the structured text string including
371
	 *          directional formatting characters.
372
	 *
373
	 *  @param  state can be used to specify that the <code>text</code>
374
	 *          argument is the continuation of text submitted in a
375
	 *          previous call and/or to receive information to pass to
376
	 *          continuation calls.
377
	 *          For more details, see <a href="#state">State</a> above.
378
	 *          <p>If all calls to this method are independent from one another,
379
	 *          this argument should be specified as <code>null</code>.
380
	 *
381
	 *  @return an array of integers with one element for each of the characters
382
	 *          in the <code>text</code> argument, equal to the offset of the
383
	 *          corresponding character in the <i>lean</i> string.
384
	 *          If there is no corresponding
385
	 *          character in the <i>lean</i> string (because the
386
	 *          specified character is a directional formatting character
387
	 *          added when invoking {@link #leanToFullText leanToFullText}),
388
	 *          the value returned for this character is -1.
389
	 */
390
	public static int[] fullToLeanMap(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
391
		if (processor == null) {
392
			int[] map = new int[text.length()];
393
			for (int i = 0; i < map.length; i++)
394
				map[i] = i;
395
			return map;
396
		}
397
		return STextImpl.fullToLeanMap(processor, features, environment, text, state);
398
	}
399
400
	/**
401
	 *  Given a <i>full</i> string, return the offsets of characters
402
	 *  which are directional formatting characters that have been added
403
	 *  in order to ensure correct presentation.
404
	 *
405
	 *  <p>LRMs (for a string with LTR base direction), RLMs (for
406
	 *  a string with RTL base direction) are considered as well as
407
	 *  leading and trailing LRE, RLE and PDF which might be prefixed or suffixed
408
	 *  depending on the {@link STextEnvironment#getOrientation orientation}
409
	 *  of the GUI component used for display.
410
	 *
411
	 *  @param  processor designates one of the registered processors.
412
	 *          It can be a string containing a keyword according to
413
	 *          the processor type, or a processor reference.
414
	 *          For more details, see above <a href="#processor">
415
	 *          How to Specify a Processor</a>.
416
	 *          <p>If this argument is <code>null</code>, this method
417
	 *          returns an empty array.
418
	 *
419
	 *  @param  features specifies features that affect the processor's
420
	 *          behavior.
421
	 *          <p>This argument may be specified as <code>null</code>,
422
	 *          in which case the processor will use its standard features
423
	 *          (as returned by the processor
424
	 *          {@link ISTextProcessor#getFeatures getFeatures}
425
	 *          method).
426
	 *
427
	 *  @param  environment specifies an environment whose characteristics
428
	 *          may affect the processor's behavior.
429
	 *          <p>This argument may be specified as <code>null</code>,
430
	 *          in which case the processor will assume a standard
431
	 *          environment as specified in
432
	 *          {@link STextEnvironment#DEFAULT}.
433
	 *
434
	 *  @param  text is the structured text string including
435
	 *          directional formatting characters.
436
	 *
437
	 *  @param  state can be used to specify that the <code>text</code>
438
	 *          argument is the continuation of text submitted in a
439
	 *          previous call and/or to receive information to pass to
440
	 *          continuation calls.
441
	 *          For more details, see <a href="#state">State</a> above.
442
	 *          <p>If all calls to this method are independent from one another,
443
	 *          this argument should be specified as <code>null</code>.
444
	 *
445
	 *  @return an array of offsets to the characters in the <code>text</code>
446
	 *          argument which are directional formatting characters
447
	 *          added to ensure correct presentation.
448
	 *          The offsets are sorted in ascending order.
449
	 */
450
	public static int[] fullBidiCharOffsets(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
451
		if (processor == null)
452
			return EMPTY_INT_ARRAY;
453
		return STextImpl.fullBidiCharOffsets(processor, features, environment, text, state);
454
	}
455
456
	/**
457
	 *  Get the base direction of a structured text.
458
	 *  This base direction may depend on
459
	 *  whether the text contains Arabic or Hebrew words
460
	 *  (if it contains both, the first Arabic or Hebrew letter in the
461
	 *  text determines which is the governing script) and on
462
	 *  whether the GUI is {@link STextEnvironment#getMirrored mirrored}.
463
	 *
464
	 *  @param  processor designates one of the registered processors.
465
	 *          It can be a string containing a keyword according to
466
	 *          the processor type, or a processor reference.
467
	 *          For more details, see above <a href="#processor">
468
	 *          How to Specify a Processor</a>.
469
	 *          <p>If this argument is <code>null</code>, this method
470
	 *          returns {@link STextFeatures#DIR_LTR}.
471
	 *
472
	 *  @param  features specifies features that affect the processor's
473
	 *          behavior.
474
	 *          <p>This argument may be specified as <code>null</code>,
475
	 *          in which case the processor will use its standard features
476
	 *          (as returned by the processor
477
	 *          {@link ISTextProcessor#getFeatures getFeatures}
478
	 *          method).
479
	 *
480
	 *  @param  environment specifies an environment whose characteristics
481
	 *          may affect the processor's behavior.
482
	 *          <p>This argument may be specified as <code>null</code>,
483
	 *          in which case the processor will assume a standard
484
	 *          environment as specified in
485
	 *          {@link STextEnvironment#DEFAULT}.
486
	 *
487
	 *  @param  text is the structured text string.
488
	 *
489
	 *  @return the base direction of the structured text.
490
	 *          It is one of the values {@link STextFeatures#DIR_LTR}
491
	 *          or {@link STextFeatures#DIR_RTL}.
492
	 */
493
	public static int getCurDirection(Object processor, STextFeatures features, STextEnvironment environment, String text) {
494
		return STextImpl.getCurDirection(processor, features, environment, text, null);
495
	}
496
497
}
(-)src/org/eclipse/equinox/bidi/STextEnvironment.java (+326 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.ISTextProcessor;
15
import org.eclipse.equinox.bidi.internal.STextActivator;
16
17
/**
18
 *  This class defines certain details of the environment within which
19
 *  structured text strings 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
 *  All methods in {@link STextEngine} have a STextEnvironment
25
 *  argument. If this argument is specified as <code>null</code>, the
26
 *  {@link #DEFAULT} environment is used.
27
 *
28
 *  <h2>Code Samples</h2>
29
 *  <p>Example (set all environment parameters)
30
 *  <pre>
31
 *
32
 *    STextEnvironment myEnv = new STextEnvironment("he_IL", true, STextEnvironment.ORIENT_RTL);
33
 *
34
 *  </pre>
35
 *  <p>
36
 *  This class also provides a number of convenience methods related to the environment.
37
 *  <p>&nbsp;</p>
38
 *  @see ISTextProcessor#getFeatures
39
 *
40
 *  @author Matitiahu Allouche
41
 */
42
public class STextEnvironment {
43
44
	/**
45
	 *  Constant specifying that the orientation of the GUI component
46
	 *  where a structured text will be displayed is LTR.
47
	 *  It can appear as <code>orientation</code> argument for the
48
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
49
	 *  and as value returned by {@link #getOrientation}.
50
	 */
51
	public static final int ORIENT_LTR = 0;
52
53
	/**
54
	 *  Constant specifying that the orientation of the GUI component
55
	 *  where a structured text will be displayed is RTL.
56
	 *  It can appear as <code>orientation</code> argument for the
57
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
58
	 *  and as value returned by {@link #getOrientation}.
59
	 */
60
	public static final int ORIENT_RTL = 1;
61
62
	/**
63
	 *  Constant specifying that the orientation of the GUI component
64
	 *  where a structured text will be displayed is contextual with
65
	 *  a default of LTR (if no strong character appears in the text).
66
	 *  It can appear as <code>orientation</code> argument for the
67
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
68
	 *  and as value returned by {@link #getOrientation}.
69
	 */
70
	public static final int ORIENT_CONTEXTUAL_LTR = 2;
71
72
	/**
73
	 *  Constant specifying that the orientation of the GUI component
74
	 *  where a structured text will be displayed is contextual with
75
	 *  a default of RTL (if no strong character appears in the text).
76
	 *  It can appear as <code>orientation</code> argument for the
77
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
78
	 *  and as value returned by {@link #getOrientation}.
79
	 */
80
	public static final int ORIENT_CONTEXTUAL_RTL = 3;
81
82
	/**
83
	 *  Constant specifying that the orientation of the GUI component
84
	 *  where a structured text will be displayed is not known.
85
	 *  Directional formatting characters must be added as prefix and
86
	 *  suffix whenever a <i>full</i> text is generated using
87
	 *  {@link STextEngine#leanToFullText leanToFullText}.
88
	 *  It can appear as <code>orientation</code> argument for the
89
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
90
	 *  and as value returned by {@link #getOrientation}.
91
	 */
92
	public static final int ORIENT_UNKNOWN = 4;
93
94
	/**
95
	 *  Constant specifying that whatever the orientation of the
96
	 *  GUI component where a structured text will be displayed, no
97
	 *  directional formatting characters must be added as prefix or
98
	 *  suffix when a <i>full</i> text is generated using
99
	 *  {@link STextEngine#leanToFullText leanToFullText}.
100
	 *  It can appear as <code>orientation</code> argument for the
101
	 *  {@link STextEnvironment#STextEnvironment STextEnvironment constructor}
102
	 *  and as value returned by {@link #getOrientation}.
103
	 */
104
	public static final int ORIENT_IGNORE = 5;
105
106
	/**
107
	 *  Pre-defined <code>STextEnvironment</code> instance with values
108
	 *  for a non-mirrored GUI and a Left-to-Right presentation component.<br>
109
	 *  The language is set to <code>null</code>, which defaults to the language
110
	 *  of the current default locale.
111
	 */
112
	public static final STextEnvironment DEFAULT = new STextEnvironment(null, false, ORIENT_LTR);
113
114
	/**
115
	 *  This string is a 2-letters code representing a language as defined by
116
	 *  ISO-639. If left as <code>null</code>, it defaults to the language
117
	 *  of the current default locale.
118
	 */
119
	final String language;
120
121
	/**
122
	 *  Flag specifying that structured text processed under this environment
123
	 *  should assume that the GUI is mirrored (globally going from right to left).
124
	 */
125
	final boolean mirrored;
126
127
	/** Specify the orientation (a.k.a. base direction) of the GUI
128
	 *  component in which the <i>full</i> structured text will
129
	 *  be displayed.
130
	 */
131
	final int orientation;
132
133
	static Locale defaultLocale;
134
	static String defaultLanguage;
135
	static boolean defaultBidi;
136
	boolean bidiFlag;
137
138
	/**
139
	 *  Constructor
140
	 *
141
	 *  @param lang represents the language to be used in this environment.
142
	 *          It should be specified as a 2-letters code as defined by
143
	 *          ISO-639.<br>
144
	 *          If longer than 2 letters, the extra letters are ignored.<br>
145
	 *          If set to <code>null</code>, it defaults to the language
146
	 *          of the default locale.
147
	 *  @see #getLanguage
148
	 *
149
	 *  @param mirrored specifies if the GUI is mirrored.
150
	 *  @see #getMirrored
151
	 *
152
	 *  @param orientation specifies the orientation of the component
153
	 *          which is to display the structured text. It must be
154
	 *          one of the values
155
	 *          {@link #ORIENT_LTR ORIENT_LTR},
156
	 *          {@link #ORIENT_LTR ORIENT_RTL},
157
	 *          {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
158
	 *          {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
159
	 *          {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
160
	 *          {@link #ORIENT_IGNORE ORIENT_IGNORE}.<br>
161
	 *          If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}.
162
	 *  @see #getOrientation
163
	 */
164
	public STextEnvironment(String lang, boolean mirrored, int orientation) {
165
		if (lang == null) {
166
			language = null;
167
		} else {
168
			if (lang.length() > 2)
169
				language = lang.substring(0, 2);
170
			else
171
				language = lang;
172
			bidiFlag = isBidiLanguage(language);
173
		}
174
		this.mirrored = mirrored;
175
		this.orientation = orientation >= ORIENT_LTR && orientation <= ORIENT_IGNORE ? orientation : ORIENT_UNKNOWN;
176
	}
177
178
	/**
179
	 *  Return a 2-letters code representing a language as defined by
180
	 *  ISO-639. If equal to <code>null</code>, it defaults to the language
181
	 *  of the current default locale.
182
	 */
183
	public String getLanguage() {
184
		return language;
185
	}
186
187
	/**
188
	 *  Return a flag indicating that structured text processed
189
	 *  within this environment should assume that the GUI is mirrored
190
	 * (globally going from right to left).
191
	 */
192
	public boolean getMirrored() {
193
		return mirrored;
194
	}
195
196
	/** Return the orientation (a.k.a. base direction) of the GUI
197
	 *  component in which the <i>full</i> structured text
198
	 *  will be displayed.<br>
199
	 *  The orientation must have one of the values
200
	 *  {@link #ORIENT_LTR ORIENT_LTR},
201
	 *  {@link #ORIENT_LTR ORIENT_RTL},
202
	 *  {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR},
203
	 *  {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL},
204
	 *  {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or
205
	 *  {@link #ORIENT_IGNORE ORIENT_IGNORE}.
206
	  *  <p>
207
	 *  When the orientation is <code>ORIENT_LTR</code> and the
208
	 *  structured text has a RTL base direction,
209
	 *  {@link STextEngine#leanToFullText leanToFullText}
210
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
211
	 *  end.
212
	 *  <p>
213
	 *  When the orientation is <code>ORIENT_RTL</code> and the
214
	 *  structured text has a LTR base direction,
215
	 *  {@link STextEngine#leanToFullText leanToFullText}
216
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
217
	 *  end.
218
	 *  <p>
219
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
220
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
221
	 *  to a RTL orientation while the structured text has a LTR base
222
	 *  direction, {@link STextEngine#leanToFullText leanToFullText}
223
	 *  adds LRM at the head of the <i>full</i> text.
224
	 *  <p>
225
	 *  When the orientation is <code>ORIENT_CONTEXTUAL_LTR</code> or
226
	 *  <code>ORIENT_CONTEXTUAL_RTL</code> and the data content would resolve
227
	 *  to a LTR orientation while the structured text has a RTL base
228
	 *  direction, {@link STextEngine#leanToFullText leanToFullText}
229
	 *  adds RLM at the head of the <i>full</i> text.
230
	 *  <p>
231
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
232
	 *  structured text has a LTR base direction,
233
	 *  {@link STextEngine#leanToFullText leanToFullText}
234
	 *  adds LRE+LRM at the head of the <i>full</i> text and LRM+PDF at its
235
	 *  end.
236
	 *  <p>
237
	 *  When the orientation is <code>ORIENT_UNKNOWN</code> and the
238
	 *  structured text has a RTL base direction,
239
	 *  {@link STextEngine#leanToFullText leanToFullText}
240
	 *  adds RLE+RLM at the head of the <i>full</i> text and RLM+PDF at its
241
	 *  end.
242
	 *  <p>
243
	 *  When the orientation is <code>ORIENT_IGNORE</code>,
244
	 *  {@link STextEngine#leanToFullText leanToFullText} does not add any directional
245
	 *  formatting characters as either prefix or suffix of the <i>full</i> text.
246
	 *  <p>
247
	 */
248
	public int getOrientation() {
249
		return orientation;
250
	}
251
252
	/**
253
	 *  Check whether the current language uses a
254
	 *  bidi script (Arabic, Hebrew, Farsi or Urdu).
255
	 *
256
	 *  @return <code>true</code> if the current language uses a bidi script.
257
	 *          The language may have been set explicitly when creating the
258
	 *          <code>STextEnvironment</code> instance, or it may have
259
	 *          defaulted to the language of the current default locale.
260
	 *  @see #getLanguage
261
	 */
262
	public boolean isBidi() {
263
		if (defaultLanguage != null && defaultLocale.equals(getDefaultLocale()))
264
			return defaultBidi;
265
266
		if (language == null) {
267
			defaultLocale = getDefaultLocale();
268
			defaultLanguage = defaultLocale.getLanguage();
269
			defaultBidi = isBidiLanguage(defaultLanguage);
270
			return defaultBidi;
271
		}
272
273
		return bidiFlag;
274
	}
275
276
	static boolean isBidiLanguage(String lang) {
277
		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$
278
	}
279
280
	static String lineSep;
281
282
	/**
283
	 *  Retrieve the string which represents a line separator in this environment.
284
	 *
285
	 *  @return the string which is used as line separator (e.g. CRLF).
286
	 */
287
	public static String getLineSep() {
288
		// use bundle properties
289
		if (lineSep == null) {
290
			//          lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$
291
			lineSep = getProperty("line.separator"); //$NON-NLS-1$/
292
		}
293
		return lineSep;
294
	}
295
296
	static String osName;
297
	static boolean flagOS;
298
299
	private static String getProperty(String key) {
300
		// use bundle properties
301
		//      osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
302
		STextActivator sTextActivator = STextActivator.getInstance();
303
		return sTextActivator.getProperty(key);
304
	}
305
306
	private Locale getDefaultLocale() {
307
		STextActivator sTextActivator = STextActivator.getInstance();
308
		return sTextActivator.getDefaultLocale();
309
	}
310
311
	/**
312
	 *  Check if the current OS is supported by the structured text packages.
313
	 *
314
	 *  @return <code>true</code> if the current OS is supported.
315
	 */
316
	public static boolean isSupportedOS() {
317
		if (osName == null) {
318
			// use bundle properties
319
			// osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
320
			osName = getProperty("os.name").toLowerCase(); //$NON-NLS-1$/
321
			flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$
322
		}
323
		return flagOS;
324
	}
325
326
}
(-)src/org/eclipse/equinox/bidi/STextStringRecord.java (+192 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.STextStringProcessor;
15
16
/**
17
 *  This class records strings which are structured text. 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. When the pool is full,
24
 *  each new element overrides the oldest element in the list.
25
 */
26
public class STextStringRecord {
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 STextStringRecord[] records = new STextStringRecord[POOLSIZE];
40
41
	// structured text types
42
	private static final String[] types = STextStringProcessor.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 the string to record
60
	 *
61
	 *  @param  triplets
62
	 *          array of short integers, the number of elements in the array
63
	 *          must be a multiple of 3, so that the array is made of one or
64
	 *          more triplets of short integers.
65
	 *          <p>
66
	 *          The first element in each triplet is the beginning offset of a
67
	 *          susbstring of <code>string</code> which is a structured text.
68
	 *          <p>
69
	 *          The second element in each triplet is the ending offset of a
70
	 *          susbstring of <code>string</code> which is a structured text.
71
	 *          This offset points to one position beyond the last
72
	 *          character of the substring.
73
	 *          <p>
74
	 *          The third element in each triplet is the numeric type of the
75
	 *          structured text.<br>
76
	 *          The type of a structured text must be one of the string
77
	 *          values listed in {@link ISTextTypes}.<br>
78
	 *          The corresponding numeric type must be obtained using the
79
	 *          method {@link #typeStringToShort typeStringToShort}.
80
	 */
81
	public STextStringRecord(String string, short[] triplets) {
82
		if (string == null || triplets == null)
83
			throw new IllegalArgumentException("The string and triplets argument must not be null!"); //$NON-NLS-1$
84
		if ((triplets.length % 3) != 0)
85
			throw new IllegalArgumentException("The number of elements in triplets must be a multiple of 3!"); //$NON-NLS-1$
86
		for (int i = 2; i < triplets.length; i += 3)
87
			if (triplets[i] < 0 || triplets[i] > MAXTYPE)
88
				throw new IllegalArgumentException("Illegal type value in element" + i); //$NON-NLS-1$
89
		strRef = new SoftReference(string);
90
		triRef = new SoftReference(triplets);
91
		hash = string.hashCode();
92
	}
93
94
	/**
95
	 *  Get the numeric type of a structured text given its string type.
96
	 *
97
	 *  @param  type type of structured text as string. It must be one
98
	 *          of the strings listed in {@link ISTextTypes}.
99
	 *
100
	 *  @return a value which is the corresponding numeric type. If
101
	 *          <code>type</code> is invalid, the method returns <code>-1</code>.
102
	 */
103
	public static short typeStringToShort(String type) {
104
		for (int i = 0; i < types.length; i++)
105
			if (types[i].equals(type))
106
				return (short) i;
107
		return -1;
108
	}
109
110
	/**
111
	 *  Get the string type of a structured text given its numeric type.
112
	 *
113
	 *  @param shType
114
	 *         the numeric type of a structured text. It should be a value
115
	 *         obtained using {@link #typeStringToShort typeStringToShort}.
116
	 *
117
	 *  @return the corresponding string type. If <code>shType</code> is invalid,
118
	 *          the method returns <code>null</code>.
119
	 */
120
	public static String typeShortToString(short shType) {
121
		if (shType < 0 || shType > MAXTYPE)
122
			return null;
123
		return types[shType];
124
	}
125
126
	/**
127
	 *  Add a record to the pool.
128
	 *
129
	 *  @param record a STextStringRecord instance
130
	 */
131
	public static synchronized void add(STextStringRecord record) {
132
		if (last < MAXINDEX)
133
			last++;
134
		else
135
			last = 0;
136
		records[last] = record;
137
	}
138
139
	/**
140
	 *  Check if a string is recorded and retrieve its triplets.
141
	 *
142
	 *  @param  string the string to check
143
	 *
144
	 *  @return <code>null</code> if the string is not recorded in the pool;
145
	 *          otherwise, return the triplets associated with this string.
146
	 */
147
	public static short[] getTriplets(String string) {
148
		if (records[0] == null) // no records at all
149
			return null;
150
		if (string == null || string.length() < 1)
151
			return null;
152
		STextStringRecord rec;
153
		String str;
154
		short[] tri;
155
		int myLast = last;
156
		int hash = string.hashCode();
157
		for (int i = myLast; i >= 0; i--) {
158
			rec = records[i];
159
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
160
				return tri;
161
			}
162
		}
163
		if (records[MAXINDEX] == null) // never recorded past myLast
164
			return null;
165
		for (int i = MAXINDEX; i > myLast; i--) {
166
			rec = records[i];
167
			if (hash == rec.hash && (tri = (short[]) rec.triRef.get()) != null && (str = (String) rec.strRef.get()) != null && string.equals(str)) {
168
				return tri;
169
			}
170
		}
171
		return null;
172
	}
173
174
	/**
175
	 *  Clear the pool. All elements of the pool are erased and any associated
176
	 *  memory is freed.
177
	 *
178
	 */
179
	public static synchronized void clear() {
180
		for (int i = 0; i <= MAXINDEX; i++) {
181
			STextStringRecord sr = records[i];
182
			if (sr == null)
183
				break;
184
			sr.hash = 0;
185
			sr.strRef.clear();
186
			sr.triRef.clear();
187
			records[i] = null;
188
		}
189
		last = MAXINDEX;
190
	}
191
192
}
(-)src/org/eclipse/equinox/bidi/STextUtil.java (+313 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.STextFeatures;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
/**
17
 *  This class provides a number of convenience functions facilitating the
18
 *  processing of structured text.
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 STextUtil {
26
27
	/**
28
	 *  prevent instantiation
29
	 */
30
	private STextUtil() {
31
		// empty
32
	}
33
34
	/** This is a convenience method which can add directional marks in a given
35
	 *  text before the characters specified in the given array of offsets,
36
	 *  and can add a prefix and/or a suffix of directional formatting characters.
37
	 *  This can be used for instance after obtaining offsets by calling
38
	 *  {@link STextEngine#leanBidiCharOffsets leanBidiCharOffsets} in order to
39
	 *  produce a <i>full</i> text corresponding to the source text.
40
	 *  The directional formatting characters that will be added at the given
41
	 *  offsets will be LRMs for structured text strings with LTR base direction
42
	 *  and RLMs for strings with RTL base direction. Leading and
43
	 *  trailing LRE, RLE and PDF which might be needed as prefix or suffix
44
	 *  depending on the orientation of the GUI component used for display
45
	 *  may be added depending on argument <code>affix</code>.
46
	 *
47
	 *  @param  text is the structured text string
48
	 *
49
	 *  @param  offsets is an array of offsets to characters in <code>text</code>
50
	 *          before which an LRM or RLM will be inserted.
51
	 *          Members of the array must be non-negative numbers smaller
52
	 *          than the length of <code>text</code>.
53
	 *          The array must be sorted in ascending order without duplicates.
54
	 *          This argument may be null if there are no marks to add.
55
	 *
56
	 *  @param  direction specifies the base direction of the structured text.
57
	 *          It must be one of the values {@link STextFeatures#DIR_LTR} or
58
	 *          {@link STextFeatures#DIR_RTL}.
59
	 *
60
	 *  @param  affix specifies if a prefix and a suffix should be added to
61
	 *          the result to make sure that the <code>direction</code>
62
	 *          specified as third argument is honored even if the string
63
	 *          is displayed in a GUI component with a different orientation.
64
	 *
65
	 *  @return a string corresponding to the source <code>text</code> with
66
	 *          directional marks (LRMs or RLMs) added at the specified offsets,
67
	 *          and directional formatting characters (LRE, RLE, PDF) added
68
	 *          as prefix and suffix if so required.
69
	 */
70
	public static String insertMarks(String text, int[] offsets, int direction, boolean affix) {
71
		int textLen = text.length();
72
		if (textLen == 0)
73
			return ""; //$NON-NLS-1$
74
75
		String curPrefix, curSuffix, full;
76
		char curMark, c;
77
		char[] fullChars;
78
		if (direction == STextFeatures.DIR_LTR) {
79
			curMark = LRM;
80
			curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$
81
			curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$
82
		} else {
83
			curMark = RLM;
84
			curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$
85
			curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$
86
		}
87
		// add marks at offsets
88
		if ((offsets != null) && (offsets.length > 0)) {
89
			int offLen = offsets.length;
90
			fullChars = new char[textLen + offLen];
91
			int added = 0;
92
			for (int i = 0, j = 0; i < textLen; i++) {
93
				c = text.charAt(i);
94
				if ((j < offLen) && (i == offsets[j])) {
95
					fullChars[i + added] = curMark;
96
					added++;
97
					j++;
98
				}
99
				fullChars[i + added] = c;
100
			}
101
			full = new String(fullChars);
102
		} else {
103
			full = text;
104
		}
105
		if (affix)
106
			return curPrefix + full + curSuffix;
107
		return full;
108
	}
109
110
	/*************************************************************************/
111
	/*                                                                       */
112
	/*  The following code is provided for compatibility with TextProcessor  */
113
	/*                                                                       */
114
	/*************************************************************************/
115
116
	//  The default set of separators to use to segment a string.
117
	private static final String defaultSeparators = ".:/\\"; //$NON-NLS-1$
118
	// left to right mark
119
	private static final char LRM = '\u200e';
120
	// left to right mark
121
	private static final char RLM = '\u200f';
122
	// left to right embedding
123
	private static final char LRE = '\u202a';
124
	// right to left embedding
125
	private static final char RLE = '\u202b';
126
	// pop directional format
127
	private static final char PDF = '\u202c';
128
129
	static boolean isProcessingNeeded() {
130
		if (!STextEnvironment.isSupportedOS())
131
			return false;
132
		return STextEnvironment.DEFAULT.isBidi();
133
	}
134
135
	/**
136
	 *  Process the given text and return a string with appropriate
137
	 *  directional formatting characters if the locale is a bidi locale.
138
	 *  This is equivalent to calling
139
	 *  {@link #process(String str, String separators)} with the default
140
	 *  set of separators (dot, colon, slash, backslash).
141
	 *
142
	 *  @param  str the text to be processed.
143
	 *
144
	 *  @return the processed string.
145
	 */
146
	public static String process(String str) {
147
		return process(str, defaultSeparators);
148
	}
149
150
	/**
151
	 *  Process a string that has a particular semantic meaning to render
152
	 *  it correctly on bidi locales. This is done by adding directional
153
	 *  formatting characters so that presentation using the Unicode
154
	 *  Bidirectional Algorithm will provide the expected result.
155
	 *  The text is segmented according to the provided separators.
156
	 *  Each segment has the Unicode Bidi Algorithm applied to it,
157
	 *  but as a whole, the string is oriented left to right.
158
	 *  <p>
159
	 *  For example, a file path such as <tt>d:\myfolder\FOLDER\MYFILE.java</tt>
160
	 *  (where capital letters indicate RTL text) should render as
161
	 *  <tt>d:\myfolder\REDLOF\ELIFYM.java</tt>.</p>
162
	 *  <p>
163
	 *  NOTE: this method inserts directional formatting characters into the
164
	 *  text. Methods like <code>String.equals(String)</code> and
165
	 *  <code>String.length()</code> called on the resulting string will not
166
	 *  return the same values as would be returned for the original string.</p>
167
	 *
168
	 *  @param  str the text to process.
169
	 *
170
	 *  @param  separators separators by which the string will be segmented.
171
	 *          If <code>null</code>, the default separators are used
172
	 *          (dot, colon, slash, backslash).
173
	 *
174
	 *  @return the processed string.
175
	 *          If <code>str</code> is <code>null</code>,
176
	 *          or of length 0, or if the current locale is not a bidi one,
177
	 *          return the original string.
178
	 */
179
	public static String process(String str, String separators) {
180
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
181
			return str;
182
183
		// do not process a string that has already been processed.
184
		if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF)
185
			return str;
186
187
		// do not process a string if all the following conditions are true:
188
		//  a) it has no RTL characters
189
		//  b) it starts with a LTR character
190
		//  c) it ends with a LTR character or a digit
191
		boolean isStringBidi = false;
192
		int strLength = str.length();
193
		char c;
194
		for (int i = 0; i < strLength; i++) {
195
			c = str.charAt(i);
196
			if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) {
197
				isStringBidi = true;
198
				break;
199
			}
200
		}
201
		while (!isStringBidi) {
202
			if (!Character.isLetter(str.charAt(0)))
203
				break;
204
			c = str.charAt(strLength - 1);
205
			if (!Character.isDigit(c) && !Character.isLetter(c))
206
				break;
207
			return str;
208
		}
209
210
		if (separators == null)
211
			separators = defaultSeparators;
212
213
		// make sure that LRE/PDF are added around the string
214
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
215
		STextFeatures features = new STextFeatures(separators, 0, -1, -1, false, false);
216
		return STextEngine.leanToFullText(new STextProcessor(), features, env, str, null);
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 structured text.
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 structured text. It must
241
	 *          be one of the values in {@link ISTextTypes} 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
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
260
		return STextEngine.leanToFullText(type, null, env, str, null);
261
	}
262
263
	/**
264
	 *  Remove directional formatting characters in the given string that
265
	 *  were inserted by one of the {@link #process process} methods.
266
	 *
267
	 *  @param  str string with directional characters to remove.
268
	 *
269
	 *  @return string with no directional formatting characters.
270
	 */
271
	public static String deprocess(String str) {
272
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
273
			return str;
274
275
		StringBuffer buf = new StringBuffer();
276
		int strLen = str.length();
277
		for (int i = 0; i < strLen; i++) {
278
			char c = str.charAt(i);
279
			switch (c) {
280
				case LRM :
281
					continue;
282
				case LRE :
283
					continue;
284
				case PDF :
285
					continue;
286
				default :
287
					buf.append(c);
288
			}
289
		}
290
		return buf.toString();
291
	}
292
293
	/**
294
	 *  Remove directional formatting characters in the given string that
295
	 *  were inserted by the {@link #processTyped processTyped} method.
296
	 *
297
	 *  @param  str string with directional characters to remove.
298
	 *
299
	 *  @param  type type of the structured text as specified when
300
	 *          calling {@link #processTyped processTyped}.
301
	 *
302
	 *  @return string with no directional formatting characters.
303
	 */
304
	public static String deprocess(String str, String type) {
305
		if ((str == null) || (str.length() <= 1) || !isProcessingNeeded())
306
			return str;
307
308
		// make sure that LRE/PDF are added around the string
309
		STextEnvironment env = new STextEnvironment(null, false, STextEnvironment.ORIENT_UNKNOWN);
310
		return STextEngine.fullToLeanText(type, null, env, str, null);
311
	}
312
313
}
(-)src/org/eclipse/equinox/bidi/custom/BidiComplexFeatures.java (-250 lines)
Removed 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.BidiComplexEnvironment;
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
 *
21
 *  <h2>Code Sample</h2>
22
 *  <p>Example 1 (set all features)
23
 *  <pre>
24
 *
25
 *    BidiComplexFeatures f1 = new BidiComplexFeatures("+-=", 0, -1, -1, false, false);
26
 *
27
 *  </pre>
28
 *  <p>Example 2 (change only the separators)
29
 *  <pre>
30
 *
31
 *    BidiComplexFeatures f2 = new BidiComplexFeatures("[]|()", f1.getSpecialsCount(),
32
 *                                     f1.getDirArabic(), f1.getDirHebrew(),
33
 *                                     f1.getIgnoreArabic(), f1.getIgnoreHebrew());
34
 *
35
 *  </pre>
36
 *
37
 *  @see IBidiComplexProcessor#getFeatures
38
 *
39
 *  @author Matitiahu Allouche
40
 */
41
public class BidiComplexFeatures {
42
43
	/**
44
	 *  Constant specifying that the base direction of a complex expression is LTR.
45
	 *  The base direction may depend on whether the GUI is
46
	 *  {@link BidiComplexEnvironment#getMirrored mirrored} and may
47
	 *  may be different for Arabic and for Hebrew.
48
	 *  This constant can appear as <code>dirArabic</code>
49
	 *  or <code>dirHebrew</code> argument for the
50
	 *  {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor}
51
	 *  and as value returned by {@link #getDirArabic} or {@link #getDirHebrew}
52
	 *  methods.
53
	 */
54
	public static final int DIR_LTR = 0;
55
56
	/**
57
	 *  Constant specifying that the base direction of a complex expression is RTL.
58
	 *  The base direction may depend on whether the GUI is
59
	 *  {@link BidiComplexEnvironment#getMirrored mirrored} and may
60
	 *  may be different for Arabic and for Hebrew.
61
	 *  This constant can appear as <code>dirArabic</code>
62
	 *  or <code>dirHebrew</code> argument for the
63
	 *  {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor}
64
	 *  and as value returned by {@link #getDirArabic} or {@link #getDirHebrew}
65
	 *  methods.
66
	 */
67
	public static final int DIR_RTL = 1;
68
69
	/**
70
	 *  Pre-defined <code>BidiComplexFeatures</code> instance with values for no
71
	 *  separators, no special processing, all directions LTR
72
	 *  and support for neither Arabic nor Hebrew.<br>
73
	 *  Since there are no separators and no special processing, a complex
74
	 *  expression processor with such features would do nothing.<br>
75
	 *  It is more efficient to do nothing with a <code>null</code> processor.
76
	 */
77
	public static final BidiComplexFeatures DEFAULT = new BidiComplexFeatures(null, 0, -1, -1, true, true);
78
79
	/**
80
	 *  String grouping one-character separators which
81
	 *  separate the text of the complex expression into tokens.
82
	 */
83
	final String separators;
84
85
	/**
86
	 *  Number of special cases for the associated processor.
87
	 *  Special cases exist for some types of complex expression processors.
88
	 *  They are implemented by overriding methods
89
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and
90
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial}.
91
	 *  Examples of special cases are comments, literals, or anything which
92
	 *  is not identified by a one-character separator.
93
	 */
94
	final int specialsCount;
95
96
	/**
97
	 *  Base direction of the complex expression for Arabic.
98
	 *  If a complex expression contains both Arabic and
99
	 *  Hebrew words, the first Arabic or Hebrew letter in the
100
	 *  expression determines which is the governing script).<br>
101
	 *  The value of this field must be one of
102
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
103
	 *
104
	 *  @see #dirHebrew
105
	 */
106
	final int dirArabic;
107
108
	/**
109
	 *  Base direction of the complex expression for Hebrew.
110
	 *  If a complex expression contains both Arabic and
111
	 *  Hebrew words, the first Arabic or Hebrew letter in the
112
	 *  expression determines which is the governing script).<br>
113
	 *  The value of this field must be one of
114
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
115
	 *
116
	 *  @see #dirArabic
117
	 */
118
	final int dirHebrew;
119
120
	/**
121
	 *  Flag indicating that Arabic letters will not be considered for
122
	 *  processing complex expressions. If both this flag and
123
	 *  ignoreHebrew are set to <code>true</code>, the
124
	 *  processor will do nothing (but some overhead can be expected).
125
	 */
126
	final boolean ignoreArabic;
127
128
	/**
129
	 *  Flag indicating that Hebrew letters will not be considered for
130
	 *  processing complex expressions. If both this flag and
131
	 *  ignoreArabic are set to <code>true</code>, the
132
	 *  processor will do nothing (but some overhead can be expected).
133
	 */
134
	final boolean ignoreHebrew;
135
136
	/**
137
	 *  Constructor
138
	 *
139
	 *  @param separators is a string where each character is a separator
140
	 *          which separates the complex expression into tokens.
141
	 *  @see #getSeparators
142
	 *
143
	 *  @param specialsCount specifies the number of special cases handled
144
	 *          by the processor. This value must be identical to the
145
	 *          number of special cases handled by the processor with which
146
	 *          this <code>BidiComplexFeatures</code> instance is associated.
147
	 *  @see #getSpecialsCount
148
	 *
149
	 *  @param dirArabic specifies the base direction of the complex expression
150
	 *          for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
151
	 *          If it is not (for instance if it is a negative value), it
152
	 *          defaults to <code>DIR_LTR</code>.
153
	 *  @see #getDirArabic
154
	 *
155
	 *  @param dirHebrew specifies the base direction of the complex expression
156
	 *          for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
157
	 *          If it is not (for instance if it is a negative value), it
158
	 *          defaults to <code>DIR_LTR</code>.
159
	 *  @see #getDirHebrew
160
	 *
161
	 *  @param ignoreArabic indicates that Arabic letters will not be
162
	 *          considered for processing complex expressions.
163
	 *          If both this flag and <code>ignoreHebrew</code>
164
	 *          are set to <code>true</code>, the processor will do
165
	 *          nothing (but some overhead can be expected).
166
	 *  @see #getIgnoreArabic
167
	 *
168
	 *  @param ignoreHebrew indicates that Hebrew letters will not be
169
	 *          considered for processing complex expressions.
170
	 *          If both this flag and <code>ignoreArabic</code>
171
	 *          are set to <code>true</code>, the processor will do
172
	 *          nothing (but some overhead can be expected).
173
	 *  @see #getIgnoreHebrew
174
	 */
175
	public BidiComplexFeatures(String separators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) {
176
177
		this.separators = separators == null ? "" : separators; //$NON-NLS-1$
178
		this.specialsCount = specialsCount;
179
		this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR;
180
		this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR;
181
		this.ignoreArabic = ignoreArabic;
182
		this.ignoreHebrew = ignoreHebrew;
183
	}
184
185
	/**
186
	 *  @return a string grouping one-character separators which separate
187
	 *          the text of the complex expression into tokens.
188
	 */
189
	public String getSeparators() {
190
		return separators;
191
	}
192
193
	/**
194
	 *  @return the number of special cases for the associated processor.
195
	 *          Special cases exist for some types of complex expression
196
	 *          processors. They are implemented by overriding methods
197
	 *          {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and
198
	 *          {@link IBidiComplexProcessor#processSpecial processSpecial}.
199
	 *          Examples of special cases are comments, literals, or
200
	 *          anything which is not identified by a one-character separator.
201
	 */
202
	public int getSpecialsCount() {
203
		return specialsCount;
204
	}
205
206
	/**
207
	 *  @return the base direction of the complex expression for Arabic.
208
	 *          If a complex expression contains both Arabic and
209
	 *          Hebrew words, the first Arabic or Hebrew letter in the
210
	 *          expression determines which is the governing script.<br>
211
	 *          The value of this field is one of
212
	 *          {@link #DIR_LTR} or {@link #DIR_RTL}.
213
	 *
214
	 *  @see #getDirHebrew
215
	 */
216
	public int getDirArabic() {
217
		return dirArabic;
218
	}
219
220
	/**
221
	 *  @return the base direction of the complex expression for Hebrew.
222
	 *          If a complex expression contains both Arabic and
223
	 *          Hebrew words, the first Arabic or Hebrew letter in the
224
	 *          expression determines which is the governing script.<br>
225
	 *          The value of this field is one of
226
	 *          {@link #DIR_LTR} or {@link #DIR_RTL}.
227
	 *
228
	 *  @see #getDirArabic
229
	 */
230
	public int getDirHebrew() {
231
		return dirHebrew;
232
	}
233
234
	/**
235
	 *  @return a flag indicating that Arabic letters will not be considered
236
	 *  for processing complex expressions.
237
	 */
238
	public boolean getIgnoreArabic() {
239
		return ignoreArabic;
240
	}
241
242
	/**
243
	 *  Flag indicating that Hebrew letters will not be considered for
244
	 *  processing complex expressions.
245
	 */
246
	public boolean getIgnoreHebrew() {
247
		return ignoreHebrew;
248
	}
249
250
}
(-)src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java (-235 lines)
Removed 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.BidiComplexEngine;
14
import org.eclipse.equinox.bidi.BidiComplexEnvironment;
15
import org.eclipse.equinox.bidi.internal.BidiComplexImpl;
16
17
/**
18
 *  Generic processor which can be used as superclass (base class)
19
 *  for specific complex expression processors.
20
 *  <p>
21
 *  Here are some guidelines about how to write complex expression
22
 *  processors.
23
 *  <ul>
24
 *    <li>Processor instances may be accessed simultaneously by
25
 *        several threads. They should have no instance variables.</li>
26
 *    <li>Each use of a processor is associated with a set of
27
 *        {@link BidiComplexFeatures features}.
28
 *        All processors must have a default set of features which may be
29
 *        queried with the {@link #getFeatures getFeatures} method.
30
 *        These default features may be overridden by specifying a
31
 *        <code>features</code> argument when calling a method.
32
 *        See for instance
33
 *        {@link BidiComplexEngine#leanToFullText leanToFullText}.
34
 *    <li>The behavior of a processor is governed by 3 factors, all included
35
 *        in associated {@link BidiComplexFeatures features} data.
36
 *        <ul>
37
 *          <li>The separators specified for its
38
 *              {@link BidiComplexFeatures features} determines how submitted
39
 *              complex expressions are split into tokens.</li>
40
 *          <li>The tokens are displayed one after the other according
41
 *              to the appropriate direction, which can be different for
42
 *              Arabic and for Hebrew.</li>
43
 *          <li>The number of special cases which need to be handled by
44
 *              code specific to that processor.</li>
45
 *        </ul></li>
46
 *  </ul>
47
 *
48
 *  @see BidiComplexFeatures#getSeparators
49
 *  @see BidiComplexFeatures#getDirArabic
50
 *  @see BidiComplexFeatures#getDirHebrew
51
 *  @see BidiComplexFeatures#getSpecialsCount
52
 *
53
 *  @author Matitiahu Allouche
54
 */
55
public class BidiComplexProcessor implements IBidiComplexProcessor {
56
57
	/**
58
	 *  In <code>BidiComplexProcessor</code> this method returns a
59
	 *  {@link BidiComplexFeatures#DEFAULT DEFAULT} value which
60
	 *  directs the processor to do nothing.
61
	 *
62
	 *  <p>A processor which extends this class must override this method
63
	 *  and return a BidiComplexFeatures instance representing its specific
64
	 *  features.
65
	 *
66
	 *  @see IBidiComplexProcessor#getFeatures the corresponding interface method
67
	 */
68
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment environment) {
69
		throw new IllegalStateException("A processor must have a getFeatures() method."); //$NON-NLS-1$
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
	 *  number of special cases is zero, which means that
77
	 *  <code>indexOfSpecial</code> should never be called for them.
78
	 *
79
	 *  <p>A processor handling special cases must override this method.
80
	 *
81
	 *  @see IBidiComplexProcessor#indexOfSpecial the corresponding interface method
82
	 */
83
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
84
		// This method must be overridden by all subclasses with special cases.
85
		throw new IllegalStateException("A processor must have an indexOfSpecial() method."); //$NON-NLS-1$
86
	}
87
88
	/**
89
	 *  In <code>BidiComplexProcessor</code> this method throws an
90
	 *  <code>IllegalStateException</code>. This is appropriate behavior
91
	 *  (and does not need to be overridden) for processors whose
92
	 *  number of special cases is zero, which means that
93
	 *  <code>processSpecial</code> should never be called for them.
94
	 *
95
	 *  <p>A processor handling special cases must override this method.
96
	 *
97
	 *  @see IBidiComplexProcessor#processSpecial the corresponding interface method
98
	 */
99
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
100
		// This method must be overridden by all subclasses with any special case.
101
		throw new IllegalStateException("A processor must have a processSpecial() method."); //$NON-NLS-1$
102
	}
103
104
	/**
105
	 *  This method can be called from within
106
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
107
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
108
	 *  implementations of {@link IBidiComplexProcessor} to retrieve the
109
	 *  bidirectional class of characters in the <i>lean</i> text.
110
	 *
111
	 *  @param  text is the text of the complex expression received as
112
	 *          parameter to <code>indexOfSpecial</code> or
113
	 *          <code>processSpecial</code>.
114
	 *
115
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
116
	 *          or <code>processSpecial</code>, uniquely to be used as argument
117
	 *          for calls to <code>getDirProp</code> and other methods used
118
	 *          by processors.
119
	 *
120
	 *  @param index position of the character in the <i>lean</i> text.
121
	 *          It must be a non-negative number smaller than the length
122
	 *          of the <i>lean</i> text.
123
	 *
124
	 *  @return the bidirectional class of the character. It is one of the
125
	 *          values which can be returned by
126
	 *          <code>java.lang.Character.getDirectionality</code>.
127
	 *          However, it is recommended to use <code>getDirProp</code>
128
	 *          rather than <code>java.lang.Character.getDirectionality</code>
129
	 *          since <code>getDirProp</code> manages a cache of character
130
	 *          properties and so can be more efficient than calling the
131
	 *          java.lang.Character method.
132
	 */
133
	public static byte getDirProp(String text, byte[] dirProps, int index) {
134
		return BidiComplexImpl.getDirProp(text, dirProps, index);
135
	}
136
137
	/**
138
	 *  This method can be called from within
139
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
140
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
141
	 *  implementations of {@link IBidiComplexProcessor} to set or
142
	 *  override the bidirectional class of characters in the <i>lean</i> text.
143
	 *
144
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
145
	 *          or <code>processSpecial</code>, uniquely to be used as argument
146
	 *          for calls to <code>setDirProp</code> and other methods used
147
	 *          by processors.
148
	 *
149
	 *  @param index position of the character in the <i>lean</i> text.
150
	 *          It must be a non-negative number smaller than the length
151
	 *          of the <i>lean</i> text.
152
	 *
153
	 *  @param  dirProp bidirectional class of the character. It is one of the
154
	 *          values which can be returned by
155
	 *          <code>java.lang.Character.getDirectionality</code>.
156
	 */
157
	public static void setDirProp(byte[] dirProps, int index, byte dirProp) {
158
		BidiComplexImpl.setDirProp(dirProps, index, dirProp);
159
	}
160
161
	/**
162
	 *  This method can be called from within
163
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
164
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
165
	 *  implementations of {@link IBidiComplexProcessor}
166
	 *  to specify that a mark character must be added before the character
167
	 *  at the specified position of the <i>lean</i> text when generating the
168
	 *  <i>full</i> text. The mark character will be LRM for complex expressions
169
	 *  with a LTR base direction, and RLM for complex expressions with RTL
170
	 *  base direction. The mark character is not added physically by this
171
	 *  method, but its position is noted and will be used when generating
172
	 *  the <i>full</i> text.
173
	 *
174
	 *  @param  text is the text of the complex expression received as
175
	 *          parameter to <code>indexOfSpecial</code> or
176
	 *          <code>processSpecial</code>.
177
	 *
178
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
179
	 *          or <code>processSpecial</code>, uniquely to be used as argument
180
	 *          for calls to <code>insertMark</code> and other methods used
181
	 *          by processors.
182
	 *
183
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
184
	 *          or <code>processSpecial</code>, uniquely to be used as argument
185
	 *          for calls to <code>insertMark</code> and other methods used
186
	 *          by processors.
187
	 *
188
	 *  @param  offset position of the character in the <i>lean</i> text.
189
	 *          It must be a non-negative number smaller than the length
190
	 *          of the <i>lean</i> text.
191
	 *          For the benefit of efficiency, it is better to insert
192
	 *          multiple marks in ascending order of the offsets.
193
	 */
194
	public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
195
		BidiComplexImpl.insertMark(text, dirProps, offsets, offset);
196
	}
197
198
	/**
199
	 *  This method can be called from within
200
	 *  {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or
201
	 *  {@link IBidiComplexProcessor#processSpecial processSpecial} in
202
	 *  implementations of {@link IBidiComplexProcessor} to add a
203
	 *  directional mark before a
204
	 *  separator if needed for correct display, depending on the
205
	 *  base direction of the expression and on the class of the
206
	 *  characters in the <i>lean</i> text preceding and following
207
	 *  the separator itself.
208
	 *
209
	 *  @param  features is the {@link BidiComplexFeatures} instance
210
	 *          received as parameter to <code>indexOfSpecial</code> or
211
	 *          <code>processSpecial</code>.
212
	 *
213
	 *  @param  text is the text of the complex expression received as
214
	 *          parameter to <code>indexOfSpecial</code> or
215
	 *          <code>processSpecial</code>.
216
	 *
217
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
218
	 *          or <code>processSpecial</code>, uniquely to be used as argument
219
	 *          for calls to <code>processSeparator</code> and other methods used
220
	 *          by processors.
221
	 *
222
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
223
	 *          or <code>processSpecial</code>, uniquely to be used as argument
224
	 *          for calls to <code>processSeparator</code> and other methods used
225
	 *          by processors.
226
	 *
227
	 *  @param  separLocation offset of the separator in the <i>lean</i> text.
228
	 *          It must be a non-negative number smaller than the length
229
	 *          of the <i>lean</i> text.
230
	 */
231
	public static void processSeparator(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int separLocation) {
232
		BidiComplexImpl.processSeparator(features, text, dirProps, offsets, separLocation);
233
	}
234
235
}
(-)src/org/eclipse/equinox/bidi/custom/BidiComplexStringProcessor.java (-40 lines)
Removed 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 (-170 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.BidiComplexEngine;
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
	 *  return the
27
	 *  {@link BidiComplexFeatures} characterizing the processor.
28
	 *
29
	 *  @param  env the current environment, which may affect the behavior of
30
	 *          the processor. This parameter may be specified as
31
	 *          <code>null</code>, in which case the
32
	 *          {@link BidiComplexEnvironment#DEFAULT DEFAULT}
33
	 *          environment should be assumed.
34
	 *
35
	 *  @return the features in use for this processor.
36
	 */
37
	public abstract BidiComplexFeatures getFeatures(BidiComplexEnvironment env);
38
39
	/**
40
	 *  Locate occurrences of special strings within a complex expression
41
	 *  and return their indexes one after the other in successive calls.
42
	 *  <p>
43
	 *  This method is called repeatedly from the code implementing
44
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText} if the
45
	 *  number of special cases appearing in the associated <code>features</code>
46
	 *  parameter is greater than zero.
47
	 *  <p>
48
	 *  The code implementing this method may use the following methods
49
	 *  in {@link BidiComplexProcessor}:
50
	 *  <ul>
51
	 *    <li>{@link BidiComplexProcessor#getDirProp getDirProp}</li>
52
	 *    <li>{@link BidiComplexProcessor#setDirProp setDirProp}</li>
53
	 *    <li>{@link BidiComplexProcessor#insertMark insertMark}</li>
54
	 *    <li>{@link BidiComplexProcessor#processSeparator processSeparator}</li>
55
	 *  </ul>
56
	 *
57
	 *  @param  features is the {@link BidiComplexFeatures} instance
58
	 *          currently associated with this processor.
59
	 *
60
	 *  @param  text is the text of the complex expression before
61
	 *          addition of any directional formatting characters.
62
	 *
63
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
64
	 *          uniquely to be used as argument for calls to methods which
65
	 *          need it.
66
	 *
67
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
68
	 *          uniquely to be used as argument for calls to methods which
69
	 *          need it.
70
	 *
71
	 *  @param  caseNumber number of the special case to locate.
72
	 *          This number varies from 1 to the number of special cases
73
	 *          in the features associated with this processor.
74
	 *          The meaning of this number is internal to the class
75
	 *          implementing <code>indexOfSpecial</code>.
76
	 *
77
	 *  @param  fromIndex the index within <code>text</code> to start
78
	 *          the search from.
79
	 *
80
	 *  @return the position where the start of the special case was located.
81
	 *          The method must return the first occurrence of whatever
82
	 *          identifies the start of the special case starting from
83
	 *          <code>fromIndex</code>. The method does not have to check if
84
	 *          this occurrence appears within the scope of another special
85
	 *          case (e.g. a comment starting delimiter within the scope of
86
	 *          a literal or vice-versa).
87
	 *          <br>If no occurrence is found, the method must return -1.
88
	 */
89
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex);
90
91
	/**
92
	 *  This method handles special cases specific to this processor.
93
	 *  It is called by {@link BidiComplexEngine#leanToFullText leanToFullText}
94
	 *  when a special case occurrence is located by
95
	 *  {@link #indexOfSpecial indexOfSpecial}.
96
	 *  <p>
97
	 *  The code implementing this method may use the following methods
98
	 *  in {@link BidiComplexProcessor}:
99
	 *  <ul>
100
	 *    <li>{@link BidiComplexProcessor#getDirProp getDirProp}</li>
101
	 *    <li>{@link BidiComplexProcessor#setDirProp setDirProp}</li>
102
	 *    <li>{@link BidiComplexProcessor#insertMark insertMark}</li>
103
	 *    <li>{@link BidiComplexProcessor#processSeparator processSeparator}</li>
104
	 *  </ul>
105
	 *  <p>
106
	 *  If a special processing cannot be completed within a current call to
107
	 *  <code>processSpecial</code> (for instance, a comment has been started
108
	 *  in the current line but its end appears in a following line),
109
	 *  <code>processSpecial</code> should specify a final state by
110
	 *  putting its value in the first element of the <code>state</code>
111
	 *  parameter.
112
	 *  The meaning of this state is internal to the processor.
113
	 *  On a later call to
114
	 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
115
	 *  specifying that state value, <code>processSpecial</code> will be
116
	 *  called with that value for parameter <code>caseNumber</code> and
117
	 *  <code>-1</code> for parameter <code>separLocation</code> and should
118
	 *  perform whatever initializations are required depending on the state.
119
	 *
120
	 *  @param  features is the {@link BidiComplexFeatures} instance
121
	 *          currently associated with this processor.
122
	 *
123
	 *  @param  text is the text of the complex expression before
124
	 *          addition of any directional formatting characters.
125
	 *
126
	 *  @param  dirProps is a parameter received by <code>processSpecial</code>
127
	 *          uniquely to be used as argument for calls to methods which
128
	 *          need it.
129
	 *
130
	 *  @param  offsets is a parameter received by <code>processSpecial</code>
131
	 *          uniquely to be used as argument for calls to methods which
132
	 *          need it.
133
	 *
134
	 *  @param  state is an integer array with at least one element.
135
	 *          If the processor needs to signal the occurrence of a
136
	 *          special case which must be passed to the next call to
137
	 *          <code>leanToFullText</code> (for instance, a comment or a
138
	 *          literal started but not closed in the current
139
	 *          <code>text</code>), it must put a value in the first element
140
	 *          of the <code>state</code> parameter.
141
	 *          This value must be a number between 1 and the number of
142
	 *          special cases appearing in the features associated with
143
	 *          this processor. This number is passed back to the caller
144
	 *          and should be specified as <code>state</code> argument
145
	 *          in the next call to <code>leanToFullText</code> together
146
	 *          with the continuation text.
147
	 *          The meaning of this number is internal to the processor.
148
	 *
149
	 *  @param  caseNumber number of the special case to handle.
150
	 *
151
	 *  @param  separLocation the position returned by
152
	 *          {@link #indexOfSpecial indexOfSpecial}. In calls to
153
	 *          {@link BidiComplexEngine#leanToFullText leanToFullText} and other
154
	 *          methods of {@link BidiComplexEngine} specifying a  non-null
155
	 *          <code>state</code> parameter, <code>processSpecial</code> is
156
	 *          called when initializing the processing with the value of
157
	 *          <code>caseNumber</code> equal to the value returned in the
158
	 *          first element of <code>state</code> and the value of
159
	 *          <code>separLocation</code> equal to <code>-1</code>.
160
	 *
161
	 *  @return the position after the scope of the special case ends.
162
	 *          For instance, the position after the end of a comment,
163
	 *          the position after the end of a literal.
164
	 *          <br>A value greater or equal to the length of <code>text</code>
165
	 *          means that there is no further occurrence of this case in the
166
	 *          current complex expression.
167
	 */
168
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation);
169
170
}
(-)src/org/eclipse/equinox/bidi/custom/ISTextProcessor.java (+170 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
16
/**
17
 *  Interface for all structured text processors.
18
 *  For guidelines about implementation, see
19
 *  {@link STextProcessor}.
20
 *
21
 *  @author Matitiahu Allouche
22
 */
23
public interface ISTextProcessor {
24
25
	/**
26
	 *  return the
27
	 *  {@link STextFeatures} characterizing the processor.
28
	 *
29
	 *  @param  env the current environment, which may affect the behavior of
30
	 *          the processor. This parameter may be specified as
31
	 *          <code>null</code>, in which case the
32
	 *          {@link STextEnvironment#DEFAULT DEFAULT}
33
	 *          environment should be assumed.
34
	 *
35
	 *  @return the features in use for this processor.
36
	 */
37
	public abstract STextFeatures getFeatures(STextEnvironment env);
38
39
	/**
40
	 *  Locate occurrences of special strings within a structured text
41
	 *  and return their indexes one after the other in successive calls.
42
	 *  <p>
43
	 *  This method is called repeatedly from the code implementing
44
	 *  {@link STextEngine#leanToFullText leanToFullText} if the
45
	 *  number of special cases appearing in the associated <code>features</code>
46
	 *  parameter is greater than zero.
47
	 *  <p>
48
	 *  The code implementing this method may use the following methods
49
	 *  in {@link STextProcessor}:
50
	 *  <ul>
51
	 *    <li>{@link STextProcessor#getDirProp getDirProp}</li>
52
	 *    <li>{@link STextProcessor#setDirProp setDirProp}</li>
53
	 *    <li>{@link STextProcessor#insertMark insertMark}</li>
54
	 *    <li>{@link STextProcessor#processSeparator processSeparator}</li>
55
	 *  </ul>
56
	 *
57
	 *  @param  features is the {@link STextFeatures} instance
58
	 *          currently associated with this processor.
59
	 *
60
	 *  @param  text is the structured text string before
61
	 *          addition of any directional formatting characters.
62
	 *
63
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
64
	 *          uniquely to be used as argument for calls to methods which
65
	 *          need it.
66
	 *
67
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
68
	 *          uniquely to be used as argument for calls to methods which
69
	 *          need it.
70
	 *
71
	 *  @param  caseNumber number of the special case to locate.
72
	 *          This number varies from 1 to the number of special cases
73
	 *          in the features associated with this processor.
74
	 *          The meaning of this number is internal to the class
75
	 *          implementing <code>indexOfSpecial</code>.
76
	 *
77
	 *  @param  fromIndex the index within <code>text</code> to start
78
	 *          the search from.
79
	 *
80
	 *  @return the position where the start of the special case was located.
81
	 *          The method must return the first occurrence of whatever
82
	 *          identifies the start of the special case starting from
83
	 *          <code>fromIndex</code>. The method does not have to check if
84
	 *          this occurrence appears within the scope of another special
85
	 *          case (e.g. a comment starting delimiter within the scope of
86
	 *          a literal or vice-versa).
87
	 *          <br>If no occurrence is found, the method must return -1.
88
	 */
89
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex);
90
91
	/**
92
	 *  This method handles special cases specific to this processor.
93
	 *  It is called by {@link STextEngine#leanToFullText leanToFullText}
94
	 *  when a special case occurrence is located by
95
	 *  {@link #indexOfSpecial indexOfSpecial}.
96
	 *  <p>
97
	 *  The code implementing this method may use the following methods
98
	 *  in {@link STextProcessor}:
99
	 *  <ul>
100
	 *    <li>{@link STextProcessor#getDirProp getDirProp}</li>
101
	 *    <li>{@link STextProcessor#setDirProp setDirProp}</li>
102
	 *    <li>{@link STextProcessor#insertMark insertMark}</li>
103
	 *    <li>{@link STextProcessor#processSeparator processSeparator}</li>
104
	 *  </ul>
105
	 *  <p>
106
	 *  If a special processing cannot be completed within a current call to
107
	 *  <code>processSpecial</code> (for instance, a comment has been started
108
	 *  in the current line but its end appears in a following line),
109
	 *  <code>processSpecial</code> should specify a final state by
110
	 *  putting its value in the first element of the <code>state</code>
111
	 *  parameter.
112
	 *  The meaning of this state is internal to the processor.
113
	 *  On a later call to
114
	 *  {@link STextEngine#leanToFullText leanToFullText}
115
	 *  specifying that state value, <code>processSpecial</code> will be
116
	 *  called with that value for parameter <code>caseNumber</code> and
117
	 *  <code>-1</code> for parameter <code>separLocation</code> and should
118
	 *  perform whatever initializations are required depending on the state.
119
	 *
120
	 *  @param  features is the {@link STextFeatures} instance
121
	 *          currently associated with this processor.
122
	 *
123
	 *  @param  text is the structured text string before
124
	 *          addition of any directional formatting characters.
125
	 *
126
	 *  @param  dirProps is a parameter received by <code>processSpecial</code>
127
	 *          uniquely to be used as argument for calls to methods which
128
	 *          need it.
129
	 *
130
	 *  @param  offsets is a parameter received by <code>processSpecial</code>
131
	 *          uniquely to be used as argument for calls to methods which
132
	 *          need it.
133
	 *
134
	 *  @param  state is an integer array with at least one element.
135
	 *          If the processor needs to signal the occurrence of a
136
	 *          special case which must be passed to the next call to
137
	 *          <code>leanToFullText</code> (for instance, a comment or a
138
	 *          literal started but not closed in the current
139
	 *          <code>text</code>), it must put a value in the first element
140
	 *          of the <code>state</code> parameter.
141
	 *          This value must be a number between 1 and the number of
142
	 *          special cases appearing in the features associated with
143
	 *          this processor. This number is passed back to the caller
144
	 *          and should be specified as <code>state</code> argument
145
	 *          in the next call to <code>leanToFullText</code> together
146
	 *          with the continuation text.
147
	 *          The meaning of this number is internal to the processor.
148
	 *
149
	 *  @param  caseNumber number of the special case to handle.
150
	 *
151
	 *  @param  separLocation the position returned by
152
	 *          {@link #indexOfSpecial indexOfSpecial}. In calls to
153
	 *          {@link STextEngine#leanToFullText leanToFullText} and other
154
	 *          methods of {@link STextEngine} specifying a  non-null
155
	 *          <code>state</code> parameter, <code>processSpecial</code> is
156
	 *          called when initializing the processing with the value of
157
	 *          <code>caseNumber</code> equal to the value returned in the
158
	 *          first element of <code>state</code> and the value of
159
	 *          <code>separLocation</code> equal to <code>-1</code>.
160
	 *
161
	 *  @return the position after the scope of the special case ends.
162
	 *          For instance, the position after the end of a comment,
163
	 *          the position after the end of a literal.
164
	 *          <br>A value greater or equal to the length of <code>text</code>
165
	 *          means that there is no further occurrence of this case in the
166
	 *          current structured text.
167
	 */
168
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation);
169
170
}
(-)src/org/eclipse/equinox/bidi/custom/STextFeatures.java (+250 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.STextEnvironment;
14
15
/**
16
 *  This class defines features of a structured text 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
 *
21
 *  <h2>Code Sample</h2>
22
 *  <p>Example 1 (set all features)
23
 *  <pre>
24
 *
25
 *    STextFeatures f1 = new STextFeatures("+-=", 0, -1, -1, false, false);
26
 *
27
 *  </pre>
28
 *  <p>Example 2 (change only the separators)
29
 *  <pre>
30
 *
31
 *    STextFeatures f2 = new STextFeatures("[]|()", f1.getSpecialsCount(),
32
 *                                     f1.getDirArabic(), f1.getDirHebrew(),
33
 *                                     f1.getIgnoreArabic(), f1.getIgnoreHebrew());
34
 *
35
 *  </pre>
36
 *
37
 *  @see ISTextProcessor#getFeatures
38
 *
39
 *  @author Matitiahu Allouche
40
 */
41
public class STextFeatures {
42
43
	/**
44
	 *  Constant specifying that the base direction of a structured text is LTR.
45
	 *  The base direction may depend on whether the GUI is
46
	 *  {@link STextEnvironment#getMirrored mirrored} and may
47
	 *  may be different for Arabic and for Hebrew.
48
	 *  This constant can appear as <code>dirArabic</code>
49
	 *  or <code>dirHebrew</code> argument for the
50
	 *  {@link STextFeatures#STextFeatures STextFeatures constructor}
51
	 *  and as value returned by {@link #getDirArabic} or {@link #getDirHebrew}
52
	 *  methods.
53
	 */
54
	public static final int DIR_LTR = 0;
55
56
	/**
57
	 *  Constant specifying that the base direction of a structured text is RTL.
58
	 *  The base direction may depend on whether the GUI is
59
	 *  {@link STextEnvironment#getMirrored mirrored} and may
60
	 *  may be different for Arabic and for Hebrew.
61
	 *  This constant can appear as <code>dirArabic</code>
62
	 *  or <code>dirHebrew</code> argument for the
63
	 *  {@link STextFeatures#STextFeatures STextFeatures constructor}
64
	 *  and as value returned by {@link #getDirArabic} or {@link #getDirHebrew}
65
	 *  methods.
66
	 */
67
	public static final int DIR_RTL = 1;
68
69
	/**
70
	 *  Pre-defined <code>STextFeatures</code> instance with values for no
71
	 *  separators, no special processing, all directions LTR
72
	 *  and support for neither Arabic nor Hebrew.<br>
73
	 *  Since there are no separators and no special processing, a structured text
74
	 *  processor with such features would do nothing.<br>
75
	 *  It is more efficient to do nothing with a <code>null</code> processor.
76
	 */
77
	public static final STextFeatures DEFAULT = new STextFeatures(null, 0, -1, -1, true, true);
78
79
	/**
80
	 *  String grouping one-character separators which
81
	 *  separate the structured text into tokens.
82
	 */
83
	final String separators;
84
85
	/**
86
	 *  Number of special cases for the associated processor.
87
	 *  Special cases exist for some types of structured text processors.
88
	 *  They are implemented by overriding methods
89
	 *  {@link ISTextProcessor#indexOfSpecial indexOfSpecial} and
90
	 *  {@link ISTextProcessor#processSpecial processSpecial}.
91
	 *  Examples of special cases are comments, literals, or anything which
92
	 *  is not identified by a one-character separator.
93
	 */
94
	final int specialsCount;
95
96
	/**
97
	 *  Base direction of the structured text for Arabic.
98
	 *  If a structured text contains both Arabic and
99
	 *  Hebrew words, the first Arabic or Hebrew letter in the
100
	 *  text determines which is the governing script).<br>
101
	 *  The value of this field must be one of
102
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
103
	 *
104
	 *  @see #dirHebrew
105
	 */
106
	final int dirArabic;
107
108
	/**
109
	 *  Base direction of the structured text for Hebrew.
110
	 *  If a structured text contains both Arabic and
111
	 *  Hebrew words, the first Arabic or Hebrew letter in the
112
	 *  text determines which is the governing script).<br>
113
	 *  The value of this field must be one of
114
	 *  {@link #DIR_LTR} or {@link #DIR_RTL}.
115
	 *
116
	 *  @see #dirArabic
117
	 */
118
	final int dirHebrew;
119
120
	/**
121
	 *  Flag indicating that Arabic letters will not be considered for
122
	 *  processing structured text. If both this flag and
123
	 *  ignoreHebrew are set to <code>true</code>, the
124
	 *  processor will do nothing (but some overhead can be expected).
125
	 */
126
	final boolean ignoreArabic;
127
128
	/**
129
	 *  Flag indicating that Hebrew letters will not be considered for
130
	 *  processing structured text. If both this flag and
131
	 *  ignoreArabic are set to <code>true</code>, the
132
	 *  processor will do nothing (but some overhead can be expected).
133
	 */
134
	final boolean ignoreHebrew;
135
136
	/**
137
	 *  Constructor
138
	 *
139
	 *  @param separators is a string where each character is a separator
140
	 *          which separates the structured text into tokens.
141
	 *  @see #getSeparators
142
	 *
143
	 *  @param specialsCount specifies the number of special cases handled
144
	 *          by the processor. This value must be identical to the
145
	 *          number of special cases handled by the processor with which
146
	 *          this <code>STextFeatures</code> instance is associated.
147
	 *  @see #getSpecialsCount
148
	 *
149
	 *  @param dirArabic specifies the base direction of the structured text
150
	 *          for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
151
	 *          If it is not (for instance if it is a negative value), it
152
	 *          defaults to <code>DIR_LTR</code>.
153
	 *  @see #getDirArabic
154
	 *
155
	 *  @param dirHebrew specifies the base direction of the structured text
156
	 *          for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}.
157
	 *          If it is not (for instance if it is a negative value), it
158
	 *          defaults to <code>DIR_LTR</code>.
159
	 *  @see #getDirHebrew
160
	 *
161
	 *  @param ignoreArabic indicates that Arabic letters will not be
162
	 *          considered for processing structured text.
163
	 *          If both this flag and <code>ignoreHebrew</code>
164
	 *          are set to <code>true</code>, the processor will do
165
	 *          nothing (but some overhead can be expected).
166
	 *  @see #getIgnoreArabic
167
	 *
168
	 *  @param ignoreHebrew indicates that Hebrew letters will not be
169
	 *          considered for processing structured text.
170
	 *          If both this flag and <code>ignoreArabic</code>
171
	 *          are set to <code>true</code>, the processor will do
172
	 *          nothing (but some overhead can be expected).
173
	 *  @see #getIgnoreHebrew
174
	 */
175
	public STextFeatures(String separators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) {
176
177
		this.separators = separators == null ? "" : separators; //$NON-NLS-1$
178
		this.specialsCount = specialsCount;
179
		this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR;
180
		this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR;
181
		this.ignoreArabic = ignoreArabic;
182
		this.ignoreHebrew = ignoreHebrew;
183
	}
184
185
	/**
186
	 *  @return a string grouping one-character separators which separate
187
	 *          the structured text into tokens.
188
	 */
189
	public String getSeparators() {
190
		return separators;
191
	}
192
193
	/**
194
	 *  @return the number of special cases for the associated processor.
195
	 *          Special cases exist for some types of structured text
196
	 *          processors. They are implemented by overriding methods
197
	 *          {@link ISTextProcessor#indexOfSpecial indexOfSpecial} and
198
	 *          {@link ISTextProcessor#processSpecial processSpecial}.
199
	 *          Examples of special cases are comments, literals, or
200
	 *          anything which is not identified by a one-character separator.
201
	 */
202
	public int getSpecialsCount() {
203
		return specialsCount;
204
	}
205
206
	/**
207
	 *  @return the base direction of the structured text for Arabic.
208
	 *          If a structured text contains both Arabic and
209
	 *          Hebrew words, the first Arabic or Hebrew letter in the
210
	 *          text determines which is the governing script.<br>
211
	 *          The value of this field is one of
212
	 *          {@link #DIR_LTR} or {@link #DIR_RTL}.
213
	 *
214
	 *  @see #getDirHebrew
215
	 */
216
	public int getDirArabic() {
217
		return dirArabic;
218
	}
219
220
	/**
221
	 *  @return the base direction of the structured text for Hebrew.
222
	 *          If a structured text contains both Arabic and
223
	 *          Hebrew words, the first Arabic or Hebrew letter in the
224
	 *          text determines which is the governing script.<br>
225
	 *          The value of this field is one of
226
	 *          {@link #DIR_LTR} or {@link #DIR_RTL}.
227
	 *
228
	 *  @see #getDirArabic
229
	 */
230
	public int getDirHebrew() {
231
		return dirHebrew;
232
	}
233
234
	/**
235
	 *  @return a flag indicating that Arabic letters will not be considered
236
	 *  for processing structured text.
237
	 */
238
	public boolean getIgnoreArabic() {
239
		return ignoreArabic;
240
	}
241
242
	/**
243
	 *  Flag indicating that Hebrew letters will not be considered for
244
	 *  processing structured text.
245
	 */
246
	public boolean getIgnoreHebrew() {
247
		return ignoreHebrew;
248
	}
249
250
}
(-)src/org/eclipse/equinox/bidi/custom/STextProcessor.java (+235 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.internal.STextImpl;
16
17
/**
18
 *  Generic processor which can be used as superclass (base class)
19
 *  for specific structured text processors.
20
 *  <p>
21
 *  Here are some guidelines about how to write structured text
22
 *  processors.
23
 *  <ul>
24
 *    <li>Processor instances may be accessed simultaneously by
25
 *        several threads. They should have no instance variables.</li>
26
 *    <li>Each use of a processor is associated with a set of
27
 *        {@link STextFeatures features}.
28
 *        All processors must have a default set of features which may be
29
 *        queried with the {@link #getFeatures getFeatures} method.
30
 *        These default features may be overridden by specifying a
31
 *        <code>features</code> argument when calling a method.
32
 *        See for instance
33
 *        {@link STextEngine#leanToFullText leanToFullText}.
34
 *    <li>The behavior of a processor is governed by 3 factors, all included
35
 *        in associated {@link STextFeatures features} data.
36
 *        <ul>
37
 *          <li>The separators specified in its
38
 *              {@link STextFeatures features} determine how submitted
39
 *              structured text is split into tokens.</li>
40
 *          <li>The tokens are displayed one after the other according
41
 *              to the appropriate direction, which can be different for
42
 *              Arabic and for Hebrew.</li>
43
 *          <li>The number of special cases which need to be handled by
44
 *              code specific to that processor.</li>
45
 *        </ul></li>
46
 *  </ul>
47
 *
48
 *  @see STextFeatures#getSeparators
49
 *  @see STextFeatures#getDirArabic
50
 *  @see STextFeatures#getDirHebrew
51
 *  @see STextFeatures#getSpecialsCount
52
 *
53
 *  @author Matitiahu Allouche
54
 */
55
public class STextProcessor implements ISTextProcessor {
56
57
	/**
58
	 *  In <code>STextProcessor</code> this method returns a
59
	 *  {@link STextFeatures#DEFAULT DEFAULT} value which
60
	 *  directs the processor to do nothing.
61
	 *
62
	 *  <p>A processor which extends this class must override this method
63
	 *  and return a STextFeatures instance representing its specific
64
	 *  features.
65
	 *
66
	 *  @see ISTextProcessor#getFeatures the corresponding interface method
67
	 */
68
	public STextFeatures getFeatures(STextEnvironment environment) {
69
		throw new IllegalStateException("A processor must have a getFeatures() method."); //$NON-NLS-1$
70
	}
71
72
	/**
73
	 *  In <code>STextProcessor</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
	 *  number of special cases is zero, which means that
77
	 *  <code>indexOfSpecial</code> should never be called for them.
78
	 *
79
	 *  <p>A processor handling special cases must override this method.
80
	 *
81
	 *  @see ISTextProcessor#indexOfSpecial the corresponding interface method
82
	 */
83
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
84
		// This method must be overridden by all subclasses with special cases.
85
		throw new IllegalStateException("A processor must have an indexOfSpecial() method."); //$NON-NLS-1$
86
	}
87
88
	/**
89
	 *  In <code>STextProcessor</code> this method throws an
90
	 *  <code>IllegalStateException</code>. This is appropriate behavior
91
	 *  (and does not need to be overridden) for processors whose
92
	 *  number of special cases is zero, which means that
93
	 *  <code>processSpecial</code> should never be called for them.
94
	 *
95
	 *  <p>A processor handling special cases must override this method.
96
	 *
97
	 *  @see ISTextProcessor#processSpecial the corresponding interface method
98
	 */
99
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
100
		// This method must be overridden by all subclasses with any special case.
101
		throw new IllegalStateException("A processor must have a processSpecial() method."); //$NON-NLS-1$
102
	}
103
104
	/**
105
	 *  This method can be called from within
106
	 *  {@link ISTextProcessor#indexOfSpecial indexOfSpecial} or
107
	 *  {@link ISTextProcessor#processSpecial processSpecial} in
108
	 *  implementations of {@link ISTextProcessor} to retrieve the
109
	 *  bidirectional class of characters in the <i>lean</i> text.
110
	 *
111
	 *  @param  text is the structured text string received as
112
	 *          parameter to <code>indexOfSpecial</code> or
113
	 *          <code>processSpecial</code>.
114
	 *
115
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
116
	 *          or <code>processSpecial</code>, uniquely to be used as argument
117
	 *          for calls to <code>getDirProp</code> and other methods used
118
	 *          by processors.
119
	 *
120
	 *  @param index position of the character in the <i>lean</i> text.
121
	 *          It must be a non-negative number smaller than the length
122
	 *          of the <i>lean</i> text.
123
	 *
124
	 *  @return the bidirectional class of the character. It is one of the
125
	 *          values which can be returned by
126
	 *          <code>java.lang.Character.getDirectionality</code>.
127
	 *          However, it is recommended to use <code>getDirProp</code>
128
	 *          rather than <code>java.lang.Character.getDirectionality</code>
129
	 *          since <code>getDirProp</code> manages a cache of character
130
	 *          properties and so can be more efficient than calling the
131
	 *          java.lang.Character method.
132
	 */
133
	public static byte getDirProp(String text, byte[] dirProps, int index) {
134
		return STextImpl.getDirProp(text, dirProps, index);
135
	}
136
137
	/**
138
	 *  This method can be called from within
139
	 *  {@link ISTextProcessor#indexOfSpecial indexOfSpecial} or
140
	 *  {@link ISTextProcessor#processSpecial processSpecial} in
141
	 *  implementations of {@link ISTextProcessor} to set or
142
	 *  override the bidirectional class of characters in the <i>lean</i> text.
143
	 *
144
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
145
	 *          or <code>processSpecial</code>, uniquely to be used as argument
146
	 *          for calls to <code>setDirProp</code> and other methods used
147
	 *          by processors.
148
	 *
149
	 *  @param index position of the character in the <i>lean</i> text.
150
	 *          It must be a non-negative number smaller than the length
151
	 *          of the <i>lean</i> text.
152
	 *
153
	 *  @param  dirProp bidirectional class of the character. It is one of the
154
	 *          values which can be returned by
155
	 *          <code>java.lang.Character.getDirectionality</code>.
156
	 */
157
	public static void setDirProp(byte[] dirProps, int index, byte dirProp) {
158
		STextImpl.setDirProp(dirProps, index, dirProp);
159
	}
160
161
	/**
162
	 *  This method can be called from within
163
	 *  {@link ISTextProcessor#indexOfSpecial indexOfSpecial} or
164
	 *  {@link ISTextProcessor#processSpecial processSpecial} in
165
	 *  implementations of {@link ISTextProcessor}
166
	 *  to specify that a mark character must be added before the character
167
	 *  at the specified position of the <i>lean</i> text when generating the
168
	 *  <i>full</i> text. The mark character will be LRM for structured text
169
	 *  with a LTR base direction, and RLM for structured text with RTL
170
	 *  base direction. The mark character is not added physically by this
171
	 *  method, but its position is noted and will be used when generating
172
	 *  the <i>full</i> text.
173
	 *
174
	 *  @param  text is the structured text string received as
175
	 *          parameter to <code>indexOfSpecial</code> or
176
	 *          <code>processSpecial</code>.
177
	 *
178
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
179
	 *          or <code>processSpecial</code>, uniquely to be used as argument
180
	 *          for calls to <code>insertMark</code> and other methods used
181
	 *          by processors.
182
	 *
183
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
184
	 *          or <code>processSpecial</code>, uniquely to be used as argument
185
	 *          for calls to <code>insertMark</code> and other methods used
186
	 *          by processors.
187
	 *
188
	 *  @param  offset position of the character in the <i>lean</i> text.
189
	 *          It must be a non-negative number smaller than the length
190
	 *          of the <i>lean</i> text.
191
	 *          For the benefit of efficiency, it is better to insert
192
	 *          multiple marks in ascending order of the offsets.
193
	 */
194
	public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
195
		STextImpl.insertMark(text, dirProps, offsets, offset);
196
	}
197
198
	/**
199
	 *  This method can be called from within
200
	 *  {@link ISTextProcessor#indexOfSpecial indexOfSpecial} or
201
	 *  {@link ISTextProcessor#processSpecial processSpecial} in
202
	 *  implementations of {@link ISTextProcessor} to add a
203
	 *  directional mark before a
204
	 *  separator if needed for correct display, depending on the
205
	 *  base direction of the text and on the class of the
206
	 *  characters in the <i>lean</i> text preceding and following
207
	 *  the separator itself.
208
	 *
209
	 *  @param  features is the {@link STextFeatures} instance
210
	 *          received as parameter to <code>indexOfSpecial</code> or
211
	 *          <code>processSpecial</code>.
212
	 *
213
	 *  @param  text is the structured text string received as
214
	 *          parameter to <code>indexOfSpecial</code> or
215
	 *          <code>processSpecial</code>.
216
	 *
217
	 *  @param  dirProps is a parameter received by <code>indexOfSpecial</code>
218
	 *          or <code>processSpecial</code>, uniquely to be used as argument
219
	 *          for calls to <code>processSeparator</code> and other methods used
220
	 *          by processors.
221
	 *
222
	 *  @param  offsets is a parameter received by <code>indexOfSpecial</code>
223
	 *          or <code>processSpecial</code>, uniquely to be used as argument
224
	 *          for calls to <code>processSeparator</code> and other methods used
225
	 *          by processors.
226
	 *
227
	 *  @param  separLocation offset of the separator in the <i>lean</i> text.
228
	 *          It must be a non-negative number smaller than the length
229
	 *          of the <i>lean</i> text.
230
	 */
231
	public static void processSeparator(STextFeatures features, String text, byte[] dirProps, int[] offsets, int separLocation) {
232
		STextImpl.processSeparator(features, text, dirProps, offsets, separLocation);
233
	}
234
235
}
(-)src/org/eclipse/equinox/bidi/custom/STextStringProcessor.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.STextTypesCollector;
14
15
/**
16
 * This class provides access to registered structured text processors.
17
 */
18
public class STextStringProcessor {
19
	/**
20
	 *  Retrieve all registered types of structured text processors.
21
	 *
22
	 *  @return an array of strings, each string identifying a type of
23
	 *  structured text processor.
24
	 */
25
	static public String[] getKnownTypes() {
26
		return STextTypesCollector.getInstance().getTypes();
27
	}
28
29
	/**
30
	 *  Get access to a structured text 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 ISTextProcessor getProcessor(String type) {
38
		return STextTypesCollector.getInstance().getProcessor(type);
39
	}
40
}
(-)src/org/eclipse/equinox/bidi/custom/package.html (-6 / +6 lines)
Lines 6-23 Link Here
6
<body bgcolor="white">
6
<body bgcolor="white">
7
7
8
This package provides an interface and classes for
8
This package provides an interface and classes for
9
developing complex expressions processors.
9
developing structured text processors.
10
10
11
<ul>
11
<ul>
12
  <li>{@link <a href="IBidiComplexProcessor.html">IBidiComplexProcessor</a>}
12
  <li>{@link <a href="ISTextProcessor.html">ISTextProcessor</a>}
13
      is an interface specifying which methods a processor must provide.</li>
13
      is an interface specifying which methods a processor must provide.</li>
14
  <li>{@link <a href="BidiComplexProcessor.html">BidiComplexProcessor</a>}
14
  <li>{@link <a href="STextProcessor.html">STextProcessor</a>}
15
      is a generic processor which can be used as superclass for specific
15
      is a generic processor which can be used as superclass for specific
16
      processors.</li>
16
      processors.</li>
17
  <li>{@link <a href="BidiComplexFeatures.html">BidiComplexFeatures</a>}
17
  <li>{@link <a href="STextFeatures.html">STextFeatures</a>}
18
      allows managing some factors which affect
18
      allows managing some factors which affect
19
      a complex expression processor's behavior</li>
19
      a structured text processor's behavior</li>
20
  <li>{@link <a href="BidiComplexStringProcessor.html">BidiComplexStringProcessor</a>}
20
  <li>{@link <a href="STextStringProcessor.html">STextStringProcessor</a>}
21
      is a class which allows retrieval of the defined processor types and of the
21
      is a class which allows retrieval of the defined processor types and of the
22
      corresponding processors.</li>
22
      corresponding processors.</li>
23
</ul>
23
</ul>
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexActivator.java (-91 lines)
Removed 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)
Removed 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.custom.BidiComplexFeatures;
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 separators where the text segments
19
 *  may include delimited parts within which separators 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(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
30
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
31
		return text.indexOf(delim, fromIndex);
32
	}
33
34
	/**
35
	 *  This method skips until after the matching end delimiter.
36
	 */
37
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
38
		BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
39
		int loc = separLocation + 1;
40
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
41
		loc = text.indexOf(delim, loc);
42
		if (loc < 0)
43
			return text.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, separators 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 (-56 lines)
Removed 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.custom.BidiComplexFeatures;
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 separators where the text segments
19
 *  may include delimited parts within which separators are treated like
20
 *  regular characters and the delimiters may be escaped.
21
 *  This is similar to {@link BidiComplexDelims} except
22
 *  that delimiters can be escaped using the backslash character.
23
 *  <ul>
24
 *    <li>Two consecutive backslashes in a delimited part are treated like
25
 *        one regular character.</li>
26
 *    <li>An ending delimiter preceded by an odd number of backslashes is
27
 *        treated like a regular character within the delimited part.</li>
28
 *  </ul>
29
 *
30
 *  @author Matitiahu Allouche
31
 */
32
public abstract class BidiComplexDelimsEsc extends BidiComplexDelims {
33
34
	/**
35
	 *  This method skips until after the matching end delimiter,
36
	 *  ignoring possibly escaped end delimiters.
37
	 */
38
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
39
		BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
40
		int location = separLocation + 1;
41
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
42
		while (true) {
43
			location = text.indexOf(delim, location);
44
			if (location < 0)
45
				return text.length();
46
			int cnt = 0;
47
			for (int i = location - 1; text.charAt(i) == '\\'; i--) {
48
				cnt++;
49
			}
50
			location++;
51
			if ((cnt & 1) == 0)
52
				return location;
53
		}
54
	}
55
56
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java (-700 lines)
Removed 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.BidiComplexEngine;
14
import org.eclipse.equinox.bidi.BidiComplexEnvironment;
15
import org.eclipse.equinox.bidi.custom.*;
16
17
/**
18
 *  <code>BidiComplexImpl</code> provides the code which implements the API in
19
 *  {@link BidiComplexEngine}. All its public methods are shadows of similarly
20
 *  signed methods of <code>BidiComplexEngine</code>, and their documentation
21
 *  is by reference to the methods in <code>BidiComplexEngine</code>.
22
 *
23
 *  @author Matitiahu Allouche
24
 */
25
public class BidiComplexImpl {
26
27
	static final String EMPTY_STRING = ""; //$NON-NLS-1$
28
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
29
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
30
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
31
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
32
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
33
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
34
	static final char LRM = 0x200E;
35
	static final char RLM = 0x200F;
36
	static final char LRE = 0x202A;
37
	static final char RLE = 0x202B;
38
	static final char PDF = 0x202C;
39
	static final char[] MARKS = {LRM, RLM};
40
	static final char[] EMBEDS = {LRE, RLE};
41
	static final byte[] STRONGS = {L, R};
42
	static final int PREFIX_LENGTH = 2;
43
	static final int SUFFIX_LENGTH = 2;
44
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
45
	static final int DIRPROPS_ADD = 2;
46
	static final int OFFSETS_SHIFT = 3;
47
	static final int[] EMPTY_INT_ARRAY = new int[0];
48
	static final BidiComplexEnvironment IGNORE_ENVIRONMENT = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_IGNORE);
49
50
	/**
51
	 *  Prevent creation of a BidiComplexEngine instance
52
	 */
53
	private BidiComplexImpl() {
54
		// nothing to do
55
	}
56
57
	/*
58
	        // keep private copy of specialsCount to avoid later modification
59
	        specialsCount = features.getSpecialsCount();
60
	        locations = new int[features.getSeparators().length() + specialsCount];
61
	    }
62
	*/
63
	static long computeNextLocation(IBidiComplexProcessor processor, BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] locations, int[] state, int curPos) {
64
		String separators = features.getSeparators();
65
		int separCount = separators.length();
66
		int specialsCount = features.getSpecialsCount();
67
		int len = text.length();
68
		int nextLocation = len;
69
		int idxLocation = 0;
70
		// Start with special sequences to give them precedence over simple
71
		// separators. This may apply to cases like slash+asterisk versus slash.
72
		for (int i = 0; i < specialsCount; i++) {
73
			int location = locations[separCount + i];
74
			if (location < curPos) {
75
				offsets = ensureRoomInOffsets(offsets);
76
				location = processor.indexOfSpecial(features, text, dirProps, offsets, i + 1, curPos);
77
				if (location < 0)
78
					location = len;
79
				locations[separCount + i] = location;
80
			}
81
			if (location < nextLocation) {
82
				nextLocation = location;
83
				idxLocation = separCount + i;
84
			}
85
		}
86
		for (int i = 0; i < separCount; i++) {
87
			int location = locations[i];
88
			if (location < curPos) {
89
				location = text.indexOf(separators.charAt(i), curPos);
90
				if (location < 0)
91
					location = len;
92
				locations[i] = location;
93
			}
94
			if (location < nextLocation) {
95
				nextLocation = location;
96
				idxLocation = i;
97
			}
98
		}
99
		return nextLocation + (((long) idxLocation) << 32);
100
	}
101
102
	static int getCurOrient(BidiComplexEnvironment environment, String text, byte[] dirProps) {
103
		int orient = environment.getOrientation();
104
		if ((orient & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) {
105
			// absolute orientation
106
			return orient;
107
		}
108
		// contextual orientation
109
		int len = text.length();
110
		byte dirProp;
111
		for (int i = 0; i < len; i++) {
112
			// In the following lines, B, L, R and AL represent bidi categories
113
			// as defined in the Unicode Bidirectional Algorithm
114
			// ( http://www.unicode.org/reports/tr9/ ).
115
			// B  represents the category Block Separator.
116
			// L  represents the category Left to Right character.
117
			// R  represents the category Right to Left character.
118
			// AL represents the category Arabic Letter.
119
			dirProp = dirProps[i];
120
			if (dirProp == 0) {
121
				dirProp = Character.getDirectionality(text.charAt(i));
122
				if (dirProp == B) // B char resolves to L or R depending on orientation
123
					continue;
124
				dirProps[i] = (byte) (dirProp + DIRPROPS_ADD);
125
			} else {
126
				dirProp -= DIRPROPS_ADD;
127
			}
128
			if (dirProp == L)
129
				return BidiComplexEnvironment.ORIENT_LTR;
130
			if (dirProp == R || dirProp == AL)
131
				return BidiComplexEnvironment.ORIENT_RTL;
132
		}
133
		// return the default orientation corresponding to the contextual orientation
134
		return orient & 1;
135
	}
136
137
	/**
138
	 *  @see BidiComplexEngine#getCurDirection BidiComplexEngine.getCurDirection
139
	 */
140
	public static int getCurDirection(Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, byte[] dirProps) {
141
		if (environment == null)
142
			environment = BidiComplexEnvironment.DEFAULT;
143
		if (features == null) {
144
			if (_processor == null)
145
				return BidiComplexFeatures.DIR_LTR;
146
			IBidiComplexProcessor processor;
147
			if (_processor instanceof java.lang.String) {
148
				processor = BidiComplexStringProcessor.getProcessor((String) _processor);
149
				if (processor == null)
150
					throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
151
			} else if (_processor instanceof IBidiComplexProcessor)
152
				processor = (IBidiComplexProcessor) _processor;
153
			else
154
				throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
155
			features = processor.getFeatures(environment);
156
		}
157
		int dirArabic = features.getDirArabic();
158
		int dirHebrew = features.getDirHebrew();
159
		// same direction for Arabic and Hebrew?
160
		if (dirArabic == dirHebrew)
161
			return dirArabic;
162
		// check if Arabic or Hebrew letter comes first
163
		int len = text.length();
164
		if (dirProps == null)
165
			dirProps = new byte[len + 1];
166
		byte dirProp;
167
		for (int i = 0; i < len; i++) {
168
			// In the following lines, R and AL represent bidi categories
169
			// as defined in the Unicode Bidirectional Algorithm
170
			// ( http://www.unicode.org/reports/tr9/ ).
171
			// R  represents the category Right to Left character.
172
			// AL represents the category Arabic Letter.
173
			byte saveOrient = dirProps[len];
174
			dirProps[len] = -1; // make getDirProp return B
175
			dirProp = getDirProp(text, dirProps, i);
176
			dirProps[len] = saveOrient;
177
			if (dirProp == AL)
178
				return dirArabic;
179
			if (dirProp == R)
180
				return dirHebrew;
181
		}
182
		// found no Arabic or Hebrew character
183
		return BidiComplexFeatures.DIR_LTR;
184
	}
185
186
	/**
187
	 *  @see BidiComplexProcessor#getDirProp BidiComplexProcessor.getDirProp
188
	 */
189
	public static byte getDirProp(String text, byte[] dirProps, int index) {
190
		byte dirProp = dirProps[index];
191
		if (dirProp == 0) {
192
			// In the following lines, B, L and R represent bidi categories
193
			// as defined in the Unicode Bidirectional Algorithm
194
			// ( http://www.unicode.org/reports/tr9/ ).
195
			// B  represents the category Block Separator.
196
			// L  represents the category Left to Right character.
197
			// R  represents the category Right to Left character.
198
			dirProp = Character.getDirectionality(text.charAt(index));
199
			if (dirProp == B) {
200
				// the last entry of dirProps contains the current component orientation
201
				byte orient = dirProps[dirProps.length - 1];
202
				if (orient == -1)
203
					return B;
204
				dirProp = orient == BidiComplexEnvironment.ORIENT_RTL ? R : L;
205
			}
206
			dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
207
			return dirProp;
208
		}
209
		return (byte) (dirProp - DIRPROPS_ADD);
210
	}
211
212
	/**
213
	 *  @see BidiComplexProcessor#setDirProp BidiComplexProcessor.setDirProp
214
	 */
215
	public static void setDirProp(byte[] dirProps, int index, byte dirProp) {
216
		dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
217
	}
218
219
	/**
220
	 *  @see BidiComplexProcessor#processSeparator BidiComplexProcessor.processSeparator
221
	 */
222
	public static void processSeparator(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int separLocation) {
223
		// In this method, L, R, AL, AN and EN represent bidi categories
224
		// as defined in the Unicode Bidirectional Algorithm
225
		// ( http://www.unicode.org/reports/tr9/ ).
226
		// L  represents the category Left to Right character.
227
		// R  represents the category Right to Left character.
228
		// AL represents the category Arabic Letter.
229
		// AN represents the category Arabic Number.
230
		// EN  represents the category European Number.
231
		int len = text.length();
232
		// offsets[2] contains the complex expression direction
233
		if (offsets[2] == BidiComplexFeatures.DIR_RTL) {
234
			// the expression base direction is RTL
235
			for (int i = separLocation - 1; i >= 0; i--) {
236
				byte dirProp = getDirProp(text, dirProps, i);
237
				if (dirProp == R || dirProp == AL)
238
					return;
239
				if (dirProp == L) {
240
					for (int j = separLocation; j < len; j++) {
241
						dirProp = getDirProp(text, dirProps, j);
242
						if (dirProp == R || dirProp == AL)
243
							return;
244
						if (dirProp == L || dirProp == EN) {
245
							insertMark(text, dirProps, offsets, separLocation);
246
							return;
247
						}
248
					}
249
					return;
250
				}
251
			}
252
			return;
253
		}
254
255
		// the expression base direction is LTR
256
		boolean doneAN = false;
257
		boolean ignoreArabic = features.getIgnoreArabic();
258
		boolean ignoreHebrew = features.getIgnoreHebrew();
259
		if (ignoreArabic && ignoreHebrew)
260
			return;
261
		byte _R, _AL, _AN;
262
		if (ignoreArabic) {
263
			_AL = Byte.MIN_VALUE; // not a real value
264
			_AN = Byte.MIN_VALUE;
265
		} else {
266
			_AL = AL;
267
			_AN = AN;
268
		}
269
		if (ignoreHebrew)
270
			_R = Byte.MIN_VALUE;
271
		else
272
			_R = R;
273
		for (int i = separLocation - 1; i >= 0; i--) {
274
			byte dirProp = getDirProp(text, dirProps, i);
275
			if (dirProp == L)
276
				return;
277
			if (dirProp == _R || dirProp == _AL) {
278
				for (int j = separLocation; j < len; j++) {
279
					dirProp = getDirProp(text, dirProps, j);
280
					if (dirProp == L)
281
						return;
282
					if (dirProp == _R || dirProp == EN || dirProp == _AL || dirProp == _AN) {
283
						insertMark(text, dirProps, offsets, separLocation);
284
						return;
285
					}
286
				}
287
				return;
288
			}
289
			if (dirProp == _AN && !doneAN) {
290
				for (int j = separLocation; j < len; j++) {
291
					dirProp = getDirProp(text, dirProps, j);
292
					if (dirProp == L)
293
						return;
294
					if (dirProp == _AL || dirProp == _AN || dirProp == _R) {
295
						insertMark(text, dirProps, offsets, separLocation);
296
						return;
297
					}
298
				}
299
				doneAN = true;
300
			}
301
		}
302
	}
303
304
	/**
305
	 *  @see BidiComplexEngine#leanToFullText BidiComplexEngine.leanToFullText
306
	 */
307
	public static String leanToFullText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
308
		int len = text.length();
309
		if (len == 0)
310
			return text;
311
		byte[] dirProps = new byte[len + 1];
312
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
313
		int prefixLength = offsets[1];
314
		int count = offsets[0] - OFFSETS_SHIFT;
315
		if (count == 0 && prefixLength == 0)
316
			return text;
317
		int newLen = len + count;
318
		if (prefixLength == 1)
319
			newLen++; /* +1 for a mark char */
320
		else if (prefixLength == 2)
321
			newLen += FIXES_LENGTH;
322
		char[] fullChars = new char[newLen];
323
		int added = prefixLength;
324
		// add marks at offsets
325
		int direction = offsets[2];
326
		char curMark = MARKS[direction];
327
		for (int i = 0, j = OFFSETS_SHIFT; i < len; i++) {
328
			char c = text.charAt(i);
329
			// offsets[0] contains the number of used entries
330
			if (j < offsets[0] && i == offsets[j]) {
331
				fullChars[i + added] = curMark;
332
				added++;
333
				j++;
334
			}
335
			fullChars[i + added] = c;
336
		}
337
		if (prefixLength > 0) { /* add prefix/suffix ? */
338
			if (prefixLength == 1) { /* contextual orientation */
339
				fullChars[0] = curMark;
340
			} else {
341
				// When the orientation is RTL, we need to add EMBED at the
342
				// start of the text and PDF at its end.
343
				// However, because of a bug in Windows' handling of LRE/PDF,
344
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
345
				char curEmbed = EMBEDS[direction];
346
				fullChars[0] = curEmbed;
347
				fullChars[1] = curMark;
348
				fullChars[newLen - 1] = PDF;
349
				fullChars[newLen - 2] = curMark;
350
			}
351
		}
352
		return new String(fullChars);
353
	}
354
355
	/**
356
	 *  @see BidiComplexEngine#leanToFullMap BidiComplexEngine.leanToFullMap
357
	 */
358
	public static int[] leanToFullMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
359
		int len = text.length();
360
		if (len == 0)
361
			return EMPTY_INT_ARRAY;
362
		byte[] dirProps = new byte[len + 1];
363
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
364
		int prefixLength = offsets[1];
365
		int[] map = new int[len];
366
		int count = offsets[0]; // number of used entries
367
		int added = prefixLength;
368
		for (int pos = 0, i = OFFSETS_SHIFT; pos < len; pos++) {
369
			if (i < count && pos == offsets[i]) {
370
				added++;
371
				i++;
372
			}
373
			map[pos] = pos + added;
374
		}
375
		return map;
376
	}
377
378
	/**
379
	 *  @see BidiComplexEngine#leanBidiCharOffsets BidiComplexEngine.leanBidiCharOffsets
380
	 */
381
	public static int[] leanBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
382
		int len = text.length();
383
		if (len == 0)
384
			return EMPTY_INT_ARRAY;
385
		byte[] dirProps = new byte[len + 1];
386
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
387
		// offsets[0] contains the number of used entries
388
		int count = offsets[0] - OFFSETS_SHIFT;
389
		int[] result = new int[count];
390
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, count);
391
		return result;
392
	}
393
394
	static int[] leanToFullCommon(Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state, byte[] dirProps) {
395
		IBidiComplexProcessor processor;
396
		if (_processor instanceof java.lang.String) {
397
			processor = BidiComplexStringProcessor.getProcessor((String) _processor);
398
			if (processor == null)
399
				throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
400
		} else if (_processor instanceof IBidiComplexProcessor)
401
			processor = (IBidiComplexProcessor) _processor;
402
		else
403
			throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
404
		if (environment == null)
405
			environment = BidiComplexEnvironment.DEFAULT;
406
		if (features == null)
407
			features = processor.getFeatures(environment);
408
		if (state == null) {
409
			state = new int[1];
410
			state[0] = BidiComplexEngine.STATE_INITIAL;
411
		}
412
		int len = text.length();
413
		// dirProps: 1 byte for each char in text, + 1 byte = current orientation
414
		int orient = getCurOrient(environment, text, dirProps);
415
		dirProps[len] = (byte) orient;
416
		int separCount = features.getSeparators().length();
417
		int direction = getCurDirection(processor, features, environment, text, dirProps);
418
		// current position
419
		int curPos = 0;
420
		// offsets of marks to add. Entry 0 is the number of used slots;
421
		//  entry 1 is reserved to pass prefixLength.
422
		//  entry 2 is reserved to pass direction..
423
		int[] offsets = new int[20];
424
		offsets[0] = OFFSETS_SHIFT;
425
		offsets[2] = direction;
426
		// initialize locations
427
		int[] locations = new int[separCount + features.getSpecialsCount()];
428
		for (int i = 0, k = locations.length; i < k; i++) {
429
			locations[i] = -1;
430
		}
431
		if (state[0] > BidiComplexEngine.STATE_INITIAL) {
432
			offsets = ensureRoomInOffsets(offsets);
433
			int initState = state[0];
434
			state[0] = BidiComplexEngine.STATE_INITIAL;
435
			curPos = processor.processSpecial(features, text, dirProps, offsets, state, initState, -1);
436
		}
437
		while (true) {
438
			// location of next token to handle
439
			int nextLocation;
440
			// index of next token to handle (if < separCount, this is a separator; otherwise a special case
441
			int idxLocation;
442
			long res = computeNextLocation(processor, features, text, dirProps, offsets, locations, state, curPos);
443
			nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
444
			if (nextLocation >= len)
445
				break;
446
			idxLocation = (int) (res >> 32); /* high word */
447
			if (idxLocation < separCount) {
448
				offsets = ensureRoomInOffsets(offsets);
449
				processSeparator(features, text, dirProps, offsets, nextLocation);
450
				curPos = nextLocation + 1;
451
			} else {
452
				offsets = ensureRoomInOffsets(offsets);
453
				idxLocation -= (separCount - 1); // because caseNumber starts from 1
454
				curPos = processor.processSpecial(features, text, dirProps, offsets, state, idxLocation, nextLocation);
455
			}
456
		}
457
		if (orient == BidiComplexEnvironment.ORIENT_IGNORE)
458
			offsets[1] = 0;
459
		else {
460
			// recompute orient since it may have changed if contextual
461
			orient = getCurOrient(environment, text, dirProps);
462
			dirProps[len] = (byte) orient;
463
			if (orient == direction && orient != BidiComplexEnvironment.ORIENT_UNKNOWN)
464
				offsets[1] = 0;
465
			else if ((environment.getOrientation() & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
466
				offsets[1] = 1;
467
			else
468
				offsets[1] = 2;
469
		}
470
		return offsets;
471
	}
472
473
	/**
474
	 *  @see BidiComplexEngine#fullToLeanText BidiComplexEngine.fullToLeanText
475
	 */
476
	public static String fullToLeanText(Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) {
477
		if (text.length() == 0)
478
			return text;
479
		IBidiComplexProcessor processor;
480
		if (_processor instanceof java.lang.String) {
481
			processor = BidiComplexStringProcessor.getProcessor((String) _processor);
482
			if (processor == null)
483
				throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
484
		} else if (_processor instanceof IBidiComplexProcessor)
485
			processor = (IBidiComplexProcessor) _processor;
486
		else
487
			throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
488
		if (environment == null)
489
			environment = BidiComplexEnvironment.DEFAULT;
490
		if (features == null)
491
			features = processor.getFeatures(environment);
492
		if (state == null) {
493
			state = new int[1];
494
			state[0] = BidiComplexEngine.STATE_INITIAL;
495
		}
496
		int dir = getCurDirection(processor, features, environment, text, null);
497
		char curMark = MARKS[dir];
498
		char curEmbed = EMBEDS[dir];
499
		int i; // used as loop index
500
		// remove any prefix and leading mark
501
		int lenText = text.length();
502
		for (i = 0; i < lenText; i++) {
503
			char c = text.charAt(i);
504
			if (c != curEmbed && c != curMark)
505
				break;
506
		}
507
		if (i > 0) { // found at least one prefix or leading mark
508
			text = text.substring(i);
509
			lenText = text.length();
510
		}
511
		// remove any suffix and trailing mark
512
		for (i = lenText - 1; i >= 0; i--) {
513
			char c = text.charAt(i);
514
			if (c != PDF && c != curMark)
515
				break;
516
		}
517
		if (i < 0) // only suffix and trailing marks, no real data
518
			return EMPTY_STRING;
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
		String full = leanToFullText(processor, features, IGNORE_ENVIRONMENT, lean, state);
535
		if (full.equals(text))
536
			return lean;
537
538
		// There are some marks in full which are not in text and/or vice versa.
539
		// We need to add to lean any mark appearing in text and not in full.
540
		// The completed lean can never be longer than text itself.
541
		char[] newChars = new char[lenText];
542
		char cFull, cText;
543
		int idxFull, idxText, idxLean, newCharsPos;
544
		int lenFull = full.length();
545
		idxFull = idxText = idxLean = newCharsPos = 0;
546
		while (idxText < lenText && idxFull < lenFull) {
547
			cFull = full.charAt(idxFull);
548
			cText = text.charAt(idxText);
549
			if (cFull == cText) { /* chars are equal, proceed */
550
				if (cFull != curMark)
551
					newChars[newCharsPos++] = chars[idxLean++];
552
				idxText++;
553
				idxFull++;
554
				continue;
555
			}
556
			if (cFull == curMark) { /* extra Mark in full text */
557
				idxFull++;
558
				continue;
559
			}
560
			if (cText == curMark) { /* extra Mark in source full text */
561
				idxText++;
562
				// idxText-2 always >= 0 since leading Marks were removed from text
563
				if (text.charAt(idxText - 2) == curMark)
564
					continue; // ignore successive Marks in text after the first one
565
				newChars[newCharsPos++] = curMark;
566
				continue;
567
			}
568
			// we should never get here (extra char which is not a Mark)
569
			throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$
570
		}
571
		if (idxText < lenText) /* full ended before text - this should never happen since
572
								             we removed all marks and PDFs at the end of text */
573
			throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$
574
575
		lean = new String(newChars, 0, newCharsPos);
576
		return lean;
577
	}
578
579
	/**
580
	 *  @see BidiComplexEngine#fullToLeanMap BidiComplexEngine.fullToLeanMap
581
	 */
582
	public static int[] fullToLeanMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String full, int[] state) {
583
		int lenFull = full.length();
584
		if (lenFull == 0)
585
			return EMPTY_INT_ARRAY;
586
		String lean = fullToLeanText(processor, features, environment, full, state);
587
		int lenLean = lean.length();
588
		int dir = getCurDirection(processor, features, environment, lean, null);
589
		char curMark = MARKS[dir];
590
		char curEmbed = EMBEDS[dir];
591
		int[] map = new int[lenFull];
592
		int idxFull, idxLean;
593
		// skip any prefix and leading mark
594
		for (idxFull = 0; idxFull < lenFull; idxFull++) {
595
			char c = full.charAt(idxFull);
596
			if (c != curEmbed && c != curMark)
597
				break;
598
			map[idxFull] = -1;
599
		}
600
		// lean must be a subset of Full, so we only check on iLean < leanLen
601
		for (idxLean = 0; idxLean < lenLean; idxFull++) {
602
			if (full.charAt(idxFull) == lean.charAt(idxLean)) {
603
				map[idxFull] = idxLean;
604
				idxLean++;
605
			} else
606
				map[idxFull] = -1;
607
		}
608
		for (; idxFull < lenFull; idxFull++)
609
			map[idxFull] = -1;
610
		return map;
611
	}
612
613
	/**
614
	 *  @see BidiComplexEngine#fullBidiCharOffsets BidiComplexEngine.fullBidiCharOffsets
615
	 */
616
	public static int[] fullBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String full, int[] state) {
617
		int lenFull = full.length();
618
		if (lenFull == 0)
619
			return EMPTY_INT_ARRAY;
620
		String lean = fullToLeanText(processor, features, environment, full, state);
621
		int[] offsets = new int[20];
622
		offsets[0] = OFFSETS_SHIFT;
623
		int lenLean = lean.length();
624
		int idxLean, idxFull;
625
		// lean must be a subset of Full, so we only check on iLean < leanLen
626
		for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) {
627
			if (full.charAt(idxFull) == lean.charAt(idxLean))
628
				idxLean++;
629
			else {
630
				offsets = ensureRoomInOffsets(offsets);
631
				insertMark(lean, null, offsets, idxFull);
632
			}
633
		}
634
		for (; idxFull < lenFull; idxFull++) {
635
			offsets = ensureRoomInOffsets(offsets);
636
			insertMark(lean, null, offsets, idxFull);
637
		}
638
		int[] result = new int[offsets[0] - OFFSETS_SHIFT];
639
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length);
640
		return result;
641
	}
642
643
	static int[] ensureRoomInOffsets(int[] offsets) {
644
		// make sure
645
		if ((offsets.length - offsets[0]) < 3) {
646
			int[] newOffsets = new int[offsets.length * 2];
647
			System.arraycopy(offsets, 0, newOffsets, 0, offsets[0]);
648
			return newOffsets;
649
		}
650
		return offsets;
651
	}
652
653
	/**
654
	 *  @see BidiComplexProcessor#insertMark BidiComplexProcessor.insertMark
655
	 */
656
	public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
657
		int count = offsets[0];// number of used entries
658
		int index = count - 1; // index of greatest member <= offset
659
		// look up after which member the new offset should be inserted
660
		while (index >= OFFSETS_SHIFT) {
661
			int wrkOffset = offsets[index];
662
			if (offset > wrkOffset)
663
				break;
664
			if (offset == wrkOffset)
665
				return; // avoid duplicates
666
			index--;
667
		}
668
		index++; // index now points at where to insert
669
		int length = count - index; // number of members to move up
670
		if (length > 0) // shift right all members greater than offset
671
			System.arraycopy(offsets, index, offsets, index + 1, length);
672
		offsets[index] = offset;
673
		offsets[0]++; // number of used entries
674
		// if the offset is 0, adding a mark does not change anything
675
		if (dirProps == null || offset < 1)
676
			return;
677
678
		byte dirProp = getDirProp(text, dirProps, offset);
679
		// if the current char is a strong one or a digit, we change the
680
		//   dirProp of the previous char to account for the inserted mark.
681
		// In the following lines, L, R, AL, AN and EN represent bidi categories
682
		// as defined in the Unicode Bidirectional Algorithm
683
		// ( http://www.unicode.org/reports/tr9/ ).
684
		// L  represents the category Left to Right character.
685
		// R  represents the category Right to Left character.
686
		// AL represents the category Arabic Letter.
687
		// AN represents the category Arabic Number.
688
		// EN  represents the category European Number.
689
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
690
			index = offset - 1;
691
		else
692
			// if the current char is a neutral, we change its own dirProp
693
			index = offset;
694
695
		int dir = offsets[2]; // current expression direction
696
		setDirProp(dirProps, index, STRONGS[dir]);
697
		return;
698
	}
699
700
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java (-52 lines)
Removed 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.custom.BidiComplexFeatures;
14
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
15
16
/**
17
 *  <code>BidiComplexSingle</code> is a processor for complex expressions
18
 *  composed of two parts separated by a separator.
19
 *  The first occurrence of the separator delimits the end of the first part
20
 *  and the start of the second part. Further occurrences of the separator,
21
 *  if any, are treated like regular characters of the second text part.
22
 *  The processor makes sure that the expression be presented in the form
23
 *  (assuming that the equal sign is the separator):
24
 *  <pre>
25
 *  part1=part2
26
 *  </pre>
27
 *  The {@link BidiComplexFeatures#getSeparators separators}
28
 *  field in the {@link BidiComplexFeatures features}
29
 *  of this processor should contain exactly one character.
30
 *  Additional characters will be ignored.
31
 *
32
 *  @author Matitiahu Allouche
33
 */
34
public abstract class BidiComplexSingle extends BidiComplexProcessor {
35
36
	/**
37
	 *  This method locates occurrences of the separator.
38
	 */
39
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
40
		return text.indexOf(features.getSeparators().charAt(0), fromIndex);
41
	}
42
43
	/**
44
	 *  This method inserts a mark before the separator if needed and
45
	 *  skips to the end of the source string.
46
	 */
47
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
48
		BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
49
		return text.length();
50
	}
51
52
}
(-)src/org/eclipse/equinox/bidi/internal/BidiComplexTypesCollector.java (-111 lines)
Removed 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/STextActivator.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 STextActivator implements BundleActivator {
21
22
	private ServiceTracker logTracker = null;
23
	private BundleContext bundleContext;
24
	private static STextActivator instance;
25
26
	public STextActivator() {
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 STextActivator 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/STextDelims.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.custom.STextFeatures;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
/**
17
 *  <code>STextDelims</code> is a processor for structured text
18
 *  composed of text segments separated by separators where the text segments
19
 *  may include delimited parts within which separators are treated like
20
 *  regular characters.
21
 *
22
 *  @author Matitiahu Allouche
23
 */
24
public abstract class STextDelims extends STextProcessor {
25
26
	/**
27
	 *  This method locates occurrences of start delimiters.
28
	 */
29
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
30
		char delim = getDelimiters().charAt((caseNumber - 1) * 2);
31
		return text.indexOf(delim, fromIndex);
32
	}
33
34
	/**
35
	 *  This method skips until after the matching end delimiter.
36
	 */
37
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
38
		STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
39
		int loc = separLocation + 1;
40
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
41
		loc = text.indexOf(delim, loc);
42
		if (loc < 0)
43
			return text.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, separators 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/STextDelimsEsc.java (+56 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.custom.STextFeatures;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
/**
17
 *  <code>STextDelims</code> is a processor for structured text
18
 *  composed of text segments separated by separators where the text segments
19
 *  may include delimited parts within which separators are treated like
20
 *  regular characters and the delimiters may be escaped.
21
 *  This is similar to {@link STextDelims} except
22
 *  that delimiters can be escaped using the backslash character.
23
 *  <ul>
24
 *    <li>Two consecutive backslashes in a delimited part are treated like
25
 *        one regular character.</li>
26
 *    <li>An ending delimiter preceded by an odd number of backslashes is
27
 *        treated like a regular character within the delimited part.</li>
28
 *  </ul>
29
 *
30
 *  @author Matitiahu Allouche
31
 */
32
public abstract class STextDelimsEsc extends STextDelims {
33
34
	/**
35
	 *  This method skips until after the matching end delimiter,
36
	 *  ignoring possibly escaped end delimiters.
37
	 */
38
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
39
		STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
40
		int location = separLocation + 1;
41
		char delim = getDelimiters().charAt((caseNumber * 2) - 1);
42
		while (true) {
43
			location = text.indexOf(delim, location);
44
			if (location < 0)
45
				return text.length();
46
			int cnt = 0;
47
			for (int i = location - 1; text.charAt(i) == '\\'; i--) {
48
				cnt++;
49
			}
50
			location++;
51
			if ((cnt & 1) == 0)
52
				return location;
53
		}
54
	}
55
56
}
(-)src/org/eclipse/equinox/bidi/internal/STextImpl.java (+700 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.*;
16
17
/**
18
 *  <code>STextImpl</code> provides the code which implements the API in
19
 *  {@link STextEngine}. All its public methods are shadows of similarly
20
 *  signed methods of <code>STextEngine</code>, and their documentation
21
 *  is by reference to the methods in <code>STextEngine</code>.
22
 *
23
 *  @author Matitiahu Allouche
24
 */
25
public class STextImpl {
26
27
	static final String EMPTY_STRING = ""; //$NON-NLS-1$
28
	static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
29
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
30
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
31
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
32
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
33
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
34
	static final char LRM = 0x200E;
35
	static final char RLM = 0x200F;
36
	static final char LRE = 0x202A;
37
	static final char RLE = 0x202B;
38
	static final char PDF = 0x202C;
39
	static final char[] MARKS = {LRM, RLM};
40
	static final char[] EMBEDS = {LRE, RLE};
41
	static final byte[] STRONGS = {L, R};
42
	static final int PREFIX_LENGTH = 2;
43
	static final int SUFFIX_LENGTH = 2;
44
	static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH;
45
	static final int DIRPROPS_ADD = 2;
46
	static final int OFFSETS_SHIFT = 3;
47
	static final int[] EMPTY_INT_ARRAY = new int[0];
48
	static final STextEnvironment IGNORE_ENVIRONMENT = new STextEnvironment(null, false, STextEnvironment.ORIENT_IGNORE);
49
50
	/**
51
	 *  Prevent creation of a STextEngine instance
52
	 */
53
	private STextImpl() {
54
		// nothing to do
55
	}
56
57
	/*
58
	        // keep private copy of specialsCount to avoid later modification
59
	        specialsCount = features.getSpecialsCount();
60
	        locations = new int[features.getSeparators().length() + specialsCount];
61
	    }
62
	*/
63
	static long computeNextLocation(ISTextProcessor processor, STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] locations, int[] state, int curPos) {
64
		String separators = features.getSeparators();
65
		int separCount = separators.length();
66
		int specialsCount = features.getSpecialsCount();
67
		int len = text.length();
68
		int nextLocation = len;
69
		int idxLocation = 0;
70
		// Start with special sequences to give them precedence over simple
71
		// separators. This may apply to cases like slash+asterisk versus slash.
72
		for (int i = 0; i < specialsCount; i++) {
73
			int location = locations[separCount + i];
74
			if (location < curPos) {
75
				offsets = ensureRoomInOffsets(offsets);
76
				location = processor.indexOfSpecial(features, text, dirProps, offsets, i + 1, curPos);
77
				if (location < 0)
78
					location = len;
79
				locations[separCount + i] = location;
80
			}
81
			if (location < nextLocation) {
82
				nextLocation = location;
83
				idxLocation = separCount + i;
84
			}
85
		}
86
		for (int i = 0; i < separCount; i++) {
87
			int location = locations[i];
88
			if (location < curPos) {
89
				location = text.indexOf(separators.charAt(i), curPos);
90
				if (location < 0)
91
					location = len;
92
				locations[i] = location;
93
			}
94
			if (location < nextLocation) {
95
				nextLocation = location;
96
				idxLocation = i;
97
			}
98
		}
99
		return nextLocation + (((long) idxLocation) << 32);
100
	}
101
102
	static int getCurOrient(STextEnvironment environment, String text, byte[] dirProps) {
103
		int orient = environment.getOrientation();
104
		if ((orient & STextEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) {
105
			// absolute orientation
106
			return orient;
107
		}
108
		// contextual orientation
109
		int len = text.length();
110
		byte dirProp;
111
		for (int i = 0; i < len; i++) {
112
			// In the following lines, B, L, R and AL represent bidi categories
113
			// as defined in the Unicode Bidirectional Algorithm
114
			// ( http://www.unicode.org/reports/tr9/ ).
115
			// B  represents the category Block Separator.
116
			// L  represents the category Left to Right character.
117
			// R  represents the category Right to Left character.
118
			// AL represents the category Arabic Letter.
119
			dirProp = dirProps[i];
120
			if (dirProp == 0) {
121
				dirProp = Character.getDirectionality(text.charAt(i));
122
				if (dirProp == B) // B char resolves to L or R depending on orientation
123
					continue;
124
				dirProps[i] = (byte) (dirProp + DIRPROPS_ADD);
125
			} else {
126
				dirProp -= DIRPROPS_ADD;
127
			}
128
			if (dirProp == L)
129
				return STextEnvironment.ORIENT_LTR;
130
			if (dirProp == R || dirProp == AL)
131
				return STextEnvironment.ORIENT_RTL;
132
		}
133
		// return the default orientation corresponding to the contextual orientation
134
		return orient & 1;
135
	}
136
137
	/**
138
	 *  @see STextEngine#getCurDirection STextEngine.getCurDirection
139
	 */
140
	public static int getCurDirection(Object _processor, STextFeatures features, STextEnvironment environment, String text, byte[] dirProps) {
141
		if (environment == null)
142
			environment = STextEnvironment.DEFAULT;
143
		if (features == null) {
144
			if (_processor == null)
145
				return STextFeatures.DIR_LTR;
146
			ISTextProcessor processor;
147
			if (_processor instanceof java.lang.String) {
148
				processor = STextStringProcessor.getProcessor((String) _processor);
149
				if (processor == null)
150
					throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
151
			} else if (_processor instanceof ISTextProcessor)
152
				processor = (ISTextProcessor) _processor;
153
			else
154
				throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
155
			features = processor.getFeatures(environment);
156
		}
157
		int dirArabic = features.getDirArabic();
158
		int dirHebrew = features.getDirHebrew();
159
		// same direction for Arabic and Hebrew?
160
		if (dirArabic == dirHebrew)
161
			return dirArabic;
162
		// check if Arabic or Hebrew letter comes first
163
		int len = text.length();
164
		if (dirProps == null)
165
			dirProps = new byte[len + 1];
166
		byte dirProp;
167
		for (int i = 0; i < len; i++) {
168
			// In the following lines, R and AL represent bidi categories
169
			// as defined in the Unicode Bidirectional Algorithm
170
			// ( http://www.unicode.org/reports/tr9/ ).
171
			// R  represents the category Right to Left character.
172
			// AL represents the category Arabic Letter.
173
			byte saveOrient = dirProps[len];
174
			dirProps[len] = -1; // make getDirProp return B
175
			dirProp = getDirProp(text, dirProps, i);
176
			dirProps[len] = saveOrient;
177
			if (dirProp == AL)
178
				return dirArabic;
179
			if (dirProp == R)
180
				return dirHebrew;
181
		}
182
		// found no Arabic or Hebrew character
183
		return STextFeatures.DIR_LTR;
184
	}
185
186
	/**
187
	 *  @see STextProcessor#getDirProp STextProcessor.getDirProp
188
	 */
189
	public static byte getDirProp(String text, byte[] dirProps, int index) {
190
		byte dirProp = dirProps[index];
191
		if (dirProp == 0) {
192
			// In the following lines, B, L and R represent bidi categories
193
			// as defined in the Unicode Bidirectional Algorithm
194
			// ( http://www.unicode.org/reports/tr9/ ).
195
			// B  represents the category Block Separator.
196
			// L  represents the category Left to Right character.
197
			// R  represents the category Right to Left character.
198
			dirProp = Character.getDirectionality(text.charAt(index));
199
			if (dirProp == B) {
200
				// the last entry of dirProps contains the current component orientation
201
				byte orient = dirProps[dirProps.length - 1];
202
				if (orient == -1)
203
					return B;
204
				dirProp = orient == STextEnvironment.ORIENT_RTL ? R : L;
205
			}
206
			dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
207
			return dirProp;
208
		}
209
		return (byte) (dirProp - DIRPROPS_ADD);
210
	}
211
212
	/**
213
	 *  @see STextProcessor#setDirProp STextProcessor.setDirProp
214
	 */
215
	public static void setDirProp(byte[] dirProps, int index, byte dirProp) {
216
		dirProps[index] = (byte) (dirProp + DIRPROPS_ADD);
217
	}
218
219
	/**
220
	 *  @see STextProcessor#processSeparator STextProcessor.processSeparator
221
	 */
222
	public static void processSeparator(STextFeatures features, String text, byte[] dirProps, int[] offsets, int separLocation) {
223
		// In this method, L, R, AL, AN and EN represent bidi categories
224
		// as defined in the Unicode Bidirectional Algorithm
225
		// ( http://www.unicode.org/reports/tr9/ ).
226
		// L  represents the category Left to Right character.
227
		// R  represents the category Right to Left character.
228
		// AL represents the category Arabic Letter.
229
		// AN represents the category Arabic Number.
230
		// EN  represents the category European Number.
231
		int len = text.length();
232
		// offsets[2] contains the structured text direction
233
		if (offsets[2] == STextFeatures.DIR_RTL) {
234
			// the structured text base direction is RTL
235
			for (int i = separLocation - 1; i >= 0; i--) {
236
				byte dirProp = getDirProp(text, dirProps, i);
237
				if (dirProp == R || dirProp == AL)
238
					return;
239
				if (dirProp == L) {
240
					for (int j = separLocation; j < len; j++) {
241
						dirProp = getDirProp(text, dirProps, j);
242
						if (dirProp == R || dirProp == AL)
243
							return;
244
						if (dirProp == L || dirProp == EN) {
245
							insertMark(text, dirProps, offsets, separLocation);
246
							return;
247
						}
248
					}
249
					return;
250
				}
251
			}
252
			return;
253
		}
254
255
		// the structured text base direction is LTR
256
		boolean doneAN = false;
257
		boolean ignoreArabic = features.getIgnoreArabic();
258
		boolean ignoreHebrew = features.getIgnoreHebrew();
259
		if (ignoreArabic && ignoreHebrew)
260
			return;
261
		byte _R, _AL, _AN;
262
		if (ignoreArabic) {
263
			_AL = Byte.MIN_VALUE; // not a real value
264
			_AN = Byte.MIN_VALUE;
265
		} else {
266
			_AL = AL;
267
			_AN = AN;
268
		}
269
		if (ignoreHebrew)
270
			_R = Byte.MIN_VALUE;
271
		else
272
			_R = R;
273
		for (int i = separLocation - 1; i >= 0; i--) {
274
			byte dirProp = getDirProp(text, dirProps, i);
275
			if (dirProp == L)
276
				return;
277
			if (dirProp == _R || dirProp == _AL) {
278
				for (int j = separLocation; j < len; j++) {
279
					dirProp = getDirProp(text, dirProps, j);
280
					if (dirProp == L)
281
						return;
282
					if (dirProp == _R || dirProp == EN || dirProp == _AL || dirProp == _AN) {
283
						insertMark(text, dirProps, offsets, separLocation);
284
						return;
285
					}
286
				}
287
				return;
288
			}
289
			if (dirProp == _AN && !doneAN) {
290
				for (int j = separLocation; j < len; j++) {
291
					dirProp = getDirProp(text, dirProps, j);
292
					if (dirProp == L)
293
						return;
294
					if (dirProp == _AL || dirProp == _AN || dirProp == _R) {
295
						insertMark(text, dirProps, offsets, separLocation);
296
						return;
297
					}
298
				}
299
				doneAN = true;
300
			}
301
		}
302
	}
303
304
	/**
305
	 *  @see STextEngine#leanToFullText STextEngine.leanToFullText
306
	 */
307
	public static String leanToFullText(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
308
		int len = text.length();
309
		if (len == 0)
310
			return text;
311
		byte[] dirProps = new byte[len + 1];
312
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
313
		int prefixLength = offsets[1];
314
		int count = offsets[0] - OFFSETS_SHIFT;
315
		if (count == 0 && prefixLength == 0)
316
			return text;
317
		int newLen = len + count;
318
		if (prefixLength == 1)
319
			newLen++; /* +1 for a mark char */
320
		else if (prefixLength == 2)
321
			newLen += FIXES_LENGTH;
322
		char[] fullChars = new char[newLen];
323
		int added = prefixLength;
324
		// add marks at offsets
325
		int direction = offsets[2];
326
		char curMark = MARKS[direction];
327
		for (int i = 0, j = OFFSETS_SHIFT; i < len; i++) {
328
			char c = text.charAt(i);
329
			// offsets[0] contains the number of used entries
330
			if (j < offsets[0] && i == offsets[j]) {
331
				fullChars[i + added] = curMark;
332
				added++;
333
				j++;
334
			}
335
			fullChars[i + added] = c;
336
		}
337
		if (prefixLength > 0) { /* add prefix/suffix ? */
338
			if (prefixLength == 1) { /* contextual orientation */
339
				fullChars[0] = curMark;
340
			} else {
341
				// When the orientation is RTL, we need to add EMBED at the
342
				// start of the text and PDF at its end.
343
				// However, because of a bug in Windows' handling of LRE/PDF,
344
				// we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end.
345
				char curEmbed = EMBEDS[direction];
346
				fullChars[0] = curEmbed;
347
				fullChars[1] = curMark;
348
				fullChars[newLen - 1] = PDF;
349
				fullChars[newLen - 2] = curMark;
350
			}
351
		}
352
		return new String(fullChars);
353
	}
354
355
	/**
356
	 *  @see STextEngine#leanToFullMap STextEngine.leanToFullMap
357
	 */
358
	public static int[] leanToFullMap(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
359
		int len = text.length();
360
		if (len == 0)
361
			return EMPTY_INT_ARRAY;
362
		byte[] dirProps = new byte[len + 1];
363
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
364
		int prefixLength = offsets[1];
365
		int[] map = new int[len];
366
		int count = offsets[0]; // number of used entries
367
		int added = prefixLength;
368
		for (int pos = 0, i = OFFSETS_SHIFT; pos < len; pos++) {
369
			if (i < count && pos == offsets[i]) {
370
				added++;
371
				i++;
372
			}
373
			map[pos] = pos + added;
374
		}
375
		return map;
376
	}
377
378
	/**
379
	 *  @see STextEngine#leanBidiCharOffsets STextEngine.leanBidiCharOffsets
380
	 */
381
	public static int[] leanBidiCharOffsets(Object processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
382
		int len = text.length();
383
		if (len == 0)
384
			return EMPTY_INT_ARRAY;
385
		byte[] dirProps = new byte[len + 1];
386
		int[] offsets = leanToFullCommon(processor, features, environment, text, state, dirProps);
387
		// offsets[0] contains the number of used entries
388
		int count = offsets[0] - OFFSETS_SHIFT;
389
		int[] result = new int[count];
390
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, count);
391
		return result;
392
	}
393
394
	static int[] leanToFullCommon(Object _processor, STextFeatures features, STextEnvironment environment, String text, int[] state, byte[] dirProps) {
395
		ISTextProcessor processor;
396
		if (_processor instanceof java.lang.String) {
397
			processor = STextStringProcessor.getProcessor((String) _processor);
398
			if (processor == null)
399
				throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
400
		} else if (_processor instanceof ISTextProcessor)
401
			processor = (ISTextProcessor) _processor;
402
		else
403
			throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
404
		if (environment == null)
405
			environment = STextEnvironment.DEFAULT;
406
		if (features == null)
407
			features = processor.getFeatures(environment);
408
		if (state == null) {
409
			state = new int[1];
410
			state[0] = STextEngine.STATE_INITIAL;
411
		}
412
		int len = text.length();
413
		// dirProps: 1 byte for each char in text, + 1 byte = current orientation
414
		int orient = getCurOrient(environment, text, dirProps);
415
		dirProps[len] = (byte) orient;
416
		int separCount = features.getSeparators().length();
417
		int direction = getCurDirection(processor, features, environment, text, dirProps);
418
		// current position
419
		int curPos = 0;
420
		// offsets of marks to add. Entry 0 is the number of used slots;
421
		//  entry 1 is reserved to pass prefixLength.
422
		//  entry 2 is reserved to pass direction..
423
		int[] offsets = new int[20];
424
		offsets[0] = OFFSETS_SHIFT;
425
		offsets[2] = direction;
426
		// initialize locations
427
		int[] locations = new int[separCount + features.getSpecialsCount()];
428
		for (int i = 0, k = locations.length; i < k; i++) {
429
			locations[i] = -1;
430
		}
431
		if (state[0] > STextEngine.STATE_INITIAL) {
432
			offsets = ensureRoomInOffsets(offsets);
433
			int initState = state[0];
434
			state[0] = STextEngine.STATE_INITIAL;
435
			curPos = processor.processSpecial(features, text, dirProps, offsets, state, initState, -1);
436
		}
437
		while (true) {
438
			// location of next token to handle
439
			int nextLocation;
440
			// index of next token to handle (if < separCount, this is a separator; otherwise a special case
441
			int idxLocation;
442
			long res = computeNextLocation(processor, features, text, dirProps, offsets, locations, state, curPos);
443
			nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */
444
			if (nextLocation >= len)
445
				break;
446
			idxLocation = (int) (res >> 32); /* high word */
447
			if (idxLocation < separCount) {
448
				offsets = ensureRoomInOffsets(offsets);
449
				processSeparator(features, text, dirProps, offsets, nextLocation);
450
				curPos = nextLocation + 1;
451
			} else {
452
				offsets = ensureRoomInOffsets(offsets);
453
				idxLocation -= (separCount - 1); // because caseNumber starts from 1
454
				curPos = processor.processSpecial(features, text, dirProps, offsets, state, idxLocation, nextLocation);
455
			}
456
		}
457
		if (orient == STextEnvironment.ORIENT_IGNORE)
458
			offsets[1] = 0;
459
		else {
460
			// recompute orient since it may have changed if contextual
461
			orient = getCurOrient(environment, text, dirProps);
462
			dirProps[len] = (byte) orient;
463
			if (orient == direction && orient != STextEnvironment.ORIENT_UNKNOWN)
464
				offsets[1] = 0;
465
			else if ((environment.getOrientation() & STextEnvironment.ORIENT_CONTEXTUAL_LTR) != 0)
466
				offsets[1] = 1;
467
			else
468
				offsets[1] = 2;
469
		}
470
		return offsets;
471
	}
472
473
	/**
474
	 *  @see STextEngine#fullToLeanText STextEngine.fullToLeanText
475
	 */
476
	public static String fullToLeanText(Object _processor, STextFeatures features, STextEnvironment environment, String text, int[] state) {
477
		if (text.length() == 0)
478
			return text;
479
		ISTextProcessor processor;
480
		if (_processor instanceof java.lang.String) {
481
			processor = STextStringProcessor.getProcessor((String) _processor);
482
			if (processor == null)
483
				throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$
484
		} else if (_processor instanceof ISTextProcessor)
485
			processor = (ISTextProcessor) _processor;
486
		else
487
			throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$
488
		if (environment == null)
489
			environment = STextEnvironment.DEFAULT;
490
		if (features == null)
491
			features = processor.getFeatures(environment);
492
		if (state == null) {
493
			state = new int[1];
494
			state[0] = STextEngine.STATE_INITIAL;
495
		}
496
		int dir = getCurDirection(processor, features, environment, text, null);
497
		char curMark = MARKS[dir];
498
		char curEmbed = EMBEDS[dir];
499
		int i; // used as loop index
500
		// remove any prefix and leading mark
501
		int lenText = text.length();
502
		for (i = 0; i < lenText; i++) {
503
			char c = text.charAt(i);
504
			if (c != curEmbed && c != curMark)
505
				break;
506
		}
507
		if (i > 0) { // found at least one prefix or leading mark
508
			text = text.substring(i);
509
			lenText = text.length();
510
		}
511
		// remove any suffix and trailing mark
512
		for (i = lenText - 1; i >= 0; i--) {
513
			char c = text.charAt(i);
514
			if (c != PDF && c != curMark)
515
				break;
516
		}
517
		if (i < 0) // only suffix and trailing marks, no real data
518
			return EMPTY_STRING;
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
		String full = leanToFullText(processor, features, IGNORE_ENVIRONMENT, lean, state);
535
		if (full.equals(text))
536
			return lean;
537
538
		// There are some marks in full which are not in text and/or vice versa.
539
		// We need to add to lean any mark appearing in text and not in full.
540
		// The completed lean can never be longer than text itself.
541
		char[] newChars = new char[lenText];
542
		char cFull, cText;
543
		int idxFull, idxText, idxLean, newCharsPos;
544
		int lenFull = full.length();
545
		idxFull = idxText = idxLean = newCharsPos = 0;
546
		while (idxText < lenText && idxFull < lenFull) {
547
			cFull = full.charAt(idxFull);
548
			cText = text.charAt(idxText);
549
			if (cFull == cText) { /* chars are equal, proceed */
550
				if (cFull != curMark)
551
					newChars[newCharsPos++] = chars[idxLean++];
552
				idxText++;
553
				idxFull++;
554
				continue;
555
			}
556
			if (cFull == curMark) { /* extra Mark in full text */
557
				idxFull++;
558
				continue;
559
			}
560
			if (cText == curMark) { /* extra Mark in source full text */
561
				idxText++;
562
				// idxText-2 always >= 0 since leading Marks were removed from text
563
				if (text.charAt(idxText - 2) == curMark)
564
					continue; // ignore successive Marks in text after the first one
565
				newChars[newCharsPos++] = curMark;
566
				continue;
567
			}
568
			// we should never get here (extra char which is not a Mark)
569
			throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$
570
		}
571
		if (idxText < lenText) /* full ended before text - this should never happen since
572
								             we removed all marks and PDFs at the end of text */
573
			throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$
574
575
		lean = new String(newChars, 0, newCharsPos);
576
		return lean;
577
	}
578
579
	/**
580
	 *  @see STextEngine#fullToLeanMap STextEngine.fullToLeanMap
581
	 */
582
	public static int[] fullToLeanMap(Object processor, STextFeatures features, STextEnvironment environment, String full, int[] state) {
583
		int lenFull = full.length();
584
		if (lenFull == 0)
585
			return EMPTY_INT_ARRAY;
586
		String lean = fullToLeanText(processor, features, environment, full, state);
587
		int lenLean = lean.length();
588
		int dir = getCurDirection(processor, features, environment, lean, null);
589
		char curMark = MARKS[dir];
590
		char curEmbed = EMBEDS[dir];
591
		int[] map = new int[lenFull];
592
		int idxFull, idxLean;
593
		// skip any prefix and leading mark
594
		for (idxFull = 0; idxFull < lenFull; idxFull++) {
595
			char c = full.charAt(idxFull);
596
			if (c != curEmbed && c != curMark)
597
				break;
598
			map[idxFull] = -1;
599
		}
600
		// lean must be a subset of Full, so we only check on iLean < leanLen
601
		for (idxLean = 0; idxLean < lenLean; idxFull++) {
602
			if (full.charAt(idxFull) == lean.charAt(idxLean)) {
603
				map[idxFull] = idxLean;
604
				idxLean++;
605
			} else
606
				map[idxFull] = -1;
607
		}
608
		for (; idxFull < lenFull; idxFull++)
609
			map[idxFull] = -1;
610
		return map;
611
	}
612
613
	/**
614
	 *  @see STextEngine#fullBidiCharOffsets STextEngine.fullBidiCharOffsets
615
	 */
616
	public static int[] fullBidiCharOffsets(Object processor, STextFeatures features, STextEnvironment environment, String full, int[] state) {
617
		int lenFull = full.length();
618
		if (lenFull == 0)
619
			return EMPTY_INT_ARRAY;
620
		String lean = fullToLeanText(processor, features, environment, full, state);
621
		int[] offsets = new int[20];
622
		offsets[0] = OFFSETS_SHIFT;
623
		int lenLean = lean.length();
624
		int idxLean, idxFull;
625
		// lean must be a subset of Full, so we only check on iLean < leanLen
626
		for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) {
627
			if (full.charAt(idxFull) == lean.charAt(idxLean))
628
				idxLean++;
629
			else {
630
				offsets = ensureRoomInOffsets(offsets);
631
				insertMark(lean, null, offsets, idxFull);
632
			}
633
		}
634
		for (; idxFull < lenFull; idxFull++) {
635
			offsets = ensureRoomInOffsets(offsets);
636
			insertMark(lean, null, offsets, idxFull);
637
		}
638
		int[] result = new int[offsets[0] - OFFSETS_SHIFT];
639
		System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length);
640
		return result;
641
	}
642
643
	static int[] ensureRoomInOffsets(int[] offsets) {
644
		// make sure
645
		if ((offsets.length - offsets[0]) < 3) {
646
			int[] newOffsets = new int[offsets.length * 2];
647
			System.arraycopy(offsets, 0, newOffsets, 0, offsets[0]);
648
			return newOffsets;
649
		}
650
		return offsets;
651
	}
652
653
	/**
654
	 *  @see STextProcessor#insertMark STextProcessor.insertMark
655
	 */
656
	public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) {
657
		int count = offsets[0];// number of used entries
658
		int index = count - 1; // index of greatest member <= offset
659
		// look up after which member the new offset should be inserted
660
		while (index >= OFFSETS_SHIFT) {
661
			int wrkOffset = offsets[index];
662
			if (offset > wrkOffset)
663
				break;
664
			if (offset == wrkOffset)
665
				return; // avoid duplicates
666
			index--;
667
		}
668
		index++; // index now points at where to insert
669
		int length = count - index; // number of members to move up
670
		if (length > 0) // shift right all members greater than offset
671
			System.arraycopy(offsets, index, offsets, index + 1, length);
672
		offsets[index] = offset;
673
		offsets[0]++; // number of used entries
674
		// if the offset is 0, adding a mark does not change anything
675
		if (dirProps == null || offset < 1)
676
			return;
677
678
		byte dirProp = getDirProp(text, dirProps, offset);
679
		// if the current char is a strong one or a digit, we change the
680
		//   dirProp of the previous char to account for the inserted mark.
681
		// In the following lines, L, R, AL, AN and EN represent bidi categories
682
		// as defined in the Unicode Bidirectional Algorithm
683
		// ( http://www.unicode.org/reports/tr9/ ).
684
		// L  represents the category Left to Right character.
685
		// R  represents the category Right to Left character.
686
		// AL represents the category Arabic Letter.
687
		// AN represents the category Arabic Number.
688
		// EN  represents the category European Number.
689
		if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN)
690
			index = offset - 1;
691
		else
692
			// if the current char is a neutral, we change its own dirProp
693
			index = offset;
694
695
		int dir = offsets[2]; // current structured text direction
696
		setDirProp(dirProps, index, STRONGS[dir]);
697
		return;
698
	}
699
700
}
(-)src/org/eclipse/equinox/bidi/internal/STextSingle.java (+52 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.custom.STextFeatures;
14
import org.eclipse.equinox.bidi.custom.STextProcessor;
15
16
/**
17
 *  <code>STextSingle</code> is a processor for structured text
18
 *  composed of two parts separated by a separator.
19
 *  The first occurrence of the separator delimits the end of the first part
20
 *  and the start of the second part. Further occurrences of the separator,
21
 *  if any, are treated like regular characters of the second text part.
22
 *  The processor makes sure that the text be presented in the form
23
 *  (assuming that the equal sign is the separator):
24
 *  <pre>
25
 *  part1=part2
26
 *  </pre>
27
 *  The {@link STextFeatures#getSeparators separators}
28
 *  field in the {@link STextFeatures features}
29
 *  of this processor should contain exactly one character.
30
 *  Additional characters will be ignored.
31
 *
32
 *  @author Matitiahu Allouche
33
 */
34
public abstract class STextSingle extends STextProcessor {
35
36
	/**
37
	 *  This method locates occurrences of the separator.
38
	 */
39
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
40
		return text.indexOf(features.getSeparators().charAt(0), fromIndex);
41
	}
42
43
	/**
44
	 *  This method inserts a mark before the separator if needed and
45
	 *  skips to the end of the source string.
46
	 */
47
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
48
		STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
49
		return text.length();
50
	}
51
52
}
(-)src/org/eclipse/equinox/bidi/internal/STextTypesCollector.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.ISTextProcessor;
17
18
public class STextTypesCollector 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 STextTypesCollector instance = new STextTypesCollector();
30
31
	private STextTypesCollector() {
32
		IExtensionRegistry registry = RegistryFactory.getRegistry();
33
		registry.addListener(this, EXT_POINT);
34
	}
35
36
	static public STextTypesCollector 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 ISTextProcessor getProcessor(String type) {
50
		if (types == null)
51
			read();
52
		Object processor = types.get(type);
53
		if (processor instanceof ISTextProcessor)
54
			return (ISTextProcessor) 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
					STextActivator.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
					STextActivator.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/consumable/BidiComplexComma.java (-36 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  Processor adapted to processing comma-delimited lists, such as:
19
 *  <pre>
20
 *    part1,part2,part3
21
 *  </pre>
22
 */
23
public class BidiComplexComma 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 separator (comma), no special cases,
30
	 *          LTR direction for Arabic and Hebrew, and support for both.
31
	 */
32
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
33
		return FEATURES;
34
	}
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java (-48 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.internal.BidiComplexDelimsEsc;
16
17
/**
18
 *  Processor adapted to processing e-mail addresses.
19
 */
20
public class BidiComplexEmail extends BidiComplexDelimsEsc {
21
	static final int LTR = BidiComplexFeatures.DIR_LTR;
22
	static final int RTL = BidiComplexFeatures.DIR_RTL;
23
	static final BidiComplexFeatures MIRRORED = new BidiComplexFeatures("<>.:,;@", 2, RTL, LTR, false, false); //$NON-NLS-1$
24
	static final BidiComplexFeatures NOT_MIRRORED = new BidiComplexFeatures("<>.:,;@", 2, LTR, LTR, false, false); //$NON-NLS-1$
25
26
	/**
27
	 *  This method retrieves the features specific to this processor.
28
	 *
29
	 *  @return features with separators "<>.:,;@", 2 special cases,
30
	 *          LTR direction for Arabic when the GUI is not mirrored,
31
	 *          RTL direction for Arabic when the GUI is mirrored,
32
	 *          LTR direction for Hebrew in all cases,
33
	 *          and support for both Arabic and Hebrew.
34
	 */
35
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
36
		if (env == null)
37
			env = BidiComplexEnvironment.DEFAULT;
38
		return env.getMirrored() ? MIRRORED : NOT_MIRRORED;
39
	}
40
41
	/**
42
	 *  @return parentheses and quotation marks as delimiters.
43
	 */
44
	protected String getDelimiters() {
45
		return "()\"\""; //$NON-NLS-1$
46
	}
47
48
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexFile.java (-33 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  Processor adapted to processing directory and file paths.
19
 */
20
public class BidiComplexFile extends BidiComplexProcessor {
21
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":/\\.", 0, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators ":/\.", no special cases,
27
	 *          LTR direction for Arabic and Hebrew, and support for both.
28
	 */
29
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
30
		return FEATURES;
31
	}
32
33
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java (-134 lines)
Removed 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.BidiComplexEngine;
14
import org.eclipse.equinox.bidi.BidiComplexEnvironment;
15
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
16
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
17
18
/**
19
 *  <code>BidiComplexJava</code> is a processor for complex expressions
20
 *  composed of Java statements. Such a complex expression may span
21
 *  multiple lines.
22
 *  <p>
23
 *  In applications like an editor where parts of the text might be modified
24
 *  while other parts are not, the user may want to call
25
 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
26
 *  separately on each line and save the initial state of each line (this is
27
 *  the final state of the previous line which can be retrieved using
28
 *  the value returned in the first element of the <code>state</code> argument).
29
 *  If both the content
30
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *
33
 *  @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText
34
 *
35
 *  @author Matitiahu Allouche
36
 */
37
public class BidiComplexJava extends BidiComplexProcessor {
38
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
39
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("[](){}.+-<>=~!&*/%^|?:,;\t", 4, -1, -1, false, false); //$NON-NLS-1$
40
	static final String lineSep = BidiComplexEnvironment.getLineSep();
41
42
	/**
43
	 *  This method retrieves the features specific to this processor.
44
	 *
45
	 *  @return features with separators "[](){}.+-<>=~!&/*%^|?:,;\t",
46
	 *          4 special cases, LTR direction for Arabic and Hebrew,
47
	 *          and support for both.
48
	 */
49
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
50
		return FEATURES;
51
	}
52
53
	/**
54
	     *  This method looks for occurrences of 4 special strings:
55
	     *  <ol>
56
	     *    <li>spaces</li>
57
	     *    <li>literals starting with quotation mark</li>
58
	     *    <li>comments starting with slash-asterisk</li>
59
	     *    <li>comments starting with slash-slash</li>
60
	     *  </ol>
61
	     */
62
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
63
		switch (caseNumber) {
64
			case 1 : /* space */
65
				return text.indexOf(' ', fromIndex);
66
			case 2 : /* literal */
67
				return text.indexOf('"', fromIndex);
68
			case 3 : /* slash-aster comment */
69
				return text.indexOf("/*", fromIndex); //$NON-NLS-1$
70
			case 4 : /* slash-slash comment */
71
				return text.indexOf("//", fromIndex); //$NON-NLS-1$
72
		}
73
		// we should never get here
74
		return -1;
75
	}
76
77
	/**
78
	 *  This method processes the 4 special cases as follows.
79
	     *  <ol>
80
	     *    <li>skip the run of spaces</li>
81
	     *    <li>look for a matching quotation mark and skip until after it</li>
82
	     *    <li>skip until after the closing asterisk-slash</li>
83
	     *    <li>skip until after a line separator</li>
84
	     *  </ol>
85
	 */
86
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
87
		int location, counter, i;
88
89
		BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
90
		switch (caseNumber) {
91
			case 1 : /* space */
92
				separLocation++;
93
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
94
					BidiComplexProcessor.setDirProp(dirProps, separLocation, WS);
95
					separLocation++;
96
				}
97
				return separLocation;
98
			case 2 : /* literal */
99
				location = separLocation + 1;
100
				while (true) {
101
					location = text.indexOf('"', location);
102
					if (location < 0)
103
						return text.length();
104
					for (counter = 0, i = location - 1; text.charAt(i) == '\\'; i--) {
105
						counter++;
106
					}
107
					location++;
108
					if ((counter & 1) == 0)
109
						return location;
110
				}
111
			case 3 : /* slash-aster comment */
112
				if (separLocation < 0) { // continuation line
113
					location = 0;
114
				} else
115
					location = separLocation + 2; // skip the opening slash-aster
116
				location = text.indexOf("*/", location); //$NON-NLS-1$
117
				if (location < 0) {
118
					state[0] = caseNumber;
119
					return text.length();
120
				}
121
				// we need to call processSeparator since text may follow the
122
				//  end of comment immediately without even a space
123
				BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, location);
124
				return location + 2;
125
			case 4 : /* slash-slash comment */
126
				location = text.indexOf(lineSep, separLocation + 2);
127
				if (location < 0)
128
					return text.length();
129
				return location + lineSep.length();
130
		}
131
		// we should never get here
132
		return text.length();
133
	}
134
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java (-35 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  Processor adapted to processing arithmetic expressions with right-to-left
19
 *  base direction.
20
 */
21
public class BidiComplexMath extends BidiComplexProcessor {
22
	static final int RTL = BidiComplexFeatures.DIR_RTL;
23
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("+-/*()=", 0, RTL, RTL, false, false); //$NON-NLS-1$
24
25
	/**
26
	 *  This method retrieves the features specific to this processor.
27
	 *
28
	 *  @return features with separators "+-/*()=", no special cases,
29
	 *          RTL direction for Arabic and Hebrew, and support for both.
30
	 */
31
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
32
		return FEATURES;
33
	}
34
35
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java (-37 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.internal.BidiComplexSingle;
16
17
/**
18
 *  Processor adapted to processing property file statements.
19
 *  It expects the following string format:
20
 *  <pre>
21
 *    name=value
22
 *  </pre>
23
 */
24
public class BidiComplexProperty extends BidiComplexSingle {
25
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("=", 1, -1, -1, false, false); //$NON-NLS-1$
26
27
	/**
28
	 *  This method retrieves the features specific to this processor.
29
	 *
30
	 *  @return features with one separator (equal sign), 1 special case,
31
	 *          LTR direction for Arabic and Hebrew, and support for both.
32
	 */
33
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
34
		return FEATURES;
35
	}
36
37
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java (-221 lines)
Removed 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.BidiComplexEngine;
14
import org.eclipse.equinox.bidi.BidiComplexEnvironment;
15
import org.eclipse.equinox.bidi.custom.*;
16
17
/**
18
 *  <code>BidiComplexRegex</code> is a processor for regular expressions.
19
 *  Such expressions may span 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 BidiComplexEngine#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
 *  the value returned in the first element of the <code>state</code> argument).
27
 *  If both the content
28
 *  of a line and its initial state have not changed, the user can be sure that
29
 *  the last <i>full</i> text computed for this line has not changed either.
30
 *
31
 *  @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText
32
 *
33
 *  @author Matitiahu Allouche
34
 */
35
public class BidiComplexRegex extends BidiComplexProcessor {
36
	static final String[] startStrings = {"", /*  0 *//* dummy *///$NON-NLS-1$
37
			"(?#", /*  1 *//* comment (?#...) *///$NON-NLS-1$
38
			"(?<", /*  2 *//* named group (?<name> *///$NON-NLS-1$
39
			"(?'", /*  3 *//* named group (?'name' *///$NON-NLS-1$
40
			"(?(<", /*  4 *//* conditional named back reference (?(<name>) *///$NON-NLS-1$
41
			"(?('", /*  5 *//* conditional named back reference (?('name') *///$NON-NLS-1$
42
			"(?(", /*  6 *//* conditional named back reference (?(name) *///$NON-NLS-1$
43
			"(?&", /*  7 *//* named parentheses reference (?&name) *///$NON-NLS-1$
44
			"(?P<", /*  8 *//* named group (?P<name> *///$NON-NLS-1$
45
			"\\k<", /*  9 *//* named back reference \k<name> *///$NON-NLS-1$
46
			"\\k'", /* 10 *//* named back reference \k'name' *///$NON-NLS-1$
47
			"\\k{", /* 11 *//* named back reference \k{name} *///$NON-NLS-1$
48
			"(?P=", /* 12 *//* named back reference (?P=name) *///$NON-NLS-1$
49
			"\\g{", /* 13 *//* named back reference \g{name} *///$NON-NLS-1$
50
			"\\g<", /* 14 *//* subroutine call \g<name> *///$NON-NLS-1$
51
			"\\g'", /* 15 *//* subroutine call \g'name' *///$NON-NLS-1$
52
			"(?(R&", /* 16 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$
53
			"\\Q" /* 17 *//* quoted sequence \Q...\E *///$NON-NLS-1$
54
	};
55
	static final char[] endChars = {
56
			// 0    1    2    3     4    5    6    7    8    9    10   11   12   13   14    15   16
57
			'.', ')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'};
58
	static final int numberOfStrings = startStrings.length; /* 18 */
59
	static final int maxSpecial = numberOfStrings;
60
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(null, maxSpecial, -1, -1, false, false);
61
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
62
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
63
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
64
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
65
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
66
67
	/**
68
	 *  This method retrieves the features specific to this processor.
69
	 *
70
	 *  @see IBidiComplexProcessor#getFeatures
71
	 *
72
	 *  @return features with no separators , special cases for each kind of
73
	 *          regular expression syntactic string,
74
	 *          LTR direction for Arabic and Hebrew, and support for both.
75
	 */
76
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
77
		return FEATURES;
78
	}
79
80
	/**
81
	 *  This method locates occurrences of the syntactic strings and of
82
	 *  R, AL, EN, AN characters.
83
	 */
84
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
85
		// In this method, L, R, AL, AN and EN represent bidi categories
86
		// as defined in the Unicode Bidirectional Algorithm
87
		// ( http://www.unicode.org/reports/tr9/ ).
88
		// L  represents the category Left to Right character.
89
		// R  represents the category Right to Left character.
90
		// AL represents the category Arabic Letter.
91
		// AN represents the category Arabic Number.
92
		// EN  represents the category European Number.
93
		byte dirProp;
94
95
		if (caseNumber < numberOfStrings) {
96
			/*  1 *//* comment (?#...) */
97
			/*  2 *//* named group (?<name> */
98
			/*  3 *//* named group (?'name' */
99
			/*  4 *//* conditional named back reference (?(name) */
100
			/*  5 *//* conditional named back reference (?(<name>) */
101
			/*  6 *//* conditional named back reference (?('name') */
102
			/*  7 *//* named parentheses reference (?&name) */
103
			/*  8 *//* named group (?P<name> */
104
			/*  9 *//* named back reference \k<name> */
105
			/* 10 *//* named back reference \k'name' */
106
			/* 11 *//* named back reference \k{name} */
107
			/* 12 *//* named back reference (?P=name) */
108
			/* 13 *//* named back reference \g{name} */
109
			/* 14 *//* subroutine call \g<name> */
110
			/* 15 *//* subroutine call \g'name' */
111
			/* 16 *//* named back reference recursion (?(R&name) */
112
			/* 17 *//* quoted sequence \Q...\E */
113
			return text.indexOf(startStrings[caseNumber], fromIndex);
114
		}
115
		// there never is a need for a mark before the first char
116
		if (fromIndex <= 0)
117
			fromIndex = 1;
118
		// look for R, AL, AN, EN which are potentially needing a mark
119
		for (; fromIndex < text.length(); fromIndex++) {
120
			dirProp = BidiComplexProcessor.getDirProp(text, dirProps, fromIndex);
121
			// R and AL will always be examined using processSeparator()
122
			if (dirProp == R || dirProp == AL)
123
				return fromIndex;
124
125
			if (dirProp == EN || dirProp == AN) {
126
				// no need for a mark after the first digit in a number
127
				if (BidiComplexProcessor.getDirProp(text, dirProps, fromIndex - 1) == dirProp)
128
					continue;
129
130
				for (int i = fromIndex - 1; i >= 0; i--) {
131
					dirProp = BidiComplexProcessor.getDirProp(text, dirProps, i);
132
					// after a L char, no need for a mark
133
					if (dirProp == L)
134
						continue;
135
136
					// digit after R or AL or AN need a mark, except for EN
137
					//   following AN, but this is a contrived case, so we
138
					//   don't check for it (and calling processSeparator()
139
					//   for it will do no harm)
140
					if (dirProp == R || dirProp == AL || dirProp == AN)
141
						return fromIndex;
142
				}
143
				continue;
144
			}
145
		}
146
		return -1;
147
	}
148
149
	/**
150
	 *  This method process the special cases.
151
	 */
152
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
153
		int location;
154
155
		switch (caseNumber) {
156
			case 1 : /* comment (?#...) */
157
				if (separLocation < 0) {
158
					// initial state from previous line
159
					location = 0;
160
				} else {
161
					BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
162
					// skip the opening "(?#"
163
					location = separLocation + 3;
164
				}
165
				location = text.indexOf(')', location);
166
				if (location < 0) {
167
					state[0] = caseNumber;
168
					return text.length();
169
				}
170
				return location + 1;
171
			case 2 : /* named group (?<name> */
172
			case 3 : /* named group (?'name' */
173
			case 4 : /* conditional named back reference (?(name) */
174
			case 5 : /* conditional named back reference (?(<name>) */
175
			case 6 : /* conditional named back reference (?('name') */
176
			case 7 : /* named parentheses reference (?&name) */
177
				BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
178
				// no need for calling processSeparator() for the following cases
179
				//   since the starting string contains a L char
180
			case 8 : /* named group (?P<name> */
181
			case 9 : /* named back reference \k<name> */
182
			case 10 : /* named back reference \k'name' */
183
			case 11 : /* named back reference \k{name} */
184
			case 12 : /* named back reference (?P=name) */
185
			case 13 : /* named back reference \g{name} */
186
			case 14 : /* subroutine call \g<name> */
187
			case 15 : /* subroutine call \g'name' */
188
			case 16 : /* named back reference recursion (?(R&name) */
189
				// skip the opening string
190
				location = separLocation + startStrings[caseNumber].length();
191
				// look for ending character
192
				location = text.indexOf(endChars[caseNumber], location);
193
				if (location < 0)
194
					return text.length();
195
				return location + 1;
196
			case 17 : /* quoted sequence \Q...\E */
197
				if (separLocation < 0) {
198
					// initial state from previous line
199
					location = 0;
200
				} else {
201
					BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
202
					// skip the opening "\Q"
203
					location = separLocation + 2;
204
				}
205
				location = text.indexOf("\\E", location); //$NON-NLS-1$
206
				if (location < 0) {
207
					state[0] = caseNumber;
208
					return text.length();
209
				}
210
				// set the dirProp for the "E" to L (Left to Right character)
211
				BidiComplexProcessor.setDirProp(dirProps, location + 1, L);
212
				return location + 2;
213
			case 18 : /* R, AL, AN, EN */
214
				BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
215
				return separLocation + 1;
216
217
		}
218
		// we should never get here
219
		return text.length();
220
	}
221
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java (-152 lines)
Removed 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.BidiComplexEngine;
14
import org.eclipse.equinox.bidi.BidiComplexEnvironment;
15
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
16
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
17
18
/**
19
 *  <code>BidiComplexSql</code> is a processor for complex expressions
20
 *  composed of SQL statements. Such a complex expression may span
21
 *  multiple lines.
22
 *  <p>
23
 *  In applications like an editor where parts of the text might be modified
24
 *  while other parts are not, the user may want to call
25
 *  {@link BidiComplexEngine#leanToFullText leanToFullText}
26
 *  separately on each line and save the initial state of each line (this is
27
 *  the final state of the previous line which can be retrieved from the
28
 *  value returned in the first element of the <code>state</code> argument).
29
 *  If both the content
30
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *
33
 *  @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText
34
 *
35
 *  @author Matitiahu Allouche
36
 */
37
public class BidiComplexSql extends BidiComplexProcessor {
38
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
39
	static final String separators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$
40
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(separators, 5, -1, -1, false, false);
41
	static final String lineSep = BidiComplexEnvironment.getLineSep();
42
43
	/**
44
	 *  This method retrieves the features specific to this processor.
45
	 *
46
	 *  @return features with separators "\t!#%&()*+,-./:;<=>?|[]{}", 5 special cases,
47
	 *          LTR direction for Arabic and Hebrew, and support for both.
48
	 */
49
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
50
		return FEATURES;
51
	}
52
53
	/**
54
	  *  This method looks for occurrences of 5 special strings:
55
	  *  <ol>
56
	  *    <li>spaces</li>
57
	  *    <li>literals starting with apostrophe</li>
58
	  *    <li>identifiers starting with quotation mark</li>
59
	  *    <li>comments starting with slash-asterisk</li>
60
	  *    <li>comments starting with hyphen-hyphen</li>
61
	  *  </ol>
62
	  */
63
	public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
64
		switch (caseNumber) {
65
			case 1 : /* space */
66
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
67
			case 2 : /* literal */
68
				return text.indexOf('\'', fromIndex);
69
			case 3 : /* delimited identifier */
70
				return text.indexOf('"', fromIndex);
71
			case 4 : /* slash-aster comment */
72
				return text.indexOf("/*", fromIndex); //$NON-NLS-1$
73
			case 5 : /* hyphen-hyphen comment */
74
				return text.indexOf("--", fromIndex); //$NON-NLS-1$
75
		}
76
		// we should never get here
77
		return -1;
78
	}
79
80
	/**
81
	 *  This method processes the 5 special cases as follows.
82
	     *  <ol>
83
	     *    <li>skip the run of spaces</li>
84
	     *    <li>look for a matching apostrophe and skip until after it</li>
85
	     *    <li>look for a matching quotation mark and skip until after it</li>
86
	     *    <li>skip until after the closing asterisk-slash</li>
87
	     *    <li>skip until after a line separator</li>
88
	     *  </ol>
89
	 */
90
	public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
91
		int location;
92
93
		BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
94
		switch (caseNumber) {
95
			case 1 : /* space */
96
				separLocation++;
97
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
98
					BidiComplexProcessor.setDirProp(dirProps, separLocation, WS);
99
					separLocation++;
100
				}
101
				return separLocation;
102
			case 2 : /* literal */
103
				location = separLocation + 1;
104
				while (true) {
105
					location = text.indexOf('\'', location);
106
					if (location < 0) {
107
						state[0] = caseNumber;
108
						return text.length();
109
					}
110
					if ((location + 1) < text.length() && text.charAt(location + 1) == '\'') {
111
						location += 2;
112
						continue;
113
					}
114
					return location + 1;
115
				}
116
			case 3 : /* delimited identifier */
117
				location = separLocation + 1;
118
				while (true) {
119
					location = text.indexOf('"', location);
120
					if (location < 0)
121
						return text.length();
122
123
					if ((location + 1) < text.length() && text.charAt(location + 1) == '"') {
124
						location += 2;
125
						continue;
126
					}
127
					return location + 1;
128
				}
129
			case 4 : /* slash-aster comment */
130
				if (separLocation < 0) // continuation line
131
					location = 0;
132
				else
133
					location = separLocation + 2; // skip the opening slash-aster
134
				location = text.indexOf("*/", location); //$NON-NLS-1$
135
				if (location < 0) {
136
					state[0] = caseNumber;
137
					return text.length();
138
				}
139
				// we need to call processSeparator since text may follow the
140
				//  end of comment immediately without even a space
141
				BidiComplexProcessor.processSeparator(features, text, dirProps, offsets, location);
142
				return location + 2;
143
			case 5 : /* hyphen-hyphen comment */
144
				location = text.indexOf(lineSep, separLocation + 2);
145
				if (location < 0)
146
					return text.length();
147
				return location + lineSep.length();
148
		}
149
		// we should never get here
150
		return text.length();
151
	}
152
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java (-36 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.internal.BidiComplexSingle;
16
17
/**
18
 *  Processor adapted to processing expressions with the following string format:
19
 *  <pre>
20
 *    system(user)
21
 *  </pre>
22
 */
23
public class BidiComplexSystem extends BidiComplexSingle {
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 separator (opening parenthesis),
30
	 *          no special cases, LTR direction for Arabic and Hebrew,
31
	 *          and support for both.
32
	 */
33
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
34
		return FEATURES;
35
	}
36
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java (-34 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  Processor adapted to processing URLs.
19
 */
20
public class BidiComplexURL extends BidiComplexProcessor {
21
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":?#/@.[]", 0, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators ":?#/@.[]",
27
	 *          no special cases, LTR direction for Arabic and Hebrew,
28
	 *          and support for both.
29
	 */
30
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
31
		return FEATURES;
32
	}
33
34
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java (-38 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.custom.BidiComplexProcessor;
16
17
/**
18
 *  Processor adapted to processing compound names.
19
 *  This type covers names made of one or more parts, separated by underscores:
20
 *  <pre>
21
 *    part1_part2_part3
22
 *  </pre>
23
 */
24
public class BidiComplexUnderscore extends BidiComplexProcessor {
25
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("_", 0, -1, -1, false, false); //$NON-NLS-1$
26
27
	/**
28
	 *  This method retrieves the features specific to this processor.
29
	 *
30
	 *  @return features with one separator (underscore),
31
	 *          no special cases, LTR direction for Arabic and Hebrew,
32
	 *          and support for both.
33
	 */
34
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
35
		return FEATURES;
36
	}
37
38
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java (-41 lines)
Removed 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.BidiComplexEnvironment;
14
import org.eclipse.equinox.bidi.custom.BidiComplexFeatures;
15
import org.eclipse.equinox.bidi.internal.BidiComplexDelims;
16
17
/**
18
 *  Processor adapted to processing XPath expressions.
19
 */
20
public class BidiComplexXPath extends BidiComplexDelims {
21
	static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(" /[]<>=!:@.|()+-*", 2, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators " /[]<>=!:@.|()+-*",
27
	 *          2 special cases, LTR direction for Arabic and Hebrew,
28
	 *          and support for both.
29
	 */
30
	public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) {
31
		return FEATURES;
32
	}
33
34
	/**
35
	 *  @return apostrophe and quotation mark as delimiters.
36
	 */
37
	protected String getDelimiters() {
38
		return "''\"\""; //$NON-NLS-1$
39
	}
40
41
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextComma.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
/**
18
 *  Processor adapted to processing comma-delimited lists, such as:
19
 *  <pre>
20
 *    part1,part2,part3
21
 *  </pre>
22
 */
23
public class STextComma extends STextProcessor {
24
	static final STextFeatures FEATURES = new STextFeatures(",", 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 separator (comma), no special cases,
30
	 *          LTR direction for Arabic and Hebrew, and support for both.
31
	 */
32
	public STextFeatures getFeatures(STextEnvironment env) {
33
		return FEATURES;
34
	}
35
36
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextEmail.java (+48 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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.internal.STextDelimsEsc;
16
17
/**
18
 *  Processor adapted to processing e-mail addresses.
19
 */
20
public class STextEmail extends STextDelimsEsc {
21
	static final int LTR = STextFeatures.DIR_LTR;
22
	static final int RTL = STextFeatures.DIR_RTL;
23
	static final STextFeatures MIRRORED = new STextFeatures("<>.:,;@", 2, RTL, LTR, false, false); //$NON-NLS-1$
24
	static final STextFeatures NOT_MIRRORED = new STextFeatures("<>.:,;@", 2, LTR, LTR, false, false); //$NON-NLS-1$
25
26
	/**
27
	 *  This method retrieves the features specific to this processor.
28
	 *
29
	 *  @return features with separators "<>.:,;@", 2 special cases,
30
	 *          LTR direction for Arabic when the GUI is not mirrored,
31
	 *          RTL direction for Arabic when the GUI is mirrored,
32
	 *          LTR direction for Hebrew in all cases,
33
	 *          and support for both Arabic and Hebrew.
34
	 */
35
	public STextFeatures getFeatures(STextEnvironment env) {
36
		if (env == null)
37
			env = STextEnvironment.DEFAULT;
38
		return env.getMirrored() ? MIRRORED : NOT_MIRRORED;
39
	}
40
41
	/**
42
	 *  @return parentheses and quotation marks as delimiters.
43
	 */
44
	protected String getDelimiters() {
45
		return "()\"\""; //$NON-NLS-1$
46
	}
47
48
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextFile.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
/**
18
 *  Processor adapted to processing directory and file paths.
19
 */
20
public class STextFile extends STextProcessor {
21
	static final STextFeatures FEATURES = new STextFeatures(":/\\.", 0, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators ":/\.", no special cases,
27
	 *          LTR direction for Arabic and Hebrew, and support for both.
28
	 */
29
	public STextFeatures getFeatures(STextEnvironment env) {
30
		return FEATURES;
31
	}
32
33
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextJava.java (+134 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextFeatures;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
17
18
/**
19
 *  <code>STextJava</code> is a processor for structured text
20
 *  composed of Java statements. Such a structured text may span
21
 *  multiple lines.
22
 *  <p>
23
 *  In applications like an editor where parts of the text might be modified
24
 *  while other parts are not, the user may want to call
25
 *  {@link STextEngine#leanToFullText leanToFullText}
26
 *  separately on each line and save the initial state of each line (this is
27
 *  the final state of the previous line which can be retrieved using
28
 *  the value returned in the first element of the <code>state</code> argument).
29
 *  If both the content
30
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *
33
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
34
 *
35
 *  @author Matitiahu Allouche
36
 */
37
public class STextJava extends STextProcessor {
38
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
39
	static final STextFeatures FEATURES = new STextFeatures("[](){}.+-<>=~!&*/%^|?:,;\t", 4, -1, -1, false, false); //$NON-NLS-1$
40
	static final String lineSep = STextEnvironment.getLineSep();
41
42
	/**
43
	 *  This method retrieves the features specific to this processor.
44
	 *
45
	 *  @return features with separators "[](){}.+-<>=~!&/*%^|?:,;\t",
46
	 *          4 special cases, LTR direction for Arabic and Hebrew,
47
	 *          and support for both.
48
	 */
49
	public STextFeatures getFeatures(STextEnvironment env) {
50
		return FEATURES;
51
	}
52
53
	/**
54
	     *  This method looks for occurrences of 4 special strings:
55
	     *  <ol>
56
	     *    <li>spaces</li>
57
	     *    <li>literals starting with quotation mark</li>
58
	     *    <li>comments starting with slash-asterisk</li>
59
	     *    <li>comments starting with slash-slash</li>
60
	     *  </ol>
61
	     */
62
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
63
		switch (caseNumber) {
64
			case 1 : /* space */
65
				return text.indexOf(' ', fromIndex);
66
			case 2 : /* literal */
67
				return text.indexOf('"', fromIndex);
68
			case 3 : /* slash-aster comment */
69
				return text.indexOf("/*", fromIndex); //$NON-NLS-1$
70
			case 4 : /* slash-slash comment */
71
				return text.indexOf("//", fromIndex); //$NON-NLS-1$
72
		}
73
		// we should never get here
74
		return -1;
75
	}
76
77
	/**
78
	 *  This method processes the 4 special cases as follows.
79
	     *  <ol>
80
	     *    <li>skip the run of spaces</li>
81
	     *    <li>look for a matching quotation mark and skip until after it</li>
82
	     *    <li>skip until after the closing asterisk-slash</li>
83
	     *    <li>skip until after a line separator</li>
84
	     *  </ol>
85
	 */
86
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
87
		int location, counter, i;
88
89
		STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
90
		switch (caseNumber) {
91
			case 1 : /* space */
92
				separLocation++;
93
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
94
					STextProcessor.setDirProp(dirProps, separLocation, WS);
95
					separLocation++;
96
				}
97
				return separLocation;
98
			case 2 : /* literal */
99
				location = separLocation + 1;
100
				while (true) {
101
					location = text.indexOf('"', location);
102
					if (location < 0)
103
						return text.length();
104
					for (counter = 0, i = location - 1; text.charAt(i) == '\\'; i--) {
105
						counter++;
106
					}
107
					location++;
108
					if ((counter & 1) == 0)
109
						return location;
110
				}
111
			case 3 : /* slash-aster comment */
112
				if (separLocation < 0) { // continuation line
113
					location = 0;
114
				} else
115
					location = separLocation + 2; // skip the opening slash-aster
116
				location = text.indexOf("*/", location); //$NON-NLS-1$
117
				if (location < 0) {
118
					state[0] = caseNumber;
119
					return text.length();
120
				}
121
				// we need to call processSeparator since text may follow the
122
				//  end of comment immediately without even a space
123
				STextProcessor.processSeparator(features, text, dirProps, offsets, location);
124
				return location + 2;
125
			case 4 : /* slash-slash comment */
126
				location = text.indexOf(lineSep, separLocation + 2);
127
				if (location < 0)
128
					return text.length();
129
				return location + lineSep.length();
130
		}
131
		// we should never get here
132
		return text.length();
133
	}
134
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextMath.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
/**
18
 *  Processor adapted to processing arithmetic expressions with right-to-left
19
 *  base direction.
20
 */
21
public class STextMath extends STextProcessor {
22
	static final int RTL = STextFeatures.DIR_RTL;
23
	static final STextFeatures FEATURES = new STextFeatures("+-/*()=", 0, RTL, RTL, false, false); //$NON-NLS-1$
24
25
	/**
26
	 *  This method retrieves the features specific to this processor.
27
	 *
28
	 *  @return features with separators "+-/*()=", no special cases,
29
	 *          RTL direction for Arabic and Hebrew, and support for both.
30
	 */
31
	public STextFeatures getFeatures(STextEnvironment env) {
32
		return FEATURES;
33
	}
34
35
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextProperty.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.internal.STextSingle;
16
17
/**
18
 *  Processor adapted to processing property file statements.
19
 *  It expects the following string format:
20
 *  <pre>
21
 *    name=value
22
 *  </pre>
23
 */
24
public class STextProperty extends STextSingle {
25
	static final STextFeatures FEATURES = new STextFeatures("=", 1, -1, -1, false, false); //$NON-NLS-1$
26
27
	/**
28
	 *  This method retrieves the features specific to this processor.
29
	 *
30
	 *  @return features with one separator (equal sign), 1 special case,
31
	 *          LTR direction for Arabic and Hebrew, and support for both.
32
	 */
33
	public STextFeatures getFeatures(STextEnvironment env) {
34
		return FEATURES;
35
	}
36
37
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextRegex.java (+221 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.*;
16
17
/**
18
 *  <code>STextRegex</code> is a processor for regular expressions.
19
 *  Such expressions may span 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 STextEngine#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
 *  the value returned in the first element of the <code>state</code> argument).
27
 *  If both the content
28
 *  of a line and its initial state have not changed, the user can be sure that
29
 *  the last <i>full</i> text computed for this line has not changed either.
30
 *
31
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
32
 *
33
 *  @author Matitiahu Allouche
34
 */
35
public class STextRegex extends STextProcessor {
36
	static final String[] startStrings = {"", /*  0 *//* dummy *///$NON-NLS-1$
37
			"(?#", /*  1 *//* comment (?#...) *///$NON-NLS-1$
38
			"(?<", /*  2 *//* named group (?<name> *///$NON-NLS-1$
39
			"(?'", /*  3 *//* named group (?'name' *///$NON-NLS-1$
40
			"(?(<", /*  4 *//* conditional named back reference (?(<name>) *///$NON-NLS-1$
41
			"(?('", /*  5 *//* conditional named back reference (?('name') *///$NON-NLS-1$
42
			"(?(", /*  6 *//* conditional named back reference (?(name) *///$NON-NLS-1$
43
			"(?&", /*  7 *//* named parentheses reference (?&name) *///$NON-NLS-1$
44
			"(?P<", /*  8 *//* named group (?P<name> *///$NON-NLS-1$
45
			"\\k<", /*  9 *//* named back reference \k<name> *///$NON-NLS-1$
46
			"\\k'", /* 10 *//* named back reference \k'name' *///$NON-NLS-1$
47
			"\\k{", /* 11 *//* named back reference \k{name} *///$NON-NLS-1$
48
			"(?P=", /* 12 *//* named back reference (?P=name) *///$NON-NLS-1$
49
			"\\g{", /* 13 *//* named back reference \g{name} *///$NON-NLS-1$
50
			"\\g<", /* 14 *//* subroutine call \g<name> *///$NON-NLS-1$
51
			"\\g'", /* 15 *//* subroutine call \g'name' *///$NON-NLS-1$
52
			"(?(R&", /* 16 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$
53
			"\\Q" /* 17 *//* quoted sequence \Q...\E *///$NON-NLS-1$
54
	};
55
	static final char[] endChars = {
56
			// 0    1    2    3     4    5    6    7    8    9    10   11   12   13   14    15   16
57
			'.', ')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'};
58
	static final int numberOfStrings = startStrings.length; /* 18 */
59
	static final int maxSpecial = numberOfStrings;
60
	static final STextFeatures FEATURES = new STextFeatures(null, maxSpecial, -1, -1, false, false);
61
	static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
62
	static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
63
	static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
64
	static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
65
	static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
66
67
	/**
68
	 *  This method retrieves the features specific to this processor.
69
	 *
70
	 *  @see ISTextProcessor#getFeatures
71
	 *
72
	 *  @return features with no separators , special cases for each kind of
73
	 *          regular expression syntactic string,
74
	 *          LTR direction for Arabic and Hebrew, and support for both.
75
	 */
76
	public STextFeatures getFeatures(STextEnvironment env) {
77
		return FEATURES;
78
	}
79
80
	/**
81
	 *  This method locates occurrences of the syntactic strings and of
82
	 *  R, AL, EN, AN characters.
83
	 */
84
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
85
		// In this method, L, R, AL, AN and EN represent bidi categories
86
		// as defined in the Unicode Bidirectional Algorithm
87
		// ( http://www.unicode.org/reports/tr9/ ).
88
		// L  represents the category Left to Right character.
89
		// R  represents the category Right to Left character.
90
		// AL represents the category Arabic Letter.
91
		// AN represents the category Arabic Number.
92
		// EN  represents the category European Number.
93
		byte dirProp;
94
95
		if (caseNumber < numberOfStrings) {
96
			/*  1 *//* comment (?#...) */
97
			/*  2 *//* named group (?<name> */
98
			/*  3 *//* named group (?'name' */
99
			/*  4 *//* conditional named back reference (?(name) */
100
			/*  5 *//* conditional named back reference (?(<name>) */
101
			/*  6 *//* conditional named back reference (?('name') */
102
			/*  7 *//* named parentheses reference (?&name) */
103
			/*  8 *//* named group (?P<name> */
104
			/*  9 *//* named back reference \k<name> */
105
			/* 10 *//* named back reference \k'name' */
106
			/* 11 *//* named back reference \k{name} */
107
			/* 12 *//* named back reference (?P=name) */
108
			/* 13 *//* named back reference \g{name} */
109
			/* 14 *//* subroutine call \g<name> */
110
			/* 15 *//* subroutine call \g'name' */
111
			/* 16 *//* named back reference recursion (?(R&name) */
112
			/* 17 *//* quoted sequence \Q...\E */
113
			return text.indexOf(startStrings[caseNumber], fromIndex);
114
		}
115
		// there never is a need for a mark before the first char
116
		if (fromIndex <= 0)
117
			fromIndex = 1;
118
		// look for R, AL, AN, EN which are potentially needing a mark
119
		for (; fromIndex < text.length(); fromIndex++) {
120
			dirProp = STextProcessor.getDirProp(text, dirProps, fromIndex);
121
			// R and AL will always be examined using processSeparator()
122
			if (dirProp == R || dirProp == AL)
123
				return fromIndex;
124
125
			if (dirProp == EN || dirProp == AN) {
126
				// no need for a mark after the first digit in a number
127
				if (STextProcessor.getDirProp(text, dirProps, fromIndex - 1) == dirProp)
128
					continue;
129
130
				for (int i = fromIndex - 1; i >= 0; i--) {
131
					dirProp = STextProcessor.getDirProp(text, dirProps, i);
132
					// after a L char, no need for a mark
133
					if (dirProp == L)
134
						continue;
135
136
					// digit after R or AL or AN need a mark, except for EN
137
					//   following AN, but this is a contrived case, so we
138
					//   don't check for it (and calling processSeparator()
139
					//   for it will do no harm)
140
					if (dirProp == R || dirProp == AL || dirProp == AN)
141
						return fromIndex;
142
				}
143
				continue;
144
			}
145
		}
146
		return -1;
147
	}
148
149
	/**
150
	 *  This method process the special cases.
151
	 */
152
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
153
		int location;
154
155
		switch (caseNumber) {
156
			case 1 : /* comment (?#...) */
157
				if (separLocation < 0) {
158
					// initial state from previous line
159
					location = 0;
160
				} else {
161
					STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
162
					// skip the opening "(?#"
163
					location = separLocation + 3;
164
				}
165
				location = text.indexOf(')', location);
166
				if (location < 0) {
167
					state[0] = caseNumber;
168
					return text.length();
169
				}
170
				return location + 1;
171
			case 2 : /* named group (?<name> */
172
			case 3 : /* named group (?'name' */
173
			case 4 : /* conditional named back reference (?(name) */
174
			case 5 : /* conditional named back reference (?(<name>) */
175
			case 6 : /* conditional named back reference (?('name') */
176
			case 7 : /* named parentheses reference (?&name) */
177
				STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
178
				// no need for calling processSeparator() for the following cases
179
				//   since the starting string contains a L char
180
			case 8 : /* named group (?P<name> */
181
			case 9 : /* named back reference \k<name> */
182
			case 10 : /* named back reference \k'name' */
183
			case 11 : /* named back reference \k{name} */
184
			case 12 : /* named back reference (?P=name) */
185
			case 13 : /* named back reference \g{name} */
186
			case 14 : /* subroutine call \g<name> */
187
			case 15 : /* subroutine call \g'name' */
188
			case 16 : /* named back reference recursion (?(R&name) */
189
				// skip the opening string
190
				location = separLocation + startStrings[caseNumber].length();
191
				// look for ending character
192
				location = text.indexOf(endChars[caseNumber], location);
193
				if (location < 0)
194
					return text.length();
195
				return location + 1;
196
			case 17 : /* quoted sequence \Q...\E */
197
				if (separLocation < 0) {
198
					// initial state from previous line
199
					location = 0;
200
				} else {
201
					STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
202
					// skip the opening "\Q"
203
					location = separLocation + 2;
204
				}
205
				location = text.indexOf("\\E", location); //$NON-NLS-1$
206
				if (location < 0) {
207
					state[0] = caseNumber;
208
					return text.length();
209
				}
210
				// set the dirProp for the "E" to L (Left to Right character)
211
				STextProcessor.setDirProp(dirProps, location + 1, L);
212
				return location + 2;
213
			case 18 : /* R, AL, AN, EN */
214
				STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
215
				return separLocation + 1;
216
217
		}
218
		// we should never get here
219
		return text.length();
220
	}
221
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextSql.java (+152 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.STextEngine;
14
import org.eclipse.equinox.bidi.STextEnvironment;
15
import org.eclipse.equinox.bidi.custom.STextFeatures;
16
import org.eclipse.equinox.bidi.custom.STextProcessor;
17
18
/**
19
 *  <code>STextSql</code> is a processor for structured text
20
 *  composed of SQL statements. Such a structured text may span
21
 *  multiple lines.
22
 *  <p>
23
 *  In applications like an editor where parts of the text might be modified
24
 *  while other parts are not, the user may want to call
25
 *  {@link STextEngine#leanToFullText leanToFullText}
26
 *  separately on each line and save the initial state of each line (this is
27
 *  the final state of the previous line which can be retrieved from the
28
 *  value returned in the first element of the <code>state</code> argument).
29
 *  If both the content
30
 *  of a line and its initial state have not changed, the user can be sure that
31
 *  the last <i>full</i> text computed for this line has not changed either.
32
 *
33
 *  @see STextEngine#leanToFullText explanation of state in leanToFullText
34
 *
35
 *  @author Matitiahu Allouche
36
 */
37
public class STextSql extends STextProcessor {
38
	private static final byte WS = Character.DIRECTIONALITY_WHITESPACE;
39
	static final String separators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$
40
	static final STextFeatures FEATURES = new STextFeatures(separators, 5, -1, -1, false, false);
41
	static final String lineSep = STextEnvironment.getLineSep();
42
43
	/**
44
	 *  This method retrieves the features specific to this processor.
45
	 *
46
	 *  @return features with separators "\t!#%&()*+,-./:;<=>?|[]{}", 5 special cases,
47
	 *          LTR direction for Arabic and Hebrew, and support for both.
48
	 */
49
	public STextFeatures getFeatures(STextEnvironment env) {
50
		return FEATURES;
51
	}
52
53
	/**
54
	  *  This method looks for occurrences of 5 special strings:
55
	  *  <ol>
56
	  *    <li>spaces</li>
57
	  *    <li>literals starting with apostrophe</li>
58
	  *    <li>identifiers starting with quotation mark</li>
59
	  *    <li>comments starting with slash-asterisk</li>
60
	  *    <li>comments starting with hyphen-hyphen</li>
61
	  *  </ol>
62
	  */
63
	public int indexOfSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) {
64
		switch (caseNumber) {
65
			case 1 : /* space */
66
				return text.indexOf(" ", fromIndex); //$NON-NLS-1$
67
			case 2 : /* literal */
68
				return text.indexOf('\'', fromIndex);
69
			case 3 : /* delimited identifier */
70
				return text.indexOf('"', fromIndex);
71
			case 4 : /* slash-aster comment */
72
				return text.indexOf("/*", fromIndex); //$NON-NLS-1$
73
			case 5 : /* hyphen-hyphen comment */
74
				return text.indexOf("--", fromIndex); //$NON-NLS-1$
75
		}
76
		// we should never get here
77
		return -1;
78
	}
79
80
	/**
81
	 *  This method processes the 5 special cases as follows.
82
	     *  <ol>
83
	     *    <li>skip the run of spaces</li>
84
	     *    <li>look for a matching apostrophe and skip until after it</li>
85
	     *    <li>look for a matching quotation mark and skip until after it</li>
86
	     *    <li>skip until after the closing asterisk-slash</li>
87
	     *    <li>skip until after a line separator</li>
88
	     *  </ol>
89
	 */
90
	public int processSpecial(STextFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int separLocation) {
91
		int location;
92
93
		STextProcessor.processSeparator(features, text, dirProps, offsets, separLocation);
94
		switch (caseNumber) {
95
			case 1 : /* space */
96
				separLocation++;
97
				while (separLocation < text.length() && text.charAt(separLocation) == ' ') {
98
					STextProcessor.setDirProp(dirProps, separLocation, WS);
99
					separLocation++;
100
				}
101
				return separLocation;
102
			case 2 : /* literal */
103
				location = separLocation + 1;
104
				while (true) {
105
					location = text.indexOf('\'', location);
106
					if (location < 0) {
107
						state[0] = caseNumber;
108
						return text.length();
109
					}
110
					if ((location + 1) < text.length() && text.charAt(location + 1) == '\'') {
111
						location += 2;
112
						continue;
113
					}
114
					return location + 1;
115
				}
116
			case 3 : /* delimited identifier */
117
				location = separLocation + 1;
118
				while (true) {
119
					location = text.indexOf('"', location);
120
					if (location < 0)
121
						return text.length();
122
123
					if ((location + 1) < text.length() && text.charAt(location + 1) == '"') {
124
						location += 2;
125
						continue;
126
					}
127
					return location + 1;
128
				}
129
			case 4 : /* slash-aster comment */
130
				if (separLocation < 0) // continuation line
131
					location = 0;
132
				else
133
					location = separLocation + 2; // skip the opening slash-aster
134
				location = text.indexOf("*/", location); //$NON-NLS-1$
135
				if (location < 0) {
136
					state[0] = caseNumber;
137
					return text.length();
138
				}
139
				// we need to call processSeparator since text may follow the
140
				//  end of comment immediately without even a space
141
				STextProcessor.processSeparator(features, text, dirProps, offsets, location);
142
				return location + 2;
143
			case 5 : /* hyphen-hyphen comment */
144
				location = text.indexOf(lineSep, separLocation + 2);
145
				if (location < 0)
146
					return text.length();
147
				return location + lineSep.length();
148
		}
149
		// we should never get here
150
		return text.length();
151
	}
152
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextSystem.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.internal.STextSingle;
16
17
/**
18
 *  Processor adapted to processing structured text with the following format:
19
 *  <pre>
20
 *    system(user)
21
 *  </pre>
22
 */
23
public class STextSystem extends STextSingle {
24
	static final STextFeatures FEATURES = new STextFeatures("(", 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 separator (opening parenthesis),
30
	 *          no special cases, LTR direction for Arabic and Hebrew,
31
	 *          and support for both.
32
	 */
33
	public STextFeatures getFeatures(STextEnvironment env) {
34
		return FEATURES;
35
	}
36
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextURL.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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
/**
18
 *  Processor adapted to processing URLs.
19
 */
20
public class STextURL extends STextProcessor {
21
	static final STextFeatures FEATURES = new STextFeatures(":?#/@.[]", 0, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators ":?#/@.[]",
27
	 *          no special cases, LTR direction for Arabic and Hebrew,
28
	 *          and support for both.
29
	 */
30
	public STextFeatures getFeatures(STextEnvironment env) {
31
		return FEATURES;
32
	}
33
34
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextUnderscore.java (+38 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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.custom.STextProcessor;
16
17
/**
18
 *  Processor adapted to processing compound names.
19
 *  This type covers names made of one or more parts, separated by underscores:
20
 *  <pre>
21
 *    part1_part2_part3
22
 *  </pre>
23
 */
24
public class STextUnderscore extends STextProcessor {
25
	static final STextFeatures FEATURES = new STextFeatures("_", 0, -1, -1, false, false); //$NON-NLS-1$
26
27
	/**
28
	 *  This method retrieves the features specific to this processor.
29
	 *
30
	 *  @return features with one separator (underscore),
31
	 *          no special cases, LTR direction for Arabic and Hebrew,
32
	 *          and support for both.
33
	 */
34
	public STextFeatures getFeatures(STextEnvironment env) {
35
		return FEATURES;
36
	}
37
38
}
(-)src/org/eclipse/equinox/bidi/internal/consumable/STextXPath.java (+41 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.STextEnvironment;
14
import org.eclipse.equinox.bidi.custom.STextFeatures;
15
import org.eclipse.equinox.bidi.internal.STextDelims;
16
17
/**
18
 *  Processor adapted to processing XPath expressions.
19
 */
20
public class STextXPath extends STextDelims {
21
	static final STextFeatures FEATURES = new STextFeatures(" /[]<>=!:@.|()+-*", 2, -1, -1, false, false); //$NON-NLS-1$
22
23
	/**
24
	 *  This method retrieves the features specific to this processor.
25
	 *
26
	 *  @return features with separators " /[]<>=!:@.|()+-*",
27
	 *          2 special cases, LTR direction for Arabic and Hebrew,
28
	 *          and support for both.
29
	 */
30
	public STextFeatures getFeatures(STextEnvironment env) {
31
		return FEATURES;
32
	}
33
34
	/**
35
	 *  @return apostrophe and quotation mark as delimiters.
36
	 */
37
	protected String getDelimiters() {
38
		return "''\"\""; //$NON-NLS-1$
39
	}
40
41
}
(-)src/org/eclipse/equinox/bidi/package.html (-31 / +31 lines)
Lines 6-15 Link Here
6
<body bgcolor="white">
6
<body bgcolor="white">
7
7
8
This package provides interfaces and classes for
8
This package provides interfaces and classes for
9
processing complex expressions.
9
processing structured text.
10
10
11
11
12
<h2>Introduction to Complex Expressions</h2>
12
<h2>Introduction to Structured Text</h2>
13
<p>
13
<p>
14
Bidirectional text offers interesting challenges to presentation systems.
14
Bidirectional text offers interesting challenges to presentation systems.
15
For plain text, the Unicode Bidirectional Algorithm
15
For plain text, the Unicode Bidirectional Algorithm
Lines 23-50 Link Here
23
has no awareness of these special cases, often gives incorrect results
23
has no awareness of these special cases, often gives incorrect results
24
when displaying such structured text.
24
when displaying such structured text.
25
</p><p>
25
</p><p>
26
The general idea in handling complex expressions is to add directional
26
The general idea in handling structured text is to add directional
27
formatting characters at proper locations in the text to supplement the
27
formatting characters at proper locations in the text to supplement the
28
standard algorithm, so that the final result is correctly displayed
28
standard algorithm, so that the final result is correctly displayed
29
using the UBA.
29
using the UBA.
30
</p><p>
30
</p><p>
31
A class which handles complex expressions is thus essentially a
31
A class which handles structured text is thus essentially a
32
transformation engine which receives text without directional formatting
32
transformation engine which receives text without directional formatting
33
characters as input and produces as output the same text with added
33
characters as input and produces as output the same text with added
34
directional formatting characters, hopefully in the minimum quantity
34
directional formatting characters, hopefully in the minimum quantity
35
which is sufficient to ensure correct display, considering the type of
35
which is sufficient to ensure correct display, considering the type of
36
complex expression involved.
36
structured text involved.
37
</p><p>
37
</p><p>
38
In this package, text without directional formatting characters is
38
In this package, text without directional formatting characters is
39
called <b><i>lean</i></b> text while the text with added directional
39
called <b><i>lean</i></b> text while the text with added directional
40
formatting characters is called <b><i>full</i></b> text.
40
formatting characters is called <b><i>full</i></b> text.
41
</p><p>
41
</p><p>
42
The class {@link
42
The class {@link
43
<a href="BidiComplexEngine.html"><b>BidiComplexEngine</b></a>}
43
<a href="STextEngine.html"><b>STextEngine</b></a>}
44
is the main tool for processing complex expressions.  It facilitates
44
is the main tool for processing structured text.  It facilitates
45
handling several types of complex expressions, each type being handled
45
handling several types of structured text, each type being handled
46
by a specific
46
by a specific
47
{@link <a href="custom\IBidiComplexProcessor.html"><b><i>processor</i></b></a>} :</p>
47
{@link <a href="custom\ISTextProcessor.html"><b><i>processor</i></b></a>} :</p>
48
<ul>
48
<ul>
49
  <li>property (name=value)</li>
49
  <li>property (name=value)</li>
50
  <li>compound name (xxx_yy_zzzz)</li>
50
  <li>compound name (xxx_yy_zzzz)</li>
Lines 62-104 Link Here
62
<p>
62
<p>
63
Other classes and one interface in this package may be used to
63
Other classes and one interface in this package may be used to
64
complement and facilitate the action of
64
complement and facilitate the action of
65
{@link <a href="BidiComplexEngine.html">BidiComplexEngine</a>}:
65
{@link <a href="STextEngine.html">STextEngine</a>}:
66
<ul>
66
<ul>
67
  <li>{@link <a href="BidiComplexEnvironment.html">BidiComplexEnvironment</a>}
67
  <li>{@link <a href="STextEnvironment.html">STextEnvironment</a>}
68
      regroups details about the environment</li>
68
      regroups details about the environment</li>
69
  <li>{@link <a href="BidiComplexUtil.html">BidiComplexUtil</a>}
69
  <li>{@link <a href="STextUtil.html">STextUtil</a>}
70
      provides a number of convenience methods to process some common types of
70
      provides a number of convenience methods to process some common types of
71
      complex expressions.  When using methods in this class, there is no need
71
      structured text.  When using methods in this class, there is no need
72
      to use other classes of this package.  However, the other classes allow
72
      to use other classes of this package.  However, the other classes allow
73
      more precise control and possibly better performance.</li>
73
      more precise control and possibly better performance.</li>
74
  <li>{@link <a href="IBidiComplexExpressionTypes.html">IBidiComplexExpressionTypes</a>}
74
  <li>{@link <a href="ISTextTypes.html">ISTextTypes</a>}
75
      is an interface which contains only literals identifying the various types
75
      is an interface which contains only literals identifying the various types
76
      of complex expressions currently supported.</li>
76
      of structured text currently supported.</li>
77
  <li>{@link <a href="BidiComplexStringRecord.html">BidiComplexStringRecord</a>}
77
  <li>{@link <a href="STextStringRecord.html">STextStringRecord</a>}
78
      allows to record strings which are complex expressions with their
78
      allows to record strings which are structured text with their
79
      type, so that another module can check if a given string has been recorded
79
      type, so that another module can check if a given string has been recorded
80
      as a complex expression and retrieve its type.</li>
80
      as a structured text string and retrieve its type.</li>
81
</ul>
81
</ul>
82
<p>
82
<p>
83
{@link <a href="BidiComplexEngine.html">BidiComplexEngine</a>} and the
83
{@link <a href="STextEngine.html">STextEngine</a>} and the
84
other classes and interface mentioned above are intended for users who
84
other classes and interface mentioned above are intended for users who
85
need to process complex expressions for which there already exist
85
need to process structured text for which there already exist
86
processors.
86
processors.
87
<p>
87
<p>
88
Developers who want to develop new processors to support types of complex
88
Developers who want to develop new processors to support types of structured text
89
expressions not currently supported can use the following components of the
89
not currently supported can use the following components of the
90
package {@link <a href="custom\package-summary.html">
90
package {@link <a href="custom\package-summary.html">
91
org.eclipse.equinox.bidi.custom</a>}:
91
org.eclipse.equinox.bidi.custom</a>}:
92
<ul>
92
<ul>
93
  <li>{@link <a href="custom\IBidiComplexProcessor.html">IBidiComplexProcessor</a>}
93
  <li>{@link <a href="custom\ISTextProcessor.html">ISTextProcessor</a>}
94
      is an interface specifying which methods a processor must provide.</li>
94
      is an interface specifying which methods a processor must provide.</li>
95
  <li>{@link <a href="custom\BidiComplexProcessor.html">BidiComplexProcessor</a>}
95
  <li>{@link <a href="custom\STextProcessor.html">STextProcessor</a>}
96
      is a generic processor which can be used as superclass for specific
96
      is a generic processor which can be used as superclass for specific
97
      processors.</li>
97
      processors.</li>
98
  <li>{@link <a href="custom\BidiComplexFeatures.html">BidiComplexFeatures</a>}
98
  <li>{@link <a href="custom\STextFeatures.html">STextFeatures</a>}
99
      allows managing some factors which affect
99
      allows managing some factors which affect
100
      a complex expression processor's behavior.</li>
100
      a structured text processor's behavior.</li>
101
  <li>{@link <a href="custom\BidiComplexStringProcessor.html">BidiComplexStringProcessor</a>}
101
  <li>{@link <a href="custom\STextStringProcessor.html">STextStringProcessor</a>}
102
      allows retrieval of the defined processor types and of the
102
      allows retrieval of the defined processor types and of the
103
      corresponding processors.</li>
103
      corresponding processors.</li>
104
</ul>
104
</ul>
Lines 111-122 Link Here
111
       org.eclipse.equinox.bidi.internal.consumable</a>}</li>
111
       org.eclipse.equinox.bidi.internal.consumable</a>}</li>
112
</ul>
112
</ul>
113
The tools in the first package can serve as example of how to develop
113
The tools in the first package can serve as example of how to develop
114
processors for currently unsupported types of complex expressions.<br>
114
processors for currently unsupported types of structured text.<br>
115
The latter package contains classes for the processors implementing
115
The latter package contains classes for the processors implementing
116
the currently supported types of complex expressions.
116
the currently supported types of structured text.
117
<p>
117
<p>
118
However, users wishing to process the currently supported types of
118
However, users wishing to process the currently supported types of
119
complex expressions typically don't need to interact with these
119
structured text typically don't need to interact with these
120
two packages.
120
two packages.
121
121
122
<p>&nbsp;</p>
122
<p>&nbsp;</p>
Lines 169-175 Link Here
169
PDF directional formatting characters.</li>
169
PDF directional formatting characters.</li>
170
170
171
<li>Because some presentation engines are not strictly conformant to the
171
<li>Because some presentation engines are not strictly conformant to the
172
UBA, the implementation of complex expressions in this package adds LRM
172
UBA, the implementation of structured text in this package adds LRM
173
or RLM characters in association with LRE, RLE or PDF in cases where
173
or RLM characters in association with LRE, RLE or PDF in cases where
174
this would not be needed if the presentation engine was fully conformant
174
this would not be needed if the presentation engine was fully conformant
175
to the UBA. Such added marks will not have harmful effects on
175
to the UBA. Such added marks will not have harmful effects on

Return to bug 183164