### Eclipse Workspace Patch 1.0 #P org.eclipse.equinox.bidi Index: src/org/eclipse/equinox/bidi/BidiComplexEngine.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/BidiComplexEngine.java diff -N src/org/eclipse/equinox/bidi/BidiComplexEngine.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/BidiComplexEngine.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,496 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.bidi; + +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; +import org.eclipse.equinox.bidi.internal.BidiComplexImpl; + +/** + * This class acts as a mediator between applications and complex + * expression processors. + * The purpose of complex expression processors is to add directional + * formatting characters to ensure correct display. + * This class shields applications from the + * intricacies of complex expression processors. + *

+ * For a general introduction to complex expressions, see + * {@link + * the package documentation}. + * + *

How to Specify a Processor

+ * + *

All the methods in this class have a first argument which + * designates a type of processor. + * + *

It can be specified as a string (usually one of the + * literals to be found in {@link IBidiComplexExpressionTypes} + * or as an instance of {@link custom.IBidiComplexProcessor}. + * + *

Such an instance can be obtained using the + * {@link custom.BidiComplexStringProcessor#getProcessor getProcessor} + * method for the registered processors, or by instantiating a private processor. + * + *

When the same processor is used in multiple calls, it may be + * beneficial to obtain a reference to the processor and to use it + * in following calls, rather than to specify the processor by its + * type expressed as a string, which necessitates a registry search + * for each call. + * + *

A processor reference is also the only way to examine the + * features of a processor by calling its + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} method. + * + *

Specifying null for the processor as first argument + * of a method causes this method to behave as a no-op. + * + *

State

+ * + *

Most of the methods in this class have a text + * argument which may be just a part of a larger body of text. + * When it is the case that the text is submitted in parts with + * repeated calls, there may be a need to pass information from + * one invocation to the next one. For instance, one invocation + * may detect that a comment or a literal has been started but + * has not been completed. In such cases, a state + * argument must be used. + * + *

The state argument must be an array of integers + * with at least one element. Only the first element is used by + * the methods of this class. + * + *

When submitting the initial part of the text, the first element + * of state must contain the value {@link #STATE_INITIAL} + * or any value <= 0. + * + *

After calling a method with a non-null state argument, + * a value is returned in the first element of state. This + * value should be passed unmodified to the method when calling it again + * with the text which is the continuation of the text submitted in the + * last call. + * + *

When the text submitted to a method is not a continuation and is not + * expected to have a continuation , e.g. it is processed all by itself, + * the state argument should be specified as null. + * + *

Code Samples

+ * + *

The following code shows how to transform a certain type of complex + * expression (directory and file paths) in order to obtain the full + * text corresponding to the lean text of such an expression. + * + *

+ *
+ *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
+ *    String fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.FILE, null, null, leanText, null);
+ *    System.out.println("full text = " + fullText);
+ *
+ *  
+ * + *

The following code shows how to transform successive lines of Java + * code in order to obtain the full + * text corresponding to the lean text of each line. + * + *

+ *
+ *    int[] state = new int[1];
+ *    state[0] = BidiComplexEngine.STATE_INITIAL;
+ *    String leanText = "int i = 3; // first Java statement";
+ *    String fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.JAVA, null, null, leanText, state);
+ *    System.out.println("full text = " + fullText);
+ *    leanText = "i += 4; // next Java statement";
+ *    fullText = BidiComplexEngine.leanToFullText(IBidiComplexExpressionTypes.JAVA, null, null, leanText, state);
+ *    System.out.println("full text = " + fullText);
+ *
+ *  
+ * + *

This class provides a user-oriented API but does not provide + * an actual implementation. The real work is done by the class + * {@link BidiComplexImpl}. Users of the API need not be concerned by, and + * should not depend upon, details of the implementation in + * BidiComplexImpl. + * + * @author Matitiahu Allouche + * + */ +public class BidiComplexEngine { + /** + * Constant to use in the first element of the state + * argument when calling most methods of this class + * to indicate that there is no context of previous lines which + * should be initialized before performing the operation. + */ + public static final int STATE_INITIAL = 0; + + private static final int[] EMPTY_INT_ARRAY = new int[0]; + + /** + * Prevent creation of a BidiComplexEngine instance + */ + private BidiComplexEngine() { + // nothing to do + } + + /** Add directional formatting characters to a complex expression + * to ensure correct presentation. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns the text string. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return the complex expression with directional formatting + * characters added at proper locations to ensure correct + * presentation. + */ + public static String leanToFullText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) + return text; + return BidiComplexImpl.leanToFullText(processor, features, environment, text, state); + } + + /** + * Given a lean string, compute the positions of each of its + * characters within the corresponding full string. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns an identity map. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return an array of integers with one element for each of the characters + * in the text argument, equal to the offset of the + * corresponding character in the full string. + */ + public static int[] leanToFullMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) { + int[] map = new int[text.length()]; + for (int i = 0; i < map.length; i++) + map[i] = i; + return map; + } + return BidiComplexImpl.leanToFullMap(processor, features, environment, text, state); + } + + /** + * Given a lean string, compute the offsets of characters + * before which directional formatting characters must be added + * in order to ensure correct presentation. + * + *

Only LRMs (for an expression with LTR base direction) and RLMs (for + * an expression with RTL base direction) are considered. Leading and + * trailing LRE, RLE and PDF which might be prefixed or suffixed + * depending on the {@link BidiComplexEnvironment#getOrientation orientation} of the + * GUI component used for display are not reflected in this method. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns an empty array. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return an array of offsets to the characters in the text + * argument before which directional marks must be + * added to ensure correct presentation. + * The offsets are sorted in ascending order. + */ + public static int[] leanBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) + return EMPTY_INT_ARRAY; + return BidiComplexImpl.leanBidiCharOffsets(processor, features, environment, text, state); + } + + /** + * Remove directional formatting characters which were added to a + * complex expression to ensure correct presentation. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns the text string. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression including + * directional formatting characters. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return the complex expression without directional formatting + * characters which might have been added by processing it + * with {@link #leanToFullText leanToFullText}. + * + */ + public static String fullToLeanText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) + return text; + return BidiComplexImpl.fullToLeanText(processor, features, environment, text, state); + } + + /** + * Given a full string, compute the positions of each of its + * characters within the corresponding lean string. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns an identity map. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression including + * directional formatting characters. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return an array of integers with one element for each of the characters + * in the text argument, equal to the offset of the + * corresponding character in the lean string. + * If there is no corresponding + * character in the lean string (because the + * specified character is a directional formatting character + * added when invoking {@link #leanToFullText leanToFullText}), + * the value returned for this character is -1. + */ + public static int[] fullToLeanMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) { + int[] map = new int[text.length()]; + for (int i = 0; i < map.length; i++) + map[i] = i; + return map; + } + return BidiComplexImpl.fullToLeanMap(processor, features, environment, text, state); + } + + /** + * Given a full string, return the offsets of characters + * which are directional formatting characters that have been added + * in order to ensure correct presentation. + * + *

LRMs (for an expression with LTR base direction), RLMs (for + * an expression with RTL base direction) are considered as well as + * leading and trailing LRE, RLE and PDF which might be prefixed or suffixed + * depending on the {@link BidiComplexEnvironment#getOrientation orientation} + * of the GUI component used for display. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns an empty array. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression including + * directional formatting characters. + * + * @param state can be used to specify that the text + * argument is the continuation of text submitted in a + * previous call and/or to receive information to pass to + * continuation calls. + * For more details, see State above. + *

If all calls to this method are independent from one another, + * this argument should be specified as null. + * + * @return an array of offsets to the characters in the text + * argument which are directional formatting characters + * added to ensure correct presentation. + * The offsets are sorted in ascending order. + */ + public static int[] fullBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (processor == null) + return EMPTY_INT_ARRAY; + return BidiComplexImpl.fullBidiCharOffsets(processor, features, environment, text, state); + } + + /** + * Get the base direction of a complex expression. + * This base direction may depend on + * whether the expression contains Arabic or Hebrew words + * (if it contains both, the first Arabic or Hebrew letter in the + * expression determines which is the governing script) and on + * whether the GUI is {@link BidiComplexEnvironment#getMirrored mirrored}. + * + * @param processor designates one of the registered processors. + * It can be a string containing a keyword according to + * the processor type, or a processor reference. + * For more details, see above + * How to Specify a Processor. + *

If this argument is null, this method + * returns {@link BidiComplexFeatures#DIR_LTR}. + * + * @param features specifies features that affect the processor's + * behavior. + *

This argument may be specified as null, + * in which case the processor will use its standard features + * (as returned by the processor + * {@link custom.IBidiComplexProcessor#getFeatures getFeatures} + * method). + * + * @param environment specifies an environment whose characteristics + * may affect the processor's behavior. + *

This argument may be specified as null, + * in which case the processor will assume a standard + * environment as specified in + * {@link BidiComplexEnvironment#DEFAULT}. + * + * @param text is the text of the complex expression. + * + * @return the base direction of the complex expression. + * It is one of the values {@link BidiComplexFeatures#DIR_LTR} + * or {@link BidiComplexFeatures#DIR_RTL}. + */ + public static int getCurDirection(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text) { + return BidiComplexImpl.getCurDirection(processor, features, environment, text, null); + } + +} Index: src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexEnvironment.java --- src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/BidiComplexEnvironment.java 26 Apr 2011 07:01:16 -0000 @@ -21,36 +21,21 @@ * All public fields in this class are final, i.e. cannot be * changed after creating an instance. *

- * A BidiComplexEnvironment instance can be associated with a BidiComplexHelper - * instance either when creating the - * {@link BidiComplexHelper#BidiComplexHelper(java.lang.String, BidiComplexEnvironment) BidiComplexHelper} instance - * or using the {@link BidiComplexHelper#setEnvironment setEnvironment} method. + * All methods in {@link BidiComplexEngine} have a BidiComplexEnvironment + * argument. If this argument is specified as null, the + * {@link #DEFAULT} environment is used. * *

Code Samples

- *

Example 1 (set all environment parameters) + *

Example (set all environment parameters) *

  *
  *    BidiComplexEnvironment myEnv = new BidiComplexEnvironment("he_IL", true, BidiComplexEnvironment.ORIENT_RTL);
- *    BidiComplexHelper myHelper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE, myEnv);
- *
- *  
- *

Example 2 (change only the orientation) - *

- *
- *    BidiComplexEnvironment env1 = myHelper.getEnvironment();
- *    BidiComplexEnvironment env2 = new BidiComplexEnvironment(env1.language, env1.mirrored, BidiComplexEnvironment.ORIENT_UNKNOWN);
- *    myHelper.setEnvironment(env2);
  *
  *  
*

* This class also provides a number of convenience methods related to the environment. *

 

- * @see BidiComplexHelper#BidiComplexHelper(String, BidiComplexEnvironment) - * @see BidiComplexHelper#BidiComplexHelper(IBidiComplexProcessor, BidiComplexEnvironment) - * @see BidiComplexHelper#getEnvironment BidiComplexHelper.getEnvironment - * @see BidiComplexHelper#setEnvironment BidiComplexHelper.setEnvironment - * @see IBidiComplexProcessor#init IBidiComplexProcessor.init - * @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment + * @see IBidiComplexProcessor#getFeatures * * @author Matitiahu Allouche */ @@ -59,18 +44,18 @@ /** * Constant specifying that the orientation of the GUI component * where a complex expression will be displayed is LTR. - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_LTR = 0; /** * Constant specifying that the orientation of the GUI component * where a complex expression will be displayed is RTL. - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_RTL = 1; @@ -78,9 +63,9 @@ * Constant specifying that the orientation of the GUI component * where a complex expression will be displayed is contextual with * a default of LTR (if no strong character appears in the text). - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_CONTEXTUAL_LTR = 2; @@ -88,9 +73,9 @@ * Constant specifying that the orientation of the GUI component * where a complex expression will be displayed is contextual with * a default of RTL (if no strong character appears in the text). - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_CONTEXTUAL_RTL = 3; @@ -99,10 +84,10 @@ * where a complex expression will be displayed is not known. * Directional formatting characters must be added as prefix and * suffix whenever a full text is generated using - * {@link BidiComplexHelper#leanToFullText leanToFullText}. - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * {@link BidiComplexEngine#leanToFullText leanToFullText}. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_UNKNOWN = 4; @@ -111,16 +96,16 @@ * GUI component where a complex expression will be displayed, no * directional formatting characters must be added as prefix or * suffix when a full text is generated using - * {@link BidiComplexHelper#leanToFullText leanToFullText}. - * It can appear as orientation argument for - * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} and as value for the - * {@link BidiComplexEnvironment#orientation} member of BidiComplexEnvironment. + * {@link BidiComplexEngine#leanToFullText leanToFullText}. + * It can appear as orientation argument for the + * {@link BidiComplexEnvironment#BidiComplexEnvironment BidiComplexEnvironment constructor} + * and as value returned by {@link #getOrientation}. */ public static final int ORIENT_IGNORE = 5; /** - * Pre-defined BidiComplexEnvironment instance with values for a non-mirrored GUI - * and a Left-to-Right presentation component.
+ * Pre-defined BidiComplexEnvironment instance with values + * for a non-mirrored GUI and a Left-to-Right presentation component.
* The language is set to null, which defaults to the language * of the current default locale. */ @@ -131,67 +116,19 @@ * ISO-639. If left as null, it defaults to the language * of the current default locale. */ - public final String language; + final String language; /** * Flag specifying that complex expressions processed under this environment * should assume that the GUI is mirrored (globally going from right to left). */ - public final boolean mirrored; + final boolean mirrored; /** Specify the orientation (a.k.a. base direction) of the GUI * component in which the full text of the complex expression will - * be displayed.
- * The orientation must have one of the values - * {@link #ORIENT_LTR ORIENT_LTR}, - * {@link #ORIENT_LTR ORIENT_RTL}, - * {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR}, - * {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL}, - * {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or - * {@link #ORIENT_IGNORE ORIENT_IGNORE}. - *

- * When the orientation is ORIENT_LTR and the complex - * expression has a RTL base direction, - * {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds RLE+RLM at the head of the full text and RLM+PDF at its - * end. - *

- * When the orientation is ORIENT_RTL and the complex - * expression has a LTR base direction, - * {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds LRE+LRM at the head of the full text and LRM+PDF at its - * end. - *

- * When the orientation is ORIENT_CONTEXTUAL_LTR or - * ORIENT_CONTEXTUAL_RTL and the data content would resolve - * to a RTL orientation while the complex expression has a LTR base - * direction, {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds LRM at the head of the full text. - *

- * When the orientation is ORIENT_CONTEXTUAL_LTR or - * ORIENT_CONTEXTUAL_RTL and the data content would resolve - * to a LTR orientation while the complex expression has a RTL base - * direction, {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds RLM at the head of the full text. - *

- * When the orientation is ORIENT_UNKNOWN and the complex - * expression has a LTR base direction, - * {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds LRE+LRM at the head of the full text and LRM+PDF at its - * end. - *

- * When the orientation is ORIENT_UNKNOWN and the complex - * expression has a RTL base direction, - * {@link BidiComplexHelper#leanToFullText leanToFullText} - * adds RLE+RLM at the head of the full text and RLM+PDF at its - * end. - *

- * When the orientation is ORIENT_IGNORE, - * {@link BidiComplexHelper#leanToFullText leanToFullText} does not add any directional - * formatting characters as either prefix or suffix of the full text. - *

+ * be displayed. */ - public final int orientation; + final int orientation; static Locale defaultLocale; static String defaultLanguage; @@ -207,10 +144,10 @@ * If longer than 2 letters, the extra letters are ignored.
* If set to null, it defaults to the language * of the default locale. - * @see #language + * @see #getLanguage * * @param mirrored specifies if the GUI is mirrored. - * @see #mirrored + * @see #getMirrored * * @param orientation specifies the orientation of the component * which is to display the complex expression. It must be @@ -222,7 +159,7 @@ * {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or * {@link #ORIENT_IGNORE ORIENT_IGNORE}.
* If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}. - * @see #orientation + * @see #getOrientation */ public BidiComplexEnvironment(String lang, boolean mirrored, int orientation) { if (lang == null) { @@ -239,14 +176,88 @@ } /** + * Return a 2-letters code representing a language as defined by + * ISO-639. If equal to null, it defaults to the language + * of the current default locale. + */ + public String getLanguage() { + return language; + } + + /** + * Return a flag indicating that complex expressions processed + * within this environment should assume that the GUI is mirrored + * (globally going from right to left). + */ + public boolean getMirrored() { + return mirrored; + } + + /** Return the orientation (a.k.a. base direction) of the GUI + * component in which the full text of the complex expression + * will be displayed.
+ * The orientation must have one of the values + * {@link #ORIENT_LTR ORIENT_LTR}, + * {@link #ORIENT_LTR ORIENT_RTL}, + * {@link #ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR}, + * {@link #ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL}, + * {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN} or + * {@link #ORIENT_IGNORE ORIENT_IGNORE}. + *

+ * When the orientation is ORIENT_LTR and the complex + * expression has a RTL base direction, + * {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds RLE+RLM at the head of the full text and RLM+PDF at its + * end. + *

+ * When the orientation is ORIENT_RTL and the complex + * expression has a LTR base direction, + * {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds LRE+LRM at the head of the full text and LRM+PDF at its + * end. + *

+ * When the orientation is ORIENT_CONTEXTUAL_LTR or + * ORIENT_CONTEXTUAL_RTL and the data content would resolve + * to a RTL orientation while the complex expression has a LTR base + * direction, {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds LRM at the head of the full text. + *

+ * When the orientation is ORIENT_CONTEXTUAL_LTR or + * ORIENT_CONTEXTUAL_RTL and the data content would resolve + * to a LTR orientation while the complex expression has a RTL base + * direction, {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds RLM at the head of the full text. + *

+ * When the orientation is ORIENT_UNKNOWN and the complex + * expression has a LTR base direction, + * {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds LRE+LRM at the head of the full text and LRM+PDF at its + * end. + *

+ * When the orientation is ORIENT_UNKNOWN and the complex + * expression has a RTL base direction, + * {@link BidiComplexEngine#leanToFullText leanToFullText} + * adds RLE+RLM at the head of the full text and RLM+PDF at its + * end. + *

+ * When the orientation is ORIENT_IGNORE, + * {@link BidiComplexEngine#leanToFullText leanToFullText} does not add any directional + * formatting characters as either prefix or suffix of the full text. + *

+ */ + public int getOrientation() { + return orientation; + } + + /** * Check whether the current language uses a * bidi script (Arabic, Hebrew, Farsi or Urdu). * * @return true if the current language uses a bidi script. * The language may have been set explicitly when creating the - * BidiComplexEnvironment instance, or it may have defaulted to - * the language of the current default locale. - * @see #BidiComplexEnvironment BidiComplexEnvironment + * BidiComplexEnvironment instance, or it may have + * defaulted to the language of the current default locale. + * @see #getLanguage */ public boolean isBidi() { if (defaultLanguage != null && defaultLocale.equals(getDefaultLocale())) Index: src/org/eclipse/equinox/bidi/BidiComplexFeatures.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/BidiComplexFeatures.java diff -N src/org/eclipse/equinox/bidi/BidiComplexFeatures.java --- src/org/eclipse/equinox/bidi/BidiComplexFeatures.java 9 Feb 2011 21:28:54 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,190 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - ******************************************************************************/ -package org.eclipse.equinox.bidi; - -import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor; - -/** - * This class defines features of a complex expression processor. - *

- * All public fields in this class are final, i.e. cannot be - * changed after creating an instance. - *

- * A BidiComplexFeatures instance can be associated with a - * BidiComplexHelper instance using - * the {@link BidiComplexHelper#setFeatures setFeatures} method. - * - *

Code Samples

- *

Example 1 (set all features) - *

- *
- *    BidiComplexFeatures myFeatures = new BidiComplexFeatures("+-=", 0, -1, -1, false, false);
- *    BidiComplexHelper myHelper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE, myEnv);
- *    myHelper.setFeatures(myFeatures);
- *
- *  
- *

Example 2 (change only the operators) - *

- *
- *    BidiComplexFeatures f1 = myHelper.getFeatures();
- *    BidiComplexFeatures f2 = new BidiComplexFeatures("[]|()", f1.specialsCount,
- *                                     f1.dirArabic, f1.dirHebrew,
- *                                     f1.ignoreArabic, f1.ignoreHebrew);
- *    myHelper.setFeatures(f2);
- *
- *  
- * - * @see BidiComplexHelper#getFeatures BidiComplexHelper.getFeatures - * @see BidiComplexHelper#setFeatures BidiComplexHelper.setFeatures - * @see IBidiComplexProcessor#init IBidiComplexProcessor.init - * @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment - * - * @author Matitiahu Allouche - */ -public class BidiComplexFeatures { - - /** - * Constant specifying that the base direction of a complex expression is LTR. - * The base direction may depend on whether the GUI is - * {@link BidiComplexEnvironment#mirrored mirrored} and may - * may be different for Arabic and for Hebrew. - * This constant can appear as dirArabic - * or dirHebrew argument for - * {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} and as value - * for the {@link #dirArabic} or {@link #dirHebrew} members of - * BidiComplexFeatures. - */ - public static final int DIR_LTR = 0; - - /** - * Constant specifying that the base direction of a complex expression is RTL. - * The base direction may depend on whether the GUI is - * {@link BidiComplexEnvironment#mirrored mirrored} and may - * may be different for Arabic and for Hebrew. - * This constant can appear as dirArabic - * or dirHebrew argument for - * {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} and as value - * for the {@link #dirArabic} or {@link #dirHebrew} members of - * BidiComplexFeatures. - */ - public static final int DIR_RTL = 1; - - /** - * Pre-defined BidiComplexFeatures instance with values for no - * operators, no special processing, all directions LTR - * and support for neither Arabic nor Hebrew.
- * Since there are no operators and no special processing, a complex - * expression processor with such features would do nothing.
- * It is more efficient to do nothing with a - * {@link BidiComplexHelper#BidiComplexHelper() BidiComplexHelper} - * instantiated with no arguments. - */ - public static final BidiComplexFeatures DEFAULT = new BidiComplexFeatures(null, 0, -1, -1, true, true); - - /** - * String grouping one-character operators which - * separate the text of the complex expression into tokens. - */ - public final String operators; - - /** - * Number of special cases for the associated processor. - * Special cases exist for some types of complex expression processors. - * They are implemented by overriding methods - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and - * {@link IBidiComplexProcessor#processSpecial processSpecial}. - * Examples of special cases are comments, literals, or anything which - * is not identified by a one-character operator. - */ - public final int specialsCount; - - /** - * Base direction of the complex expression for Arabic. - * If a complex expression contains both Arabic and - * Hebrew words, the first Arabic or Hebrew letter in the - * expression determines which is the governing script).
- * The value of this field must be one of - * {@link #DIR_LTR} or {@link #DIR_RTL}. - * - * @see #dirHebrew - */ - public final int dirArabic; - - /** - * Base direction of the complex expression for Hebrew. - * If a complex expression contains both Arabic and - * Hebrew words, the first Arabic or Hebrew letter in the - * expression determines which is the governing script).
- * The value of this field must be one of - * {@link #DIR_LTR} or {@link #DIR_RTL}. - * - * @see #dirArabic - */ - public final int dirHebrew; - - /** - * Flag indicating that Arabic letters will not be considered for - * processing complex expressions. If both this flag and - * {@link #ignoreHebrew} are set to true, the - * processor will do nothing (but some overhead can be expected). - */ - public final boolean ignoreArabic; - - /** - * Flag indicating that Hebrew letters will not be considered for - * processing complex expressions. If both this flag and - * {@link #ignoreArabic} are set to true, the - * processor will do nothing (but some overhead can be expected). - */ - public final boolean ignoreHebrew; - - /** - * Constructor - * - * @param operators is a string where each character is a delimiter - * which separates the complex expression into tokens. - * @see #operators - * - * @param specialsCount specifies the number of special cases handled - * by the processor. - * @see #specialsCount - * - * @param dirArabic specifies the base direction of the complex expression - * for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}. - * If it is not (for instance if it is a negative value), it - * defaults to DIR_LTR. - * @see #dirArabic - * - * @param dirHebrew specifies the base direction of the complex expression - * for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}. - * If it is not (for instance if it is a negative value), it - * defaults to DIR_LTR. - * @see #dirHebrew - * - * @param ignoreArabic indicates that Arabic letters will not be - * considered for processing complex expressions. - * @see #ignoreArabic - * - * @param ignoreHebrew indicates that Hebrew letters will not be - * considered for processing complex expressions. - * @see #ignoreHebrew - */ - public BidiComplexFeatures(String operators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) { - - this.operators = operators == null ? "" : operators; //$NON-NLS-1$ - this.specialsCount = specialsCount; - this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR; - this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR; - this.ignoreArabic = ignoreArabic; - this.ignoreHebrew = ignoreHebrew; - } - -} Index: src/org/eclipse/equinox/bidi/BidiComplexHelper.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/BidiComplexHelper.java diff -N src/org/eclipse/equinox/bidi/BidiComplexHelper.java --- src/org/eclipse/equinox/bidi/BidiComplexHelper.java 9 Feb 2011 21:28:54 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,568 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2011 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - ******************************************************************************/ -package org.eclipse.equinox.bidi; - -import org.eclipse.equinox.bidi.custom.BidiComplexStringProcessor; -import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor; -import org.eclipse.equinox.bidi.internal.BidiComplexImpl; - -/** - * This class acts as a mediator between applications and complex - * expression processors. - * The purpose of complex expression processors is to add directional - * formatting characters to ensure correct display. - * This class shields applications from the - * intricacies of complex expression processors. - *

- * For a general introduction to complex expressions, see - * {@link - * the package documentation}. - * - *

Code Sample

- * - *

The following code shows how to instantiate a BidiComplexHelper adapted for a - * certain type of complex expression (directory and file paths), and how - * to obtain the full text corresponding to the lean text - * of such an expression. - * - *

- *
- *    BidiComplexHelper helper = new BidiComplexHelper(IBidiComplexExpressionTypes.FILE);
- *    String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
- *    String fullText = helper.leanToFullText(leanText);
- *    System.out.println("full text = " + fullText);
- *
- *  
- * This class provides a user-oriented API but does not provides - * an actual implementation. The real work is done by the class - * {@link BidiComplexImpl}. Users of the API need not be concerned by, and - * should not depend upon, details of the implementation by - * BidiComplexImpl. - * - * @author Matitiahu Allouche - * - */ -public class BidiComplexHelper { - /** - * Constant to use as initState argument when calling - * {@link #leanToFullText(java.lang.String, int) leanToFullText} or - * {@link #fullToLeanText(java.lang.String, int) fullToLeanText} - * to indicate that there is no context of previous lines which - * should be initialized before performing the operation. - */ - public static final int STATE_NOTHING_GOING = -1; - - private static final int[] EMPTY_INT_ARRAY = new int[0]; - - /** - * Reference to the {@link BidiComplexImpl} instance which accomplishes - * most of the work. This member should be accessed only by - * complex expression processors (implementing {@link IBidiComplexProcessor}). - */ - public BidiComplexImpl impl; - - /** - * Create a BidiComplexHelper instance which does nothing tangible - * but does it quickly. We will call it a no-op helper. - * The {@link #BidiComplexHelper() no-op helper} does not modify text submitted to it, and can be - * used when it is known that no complex expression processing - * is needed, for instance because no bidi text is expected. With this - * helper, the cost of invoking the complex expression API is minimal. - */ - public BidiComplexHelper() { - // let impl stay null - } - - /** - * Create a BidiComplexHelper instance to process expressions - * of type type with a - * {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment. - * - * @param type represents the type of the complex expression. It must - * be one of the values in {@link IBidiComplexExpressionTypes}, or a type - * added in a plug-in extension. - * - * @throws IllegalArgumentException if the type is not - * supported. - */ - public BidiComplexHelper(String type) { - this(type, null); - } - - /** - * Create a BidiComplexHelper instance to process expressions - * of type type operating under the environment - * {@link BidiComplexEnvironment environment}. - * - * @param type represents the type of the complex expression. It must - * be one of the values in {@link IBidiComplexExpressionTypes}, or a type - * added in a plug-in extension. - * - * @param environment represents the environment where the complex expression - * will be displayed. It is better to specify the environment - * when instantiating a BidiComplexHelper than to specify - * it later using {@link #setEnvironment setEnvironment}.
- * null can be specified here for a - * {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment. - * - * @throws IllegalArgumentException if the type is not - * supported. - */ - public BidiComplexHelper(String type, BidiComplexEnvironment environment) { - IBidiComplexProcessor processor = BidiComplexStringProcessor.getProcessor(type); - if (processor == null) { - throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$ - } - impl = new BidiComplexImpl(this, processor, environment); - } - - /** - * Create a BidiComplexHelper instance to process complex - * expressions by means of a given processor myProcessor, - * operating under the environment {@link BidiComplexEnvironment environment}. - * - * @param myProcessor is a complex expression processor. - * - * @param environment represents the environment where the complex expression - * will be displayed. It is better to specify the environment - * when instantiating a BidiComplexHelper than to specify - * it later using {@link #setEnvironment setEnvironment}.
- * null can be specified here for a - * {@link BidiComplexEnvironment#DEFAULT DEFAULT} environment. - */ - public BidiComplexHelper(IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment) { - impl = new BidiComplexImpl(this, myProcessor, environment); - } - - /** Add directional formatting characters to a complex expression - * to ensure correct presentation. - * - * @param text is the text of the complex expression. - * - * @return the complex expression with directional formatting - * characters added at proper locations to ensure correct - * presentation.
- * The {@link #BidiComplexHelper() no-op helper} returns text. - */ - public String leanToFullText(String text) { - return leanToFullText(text, STATE_NOTHING_GOING); - } - - /** - * Add directional formatting characters to a complex expression - * to ensure correct presentation. - * - * @param text is the text of the complex expression. - * - * @param initState specifies that the first parameter is the - * continuation of text submitted in a previous call. - * The initState of the present call must be - * the final state obtained by calling - * {@link #getFinalState() getFinalState} - * after the previous call. - *
If the present call is not a continuation of - * text submitted in a previous call, the value - * {@link #STATE_NOTHING_GOING} should be used as argument. - * - * @return the complex expression with directional formatting - * characters added at proper locations to ensure correct - * presentation.
- * The {@link #BidiComplexHelper() no-op helper} returns text. - * - * @see #getFinalState getFinalState - */ - public String leanToFullText(String text, int initState) { - if (impl == null) - return text; - return impl.leanToFullText(text, initState); - } - - /** - * Given a complex expression, get the offsets of characters before - * which directional formatting characters must be added in order to - * ensure correct presentation. - * Only LRMs (for an expression with LTR base direction) and RLMs (for - * an expression with RTL base direction) are considered. Leading and - * trailing LRE, RLE and PDF which might be prefixed or suffixed - * depending on the {@link BidiComplexEnvironment#orientation orientation} of the - * GUI component used for display are not reflected in this method. - *

- * This method assumes that a successful call to - * {@link #leanToFullText leanToFullText} has been performed, and it - * returns the offsets relevant for the last text submitted. - * - * @return an array of offsets to the characters in the last submitted - * complex expression before which directional marks must be - * added to ensure correct presentation. - * The offsets are sorted in ascending order.
- * The {@link #BidiComplexHelper() no-op helper} returns an array of 0 elements. - */ - public int[] leanBidiCharOffsets() { - if (impl == null) - return EMPTY_INT_ARRAY; - return impl.leanBidiCharOffsets(); - } - - /** - * Get the offsets of characters in the full text of a - * complex expression corresponding to directional formatting - * characters which have been added in order to ensure correct presentation. - * LRMs (for an expression with LTR base direction), RLMs (for - * an expression with RTL base direction) are considered as well as - * leading and trailing LRE, RLE and PDF which might be prefixed or suffixed - * depending on the {@link BidiComplexEnvironment#orientation orientation} of the - * GUI component used for display. - *

- * This method assumes that a successful call to - * {@link #leanToFullText leanToFullText} has been performed, and it - * returns the offsets relevant for the last text submitted. - * - * @return an array of offsets to the characters in the full - * text of the last submitted complex expression which are - * directional formatting characters added to ensure correct - * presentation. - * The offsets are sorted in ascending order.
- * The {@link #BidiComplexHelper() no-op helper} returns an array of 0 elements. - */ - public int[] fullBidiCharOffsets() { - if (impl == null) - return EMPTY_INT_ARRAY; - return impl.fullBidiCharOffsets(); - } - - /** - * Remove directional formatting characters which were added to a - * complex expression to ensure correct presentation. - * - * @param text is the text of the complex expression including - * directional formatting characters. - * - * @return the complex expression without directional formatting - * characters which might have been added by processing it - * with {@link #leanToFullText leanToFullText}.
- * The {@link #BidiComplexHelper() no-op helper} returns text - * - */ - public String fullToLeanText(String text) { - return fullToLeanText(text, STATE_NOTHING_GOING); - } - - /** - * Remove directional formatting characters which were added to a - * complex expression to ensure correct presentation. - * - * @param text is the text of the complex expression including - * directional formatting characters. - * - * @param initState specifies that the first parameter is the - * continuation of text submitted in a previous call. - * The initState of the present call must be - * the final state obtained by calling - * {@link #getFinalState getFinalState} after the previous call. - *
If the present call is not a continuation of - * text submitted in a previous call, the value - * {@link #STATE_NOTHING_GOING} should be used as argument. - * - * @return the complex expression without directional formatting - * characters which might have been added by processing it - * with {@link #leanToFullText leanToFullText}.
- * The {@link #BidiComplexHelper() no-op helper} returns text - * - * @see #getFinalState getFinalState - */ - public String fullToLeanText(String text, int initState) { - if (impl == null) - return text; - return impl.fullToLeanText(text, initState); - } - - /** - * Retrieve the final state achieved in a previous call to - * {@link #leanToFullText leanToFullText} or - * {@link #fullToLeanText fullToLeanText}. - * This state is an opaque value which is meaningful only - * within calls to the same complex expression processor. - * The only externalized value is - * {@link #STATE_NOTHING_GOING} which means that - * there is nothing to remember from the last call. - *

- * The state should be used only for complex expressions which come - * in parts, like when spanning multiple lines. The user can make - * a separate call to - * leanToFullText or fullToLeanText for each - * line in the expression. The final state value retrieved after the - * call for one line should be used as the initial state in the call - * which processes the next line. - *

- * If a line within a complex expression has already been processed by - * leanToFullText and the lean version of that line has - * not changed, and its initial state has not changed either, the user - * can be sure that the full version of that line is also - * identical to the result of the previous processing. - * - * @see #leanToFullText(String text, int initState) - * @see #fullToLeanText(String text, int initState) - * - * @return the last final state.
- * The {@link #BidiComplexHelper() no-op helper} returns {@link #STATE_NOTHING_GOING}. - */ - public int getFinalState() { - if (impl == null) - return STATE_NOTHING_GOING; - return impl.getFinalState(); - } - - /** - * After transforming a lean string into a full string - * using {@link #leanToFullText leanToFullText}, compute the index in the - * full string of the character corresponding to the - * character with the specified position in the lean string. - * - * @param position is the index of a character in the lean string. - * It must be a non-negative number smaller than the length - * of the lean text. - * - * @return the index of the corresponding character in the - * full string.
- * The {@link #BidiComplexHelper() no-op helper} returns position. - */ - public int leanToFullPos(int position) { - if (impl == null) - return position; - return impl.leanToFullPos(position); - } - - /** - * After transforming a lean string into a full string - * using {@link #leanToFullText leanToFullText}, compute the index in the - * lean string of the character corresponding to the - * character with the specified position in the full string. - * - * @param position is the index of a character in the full string. - * It must be a non-negative number smaller than the length - * of the full text. - * - * @return the index of the corresponding character in the - * lean string. If there is no corresponding - * character in the lean string (because the - * specified character is a directional formatting character - * added when invoking {@link #leanToFullText leanToFullText}), - * the value returned will be that corresponding to the - * next character which is not a directional formatting - * character.
- * If position corresponds to a directional formatting - * character beyond all characters of the original - * lean text, the value returned is the length of the - * lean text.
- * The {@link #BidiComplexHelper() no-op helper} returns position. - */ - public int fullToLeanPos(int position) { - if (impl == null) - return position; - return impl.fullToLeanPos(position); - } - - /** - * Get the base direction of the complex expression last - * submitted to {@link #leanToFullText leanToFullText}. - * This base direction may depend on - * whether the expression contains Arabic or Hebrew words - * (if it contains both, the first Arabic or Hebrew letter in the - * expression determines which is the governing script) and on - * whether the GUI is {@link BidiComplexEnvironment#mirrored mirrored}. - * - * @return the base direction of the last submitted complex - * expression. It must be one of the values - * {@link BidiComplexFeatures#DIR_LTR} or {@link BidiComplexFeatures#DIR_RTL}.
- * The {@link #BidiComplexHelper() no-op helper} returns DIR_LTR. - */ - public int getCurDirection() { - if (impl == null) - return BidiComplexFeatures.DIR_LTR; - return impl.getCurDirection(); - } - - /** - * Get the current environment under which the BidiComplexHelper - * operates. - * This environment may have been specified in the constructor or - * specified later using {@link #setEnvironment setEnvironment}.
- * - * @return the current environment.
- * The {@link #BidiComplexHelper() no-op helper} returns a {@link BidiComplexEnvironment#DEFAULT DEFAULT} - * environment. - * - * @see #setEnvironment setEnvironment - */ - public BidiComplexEnvironment getEnvironment() { - if (impl == null) - return BidiComplexEnvironment.DEFAULT; - return impl.getEnvironment(); - } - - /** - * Specify the environment under which the BidiComplexHelper - * must operate. - *

- * Note that calling this method causes the processor - * associated with this instance of BidiComplexHelper - * to re-initialize its features. The effect of a previous call - * to {@link #setFeatures(BidiComplexFeatures) setFeatures} is lost.
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - * - * @see #getEnvironment getEnvironment - * @see IBidiComplexProcessor#updateEnvironment IBidiComplexProcessor.updateEnvironment - */ - public void setEnvironment(BidiComplexEnvironment environment) { - if (impl != null) - impl.setEnvironment(environment); - } - - /** - * Get the current features of the processor associated with this - * BidiComplexHelper instance. - * - * @return the current features.
- * The {@link #BidiComplexHelper() no-op helper} returns {@link BidiComplexFeatures#DEFAULT DEFAULT} - * features. - * - * @see #setFeatures setFeatures - */ - public BidiComplexFeatures getFeatures() { - if (impl == null) - return BidiComplexFeatures.DEFAULT; - return impl.getFeatures(); - } - - /** - * Specify the features to be applied to the processor associated with this - * BidiComplexHelper instance. - * Note that the value of {@link BidiComplexFeatures#specialsCount specialsCount} - * cannot be changed (the new value will be ignored).
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - * - * @see #getFeatures getFeatures - */ - public void setFeatures(BidiComplexFeatures features) { - if (impl != null) - impl.setFeatures(features); - } - - /** - * This method can be called from within - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or - * {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations - * of {@link IBidiComplexProcessor} to retrieve the bidirectional class of - * characters in the lean text. - * - * @param index position of the character in the lean text. - * It must be a non-negative number smaller than the length - * of the lean text. - * - * @return the bidirectional class of the character. It is one of the - * values which can be returned by - * java.lang.Character#getDirectionality. - * However, it is recommended to use getDirProp - * rather than java.lang.Character.getDirectionality - * since getDirProp manages a cache of character - * properties and so can be more efficient than calling the - * java.lang.Character method.
- * The {@link #BidiComplexHelper() no-op helper} returns - * Character.DIRECTIONALITY_UNDEFINED. - */ - public byte getDirProp(int index) { - if (impl == null) - return Character.DIRECTIONALITY_UNDEFINED; - return impl.getDirProp(index); - } - - /** - * This method can be called from within - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or - * {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations - * of {@link IBidiComplexProcessor} to set or override the bidirectional - * class of characters in the lean text. - * - * @param index position of the character in the lean text. - * It must be a non-negative number smaller than the length - * of the lean text. - * - * @param dirProp bidirectional class of the character. It is one of the - * values which can be returned by - * java.lang.Character.getDirectionality.
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - */ - public void setDirProp(int index, byte dirProp) { - if (impl != null) - impl.getDirProp(index); - } - - /** - * This method can be called from within - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or - * {@link IBidiComplexProcessor#processSpecial processSpecial} in implementations - * of {@link IBidiComplexProcessor} - * to specify that a mark character must be added before the character - * at the specified position of the lean text when generating the - * full text. The mark character will be LRM for complex expressions - * with a LTR base direction, and RLM for complex expressions with RTL - * base direction. The mark character is not added physically by this - * method, but its position is noted and will be used when generating - * the full text. - * - * @param offset position of the character in the lean text. - * It must be a non-negative number smaller than the length - * of the lean text. - * For the benefit of efficiency, it is better to insert - * multiple marks in ascending order of the offsets.
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - */ - public void insertMark(int offset) { - if (impl != null) - impl.insertMark(offset); - } - - /** - * This method can be called from within - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or - * {@link IBidiComplexProcessor#processSpecial processSpecial} in - * implementations of {@link IBidiComplexProcessor} to add a - * directional mark before an - * operator if needed for correct display, depending on the - * base direction of the expression and on the class of the - * characters in the lean text preceding and following - * the operator itself.
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - * - * @param operLocation offset of the operator in the lean text. - * It must be a non-negative number smaller than the length - * of the lean text. - */ - public void processOperator(int operLocation) { - if (impl != null) - impl.processOperator(operLocation); - } - - /** - * This method can be called from within - * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or - * {@link IBidiComplexProcessor#processSpecial processSpecial} in - * implementations of {@link IBidiComplexProcessor} to - * set the final state which should be used for the next call to - * {@link #leanToFullText(java.lang.String, int)}.
- * The {@link #BidiComplexHelper() no-op helper} does nothing. - */ - public void setFinalState(int newState) { - if (impl != null) - impl.setFinalState(newState); - } - -} Index: src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexStringRecord.java --- src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/BidiComplexStringRecord.java 26 Apr 2011 07:01:16 -0000 @@ -14,14 +14,14 @@ import org.eclipse.equinox.bidi.custom.BidiComplexStringProcessor; /** - * This class records strings which are complex expressions. Several static - * methods in this class allow to record such strings in a pool, and to find if - * a given string is member of the pool. - *

- * Instances of this class are the records which are members of the pool. - *

- * The pool is managed as a cyclic list, each new element overrides the oldest - * element in the list. + * This class records strings which are complex expressions. Several static + * methods in this class allow to record such strings in a pool, and to find if + * a given string is member of the pool. + *

+ * Instances of this class are the records which are members of the pool. + *

+ * The pool is managed as a cyclic list. When the pool is full, + * each new element overrides the oldest element in the list. */ public class BidiComplexStringRecord { /** @@ -54,52 +54,52 @@ private SoftReference triRef; /** - * Constructor. - * - * @param string - * the string to record - * - * @param triplets - * array of short integers, the number of elements in the array - * must be a multiple of 3, so that the array is made of one or - * more triplets of short integers. - *

- * The first element in each triplet is the beginning index of a - * susbstring of string which is a complex - * expression. - *

- * The second element in each triplet is the ending index of a - * susbstring of string which is a complex - * expression. This index points to one position beyond the last - * character of the substring. - *

- * The third element in each triplet is the numeric type of the - * complex expression.
- * The type of a complex expression must be one of the string - * values listed in {@link IBidiComplexExpressionTypes}.
- * The corresponding numeric type must be obtained using the - * method {@link #typeStringToShort typeStringToShort}. + * Constructor. + * + * @param string the string to record + * + * @param triplets + * array of short integers, the number of elements in the array + * must be a multiple of 3, so that the array is made of one or + * more triplets of short integers. + *

+ * The first element in each triplet is the beginning offset of a + * susbstring of string which is a complex + * expression. + *

+ * The second element in each triplet is the ending offset of a + * susbstring of string which is a complex + * expression. This offset points to one position beyond the last + * character of the substring. + *

+ * The third element in each triplet is the numeric type of the + * complex expression.
+ * The type of a complex expression must be one of the string + * values listed in {@link IBidiComplexExpressionTypes}.
+ * The corresponding numeric type must be obtained using the + * method {@link #typeStringToShort typeStringToShort}. */ public BidiComplexStringRecord(String string, short[] triplets) { - if (string == null || triplets == null || (triplets.length % 3) != 0) - throw new IllegalArgumentException(); + if (string == null || triplets == null) + throw new IllegalArgumentException("The string and triplets argument must not be null!"); //$NON-NLS-1$ + if ((triplets.length % 3) != 0) + throw new IllegalArgumentException("The number of elements in triplets must be a multiple of 3!"); //$NON-NLS-1$ for (int i = 2; i < triplets.length; i += 3) if (triplets[i] < 0 || triplets[i] > MAXTYPE) - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Illegal type value in element" + i); strRef = new SoftReference(string); triRef = new SoftReference(triplets); hash = string.hashCode(); } /** - * Get the numeric type of a complex expression given its string type. - * - * @param type - * type of complex expression as string. It must be one of the - * strings listed in {@link IBidiComplexExpressionTypes}. - * - * @return a value which is the corresponding numeric type. If - * type is invalid, the method returns -1. + * Get the numeric type of a complex expression given its string type. + * + * @param type type of complex expression as string. It must be one + * of the strings listed in {@link IBidiComplexExpressionTypes}. + * + * @return a value which is the corresponding numeric type. If + * type is invalid, the method returns -1. */ public static short typeStringToShort(String type) { for (int i = 0; i < types.length; i++) @@ -109,14 +109,14 @@ } /** - * Get the string type of a complex expression given its numeric type. - * - * @param shType - * the numeric type of a complex expression. It should be a value - * obtained using {@link #typeStringToShort typeStringToShort}. - * - * @return the corresponding string type. If shType is invalid, - * the method returns null. + * Get the string type of a complex expression given its numeric type. + * + * @param shType + * the numeric type of a complex expression. It should be a value + * obtained using {@link #typeStringToShort typeStringToShort}. + * + * @return the corresponding string type. If shType is invalid, + * the method returns null. */ public static String typeShortToString(short shType) { if (shType < 0 || shType > MAXTYPE) @@ -125,10 +125,9 @@ } /** - * /** Add a record to the pool. - * - * @param record - * a BidiComplexStringRecord instance + * Add a record to the pool. + * + * @param record a BidiComplexStringRecord instance */ public static synchronized void add(BidiComplexStringRecord record) { if (last < MAXINDEX) @@ -139,13 +138,12 @@ } /** - * Check if a string is recorded and retrieve its triplets. - * - * @param string - * the string to check - * - * @return null if the string is not recorded in the pool; - * otherwise, return the triplets associated with this string. + * Check if a string is recorded and retrieve its triplets. + * + * @param string the string to check + * + * @return null if the string is not recorded in the pool; + * otherwise, return the triplets associated with this string. */ public static short[] getTriplets(String string) { if (records[0] == null) // no records at all @@ -175,9 +173,9 @@ } /** - * Clear the pool. All elements of the pool are erased and any associated - * memory is freed. - * + * Clear the pool. All elements of the pool are erased and any associated + * memory is freed. + * */ public static synchronized void clear() { for (int i = 0; i <= MAXINDEX; i++) { Index: src/org/eclipse/equinox/bidi/BidiComplexUtil.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/BidiComplexUtil.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexUtil.java --- src/org/eclipse/equinox/bidi/BidiComplexUtil.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/BidiComplexUtil.java 26 Apr 2011 07:01:16 -0000 @@ -10,6 +10,7 @@ ******************************************************************************/ package org.eclipse.equinox.bidi; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** @@ -34,7 +35,7 @@ * text before the characters specified in the given array of offsets, * and can add a prefix and/or a suffix of directional formatting characters. * This can be used for instance after obtaining offsets by calling - * {@link BidiComplexHelper#leanBidiCharOffsets() leanBidiCharOffsets} in order to + * {@link BidiComplexEngine#leanBidiCharOffsets leanBidiCharOffsets} in order to * produce a full text corresponding to the source text. * The directional formatting characters that will be added at the given * offsets will be LRMs for expressions with LTR base direction and @@ -211,9 +212,8 @@ // make sure that LRE/PDF are added around the string BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN); - BidiComplexHelper helper = new BidiComplexHelper(new BidiComplexProcessor(), env); - helper.setFeatures(new BidiComplexFeatures(delimiters, 0, -1, -1, false, false)); - return helper.leanToFullText(str); + BidiComplexFeatures features = new BidiComplexFeatures(delimiters, 0, -1, -1, false, false); + return BidiComplexEngine.leanToFullText(new BidiComplexProcessor(), features, env, str, null); } /** @@ -257,8 +257,7 @@ // make sure that LRE/PDF are added around the string BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN); - BidiComplexHelper helper = new BidiComplexHelper(type, env); - return helper.leanToFullText(str); + return BidiComplexEngine.leanToFullText(type, null, env, str, null); } /** @@ -308,8 +307,7 @@ // make sure that LRE/PDF are added around the string BidiComplexEnvironment env = new BidiComplexEnvironment(null, false, BidiComplexEnvironment.ORIENT_UNKNOWN); - BidiComplexHelper helper = new BidiComplexHelper(type, env); - return helper.fullToLeanText(str); + return BidiComplexEngine.fullToLeanText(type, null, env, str, null); } } Index: src/org/eclipse/equinox/bidi/custom/BidiComplexFeatures.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/custom/BidiComplexFeatures.java diff -N src/org/eclipse/equinox/bidi/custom/BidiComplexFeatures.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/custom/BidiComplexFeatures.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.equinox.bidi.custom; + +import org.eclipse.equinox.bidi.BidiComplexEnvironment; + +/** + * This class defines features of a complex expression processor. + *

+ * All public fields in this class are final, i.e. cannot be + * changed after creating an instance. + * + *

Code Sample

+ *

Example 1 (set all features) + *

+ *
+ *    BidiComplexFeatures f1 = new BidiComplexFeatures("+-=", 0, -1, -1, false, false);
+ *
+ *  
+ *

Example 2 (change only the operators) + *

+ *
+ *    BidiComplexFeatures f2 = new BidiComplexFeatures("[]|()", f1.getSpecialsCount(),
+ *                                     f1.getDirArabic(), f1.getDirHebrew(),
+ *                                     f1.getIgnoreArabic(), f1.getIgnoreHebrew());
+ *
+ *  
+ * + * @see IBidiComplexProcessor#getFeatures + * + * @author Matitiahu Allouche + */ +public class BidiComplexFeatures { + + /** + * Constant specifying that the base direction of a complex expression is LTR. + * The base direction may depend on whether the GUI is + * {@link BidiComplexEnvironment#getMirrored mirrored} and may + * may be different for Arabic and for Hebrew. + * This constant can appear as dirArabic + * or dirHebrew argument for the + * {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} + * and as value returned by {@link #getDirArabic} or {@link #getDirHebrew} + * methods. + */ + public static final int DIR_LTR = 0; + + /** + * Constant specifying that the base direction of a complex expression is RTL. + * The base direction may depend on whether the GUI is + * {@link BidiComplexEnvironment#getMirrored mirrored} and may + * may be different for Arabic and for Hebrew. + * This constant can appear as dirArabic + * or dirHebrew argument for the + * {@link BidiComplexFeatures#BidiComplexFeatures BidiComplexFeatures constructor} + * and as value returned by {@link #getDirArabic} or {@link #getDirHebrew} + * methods. + */ + public static final int DIR_RTL = 1; + + /** + * Pre-defined BidiComplexFeatures instance with values for no + * operators, no special processing, all directions LTR + * and support for neither Arabic nor Hebrew.
+ * Since there are no operators and no special processing, a complex + * expression processor with such features would do nothing.
+ * It is more efficient to do nothing with a null processor. + */ + public static final BidiComplexFeatures DEFAULT = new BidiComplexFeatures(null, 0, -1, -1, true, true); + + /** + * String grouping one-character operators which + * separate the text of the complex expression into tokens. + */ + final String operators; + + /** + * Number of special cases for the associated processor. + * Special cases exist for some types of complex expression processors. + * They are implemented by overriding methods + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and + * {@link IBidiComplexProcessor#processSpecial processSpecial}. + * Examples of special cases are comments, literals, or anything which + * is not identified by a one-character operator. + */ + final int specialsCount; + + /** + * Base direction of the complex expression for Arabic. + * If a complex expression contains both Arabic and + * Hebrew words, the first Arabic or Hebrew letter in the + * expression determines which is the governing script).
+ * The value of this field must be one of + * {@link #DIR_LTR} or {@link #DIR_RTL}. + * + * @see #dirHebrew + */ + final int dirArabic; + + /** + * Base direction of the complex expression for Hebrew. + * If a complex expression contains both Arabic and + * Hebrew words, the first Arabic or Hebrew letter in the + * expression determines which is the governing script).
+ * The value of this field must be one of + * {@link #DIR_LTR} or {@link #DIR_RTL}. + * + * @see #dirArabic + */ + final int dirHebrew; + + /** + * Flag indicating that Arabic letters will not be considered for + * processing complex expressions. If both this flag and + * ignoreHebrew are set to true, the + * processor will do nothing (but some overhead can be expected). + */ + final boolean ignoreArabic; + + /** + * Flag indicating that Hebrew letters will not be considered for + * processing complex expressions. If both this flag and + * ignoreArabic are set to true, the + * processor will do nothing (but some overhead can be expected). + */ + final boolean ignoreHebrew; + + /** + * Constructor + * + * @param operators is a string where each character is a delimiter + * which separates the complex expression into tokens. + * @see #getOperators + * + * @param specialsCount specifies the number of special cases handled + * by the processor. This value must be identical to the + * number of special cases handled by the processor with which + * this BidiComplexFeatures instance is associated. + * @see #getSpecialsCount + * + * @param dirArabic specifies the base direction of the complex expression + * for Arabic. It must be {@link #DIR_LTR} or {@link #DIR_RTL}. + * If it is not (for instance if it is a negative value), it + * defaults to DIR_LTR. + * @see #getDirArabic + * + * @param dirHebrew specifies the base direction of the complex expression + * for Hebrew. It must be {@link #DIR_LTR} or {@link #DIR_RTL}. + * If it is not (for instance if it is a negative value), it + * defaults to DIR_LTR. + * @see #getDirHebrew + * + * @param ignoreArabic indicates that Arabic letters will not be + * considered for processing complex expressions. + * If both this flag and ignoreHebrew + * are set to true, the processor will do + * nothing (but some overhead can be expected). + * @see #getIgnoreArabic + * + * @param ignoreHebrew indicates that Hebrew letters will not be + * considered for processing complex expressions. + * If both this flag and ignoreArabic + * are set to true, the processor will do + * nothing (but some overhead can be expected). + * @see #getIgnoreHebrew + */ + public BidiComplexFeatures(String operators, int specialsCount, int dirArabic, int dirHebrew, boolean ignoreArabic, boolean ignoreHebrew) { + + this.operators = operators == null ? "" : operators; //$NON-NLS-1$ + this.specialsCount = specialsCount; + this.dirArabic = dirArabic == DIR_LTR || dirArabic == DIR_RTL ? dirArabic : DIR_LTR; + this.dirHebrew = dirHebrew == DIR_LTR || dirHebrew == DIR_RTL ? dirHebrew : DIR_LTR; + this.ignoreArabic = ignoreArabic; + this.ignoreHebrew = ignoreHebrew; + } + + /** + * @return a string grouping one-character operators which separate + * the text of the complex expression into tokens. + */ + public String getOperators() { + return operators; + } + + /** + * @return the number of special cases for the associated processor. + * Special cases exist for some types of complex expression + * processors. They are implemented by overriding methods + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} and + * {@link IBidiComplexProcessor#processSpecial processSpecial}. + * Examples of special cases are comments, literals, or + * anything which is not identified by a one-character operator. + */ + public int getSpecialsCount() { + return specialsCount; + } + + /** + * @return the base direction of the complex expression for Arabic. + * If a complex expression contains both Arabic and + * Hebrew words, the first Arabic or Hebrew letter in the + * expression determines which is the governing script.
+ * The value of this field is one of + * {@link #DIR_LTR} or {@link #DIR_RTL}. + * + * @see #getDirHebrew + */ + public int getDirArabic() { + return dirArabic; + } + + /** + * @return the base direction of the complex expression for Hebrew. + * If a complex expression contains both Arabic and + * Hebrew words, the first Arabic or Hebrew letter in the + * expression determines which is the governing script.
+ * The value of this field is one of + * {@link #DIR_LTR} or {@link #DIR_RTL}. + * + * @see #getDirArabic + */ + public int getDirHebrew() { + return dirHebrew; + } + + /** + * @return a flag indicating that Arabic letters will not be considered + * for processing complex expressions. + */ + public boolean getIgnoreArabic() { + return ignoreArabic; + } + + /** + * Flag indicating that Hebrew letters will not be considered for + * processing complex expressions. + */ + public boolean getIgnoreHebrew() { + return ignoreHebrew; + } + +} Index: src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexProcessor.java --- src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/custom/BidiComplexProcessor.java 26 Apr 2011 07:01:24 -0000 @@ -10,7 +10,8 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.custom; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEngine; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; import org.eclipse.equinox.bidi.internal.BidiComplexImpl; /** @@ -22,27 +23,33 @@ * * + * @see BidiComplexFeatures#getOperators + * @see BidiComplexFeatures#getDirArabic + * @see BidiComplexFeatures#getDirHebrew + * @see BidiComplexFeatures#getSpecialsCount + * * @author Matitiahu Allouche */ public class BidiComplexProcessor implements IBidiComplexProcessor { @@ -51,48 +58,178 @@ * In BidiComplexProcessor this method returns a * {@link BidiComplexFeatures#DEFAULT DEFAULT} value which * directs the processor to do nothing. + * + *

A processor which extends this class must override this method + * and return a BidiComplexFeatures instance representing its specific + * features. + * + * @see IBidiComplexProcessor#getFeatures the corresponding interface method */ - public BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment environment) { - return BidiComplexFeatures.DEFAULT; - } - - /** - * In BidiComplexProcessor this method simply calls the - * {@link #init init} method. If this is good enough, i.e. - * if the {@link BidiComplexFeatures features} of the processor are - * determined identically for initialization and after a - * change in the {@link BidiComplexEnvironment environment}, subclasses of - * BidiComplexProcessor don't need to override this - * method. - */ - public BidiComplexFeatures updateEnvironment(BidiComplexHelper caller, BidiComplexEnvironment environment) { - return init(caller, environment); + public BidiComplexFeatures getFeatures(BidiComplexEnvironment environment) { + throw new IllegalStateException("A processor must have a getFeatures() method."); //$NON-NLS-1$ } /** * In BidiComplexProcessor this method throws an * IllegalStateException. This is appropriate behavior * (and does not need to be overridden) for processors whose - * {@link BidiComplexFeatures#specialsCount specialsCount} is zero, which - * means that indexOfSpecial should never be called - * for them. + * number of special cases is zero, which means that + * indexOfSpecial should never be called for them. + * + *

A processor handling special cases must override this method. + * + * @see IBidiComplexProcessor#indexOfSpecial the corresponding interface method */ - public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex) { + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { // This method must be overridden by all subclasses with special cases. - throw new IllegalStateException(); + throw new IllegalStateException("A processor must have an indexOfSpecial() method."); //$NON-NLS-1$ } /** * In BidiComplexProcessor this method throws an * IllegalStateException. This is appropriate behavior * (and does not need to be overridden) for processors whose - * {@link BidiComplexFeatures#specialsCount specialsCount} is zero, which - * means that processSpecial should never be called - * for them. + * number of special cases is zero, which means that + * processSpecial should never be called for them. + * + *

A processor handling special cases must override this method. + * + * @see IBidiComplexProcessor#processSpecial the corresponding interface method */ - public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation) { + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { // This method must be overridden by all subclasses with any special case. - throw new IllegalStateException(); + throw new IllegalStateException("A processor must have a processSpecial() method."); //$NON-NLS-1$ + } + + /** + * This method can be called from within + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or + * {@link IBidiComplexProcessor#processSpecial processSpecial} in + * implementations of {@link IBidiComplexProcessor} to retrieve the + * bidirectional class of characters in the lean text. + * + * @param text is the text of the complex expression received as + * parameter to indexOfSpecial or + * processSpecial. + * + * @param dirProps is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to getDirProp and other methods used + * by processors. + * + * @param index position of the character in the lean text. + * It must be a non-negative number smaller than the length + * of the lean text. + * + * @return the bidirectional class of the character. It is one of the + * values which can be returned by + * java.lang.Character.getDirectionality. + * However, it is recommended to use getDirProp + * rather than java.lang.Character.getDirectionality + * since getDirProp manages a cache of character + * properties and so can be more efficient than calling the + * java.lang.Character method. + */ + public static byte getDirProp(String text, byte[] dirProps, int index) { + return BidiComplexImpl.getDirProp(text, dirProps, index); + } + + /** + * This method can be called from within + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or + * {@link IBidiComplexProcessor#processSpecial processSpecial} in + * implementations of {@link IBidiComplexProcessor} to set or + * override the bidirectional class of characters in the lean text. + * + * @param dirProps is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to setDirProp and other methods used + * by processors. + * + * @param index position of the character in the lean text. + * It must be a non-negative number smaller than the length + * of the lean text. + * + * @param dirProp bidirectional class of the character. It is one of the + * values which can be returned by + * java.lang.Character.getDirectionality. + */ + public static void setDirProp(byte[] dirProps, int index, byte dirProp) { + BidiComplexImpl.setDirProp(dirProps, index, dirProp); + } + + /** + * This method can be called from within + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or + * {@link IBidiComplexProcessor#processSpecial processSpecial} in + * implementations of {@link IBidiComplexProcessor} + * to specify that a mark character must be added before the character + * at the specified position of the lean text when generating the + * full text. The mark character will be LRM for complex expressions + * with a LTR base direction, and RLM for complex expressions with RTL + * base direction. The mark character is not added physically by this + * method, but its position is noted and will be used when generating + * the full text. + * + * @param text is the text of the complex expression received as + * parameter to indexOfSpecial or + * processSpecial. + * + * @param dirProps is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to insertMark and other methods used + * by processors. + * + * @param offsets is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to insertMark and other methods used + * by processors. + * + * @param offset position of the character in the lean text. + * It must be a non-negative number smaller than the length + * of the lean text. + * For the benefit of efficiency, it is better to insert + * multiple marks in ascending order of the offsets. + */ + public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) { + BidiComplexImpl.insertMark(text, dirProps, offsets, offset); + } + + /** + * This method can be called from within + * {@link IBidiComplexProcessor#indexOfSpecial indexOfSpecial} or + * {@link IBidiComplexProcessor#processSpecial processSpecial} in + * implementations of {@link IBidiComplexProcessor} to add a + * directional mark before an + * operator if needed for correct display, depending on the + * base direction of the expression and on the class of the + * characters in the lean text preceding and following + * the operator itself. + * + * @param features is the {@link BidiComplexFeatures} instance + * received as parameter to indexOfSpecial or + * processSpecial. + * + * @param text is the text of the complex expression received as + * parameter to indexOfSpecial or + * processSpecial. + * + * @param dirProps is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to processOperator and other methods used + * by processors. + * + * @param offsets is a parameter received by indexOfSpecial + * or processSpecial, uniquely to be used as argument + * for calls to processOperator and other methods used + * by processors. + * + * @param operLocation offset of the operator in the lean text. + * It must be a non-negative number smaller than the length + * of the lean text. + */ + public static void processOperator(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int operLocation) { + BidiComplexImpl.processOperator(features, text, dirProps, offsets, operLocation); } } Index: src/org/eclipse/equinox/bidi/custom/IBidiComplexProcessor.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/custom/IBidiComplexProcessor.java,v retrieving revision 1.1 diff -u -r1.1 IBidiComplexProcessor.java --- src/org/eclipse/equinox/bidi/custom/IBidiComplexProcessor.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/custom/IBidiComplexProcessor.java 26 Apr 2011 07:01:24 -0000 @@ -10,8 +10,8 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.custom; -import org.eclipse.equinox.bidi.*; -import org.eclipse.equinox.bidi.internal.BidiComplexImpl; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.BidiComplexEngine; /** * Interface for all complex expression processors. @@ -23,66 +23,58 @@ public interface IBidiComplexProcessor { /** - * Do whatever initializations are needed and return the + * return the * {@link BidiComplexFeatures} characterizing the processor. * - * @param env the current environment, which may affect the - * initializations. - * - * @param caller BidiComplexHelper instance which called this method. - * This allows access to the field - * {@link BidiComplexImpl#processorData caller.impl.processorData} where - * the processor can keep whatever data it needs. + * @param env the current environment, which may affect the behavior of + * the processor. This parameter may be specified as + * null, in which case the + * {@link BidiComplexEnvironment#DEFAULT DEFAULT} + * environment should be assumed. * * @return the features in use for this processor. */ - public abstract BidiComplexFeatures init(BidiComplexHelper caller, BidiComplexEnvironment env); - - /** - * Do whatever renewed initializations are needed after a - * change in the environment and return the possibly updated - * {@link BidiComplexFeatures} characterizing the processor. - * - * @param env the updated environment, which may affect the - * initializations. - * - * @param caller BidiComplexHelper instance which called this method. - * This allows access to the field - * {@link BidiComplexImpl#processorData caller.impl.processorData} where - * the processor can keep whatever data it needs. - * - * @return the features to use for this processor. - */ - public BidiComplexFeatures updateEnvironment(BidiComplexHelper caller, BidiComplexEnvironment env); + public abstract BidiComplexFeatures getFeatures(BidiComplexEnvironment env); /** * Locate occurrences of special strings within a complex expression * and return their indexes one after the other in successive calls. *

* This method is called repeatedly from the code implementing - * {@link BidiComplexHelper#leanToFullText leanToFullText} if the field - * {@link BidiComplexFeatures#specialsCount specialsCount} returned when - * {@link #init initializing} the processor is greater than zero. + * {@link BidiComplexEngine#leanToFullText leanToFullText} if the + * number of special cases appearing in the associated features + * parameter is greater than zero. *

* The code implementing this method may use the following methods - * in {@link BidiComplexHelper}: + * in {@link BidiComplexProcessor}: *

* + * @param features is the {@link BidiComplexFeatures} instance + * currently associated with this processor. + * + * @param text is the text of the complex expression before + * addition of any directional formatting characters. + * + * @param dirProps is a parameter received by indexOfSpecial + * uniquely to be used as argument for calls to methods which + * need it. + * + * @param offsets is a parameter received by indexOfSpecial + * uniquely to be used as argument for calls to methods which + * need it. + * * @param caseNumber number of the special case to locate. - * This number varies from zero to specialsCount - 1. + * This number varies from 1 to the number of special cases + * in the features associated with this processor. * The meaning of this number is internal to the class * implementing indexOfSpecial. * - * @param srcText text of the complex expression before addition of any - * directional formatting characters. - * - * @param fromIndex the index within srcText to start + * @param fromIndex the index within text to start * the search from. * * @return the position where the start of the special case was located. @@ -94,57 +86,85 @@ * a literal or vice-versa). *
If no occurrence is found, the method must return -1. */ - public int indexOfSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int fromIndex); + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex); /** - * This method is called by {@link BidiComplexHelper#leanToFullText leanToFullText} + * This method handles special cases specific to this processor. + * It is called by {@link BidiComplexEngine#leanToFullText leanToFullText} * when a special case occurrence is located by * {@link #indexOfSpecial indexOfSpecial}. *

* The code implementing this method may use the following methods - * in {@link BidiComplexHelper}: + * in {@link BidiComplexProcessor}: *

*

* If a special processing cannot be completed within a current call to * processSpecial (for instance, a comment has been started * in the current line but its end appears in a following line), - * processSpecial should specify a final state using - * the method {@link BidiComplexHelper#setFinalState setFinalState}. + * processSpecial should specify a final state by + * putting its value in the first element of the state + * parameter. * The meaning of this state is internal to the processor. * On a later call to - * {@link BidiComplexHelper#leanToFullText(String text, int initState)} + * {@link BidiComplexEngine#leanToFullText leanToFullText} * specifying that state value, processSpecial will be * called with that value for parameter caseNumber and * -1 for parameter operLocation and should * perform whatever initializations are required depending on the state. * - * @param caseNumber number of the special case to handle. + * @param features is the {@link BidiComplexFeatures} instance + * currently associated with this processor. + * + * @param text is the text of the complex expression before + * addition of any directional formatting characters. * - * @param srcText text of the complex expression. + * @param dirProps is a parameter received by processSpecial + * uniquely to be used as argument for calls to methods which + * need it. + * + * @param offsets is a parameter received by processSpecial + * uniquely to be used as argument for calls to methods which + * need it. + * + * @param state is an integer array with at least one element. + * If the processor needs to signal the occurrence of a + * special case which must be passed to the next call to + * leanToFullText (for instance, a comment or a + * literal started but not closed in the current + * text), it must put a value in the first element + * of the state parameter. + * This value must be a number between 1 and the number of + * special cases appearing in the features associated with + * this processor. This number is passed back to the caller + * and should be specified as state argument + * in the next call to leanToFullText together + * with the continuation text. + * The meaning of this number is internal to the processor. + * + * @param caseNumber number of the special case to handle. * * @param operLocation the position returned by * {@link #indexOfSpecial indexOfSpecial}. In calls to - * {@link BidiComplexHelper#leanToFullText(String text, int initState)} or - * {@link BidiComplexHelper#fullToLeanText(String text, int initState)} - * specifying an initState - * parameter, processSpecial is called when initializing - * the processing with the value of caseNumber - * equal to initState and the value of + * {@link BidiComplexEngine#leanToFullText leanToFullText} and other + * methods of {@link BidiComplexEngine} specifying a non-null + * state parameter, processSpecial is + * called when initializing the processing with the value of + * caseNumber equal to the value returned in the + * first element of state and the value of * operLocation equal to -1. * * @return the position after the scope of the special case ends. * For instance, the position after the end of a comment, * the position after the end of a literal. - *
A value greater or equal to the length of srcText + *
A value greater or equal to the length of text * means that there is no further occurrence of this case in the * current complex expression. */ - public int processSpecial(BidiComplexHelper caller, int caseNumber, String srcText, int operLocation); + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation); } Index: src/org/eclipse/equinox/bidi/custom/package.html =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/custom/package.html,v retrieving revision 1.1 diff -u -r1.1 package.html --- src/org/eclipse/equinox/bidi/custom/package.html 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/custom/package.html 26 Apr 2011 07:01:24 -0000 @@ -14,6 +14,9 @@

  • {@link BidiComplexProcessor} is a generic processor which can be used as superclass for specific processors.
  • +
  • {@link BidiComplexFeatures} + allows managing some factors which affect + a complex expression processor's behavior
  • {@link BidiComplexStringProcessor} is a class which allows retrieval of the defined processor types and of the corresponding processors.
  • Index: src/org/eclipse/equinox/bidi/internal/BidiComplexDelims.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/BidiComplexDelims.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexDelims.java --- src/org/eclipse/equinox/bidi/internal/BidiComplexDelims.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/BidiComplexDelims.java 26 Apr 2011 07:01:24 -0000 @@ -10,7 +10,7 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal; -import org.eclipse.equinox.bidi.BidiComplexHelper; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** @@ -26,21 +26,21 @@ /** * This method locates occurrences of start delimiters. */ - public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) { - char delim = getDelimiters().charAt(caseNumber * 2); - return srcText.indexOf(delim, fromIndex); + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { + char delim = getDelimiters().charAt((caseNumber - 1) * 2); + return text.indexOf(delim, fromIndex); } /** * This method skips until after the matching end delimiter. */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { - helper.processOperator(operLocation); + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); int loc = operLocation + 1; - char delim = getDelimiters().charAt((caseNumber * 2) + 1); - loc = srcText.indexOf(delim, loc); + char delim = getDelimiters().charAt((caseNumber * 2) - 1); + loc = text.indexOf(delim, loc); if (loc < 0) - return srcText.length(); + return text.length(); return loc + 1; } Index: src/org/eclipse/equinox/bidi/internal/BidiComplexDelimsEsc.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/BidiComplexDelimsEsc.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexDelimsEsc.java --- src/org/eclipse/equinox/bidi/internal/BidiComplexDelimsEsc.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/BidiComplexDelimsEsc.java 26 Apr 2011 07:01:24 -0000 @@ -10,7 +10,8 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal; -import org.eclipse.equinox.bidi.BidiComplexHelper; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; +import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** * BidiComplexDelims is a processor for complex expressions @@ -21,9 +22,9 @@ * that delimiters can be escaped using the backslash character. * * * @author Matitiahu Allouche @@ -31,19 +32,19 @@ public abstract class BidiComplexDelimsEsc extends BidiComplexDelims { /** - * This method skips until after the matching end delimiter, - * ignoring possibly escaped end delimiters. - */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { - helper.processOperator(operLocation); + * This method skips until after the matching end delimiter, + * ignoring possibly escaped end delimiters. + */ + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); int location = operLocation + 1; - char delim = getDelimiters().charAt((caseNumber * 2) + 1); + char delim = getDelimiters().charAt((caseNumber * 2) - 1); while (true) { - location = srcText.indexOf(delim, location); + location = text.indexOf(delim, location); if (location < 0) - return srcText.length(); + return text.length(); int cnt = 0; - for (int i = location - 1; srcText.charAt(i) == '\\'; i--) { + for (int i = location - 1; text.charAt(i) == '\\'; i--) { cnt++; } location++; Index: src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexImpl.java --- src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/BidiComplexImpl.java 26 Apr 2011 07:01:24 -0000 @@ -10,14 +10,15 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal; -import org.eclipse.equinox.bidi.*; -import org.eclipse.equinox.bidi.custom.IBidiComplexProcessor; +import org.eclipse.equinox.bidi.BidiComplexEngine; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.*; /** * BidiComplexImpl provides the code which implements the API in - * {@link BidiComplexHelper}. All its public methods are shadows of similarly - * signed methods of BidiComplexHelper, and their documentation - * is by reference to the methods in BidiComplexHelper. + * {@link BidiComplexEngine}. All its public methods are shadows of similarly + * signed methods of BidiComplexEngine, and their documentation + * is by reference to the methods in BidiComplexEngine. * * @author Matitiahu Allouche */ @@ -41,75 +42,28 @@ static final int PREFIX_LENGTH = 2; static final int SUFFIX_LENGTH = 2; static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH; - - BidiComplexHelper helper; - - BidiComplexEnvironment environment; - - IBidiComplexProcessor processor; - - /** - * This field is reserved for use of the complex expression - * processor associated with this instance of BidiComplexImpl. - * The processor can keep here a reference to an object that it - * has sole control of. - */ - public Object processorData; - - /** - * Features of the associated processor. - * - */ - public BidiComplexFeatures features; - - int state = BidiComplexHelper.STATE_NOTHING_GOING; - - // strong bidi class (L or R) for current expression direction - byte curStrong = -1; - // strong character (LRM or RLM) for current expression direction - char curMark; - // strong directional control (LRE or RLE) for current expression direction - char curEmbed; - int prefixLength; - // index of next occurrence for each operator and each special case - int[] locations; - // number of special cases - int specialsCount; - String leanText; - // positions where LRM/RLM must be added - int[] offsets; - // number of LRM/RLM to add - int count; - // For positions where it has been looked up, the entry will receive - // the Character directionality + 2 (so that 0 indicates that the - // the directionality has not been looked up yet. - byte[] dirProps; - // current UI orientation (after resolution if contextual) - int curOrient = -1; - // Current expression base direction (after resolution if depending on - // script and/or on GUI mirroring (0=LTR, 1=RTL)) - int curDirection = -1; - - /** - * @see BidiComplexHelper#BidiComplexHelper(IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment) - */ - public BidiComplexImpl(BidiComplexHelper caller, IBidiComplexProcessor myProcessor, BidiComplexEnvironment environment) { - helper = caller; - if (environment == null) { - this.environment = BidiComplexEnvironment.DEFAULT; - } else { - this.environment = environment; - } - processor = myProcessor; - features = processor.init(helper, this.environment); - // keep private copy of specialsCount to avoid later modification - specialsCount = features.specialsCount; - locations = new int[features.operators.length() + specialsCount]; - } - - long computeNextLocation(int curPos) { - int operCount = features.operators.length(); - int len = leanText.length(); + static final int DIRPROPS_ADD = 2; + static final int OFFSETS_SHIFT = 3; + static final int[] EMPTY_INT_ARRAY = new int[0]; + + /** + * Prevent creation of a BidiComplexEngine instance + */ + private BidiComplexImpl() { + // nothing to do + } + + /* + // keep private copy of specialsCount to avoid later modification + specialsCount = features.getSpecialsCount(); + locations = new int[features.getOperators().length() + specialsCount]; + } + */ + static long computeNextLocation(IBidiComplexProcessor processor, BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] locations, int[] state, int curPos) { + String operators = features.getOperators(); + int operCount = operators.length(); + int specialsCount = features.getSpecialsCount(); + int len = text.length(); int nextLocation = len; int idxLocation = 0; // Start with special sequences to give them precedence over simple @@ -117,7 +71,8 @@ for (int i = 0; i < specialsCount; i++) { int location = locations[operCount + i]; if (location < curPos) { - location = processor.indexOfSpecial(helper, i, leanText, curPos); + offsets = ensureRoomInOffsets(offsets); + location = processor.indexOfSpecial(features, text, dirProps, offsets, i + 1, curPos); if (location < 0) location = len; locations[operCount + i] = location; @@ -130,7 +85,7 @@ for (int i = 0; i < operCount; i++) { int location = locations[i]; if (location < curPos) { - location = leanText.indexOf(features.operators.charAt(i), curPos); + location = text.indexOf(operators.charAt(i), curPos); if (location < 0) location = len; locations[i] = location; @@ -143,17 +98,14 @@ return nextLocation + (((long) idxLocation) << 32); } - int getCurOrient() { - if (curOrient >= 0) - return curOrient; - - if ((environment.orientation & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) { + static int getCurOrient(BidiComplexEnvironment environment, String text, byte[] dirProps) { + int orient = environment.getOrientation(); + if ((orient & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) { // absolute orientation - curOrient = environment.orientation; - return curOrient; + return orient; } // contextual orientation - int len = leanText.length(); + int len = text.length(); byte dirProp; for (int i = 0; i < len; i++) { // In the following lines, B, L, R and AL represent bidi categories @@ -165,41 +117,51 @@ // AL represents the category Arabic Letter. dirProp = dirProps[i]; if (dirProp == 0) { - dirProp = Character.getDirectionality(leanText.charAt(i)); + dirProp = Character.getDirectionality(text.charAt(i)); if (dirProp == B) // B char resolves to L or R depending on orientation continue; - dirProps[i] = (byte) (dirProp + 2); + dirProps[i] = (byte) (dirProp + DIRPROPS_ADD); } else { - dirProp -= 2; - } - if (dirProp == L) { - curOrient = BidiComplexEnvironment.ORIENT_LTR; - return curOrient; + dirProp -= DIRPROPS_ADD; } - if (dirProp == R || dirProp == AL) { - curOrient = BidiComplexEnvironment.ORIENT_RTL; - return curOrient; - } - } - curOrient = environment.orientation & 1; - return curOrient; + if (dirProp == L) + return BidiComplexEnvironment.ORIENT_LTR; + if (dirProp == R || dirProp == AL) + return BidiComplexEnvironment.ORIENT_RTL; + } + // return the default orientation corresponding to the contextual orientation + return orient & 1; } /** - * @see BidiComplexHelper#getCurDirection - */ - public int getCurDirection() { - if (curDirection >= 0) - return curDirection; - - curStrong = -1; - // same direction for Arabic and Hebrew? - if (features.dirArabic == features.dirHebrew) { - curDirection = features.dirArabic; - return curDirection; + * @see BidiComplexEngine#getCurDirection BidiComplexEngine.getCurDirection + */ + public static int getCurDirection(Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, byte[] dirProps) { + if (environment == null) + environment = BidiComplexEnvironment.DEFAULT; + if (features == null) { + if (_processor == null) + return BidiComplexFeatures.DIR_LTR; + IBidiComplexProcessor processor; + if (_processor instanceof java.lang.String) { + processor = BidiComplexStringProcessor.getProcessor((String) _processor); + if (processor == null) + throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$ + } else if (_processor instanceof IBidiComplexProcessor) + processor = (IBidiComplexProcessor) _processor; + else + throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$ + features = processor.getFeatures(environment); } + int dirArabic = features.getDirArabic(); + int dirHebrew = features.getDirHebrew(); + // same direction for Arabic and Hebrew? + if (dirArabic == dirHebrew) + return dirArabic; // check if Arabic or Hebrew letter comes first - int len = leanText.length(); + int len = text.length(); + if (dirProps == null) + dirProps = new byte[len + 1]; byte dirProp; for (int i = 0; i < len; i++) { // In the following lines, R and AL represent bidi categories @@ -207,34 +169,23 @@ // ( http://www.unicode.org/reports/tr9/ ). // R represents the category Right to Left character. // AL represents the category Arabic Letter. - dirProp = getDirProp(i); - if (dirProp == AL) { - curDirection = features.dirArabic; - return curDirection; - } - if (dirProp == R) { - curDirection = features.dirHebrew; - return curDirection; - } + byte saveOrient = dirProps[len]; + dirProps[len] = -1; // make getDirProp return B + dirProp = getDirProp(text, dirProps, i); + dirProps[len] = saveOrient; + if (dirProp == AL) + return dirArabic; + if (dirProp == R) + return dirHebrew; } // found no Arabic or Hebrew character - curDirection = BidiComplexFeatures.DIR_LTR; - return curDirection; - } - - void setMarkAndFixes() { - int dir = getCurDirection(); - if (curStrong == STRONGS[dir]) - return; - curStrong = STRONGS[dir]; - curMark = MARKS[dir]; - curEmbed = EMBEDS[dir]; + return BidiComplexFeatures.DIR_LTR; } /** - * @see BidiComplexHelper#getDirProp(int index) + * @see BidiComplexProcessor#getDirProp BidiComplexProcessor.getDirProp */ - public byte getDirProp(int index) { + public static byte getDirProp(String text, byte[] dirProps, int index) { byte dirProp = dirProps[index]; if (dirProp == 0) { // In the following lines, B, L and R represent bidi categories @@ -243,26 +194,31 @@ // B represents the category Block Separator. // L represents the category Left to Right character. // R represents the category Right to Left character. - dirProp = Character.getDirectionality(leanText.charAt(index)); - if (dirProp == B) - dirProp = getCurOrient() == BidiComplexEnvironment.ORIENT_RTL ? R : L; - dirProps[index] = (byte) (dirProp + 2); + dirProp = Character.getDirectionality(text.charAt(index)); + if (dirProp == B) { + // the last entry of dirProps contains the current component orientation + byte orient = dirProps[dirProps.length - 1]; + if (orient == -1) + return B; + dirProp = orient == BidiComplexEnvironment.ORIENT_RTL ? R : L; + } + dirProps[index] = (byte) (dirProp + DIRPROPS_ADD); return dirProp; } - return (byte) (dirProp - 2); + return (byte) (dirProp - DIRPROPS_ADD); } /** - * @see BidiComplexHelper#setDirProp(int index, byte dirProp) + * @see BidiComplexProcessor#setDirProp BidiComplexProcessor.setDirProp */ - public void setDirProp(int index, byte dirProp) { - dirProps[index] = (byte) (dirProp + 2); + public static void setDirProp(byte[] dirProps, int index, byte dirProp) { + dirProps[index] = (byte) (dirProp + DIRPROPS_ADD); } /** - * @see BidiComplexHelper#processOperator(int operLocation) + * @see BidiComplexProcessor#processOperator BidiComplexProcessor.processOperator */ - public void processOperator(int operLocation) { + public static void processOperator(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int operLocation) { // In this method, L, R, AL, AN and EN represent bidi categories // as defined in the Unicode Bidirectional Algorithm // ( http://www.unicode.org/reports/tr9/ ). @@ -271,23 +227,21 @@ // AL represents the category Arabic Letter. // AN represents the category Arabic Number. // EN represents the category European Number. - int len = leanText.length(); - boolean doneAN = false; - - if (getCurDirection() == BidiComplexFeatures.DIR_RTL) { + int len = text.length(); + // offsets[2] contains the complex expression direction + if (offsets[2] == BidiComplexFeatures.DIR_RTL) { // the expression base direction is RTL for (int i = operLocation - 1; i >= 0; i--) { - byte dirProp = getDirProp(i); + byte dirProp = getDirProp(text, dirProps, i); if (dirProp == R || dirProp == AL) return; - if (dirProp == L) { for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); + dirProp = getDirProp(text, dirProps, j); if (dirProp == R || dirProp == AL) return; if (dirProp == L || dirProp == EN) { - insertMark(operLocation); + insertMark(text, dirProps, offsets, operLocation); return; } } @@ -298,201 +252,265 @@ } // the expression base direction is LTR - if (features.ignoreArabic) { - if (features.ignoreHebrew) /* process neither Arabic nor Hebrew */ - return; - /* process Hebrew, not Arabic */ - for (int i = operLocation - 1; i >= 0; i--) { - byte dirProp = getDirProp(i); - if (dirProp == L) - return; - if (dirProp == R) { - for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); - if (dirProp == L) - return; - if (dirProp == R || dirProp == EN) { - insertMark(operLocation); - return; - } - } - return; - } - } + boolean doneAN = false; + boolean ignoreArabic = features.getIgnoreArabic(); + boolean ignoreHebrew = features.getIgnoreHebrew(); + if (ignoreArabic && ignoreHebrew) + return; + byte _R, _AL, _AN; + if (ignoreArabic) { + _AL = Byte.MIN_VALUE; // not a real value + _AN = Byte.MIN_VALUE; } else { - if (features.ignoreHebrew) { /* process Arabic, not Hebrew */ - for (int i = operLocation - 1; i >= 0; i--) { - byte dirProp = getDirProp(i); + _AL = AL; + _AN = AN; + } + if (ignoreHebrew) + _R = Byte.MIN_VALUE; + else + _R = R; + for (int i = operLocation - 1; i >= 0; i--) { + byte dirProp = getDirProp(text, dirProps, i); + if (dirProp == L) + return; + if (dirProp == _R || dirProp == _AL) { + for (int j = operLocation; j < len; j++) { + dirProp = getDirProp(text, dirProps, j); if (dirProp == L) return; - if (dirProp == AL) { - for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); - if (dirProp == L) - return; - if (dirProp == EN || dirProp == AL || dirProp == AN) { - insertMark(operLocation); - return; - } - } + if (dirProp == _R || dirProp == EN || dirProp == _AL || dirProp == _AN) { + insertMark(text, dirProps, offsets, operLocation); return; } - if (dirProp == AN && !doneAN) { - for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); - if (dirProp == L) - return; - if (dirProp == AL || dirProp == AN) { - insertMark(operLocation); - return; - } - } - doneAN = true; - } } - } else { /* process Arabic and Hebrew */ - for (int i = operLocation - 1; i >= 0; i--) { - byte dirProp = getDirProp(i); + return; + } + if (dirProp == _AN && !doneAN) { + for (int j = operLocation; j < len; j++) { + dirProp = getDirProp(text, dirProps, j); if (dirProp == L) return; - if (dirProp == R || dirProp == AL) { - for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); - if (dirProp == L) - return; - if (dirProp == R || dirProp == EN || dirProp == AL || dirProp == AN) { - insertMark(operLocation); - return; - } - } + if (dirProp == _AL || dirProp == _AN || dirProp == _R) { + insertMark(text, dirProps, offsets, operLocation); return; } - if (dirProp == AN && !doneAN) { - for (int j = operLocation; j < len; j++) { - dirProp = getDirProp(j); - if (dirProp == L) - return; - if (dirProp == AL || dirProp == AN || dirProp == R) { - insertMark(operLocation); - return; - } - } - doneAN = true; - } } + doneAN = true; } } } + static final int TEXT = 0; // full text with marks, prefix and suffix + static final int TEXT_NOFIX = 1; // full text with marks, no prefix or suffix + static final int OFFSETS = 3; // offsets to marks + static final int MAP = 4; // source to dest map + /** - * @see BidiComplexHelper#getFinalState() + * @see BidiComplexEngine#leanToFullText BidiComplexEngine.leanToFullText */ - public int getFinalState() { - return state; + public static String leanToFullText(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (text.length() == 0) + return text; + return (String) leanToFullCommon(TEXT, processor, features, environment, text, state); } /** - * @see BidiComplexHelper#setFinalState(int newState) + * @see BidiComplexEngine#leanToFullMap BidiComplexEngine.leanToFullMap */ - public void setFinalState(int newState) { - state = newState; + public static int[] leanToFullMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + int len = text.length(); + if (len == 0) + return EMPTY_INT_ARRAY; + int[] offsets = (int[]) leanToFullCommon(MAP, processor, features, environment, text, state); + int[] map = new int[len]; + int count = offsets[0]; // number of used entries + int added = offsets[1]; // prefixLength; + for (int pos = 0, i = OFFSETS_SHIFT; pos < len; pos++) { + if (i < count && pos == offsets[i]) { + added++; + i++; + } + map[pos] = pos + added; + } + return map; } /** - * @see BidiComplexHelper#leanToFullText(String text, int initState) + * @see BidiComplexEngine#leanBidiCharOffsets BidiComplexEngine.leanBidiCharOffsets */ - public String leanToFullText(String text, int initState) { - if (text.length() == 0) { - prefixLength = 0; - count = 0; - return text; - } - leanToFullTextNofix(text, initState); - return addMarks(true); + public static int[] leanBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (text.length() == 0) + return EMPTY_INT_ARRAY; + int[] offsets = (int[]) leanToFullCommon(OFFSETS, processor, features, environment, text, state); + // offsets[0] contains the number of used entries + int count = offsets[0] - OFFSETS_SHIFT; + int[] result = new int[count]; + System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, count); + return result; } - void leanToFullTextNofix(String text, int initState) { - int operCount = features.operators.length(); + static Object leanToFullCommon(int option, Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + IBidiComplexProcessor processor; + if (_processor instanceof java.lang.String) { + processor = BidiComplexStringProcessor.getProcessor((String) _processor); + if (processor == null) + throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$ + } else if (_processor instanceof IBidiComplexProcessor) + processor = (IBidiComplexProcessor) _processor; + else + throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$ + if (environment == null) + environment = BidiComplexEnvironment.DEFAULT; + if (features == null) + features = processor.getFeatures(environment); + if (state == null) { + state = new int[1]; + state[0] = BidiComplexEngine.STATE_INITIAL; + } + int len = text.length(); + // 1 byte for each char in text, + 1 byte = current orientation + byte[] dirProps = new byte[len + 1]; + int orient = getCurOrient(environment, text, dirProps); + dirProps[len] = (byte) orient; + int operCount = features.getOperators().length(); + int direction = getCurDirection(processor, features, environment, text, dirProps); // current position int curPos = 0; - int len = text.length(); - // location of next token to handle - int nextLocation; - // index of next token to handle (if < operCount, this is an operator; otherwise a special case - int idxLocation; - leanText = text; - offsets = new int[20]; - count = 0; - dirProps = new byte[len]; - curOrient = -1; - curDirection = -1; + // offsets of marks to add. Entry 0 is the number of used slots; + // entry 1 is reserved to pass prefixLength. + // entry 2 is reserved to pass direction.. + int[] offsets = new int[20]; + offsets[0] = OFFSETS_SHIFT; + offsets[2] = direction; // initialize locations - int k = locations.length; - for (int i = 0; i < k; i++) { + int[] locations = new int[operCount + features.getSpecialsCount()]; + for (int i = 0, k = locations.length; i < k; i++) { locations[i] = -1; } - state = BidiComplexHelper.STATE_NOTHING_GOING; - if (initState != BidiComplexHelper.STATE_NOTHING_GOING) - curPos = processor.processSpecial(helper, initState, leanText, -1); - + if (state[0] > BidiComplexEngine.STATE_INITIAL) { + offsets = ensureRoomInOffsets(offsets); + int initState = state[0]; + state[0] = BidiComplexEngine.STATE_INITIAL; + curPos = processor.processSpecial(features, text, dirProps, offsets, state, initState, -1); + } while (true) { - long res = computeNextLocation(curPos); + // location of next token to handle + int nextLocation; + // index of next token to handle (if < operCount, this is an operator; otherwise a special case + int idxLocation; + long res = computeNextLocation(processor, features, text, dirProps, offsets, locations, state, curPos); nextLocation = (int) (res & 0x00000000FFFFFFFF); /* low word */ if (nextLocation >= len) break; idxLocation = (int) (res >> 32); /* high word */ if (idxLocation < operCount) { - processOperator(nextLocation); + offsets = ensureRoomInOffsets(offsets); + processOperator(features, text, dirProps, offsets, nextLocation); curPos = nextLocation + 1; } else { - curPos = processor.processSpecial(helper, idxLocation - operCount, leanText, nextLocation); + offsets = ensureRoomInOffsets(offsets); + idxLocation -= (operCount - 1); // because caseNumber starts from 1 + curPos = processor.processSpecial(features, text, dirProps, offsets, state, idxLocation, nextLocation); } } - } - /** - * @see BidiComplexHelper#leanBidiCharOffsets() - */ - public int[] leanBidiCharOffsets() { - int[] result = new int[count]; - System.arraycopy(offsets, 0, result, 0, count); - return result; - } - - /** - * @see BidiComplexHelper#fullBidiCharOffsets() - */ - public int[] fullBidiCharOffsets() { - int lim = count; - if (prefixLength > 0) { - if (prefixLength == 1) - lim++; - else - lim += FIXES_LENGTH; + if (option == OFFSETS) + return offsets; + + boolean addFixes = (option == TEXT) || (option == MAP); + int count = offsets[0] - OFFSETS_SHIFT; + if ((count == 0) && (!addFixes || (orient == BidiComplexEnvironment.ORIENT_IGNORE) || (orient == direction))) { + if (option != MAP) + return text; + offsets[1] = 0; // no prefix + return offsets; + } + int newLen = len + count; + int prefixLength; + boolean contextual = ((environment.getOrientation() & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) != 0); + if (contextual) { + // orient and direction may be affected by added marks, thus recompute them + orient = getCurOrient(environment, text, dirProps); + dirProps[len] = (byte) orient; + direction = getCurDirection(processor, features, environment, text, dirProps); + offsets[2] = direction; + } + if (addFixes && ((orient != direction) || (orient == BidiComplexEnvironment.ORIENT_UNKNOWN))) { + if (contextual) { + prefixLength = 1; + newLen++; /* +1 for a mark char */ + } else { + prefixLength = PREFIX_LENGTH; + newLen += FIXES_LENGTH; + } + } else { + prefixLength = 0; } - int[] fullOffsets = new int[lim]; - for (int i = 0; i < prefixLength; i++) { - fullOffsets[i] = i; + + if (option == MAP) { + offsets[1] = prefixLength; + return offsets; } + + char[] fullChars = new char[newLen]; int added = prefixLength; - for (int i = 0; i < count; i++) { - fullOffsets[prefixLength + i] = offsets[i] + added; - added++; + // add marks at offsets + char curMark = MARKS[direction]; + char curEmbed = EMBEDS[direction]; + for (int i = 0, j = OFFSETS_SHIFT; i < len; i++) { + char c = text.charAt(i); + // offsets[0] contains the number of used entries + if (j < offsets[0] && i == offsets[j]) { + fullChars[i + added] = curMark; + added++; + j++; + } + fullChars[i + added] = c; } - if (prefixLength > 1) { - int len = leanText.length(); - fullOffsets[lim - 2] = len + lim - 2; - fullOffsets[lim - 1] = len + lim - 1; + if (prefixLength > 0) { /* add prefix/suffix ? */ + if (prefixLength == 1) { /* contextual orientation */ + fullChars[0] = curMark; + } else { + // When the orientation is RTL, we need to add EMBED at the + // start of the text and PDF at its end. + // However, because of a bug in Windows' handling of LRE/PDF, + // we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end. + fullChars[0] = curEmbed; + fullChars[1] = curMark; + fullChars[newLen - 1] = PDF; + fullChars[newLen - 2] = curMark; + } } - return fullOffsets; + return new String(fullChars); } /** - * @see BidiComplexHelper#fullToLeanText(String text, int initState) + * @see BidiComplexEngine#fullToLeanText BidiComplexEngine.fullToLeanText */ - public String fullToLeanText(String text, int initState) { + public static String fullToLeanText(Object _processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String text, int[] state) { + if (text.length() == 0) + return text; + IBidiComplexProcessor processor; + if (_processor instanceof java.lang.String) { + processor = BidiComplexStringProcessor.getProcessor((String) _processor); + if (processor == null) + throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$ + } else if (_processor instanceof IBidiComplexProcessor) + processor = (IBidiComplexProcessor) _processor; + else + throw new IllegalArgumentException("Invalid processor argument!"); //$NON-NLS-1$ + if (environment == null) + environment = BidiComplexEnvironment.DEFAULT; + if (features == null) + features = processor.getFeatures(environment); + if (state == null) { + state = new int[1]; + state[0] = BidiComplexEngine.STATE_INITIAL; + } + int dir = getCurDirection(processor, features, environment, text, null); + char curMark = MARKS[dir]; + char curEmbed = EMBEDS[dir]; int i; // used as loop index - setMarkAndFixes(); // remove any prefix and leading mark int lenText = text.length(); for (i = 0; i < lenText; i++) { @@ -510,12 +528,8 @@ if (c != PDF && c != curMark) break; } - if (i < 0) { // only suffix and trailing marks, no real data - leanText = EMPTY_STRING; - prefixLength = 0; - count = 0; - return leanText; - } + if (i < 0) // only suffix and trailing marks, no real data + return EMPTY_STRING; if (i < (lenText - 1)) { // found at least one suffix or trailing mark text = text.substring(0, i + 1); lenText = text.length(); @@ -531,8 +545,7 @@ chars[i - cnt] = c; } String lean = new String(chars, 0, lenText - cnt); - leanToFullTextNofix(lean, initState); - String full = addMarks(false); /* only marks, no prefix/suffix */ + String full = (String) leanToFullCommon(TEXT_NOFIX, processor, features, environment, lean, state); if (full.equals(text)) return lean; @@ -541,13 +554,15 @@ // The completed lean can never be longer than text itself. char[] newChars = new char[lenText]; char cFull, cText; - int idxFull, idxText, idxLean, markPos, newCharsPos; + int idxFull, idxText, idxLean, newCharsPos; int lenFull = full.length(); idxFull = idxText = idxLean = newCharsPos = 0; while (idxText < lenText && idxFull < lenFull) { cFull = full.charAt(idxFull); cText = text.charAt(idxText); if (cFull == cText) { /* chars are equal, proceed */ + if (cFull != curMark) + newChars[newCharsPos++] = chars[idxLean++]; idxText++; idxFull++; continue; @@ -561,72 +576,102 @@ // idxText-2 always >= 0 since leading Marks were removed from text if (text.charAt(idxText - 2) == curMark) continue; // ignore successive Marks in text after the first one - markPos = fullToLeanPos(idxFull); - // copy from chars (== lean) to newChars until here - for (i = idxLean; i < markPos; i++) { - newChars[newCharsPos++] = chars[i]; - } - idxLean = markPos; newChars[newCharsPos++] = curMark; continue; } // we should never get here (extra char which is not a Mark) throw new IllegalStateException("Internal error: extra character not a Mark."); //$NON-NLS-1$ } - if (idxText < lenText) /* full ended before text - this should never happen */ + if (idxText < lenText) /* full ended before text - this should never happen since + we removed all marks and PDFs at the end of text */ throw new IllegalStateException("Internal error: unexpected EOL."); //$NON-NLS-1$ - // copy the last part of chars to newChars - for (i = idxLean; i < lean.length(); i++) { - newChars[newCharsPos++] = chars[i]; - } lean = new String(newChars, 0, newCharsPos); - leanText = lean; return lean; } /** - * @see BidiComplexHelper#leanToFullPos(int pos) + * @see BidiComplexEngine#fullToLeanMap BidiComplexEngine.fullToLeanMap */ - public int leanToFullPos(int pos) { - int added = prefixLength; - for (int i = 0; i < count; i++) { - if (offsets[i] <= pos) - added++; - else - return pos + added; + public static int[] fullToLeanMap(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String full, int[] state) { + int lenFull = full.length(); + if (lenFull == 0) + return EMPTY_INT_ARRAY; + String lean = fullToLeanText(processor, features, environment, full, state); + int lenLean = lean.length(); + int dir = getCurDirection(processor, features, environment, lean, null); + char curMark = MARKS[dir]; + char curEmbed = EMBEDS[dir]; + int[] map = new int[lenFull]; + int idxFull, idxLean; + // skip any prefix and leading mark + for (idxFull = 0; idxFull < lenFull; idxFull++) { + char c = full.charAt(idxFull); + if (c != curEmbed && c != curMark) + break; + map[idxFull] = -1; + } + // lean must be a subset of Full, so we only check on iLean < leanLen + for (idxLean = 0; idxLean < lenLean; idxFull++) { + if (full.charAt(idxFull) == lean.charAt(idxLean)) { + map[idxFull] = idxLean; + idxLean++; + } else + map[idxFull] = -1; } - return pos + added; + for (; idxFull < lenFull; idxFull++) + map[idxFull] = -1; + return map; } /** - * @see BidiComplexHelper#fullToLeanPos(int pos) + * @see BidiComplexEngine#fullBidiCharOffsets BidiComplexEngine.fullBidiCharOffsets */ - public int fullToLeanPos(int pos) { - int len = leanText.length(); - int added = 0; - pos -= prefixLength; - for (int i = 0; i < count; i++) { - if ((offsets[i] + added) < pos) - added++; - else - break; + public static int[] fullBidiCharOffsets(Object processor, BidiComplexFeatures features, BidiComplexEnvironment environment, String full, int[] state) { + int lenFull = full.length(); + if (lenFull == 0) + return EMPTY_INT_ARRAY; + String lean = fullToLeanText(processor, features, environment, full, state); + int[] offsets = new int[20]; + offsets[0] = OFFSETS_SHIFT; + int lenLean = lean.length(); + int idxLean, idxFull; + // lean must be a subset of Full, so we only check on iLean < leanLen + for (idxLean = idxFull = 0; idxLean < lenLean; idxFull++) { + if (full.charAt(idxFull) == lean.charAt(idxLean)) + idxLean++; + else { + offsets = ensureRoomInOffsets(offsets); + insertMark(lean, null, offsets, idxFull); + } + } + for (; idxFull < lenFull; idxFull++) { + offsets = ensureRoomInOffsets(offsets); + insertMark(lean, null, offsets, idxFull); + } + int[] result = new int[offsets[0] - OFFSETS_SHIFT]; + System.arraycopy(offsets, OFFSETS_SHIFT, result, 0, result.length); + return result; + } + + static int[] ensureRoomInOffsets(int[] offsets) { + // make sure + if ((offsets.length - offsets[0]) < 3) { + int[] newOffsets = new int[offsets.length * 2]; + System.arraycopy(offsets, 0, newOffsets, 0, offsets[0]); + return newOffsets; } - pos -= added; - if (pos < 0) - pos = 0; - else if (pos > len) - pos = len; - return pos; + return offsets; } /** - * @see BidiComplexHelper#insertMark(int offset) + * @see BidiComplexProcessor#insertMark BidiComplexProcessor.insertMark */ - public void insertMark(int offset) { + public static void insertMark(String text, byte[] dirProps, int[] offsets, int offset) { + int count = offsets[0];// number of used entries int index = count - 1; // index of greatest member <= offset // look up after which member the new offset should be inserted - while (index >= 0) { + while (index >= OFFSETS_SHIFT) { int wrkOffset = offsets[index]; if (offset > wrkOffset) break; @@ -635,24 +680,16 @@ index--; } index++; // index now points at where to insert - // check if we have an available slot for new member - if (count >= (offsets.length - 1)) { - int[] newOffsets = new int[offsets.length * 2]; - System.arraycopy(offsets, 0, newOffsets, 0, count); - offsets = newOffsets; - } - int length = count - index; // number of members to move up if (length > 0) // shift right all members greater than offset System.arraycopy(offsets, index, offsets, index + 1, length); - offsets[index] = offset; - count++; + offsets[0]++; // number of used entries // if the offset is 0, adding a mark does not change anything - if (offset < 1) + if (dirProps == null || offset < 1) return; - byte dirProp = getDirProp(offset); + byte dirProp = getDirProp(text, dirProps, offset); // if the current char is a strong one or a digit, we change the // dirProp of the previous char to account for the inserted mark. // In the following lines, L, R, AL, AN and EN represent bidi categories @@ -668,94 +705,10 @@ else // if the current char is a neutral, we change its own dirProp index = offset; - setMarkAndFixes(); - setDirProp(index, curStrong); - } - String addMarks(boolean addFixes) { - // add prefix/suffix only if addFixes is true - if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == BidiComplexEnvironment.ORIENT_IGNORE))) { - prefixLength = 0; - return leanText; - } - int len = leanText.length(); - int newLen = len + count; - if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == BidiComplexEnvironment.ORIENT_UNKNOWN))) { - if ((environment.orientation & BidiComplexEnvironment.ORIENT_CONTEXTUAL_LTR) == 0) { - prefixLength = PREFIX_LENGTH; - newLen += FIXES_LENGTH; - } else { /* contextual orientation */ - prefixLength = 1; - newLen++; /* +1 for a mark char */ - } - } else { - prefixLength = 0; - } - char[] fullChars = new char[newLen]; - // add a dummy offset as fence - offsets[count] = len; - int added = prefixLength; - // add marks at offsets - setMarkAndFixes(); - for (int i = 0, j = 0; i < len; i++) { - char c = leanText.charAt(i); - if (i == offsets[j]) { - fullChars[i + added] = curMark; - added++; - j++; - } - fullChars[i + added] = c; - } - if (prefixLength > 0) { /* add prefix/suffix ? */ - if (prefixLength == 1) { /* contextual orientation */ - fullChars[0] = curMark; - } else { - // When the orientation is RTL, we need to add EMBED at the - // start of the text and PDF at its end. - // However, because of a bug in Windows' handling of LRE/PDF, - // we add EMBED_PREFIX at the start and EMBED_SUFFIX at the end. - fullChars[0] = curEmbed; - fullChars[1] = curMark; - fullChars[newLen - 1] = PDF; - fullChars[newLen - 2] = curMark; - } - } - return new String(fullChars); - } - - /** - * @see BidiComplexHelper#getEnvironment() - */ - public BidiComplexEnvironment getEnvironment() { - return environment; - } - - /** - * @see BidiComplexHelper#setEnvironment(BidiComplexEnvironment environment) - */ - public void setEnvironment(BidiComplexEnvironment environment) { - this.environment = environment; - features = processor.updateEnvironment(helper, environment); - specialsCount = features.specialsCount; - if ((features.operators.length() + specialsCount) > locations.length) - locations = new int[features.operators.length() + specialsCount]; - - } - - /** - * @see BidiComplexHelper#getFeatures() - */ - public BidiComplexFeatures getFeatures() { - return features; - } - - /** - * @see BidiComplexHelper#setFeatures(BidiComplexFeatures features) - */ - public void setFeatures(BidiComplexFeatures features) { - if ((features.operators.length() + specialsCount) > locations.length) - locations = new int[features.operators.length() + specialsCount]; - this.features = features; + int dir = offsets[2]; // current expression direction + setDirProp(dirProps, index, STRONGS[dir]); + return; } } Index: src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexSingle.java --- src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java 9 Feb 2011 21:28:55 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/BidiComplexSingle.java 26 Apr 2011 07:01:24 -0000 @@ -10,8 +10,7 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal; -import org.eclipse.equinox.bidi.BidiComplexFeatures; -import org.eclipse.equinox.bidi.BidiComplexHelper; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** @@ -25,7 +24,7 @@ *
      *  part1=part2
      *  
    - * The {@link BidiComplexFeatures#operators operators} + * The {@link BidiComplexFeatures#getOperators operators} * field in the {@link BidiComplexFeatures features} * of this processor should contain exactly one character. * Additional characters will be ignored. @@ -37,17 +36,17 @@ /** * This method locates occurrences of the operator. */ - public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) { - return srcText.indexOf(helper.impl.features.operators.charAt(0), fromIndex); + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { + return text.indexOf(features.getOperators().charAt(0), fromIndex); } /** * This method inserts a mark before the operator if needed and * skips to the end of the source string. */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { - helper.processOperator(operLocation); - return srcText.length(); + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); + return text.length(); } } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexComma.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexComma.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexComma.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexComma.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexComma.java 26 Apr 2011 07:01:24 -0000 @@ -10,14 +10,15 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** - * Processor adapted to processing comma-delimited lists, such as: - *
    - *  part1,part2,part3
    - * 
    + * Processor adapted to processing comma-delimited lists, such as: + *
    + *    part1,part2,part3
    + *  
    */ public class BidiComplexComma extends BidiComplexProcessor { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(",", 0, -1, -1, false, false); //$NON-NLS-1$ @@ -28,7 +29,7 @@ * @return features with one operator (comma), no special cases, * LTR direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexEmail.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexEmail.java 26 Apr 2011 07:01:24 -0000 @@ -10,11 +10,12 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.internal.BidiComplexDelimsEsc; /** - * Processor adapted to processing e-mail addresses. + * Processor adapted to processing e-mail addresses. */ public class BidiComplexEmail extends BidiComplexDelimsEsc { static final int LTR = BidiComplexFeatures.DIR_LTR; @@ -31,8 +32,10 @@ * LTR direction for Hebrew in all cases, * and support for both Arabic and Hebrew. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { - return env.mirrored ? MIRRORED : NOT_MIRRORED; + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { + if (env == null) + env = BidiComplexEnvironment.DEFAULT; + return env.getMirrored() ? MIRRORED : NOT_MIRRORED; } /** Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexFile.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexFile.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexFile.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexFile.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexFile.java 26 Apr 2011 07:01:25 -0000 @@ -10,11 +10,12 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** - * Processor adapted to processing directory and file paths. + * Processor adapted to processing directory and file paths. */ public class BidiComplexFile extends BidiComplexProcessor { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":/\\.", 0, -1, -1, false, false); //$NON-NLS-1$ @@ -25,7 +26,7 @@ * @return features with operators ":/\.", no special cases, * LTR direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexJava.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexJava.java 26 Apr 2011 07:01:25 -0000 @@ -10,7 +10,9 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEngine; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** @@ -20,14 +22,15 @@ *

    * In applications like an editor where parts of the text might be modified * while other parts are not, the user may want to call - * {@link BidiComplexHelper#leanToFullText leanToFullText} + * {@link BidiComplexEngine#leanToFullText leanToFullText} * separately on each line and save the initial state of each line (this is * the final state of the previous line which can be retrieved using - * {@link BidiComplexHelper#getFinalState getFinalState}. If both the content + * the value returned in the first element of the state argument). + * If both the content * of a line and its initial state have not changed, the user can be sure that * the last full text computed for this line has not changed either. * - * @see BidiComplexHelper + * @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText * * @author Matitiahu Allouche */ @@ -43,7 +46,7 @@ * 4 special cases, LTR direction for Arabic and Hebrew, * and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } @@ -56,16 +59,16 @@ *

  • comments starting with slash-slash
  • * */ - public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) { + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { switch (caseNumber) { - case 0 : /* space */ - return srcText.indexOf(' ', fromIndex); - case 1 : /* literal */ - return srcText.indexOf('"', fromIndex); - case 2 : /* slash-aster comment */ - return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$ - case 3 : /* slash-slash comment */ - return srcText.indexOf("//", fromIndex); //$NON-NLS-1$ + case 1 : /* space */ + return text.indexOf(' ', fromIndex); + case 2 : /* literal */ + return text.indexOf('"', fromIndex); + case 3 : /* slash-aster comment */ + return text.indexOf("/*", fromIndex); //$NON-NLS-1$ + case 4 : /* slash-slash comment */ + return text.indexOf("//", fromIndex); //$NON-NLS-1$ } // we should never get here return -1; @@ -80,49 +83,52 @@ *
  • skip until after a line separator
  • * */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { int location, counter, i; - helper.processOperator(operLocation); + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); switch (caseNumber) { - case 0 : /* space */ + case 1 : /* space */ operLocation++; - while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') { - helper.setDirProp(operLocation, WS); + while (operLocation < text.length() && text.charAt(operLocation) == ' ') { + BidiComplexProcessor.setDirProp(dirProps, operLocation, WS); operLocation++; } return operLocation; - case 1 : /* literal */ + case 2 : /* literal */ location = operLocation + 1; while (true) { - location = srcText.indexOf('"', location); + location = text.indexOf('"', location); if (location < 0) - return srcText.length(); - for (counter = 0, i = location - 1; srcText.charAt(i) == '\\'; i--) { + return text.length(); + for (counter = 0, i = location - 1; text.charAt(i) == '\\'; i--) { counter++; } location++; if ((counter & 1) == 0) return location; } - case 2 : /* slash-aster comment */ - if (operLocation < 0) - location = 0; // initial state from previous line - else + case 3 : /* slash-aster comment */ + if (operLocation < 0) { // continuation line + location = 0; + } else location = operLocation + 2; // skip the opening slash-aster - location = srcText.indexOf("*/", location); //$NON-NLS-1$ + location = text.indexOf("*/", location); //$NON-NLS-1$ if (location < 0) { - helper.setFinalState(2); - return srcText.length(); + state[0] = caseNumber; + return text.length(); } + // we need to call processOperator since text may follow the + // end of comment immediately without even a space + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, location); return location + 2; - case 3 : /* slash-slash comment */ - location = srcText.indexOf(lineSep, operLocation + 2); + case 4 : /* slash-slash comment */ + location = text.indexOf(lineSep, operLocation + 2); if (location < 0) - return srcText.length(); + return text.length(); return location + lineSep.length(); } // we should never get here - return srcText.length(); + return text.length(); } } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexMath.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexMath.java 26 Apr 2011 07:01:25 -0000 @@ -10,12 +10,13 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** - * Processor adapted to processing arithmetic expressions with right-to-left - * base direction. + * Processor adapted to processing arithmetic expressions with right-to-left + * base direction. */ public class BidiComplexMath extends BidiComplexProcessor { static final int RTL = BidiComplexFeatures.DIR_RTL; @@ -27,7 +28,7 @@ * @return features with operators "+-/*()=", no special cases, * RTL direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexProperty.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexProperty.java 26 Apr 2011 07:01:25 -0000 @@ -10,15 +10,16 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.internal.BidiComplexSingle; /** - * Processor adapted to processing property file statements. - * It expects the following string format: - *
    - *  name=value
    - * 
    + * Processor adapted to processing property file statements. + * It expects the following string format: + *
    + *    name=value
    + *  
    */ public class BidiComplexProperty extends BidiComplexSingle { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("=", 1, -1, -1, false, false); //$NON-NLS-1$ @@ -29,7 +30,7 @@ * @return features with one operator (equal sign), 1 special case, * LTR direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexRegex.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexRegex.java 26 Apr 2011 07:01:25 -0000 @@ -10,8 +10,9 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; -import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; +import org.eclipse.equinox.bidi.BidiComplexEngine; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.*; /** * BidiComplexRegex is a processor for regular expressions. @@ -19,41 +20,43 @@ *

    * In applications like an editor where parts of the text might be modified * while other parts are not, the user may want to call - * {@link BidiComplexHelper#leanToFullText leanToFullText} + * {@link BidiComplexEngine#leanToFullText leanToFullText} * separately on each line and save the initial state of each line (this is * the final state of the previous line which can be retrieved using - * {@link BidiComplexHelper#getFinalState getFinalState}. If both the content + * the value returned in the first element of the state argument). + * If both the content * of a line and its initial state have not changed, the user can be sure that * the last full text computed for this line has not changed either. * - * @see BidiComplexHelper + * @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText * * @author Matitiahu Allouche */ public class BidiComplexRegex extends BidiComplexProcessor { - static final String[] startStrings = {"(?#", /* 0 *//* comment (?#...) *///$NON-NLS-1$ - "(?<", /* 1 *//* named group (? *///$NON-NLS-1$ - "(?'", /* 2 *//* named group (?'name' *///$NON-NLS-1$ - "(?(<", /* 3 *//* conditional named back reference (?() *///$NON-NLS-1$ - "(?('", /* 4 *//* conditional named back reference (?('name') *///$NON-NLS-1$ - "(?(", /* 5 *//* conditional named back reference (?(name) *///$NON-NLS-1$ - "(?&", /* 6 *//* named parentheses reference (?&name) *///$NON-NLS-1$ - "(?P<", /* 7 *//* named group (?P *///$NON-NLS-1$ - "\\k<", /* 8 *//* named back reference \k *///$NON-NLS-1$ - "\\k'", /* 9 *//* named back reference \k'name' *///$NON-NLS-1$ - "\\k{", /* 10 *//* named back reference \k{name} *///$NON-NLS-1$ - "(?P=", /* 11 *//* named back reference (?P=name) *///$NON-NLS-1$ - "\\g{", /* 12 *//* named back reference \g{name} *///$NON-NLS-1$ - "\\g<", /* 13 *//* subroutine call \g *///$NON-NLS-1$ - "\\g'", /* 14 *//* subroutine call \g'name' *///$NON-NLS-1$ - "(?(R&", /* 15 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$ - "\\Q" /* 16 *//* quoted sequence \Q...\E *///$NON-NLS-1$ + static final String[] startStrings = {"", /* 0 *//* dummy *///$NON-NLS-1$ + "(?#", /* 1 *//* comment (?#...) *///$NON-NLS-1$ + "(?<", /* 2 *//* named group (? *///$NON-NLS-1$ + "(?'", /* 3 *//* named group (?'name' *///$NON-NLS-1$ + "(?(<", /* 4 *//* conditional named back reference (?() *///$NON-NLS-1$ + "(?('", /* 5 *//* conditional named back reference (?('name') *///$NON-NLS-1$ + "(?(", /* 6 *//* conditional named back reference (?(name) *///$NON-NLS-1$ + "(?&", /* 7 *//* named parentheses reference (?&name) *///$NON-NLS-1$ + "(?P<", /* 8 *//* named group (?P *///$NON-NLS-1$ + "\\k<", /* 9 *//* named back reference \k *///$NON-NLS-1$ + "\\k'", /* 10 *//* named back reference \k'name' *///$NON-NLS-1$ + "\\k{", /* 11 *//* named back reference \k{name} *///$NON-NLS-1$ + "(?P=", /* 12 *//* named back reference (?P=name) *///$NON-NLS-1$ + "\\g{", /* 13 *//* named back reference \g{name} *///$NON-NLS-1$ + "\\g<", /* 14 *//* subroutine call \g *///$NON-NLS-1$ + "\\g'", /* 15 *//* subroutine call \g'name' *///$NON-NLS-1$ + "(?(R&", /* 16 *//* named back reference recursion (?(R&name) *///$NON-NLS-1$ + "\\Q" /* 17 *//* quoted sequence \Q...\E *///$NON-NLS-1$ }; static final char[] endChars = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - ')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'}; - static final int numberOfStrings = startStrings.length; - static final int maxSpecial = numberOfStrings + 1; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + '.', ')', '>', '\'', ')', ')', ')', ')', '>', '>', '\'', '}', ')', '}', '>', '\'', ')'}; + static final int numberOfStrings = startStrings.length; /* 18 */ + static final int maxSpecial = numberOfStrings; static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(null, maxSpecial, -1, -1, false, false); static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; @@ -64,11 +67,13 @@ /** * This method retrieves the features specific to this processor. * + * @see IBidiComplexProcessor#getFeatures + * * @return features with no operators , special cases for each kind of * regular expression syntactic string, * LTR direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } @@ -76,7 +81,7 @@ * This method locates occurrences of the syntactic strings and of * R, AL, EN, AN characters. */ - public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) { + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { // In this method, L, R, AL, AN and EN represent bidi categories // as defined in the Unicode Bidirectional Algorithm // ( http://www.unicode.org/reports/tr9/ ). @@ -88,42 +93,42 @@ byte dirProp; if (caseNumber < numberOfStrings) { - /* 0 *//* comment (?#...) */ - /* 1 *//* named group (? */ - /* 2 *//* named group (?'name' */ - /* 3 *//* conditional named back reference (?(name) */ - /* 4 *//* conditional named back reference (?() */ - /* 5 *//* conditional named back reference (?('name') */ - /* 6 *//* named parentheses reference (?&name) */ - /* 7 *//* named group (?P */ - /* 8 *//* named back reference \k */ - /* 9 *//* named back reference \k'name' */ - /* 10 *//* named back reference \k{name} */ - /* 11 *//* named back reference (?P=name) */ - /* 12 *//* named back reference \g{name} */ - /* 13 *//* subroutine call \g */ - /* 14 *//* subroutine call \g'name' */ - /* 15 *//* named back reference recursion (?(R&name) */ - /* 16 *//* quoted sequence \Q...\E */ - return srcText.indexOf(startStrings[caseNumber], fromIndex); + /* 1 *//* comment (?#...) */ + /* 2 *//* named group (? */ + /* 3 *//* named group (?'name' */ + /* 4 *//* conditional named back reference (?(name) */ + /* 5 *//* conditional named back reference (?() */ + /* 6 *//* conditional named back reference (?('name') */ + /* 7 *//* named parentheses reference (?&name) */ + /* 8 *//* named group (?P */ + /* 9 *//* named back reference \k */ + /* 10 *//* named back reference \k'name' */ + /* 11 *//* named back reference \k{name} */ + /* 12 *//* named back reference (?P=name) */ + /* 13 *//* named back reference \g{name} */ + /* 14 *//* subroutine call \g */ + /* 15 *//* subroutine call \g'name' */ + /* 16 *//* named back reference recursion (?(R&name) */ + /* 17 *//* quoted sequence \Q...\E */ + return text.indexOf(startStrings[caseNumber], fromIndex); } // there never is a need for a mark before the first char if (fromIndex <= 0) fromIndex = 1; // look for R, AL, AN, EN which are potentially needing a mark - for (; fromIndex < srcText.length(); fromIndex++) { - dirProp = helper.getDirProp(fromIndex); + for (; fromIndex < text.length(); fromIndex++) { + dirProp = BidiComplexProcessor.getDirProp(text, dirProps, fromIndex); // R and AL will always be examined using processOperator() if (dirProp == R || dirProp == AL) return fromIndex; if (dirProp == EN || dirProp == AN) { // no need for a mark after the first digit in a number - if (helper.getDirProp(fromIndex - 1) == dirProp) + if (BidiComplexProcessor.getDirProp(text, dirProps, fromIndex - 1) == dirProp) continue; for (int i = fromIndex - 1; i >= 0; i--) { - dirProp = helper.getDirProp(i); + dirProp = BidiComplexProcessor.getDirProp(text, dirProps, i); // after a L char, no need for a mark if (dirProp == L) continue; @@ -144,73 +149,73 @@ /** * This method process the special cases. */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { int location; switch (caseNumber) { - case 0 : /* comment (?#...) */ + case 1 : /* comment (?#...) */ if (operLocation < 0) { // initial state from previous line location = 0; } else { - helper.processOperator(operLocation); + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); // skip the opening "(?#" location = operLocation + 3; } - location = srcText.indexOf(')', location); + location = text.indexOf(')', location); if (location < 0) { - helper.setFinalState(caseNumber); - return srcText.length(); + state[0] = caseNumber; + return text.length(); } return location + 1; - case 1 : /* named group (? */ - case 2 : /* named group (?'name' */ - case 3 : /* conditional named back reference (?(name) */ - case 4 : /* conditional named back reference (?() */ - case 5 : /* conditional named back reference (?('name') */ - case 6 : /* named parentheses reference (?&name) */ - helper.processOperator(operLocation); + case 2 : /* named group (? */ + case 3 : /* named group (?'name' */ + case 4 : /* conditional named back reference (?(name) */ + case 5 : /* conditional named back reference (?() */ + case 6 : /* conditional named back reference (?('name') */ + case 7 : /* named parentheses reference (?&name) */ + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); // no need for calling processOperator() for the following cases // since the starting string contains a L char - case 7 : /* named group (?P */ - case 8 : /* named back reference \k */ - case 9 : /* named back reference \k'name' */ - case 10 : /* named back reference \k{name} */ - case 11 : /* named back reference (?P=name) */ - case 12 : /* named back reference \g{name} */ - case 13 : /* subroutine call \g */ - case 14 : /* subroutine call \g'name' */ - case 15 : /* named back reference recursion (?(R&name) */ + case 8 : /* named group (?P */ + case 9 : /* named back reference \k */ + case 10 : /* named back reference \k'name' */ + case 11 : /* named back reference \k{name} */ + case 12 : /* named back reference (?P=name) */ + case 13 : /* named back reference \g{name} */ + case 14 : /* subroutine call \g */ + case 15 : /* subroutine call \g'name' */ + case 16 : /* named back reference recursion (?(R&name) */ // skip the opening string location = operLocation + startStrings[caseNumber].length(); // look for ending character - location = srcText.indexOf(endChars[caseNumber], location); + location = text.indexOf(endChars[caseNumber], location); if (location < 0) - return srcText.length(); + return text.length(); return location + 1; - case 16 : /* quoted sequence \Q...\E */ + case 17 : /* quoted sequence \Q...\E */ if (operLocation < 0) { // initial state from previous line location = 0; } else { - helper.processOperator(operLocation); + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); // skip the opening "\Q" location = operLocation + 2; } - location = srcText.indexOf("\\E", location); //$NON-NLS-1$ + location = text.indexOf("\\E", location); //$NON-NLS-1$ if (location < 0) { - helper.setFinalState(caseNumber); - return srcText.length(); + state[0] = caseNumber; + return text.length(); } // set the dirProp for the "E" to L (Left to Right character) - helper.setDirProp(location + 1, L); + BidiComplexProcessor.setDirProp(dirProps, location + 1, L); return location + 2; - case 17 : /* R, AL, AN, EN */ - helper.processOperator(operLocation); + case 18 : /* R, AL, AN, EN */ + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); return operLocation + 1; } // we should never get here - return srcText.length(); + return text.length(); } } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexSql.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSql.java 26 Apr 2011 07:01:25 -0000 @@ -10,7 +10,9 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEngine; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** @@ -20,14 +22,15 @@ *

    * In applications like an editor where parts of the text might be modified * while other parts are not, the user may want to call - * {@link BidiComplexHelper#leanToFullText leanToFullText} + * {@link BidiComplexEngine#leanToFullText leanToFullText} * separately on each line and save the initial state of each line (this is - * the final state of the previous line which can be retrieved using - * {@link BidiComplexHelper#getFinalState getFinalState}. If both the content + * the final state of the previous line which can be retrieved from the + * value returned in the first element of the state argument). + * If both the content * of a line and its initial state have not changed, the user can be sure that * the last full text computed for this line has not changed either. * - * @see BidiComplexHelper + * @see BidiComplexEngine#leanToFullText explanation of state in leanToFullText * * @author Matitiahu Allouche */ @@ -43,7 +46,7 @@ * @return features with operators "\t!#%&()*+,-./:;<=>?|[]{}", 5 special cases, * LTR direction for Arabic and Hebrew, and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } @@ -57,18 +60,18 @@ *

  • comments starting with hyphen-hyphen
  • * */ - public int indexOfSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int fromIndex) { + public int indexOfSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int caseNumber, int fromIndex) { switch (caseNumber) { - case 0 : /* space */ - return srcText.indexOf(" ", fromIndex); //$NON-NLS-1$ - case 1 : /* literal */ - return srcText.indexOf('\'', fromIndex); - case 2 : /* delimited identifier */ - return srcText.indexOf('"', fromIndex); - case 3 : /* slash-aster comment */ - return srcText.indexOf("/*", fromIndex); //$NON-NLS-1$ - case 4 : /* hyphen-hyphen comment */ - return srcText.indexOf("--", fromIndex); //$NON-NLS-1$ + case 1 : /* space */ + return text.indexOf(" ", fromIndex); //$NON-NLS-1$ + case 2 : /* literal */ + return text.indexOf('\'', fromIndex); + case 3 : /* delimited identifier */ + return text.indexOf('"', fromIndex); + case 4 : /* slash-aster comment */ + return text.indexOf("/*", fromIndex); //$NON-NLS-1$ + case 5 : /* hyphen-hyphen comment */ + return text.indexOf("--", fromIndex); //$NON-NLS-1$ } // we should never get here return -1; @@ -84,66 +87,66 @@ *
  • skip until after a line separator
  • * */ - public int processSpecial(BidiComplexHelper helper, int caseNumber, String srcText, int operLocation) { + public int processSpecial(BidiComplexFeatures features, String text, byte[] dirProps, int[] offsets, int[] state, int caseNumber, int operLocation) { int location; - helper.processOperator(operLocation); + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, operLocation); switch (caseNumber) { - case 0 : /* space */ + case 1 : /* space */ operLocation++; - while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') { - helper.setDirProp(operLocation, WS); + while (operLocation < text.length() && text.charAt(operLocation) == ' ') { + BidiComplexProcessor.setDirProp(dirProps, operLocation, WS); operLocation++; } return operLocation; - case 1 : /* literal */ + case 2 : /* literal */ location = operLocation + 1; while (true) { - location = srcText.indexOf('\'', location); + location = text.indexOf('\'', location); if (location < 0) { - helper.setFinalState(caseNumber); - return srcText.length(); + state[0] = caseNumber; + return text.length(); } - if ((location + 1) < srcText.length() && srcText.charAt(location + 1) == '\'') { + if ((location + 1) < text.length() && text.charAt(location + 1) == '\'') { location += 2; continue; } return location + 1; } - case 2 : /* delimited identifier */ + case 3 : /* delimited identifier */ location = operLocation + 1; while (true) { - location = srcText.indexOf('"', location); + location = text.indexOf('"', location); if (location < 0) - return srcText.length(); + return text.length(); - if ((location + 1) < srcText.length() && srcText.charAt(location + 1) == '"') { + if ((location + 1) < text.length() && text.charAt(location + 1) == '"') { location += 2; continue; } return location + 1; } - case 3 : /* slash-aster comment */ - if (operLocation < 0) - location = 0; // initial state from previous line + case 4 : /* slash-aster comment */ + if (operLocation < 0) // continuation line + location = 0; else location = operLocation + 2; // skip the opening slash-aster - location = srcText.indexOf("*/", location); //$NON-NLS-1$ + location = text.indexOf("*/", location); //$NON-NLS-1$ if (location < 0) { - helper.setFinalState(caseNumber); - return srcText.length(); + state[0] = caseNumber; + return text.length(); } // we need to call processOperator since text may follow the // end of comment immediately without even a space - helper.processOperator(location); + BidiComplexProcessor.processOperator(features, text, dirProps, offsets, location); return location + 2; - case 4 : /* hyphen-hyphen comment */ - location = srcText.indexOf(lineSep, operLocation + 2); + case 5 : /* hyphen-hyphen comment */ + location = text.indexOf(lineSep, operLocation + 2); if (location < 0) - return srcText.length(); + return text.length(); return location + lineSep.length(); } // we should never get here - return srcText.length(); + return text.length(); } } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexSystem.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexSystem.java 26 Apr 2011 07:01:25 -0000 @@ -10,14 +10,15 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.internal.BidiComplexSingle; /** - * Processor adapted to processing expressions with the following string format: - *
    - *  system(user)
    - * 
    + * Processor adapted to processing expressions with the following string format: + *
    + *    system(user)
    + *  
    */ public class BidiComplexSystem extends BidiComplexSingle { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("(", 0, -1, -1, false, false); //$NON-NLS-1$ @@ -29,7 +30,7 @@ * no special cases, LTR direction for Arabic and Hebrew, * and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexURL.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexURL.java 26 Apr 2011 07:01:25 -0000 @@ -10,11 +10,12 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** - * Processor adapted to processing URLs. + * Processor adapted to processing URLs. */ public class BidiComplexURL extends BidiComplexProcessor { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(":?#/@.[]", 0, -1, -1, false, false); //$NON-NLS-1$ @@ -26,7 +27,7 @@ * no special cases, LTR direction for Arabic and Hebrew, * and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexUnderscore.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexUnderscore.java 26 Apr 2011 07:01:25 -0000 @@ -10,15 +10,16 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.custom.BidiComplexProcessor; /** - * Processor adapted to processing compound names. - * This type covers names made of one or more parts, separated by underscores: - *
    - *  part1_part2_part3
    - * 
    + * Processor adapted to processing compound names. + * This type covers names made of one or more parts, separated by underscores: + *
    + *    part1_part2_part3
    + *  
    */ public class BidiComplexUnderscore extends BidiComplexProcessor { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures("_", 0, -1, -1, false, false); //$NON-NLS-1$ @@ -30,7 +31,7 @@ * no special cases, LTR direction for Arabic and Hebrew, * and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } Index: src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java,v retrieving revision 1.1 diff -u -r1.1 BidiComplexXPath.java --- src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/internal/consumable/BidiComplexXPath.java 26 Apr 2011 07:01:25 -0000 @@ -10,11 +10,12 @@ ******************************************************************************/ package org.eclipse.equinox.bidi.internal.consumable; -import org.eclipse.equinox.bidi.*; +import org.eclipse.equinox.bidi.BidiComplexEnvironment; +import org.eclipse.equinox.bidi.custom.BidiComplexFeatures; import org.eclipse.equinox.bidi.internal.BidiComplexDelims; /** - * Processor adapted to processing XPath expressions. + * Processor adapted to processing XPath expressions. */ public class BidiComplexXPath extends BidiComplexDelims { static final BidiComplexFeatures FEATURES = new BidiComplexFeatures(" /[]<>=!:@.|()+-*", 2, -1, -1, false, false); //$NON-NLS-1$ @@ -26,12 +27,12 @@ * 2 special cases, LTR direction for Arabic and Hebrew, * and support for both. */ - public BidiComplexFeatures init(BidiComplexHelper helper, BidiComplexEnvironment env) { + public BidiComplexFeatures getFeatures(BidiComplexEnvironment env) { return FEATURES; } /** - * @return parentheses apostrophe and quotation mark as delimiters. + * @return apostrophe and quotation mark as delimiters. */ protected String getDelimiters() { return "''\"\""; //$NON-NLS-1$ Index: src/org/eclipse/equinox/bidi/package.html =================================================================== RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/package.html,v retrieving revision 1.1 diff -u -r1.1 package.html --- src/org/eclipse/equinox/bidi/package.html 9 Feb 2011 21:28:54 -0000 1.1 +++ src/org/eclipse/equinox/bidi/package.html 26 Apr 2011 07:01:24 -0000 @@ -15,31 +15,32 @@ For plain text, the Unicode Bidirectional Algorithm (UBA) generally specifies satisfactorily how to reorder bidirectional text for -display. This algorithm is implemented in Java's presentation system.

    -

    +display. This algorithm is implemented in Java's presentation system. +

    However, all bidirectional text is not necessarily plain text. There are also instances of text structured to follow a given syntax, which should be reflected in the display order. The general algorithm, which has no awareness of these special cases, often gives incorrect results -when displaying such structured text.

    -

    +when displaying such structured text. +

    The general idea in handling complex expressions is to add directional formatting characters at proper locations in the text to supplement the standard algorithm, so that the final result is correctly displayed using the UBA. +

    A class which handles complex expressions is thus essentially a transformation engine which receives text without directional formatting characters as input and produces as output the same text with added directional formatting characters, hopefully in the minimum quantity which is sufficient to ensure correct display, considering the type of -complex expression involved.

    -

    +complex expression involved. +

    In this package, text without directional formatting characters is called lean text while the text with added directional -formatting characters is called full text.

    -

    +formatting characters is called full text. +

    The class {@link -BidiComplexHelper} +BidiComplexEngine} is the main tool for processing complex expressions. It facilitates handling several types of complex expressions, each type being handled by a specific @@ -61,13 +62,10 @@

    Other classes and one interface in this package may be used to complement and facilitate the action of -{@link BidiComplexHelper}: +{@link BidiComplexEngine}:

    -{@link BidiComplexHelper} and the +{@link BidiComplexEngine} and the other classes and interface mentioned above are intended for users who need to process complex expressions for which there already exist processors. @@ -97,8 +95,11 @@

  • {@link BidiComplexProcessor} is a generic processor which can be used as superclass for specific processors.
  • +
  • {@link BidiComplexFeatures} + allows managing some factors which affect + a complex expression processor's behavior.
  • {@link BidiComplexStringProcessor} - is a class which allows retrieval of the defined processor types and of the + allows retrieval of the defined processor types and of the corresponding processors.