### Eclipse Workspace Patch 1.0 #P org.eclipse.equinox.bidi Index: src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java --- src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java 3 Feb 2010 20:00:59 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 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.complexp; - -import org.eclipse.equinox.bidi.internal.complexp.BiDiTypesCollector; - -/** - * @noinstantiate This class is not intended to be instantiated by clients. - */ -// TBD do we really want to provide individual instances of the text processors? -final public class ComplExpFactory implements IBiDiProcessor { - - /** - * Factory method to create a new instance of the bi-directional text - * processor for the specified text type. This method may return null - * if it is unable to locate processor for the specified text type. - * - * @see #PROPERTY - * @see #UNDERSCORE - * @see #COMMA_DELIMITED - * @see #SYSTEM_USER - * @see #FILE - * @see #EMAIL - * @see #URL - * @see #REGEXP - * @see #XPATH - * @see #JAVA - * @see #SQL - * @see #RTL_ARITHMETIC - * - * @param type specifies the type of complex expression to process. - * @return a IComplExpProcessor instance capable of handling - * the type of complex expression specified. May return null - * if the processor not found. - */ - public static IComplExpProcessor create(String type) { - return BiDiTypesCollector.getInstance().makeProcessor(type); - } - -} Index: src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java --- src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java 12 Apr 2010 18:51:17 -0000 1.4 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,369 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010 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.complexp; - -import java.util.Locale; -import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; - -/** - * This class provides a number of convenience functions facilitating the - * processing of complex expressions. - * - * @noextend This class is not intended to be subclassed by clients. - * @noinstantiate This class is not intended to be instantiated by clients. - * - * @author Matitiahu Allouche - */ -final public class ComplExpUtil { - - /** - * Flag specifying that all complex expressions should by default assume - * that the GUI is mirrored (globally going from right to left). - * The default can be overridden for specific instances of complex - * expressions. - * @see #assumeMirroredDefault - * @see #isMirroredDefault - */ - static boolean mirroredDefault; - - /** - * prevents instantiation - */ - private ComplExpUtil() { - // empty - } - - /** Specify whether the GUI where the complex expression will be displayed - * is mirrored (is laid out from right to left). The value specified in - * this method sets a default for all complex expressions to be created - * from now on. If no value has been specified ever, the GUI - * is assumed not to be mirrored. - * - * @param mirrored must be specified as false if the GUI - * is not mirrored, as true if it is. - * - * @see #isMirroredDefault - * @see IComplExpProcessor#assumeMirrored - */ - public static void assumeMirroredDefault(boolean mirrored) { - mirroredDefault = mirrored; - } - - /** Retrieve the value currently assumed as default for GUI mirroring. - * - * @return the current value assumed by default for GUI mirroring. - * - * @see #assumeMirroredDefault - */ - public static boolean isMirroredDefault() { - return mirroredDefault; - } - - /** This is a convenience method which can add directional marks in a given - * 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 IComplExpProcessor#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 - * RLMs for expressions with RTL base direction. Leading and - * trailing LRE, RLE and PDF which might be needed as prefix or suffix - * depending on the orientation of the GUI component used for display - * may be added depending on argument affix. - * - * @param text is the text of the complex expression. - * - * @param offsets is an array of offsets to characters in text - * before which an LRM or RLM will be inserted. - * Members of the array must be non-negative numbers smaller - * than the length of text. - * The array must be sorted in ascending order without duplicates. - * This argument may be null if there are no marks to add. - * - * @param direction specifies the base direction of the complex expression. - * It must be one of the values {@link IComplExpProcessor#DIRECTION_LTR} or - * {@link IComplExpProcessor#DIRECTION_RTL}. - * - * @param affix specifies if a prefix and a suffix should be added to - * the result to make sure that the direction - * specified as second argument is honored even if the expression - * is displayed in a GUI component with a different orientation. - * - * @return a string corresponding to the source text with - * directional marks (LRMs or RLMs) added at the specified offsets, - * and directional formatting characters (LRE, RLE, PDF) added - * as prefix and suffix if so required. - * - */ - public static String insertMarks(String text, int[] offsets, int direction, boolean affix) { - int textLen = text.length(); - if (textLen == 0) - return ""; //$NON-NLS-1$ - - String curPrefix, curSuffix, full; - char curMark, c; - char[] fullChars; - if (direction == IComplExpProcessor.DIRECTION_LTR) { - curMark = LRM; - curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$ - curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$ - } else { - curMark = RLM; - curPrefix = "\u202b\u200f"; /* RLE+RLM *///$NON-NLS-1$ - curSuffix = "\u200f\u202c"; /* RLM+PDF *///$NON-NLS-1$ - } - // add marks at offsets - if ((offsets != null) && (offsets.length > 0)) { - int offLen = offsets.length; - fullChars = new char[textLen + offLen]; - int added = 0; - for (int i = 0, j = 0; i < textLen; i++) { - c = text.charAt(i); - if ((j < offLen) && (i == offsets[j])) { - fullChars[i + added] = curMark; - added++; - j++; - } - fullChars[i + added] = c; - } - full = new String(fullChars); - } else { - full = text; - } - if (affix) - return curPrefix + full + curSuffix; - return full; - } - - /*************************************************************************/ - /* */ - /* The following code is provided for compatibility with TextProcessor */ - /* */ - /*************************************************************************/ - - // The default set of delimiters to use to segment a string. - private static final String defaultDelimiters = ".:/\\"; //$NON-NLS-1$ - // left to right mark - private static final char LRM = '\u200e'; - // left to right mark - private static final char RLM = '\u200f'; - // left to right embedding - private static final char LRE = '\u202a'; - // right to left embedding - private static final char RLE = '\u202b'; - // pop directional format - private static final char PDF = '\u202c'; - // TBD use bundle properties - private static String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ private static String - private static boolean flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$ - private static String lastLanguage; - private static boolean lastGoodLang; - - static boolean isProcessingNeeded() { - if (!flagOS) - return false; - // TBD use OSGi service - String lang = Locale.getDefault().getLanguage(); - if (lang.equals(lastLanguage)) - return lastGoodLang; - lastLanguage = lang; - lastGoodLang = "iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - return lastGoodLang; - } - - /** - * Process the given text and return a string with appropriate - * directional formatting characters if the locale is a Bidi locale. - * This is equivalent to calling - * {@link #process(String, String)} with the default set of - * delimiters (dot, colon, slash, backslash). - * - * @param str the text to be processed - * - * @return the processed string - * - */ - public static String process(String str) { - return process(str, defaultDelimiters); - } - - /** - * Process a string that has a particular semantic meaning to render - * it correctly on Bidi locales. This is done by adding directional - * formatting characters so that presentation using the Unicode Bidi - * Algorithm will provide the expected result. - * The text is segmented according to the provided delimiters. - * Each segment has the Unicode Bidi Algorithm applied to it, - * but as a whole, the string is oriented left to right. - *

- * For example, a file path such as d:\myfolder\FOLDER\MYFILE.java - * (where capital letters indicate RTL text) should render as - * d:\myfolder\REDLOF\ELIFYM.java.

- *

- * NOTE: this method inserts directional formatting characters into the - * text. Methods like String.equals(String) and - * String.length() called on the resulting string will not - * return the same values as would be returned for the original string.

- * - * @param str the text to process. If null, return - * the string itself - * - * @param delimiters delimiters by which the string will be segmented. - * If null, the default delimiters are used - * (dot, colon, slash, backslash). - * - * @return the processed string - */ - public static String process(String str, String delimiters) { - if ((str == null) || (str.length() <= 1) || !isProcessingNeeded()) - return str; - - // do not process a string that has already been processed. - if (str.charAt(0) == LRE && str.charAt(str.length() - 1) == PDF) - return str; - - // do not process a string if all the following conditions are true: - // a) it has no RTL characters - // b) it starts with a LTR character - // c) it ends with a LTR character or a digit - boolean isStringBidi = false; - int strLength = str.length(); - char c; - for (int i = 0; i < strLength; i++) { - c = str.charAt(i); - if (((c >= 0x05d0) && (c <= 0x07b1)) || ((c >= 0xfb1d) && (c <= 0xfefc))) { - isStringBidi = true; - break; - } - } - while (!isStringBidi) { - if (!Character.isLetter(str.charAt(0))) - break; - c = str.charAt(strLength - 1); - if (!Character.isDigit(c) && !Character.isLetter(c)) - break; - return str; - } - - if (delimiters == null) - delimiters = defaultDelimiters; - - IComplExpProcessor processor = new ComplExpBasic(delimiters); - // make sure that LRE/PDF are added around the string - processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN); - return processor.leanToFullText(str); - } - - /** - * Process a string that has a particular semantic meaning to render - * it correctly on Bidi locales. This is done by adding directional - * formatting characters so that presentation using the Unicode Bidi - * Algorithm will provide the expected result.. - * The text is segmented according to the syntax specified in the - * type argument. - * Each segment has the Unicode Bidi Algorithm applied to it, but the - * order of the segments is governed by the type of the complex expression. - *

- * For example, a file path such as d:\myfolder\FOLDER\MYFILE.java - * (where capital letters indicate RTL text) should render as - * d:\myfolder\REDLOF\ELIFYM.java.

- *

- * NOTE: this method inserts directional formatting characters into the - * text. Methods like String.equals(String) and - * String.length() called on the resulting string will not - * return the same values as would be returned for the original string.

- * - * @param str the text to process. If null, return - * the string itself - * - * @param type specifies the type of the complex expression. It must - * be one of the values allowed as argument for method - * {@link ComplExpFactory#create}. - * - * @return the processed string - */ - public static String processTyped(String str, String type) { - if ((str == null) || (str.length() <= 1) || !isProcessingNeeded()) - return str; - - // do not process a string that has already been processed. - char c = str.charAt(0); - if (((c == LRE) || (c == RLE)) && str.charAt(str.length() - 1) == PDF) - return str; - - IComplExpProcessor processor = ComplExpFactory.create(type); - if (processor == null) // invalid type - return str; - - // make sure that LRE/PDF are added around the string - processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN); - return processor.leanToFullText(str); - } - - /** - * Removes directional marker characters in the given string that were inserted - * by the {@link #process(String)} or {@link #process(String, String)} - * methods. - * - * @param str string with directional markers to remove - * - * @return string with no directional formatting characters - * - */ - public static String deprocess(String str) { - if ((str == null) || (str.length() <= 1) || !isProcessingNeeded()) - return str; - - StringBuffer buf = new StringBuffer(); - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - char c = str.charAt(i); - switch (c) { - case LRM : - continue; - case LRE : - continue; - case PDF : - continue; - default : - buf.append(c); - } - } - return buf.toString(); - } - - /** - * Removes directional marker characters in the given string that were inserted - * by the {@link #process(String, String)} method. - * - * @param str string with directional markers to remove - * - * @param type type of the complex expression as specified when - * calling process(String str, int type) - * - * @return string with no directional formatting characters - * - */ - public static String deprocess(String str, String type) { - if ((str == null) || (str.length() <= 1) || !isProcessingNeeded()) - return str; - - IComplExpProcessor processor = ComplExpFactory.create(type); - if (processor == null) // invalid type - return str; - - // make sure that LRE/PDF are added around the string - processor.assumeOrientation(IComplExpProcessor.ORIENT_UNKNOWN); - return processor.fullToLeanText(str); - } - -} Index: src/org/eclipse/equinox/bidi/complexp/CxpEnv.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/CxpEnv.java diff -N src/org/eclipse/equinox/bidi/complexp/CxpEnv.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/complexp/CxpEnv.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,301 @@ +/******************************************************************************* + * Copyright (c) 2010 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.complexp; + +import java.util.Locale; + +/** + * This class defines certain details of the environment within which + * complex expressions are processed. + *

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

+ * A CxpEnv instance can be associated with a CxpHelper + * instance either when creating the + * {@link CxpHelper#CxpHelper(java.lang.String, CxpEnv) CxpHelper} instance + * or using the {@link CxpHelper#setEnvironment setEnvironment} method. + * + *

Code Samples

+ *

Example 1 (set all environment parameters) + *

+ *
+ *    CxpEnv myEnv = new CxpEnv("he_IL", true, CxpEnv.ORIENT_RTL);
+ *    CxpHelper myHelper = new CxpHelper(IProcessorTypes.FILE, myEnv);
+ *
+ *  
+ *

Example 2 (change only the orientation) + *

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

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

 

+ * @see CxpHelper#CxpHelper(String, CxpEnv) + * @see CxpHelper#CxpHelper(ICxpProcessor, CxpEnv) + * @see CxpHelper#getEnvironment CxpHelper.getEnvironment + * @see CxpHelper#setEnvironment CxpHelper.setEnvironment + * @see ICxpProcessor#init ICxpProcessor.init + * @see ICxpProcessor#init2 ICxpProcessor.init2 + * + * @author Matitiahu Allouche + */ +public class CxpEnv { + + /** + * 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 CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + 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 CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + public static final int ORIENT_RTL = 1; + + /** + * 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 CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + public static final int ORIENT_CONTEXTUAL_LTR = 2; + + /** + * 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 CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + public static final int ORIENT_CONTEXTUAL_RTL = 3; + + /** + * Constant specifying that the orientation of the GUI component + * 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 CxpHelper#leanToFullText leanToFullText}. + * It can appear as orientation argument for + * {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + public static final int ORIENT_UNKNOWN = 4; + + /** + * Constant specifying that whatever the orientation of the + * 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 CxpHelper#leanToFullText leanToFullText}. + * It can appear as orientation argument for + * {@link CxpEnv#CxpEnv CxpEnv constructor} and as value for the + * {@link CxpEnv#orientation} member of CxpEnv. + */ + public static final int ORIENT_IGNORE = 5; + + /** + * Pre-defined CxpEnv 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. + */ + public static final CxpEnv DEFAULT = new CxpEnv(null, false, ORIENT_LTR); + + /** + * This string is a 2-letters code representing a language as defined by + * ISO-639. If left as null, it defaults to the language + * of the current default locale. + */ + public 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; + + /** 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 CxpHelper#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 CxpHelper#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 CxpHelper#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 CxpHelper#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 CxpHelper#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 CxpHelper#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 CxpHelper#leanToFullText leanToFullText} does not add any directional + * formatting characters as either prefix or suffix of the full text. + *

+ */ + public final int orientation; + + static Locale defLocale; + static String defLanguage; + static boolean defBidi; + boolean bidiFlag; + + /** + * Constructor + * + * @param lang represents the language to be used in this environment. + * It should be specified as a 2-letters code as defined by + * ISO-639.
+ * 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 + * + * @param mirrored specifies if the GUI is mirrored. + * @see #mirrored + * + * @param orientation specifies the orientation of the component + * which is to display the complex expression. It must be + * 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}.
+ * If different, it defaults to {@link #ORIENT_UNKNOWN ORIENT_UNKNOWN}. + * @see #orientation + */ + public CxpEnv(String lang, boolean mirrored, int orientation) { + if (lang == null) { + language = null; + } else { + if (lang.length() > 2) { + language = lang.substring(0, 2); + } else { + language = lang; + } + bidiFlag = isBidiLanguage(language); + } + this.mirrored = mirrored; + this.orientation = orientation >= ORIENT_LTR && orientation <= ORIENT_IGNORE ? orientation : ORIENT_UNKNOWN; + } + + /** + * 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 + * CxpEnv instance, or it may have defaulted to + * the language of the current default locale. + * @see #CxpEnv CxpEnv + */ + public boolean isBidi() { + // TBD use OSGi service + if (defLanguage != null && defLocale.equals(Locale.getDefault())) + return defBidi; + + if (language == null) { + // TBD use OSGi service + defLocale = Locale.getDefault(); + defLanguage = defLocale.getLanguage(); + defBidi = isBidiLanguage(defLanguage); + return defBidi; + } + + return bidiFlag; + } + + static boolean isBidiLanguage(String lang) { + return "iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + } + + static String lineSep; + + /** + * Retrieve the string which represents a line separator in this environment. + * + * @return the string which is used as line separator (e.g. CRLF). + */ + public static String getLineSep() { + // TBD use bundle properties + if (lineSep == null) + lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$ + return lineSep; + } + + static String osName; + static boolean flagOS; + + /** + * Check if the current OS is supported by the complex expression packages. + * + * @return true if the current OS is supported. + */ + public static boolean isSupportedOS() { + if (osName == null) { + // TBD use bundle properties + osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ + flagOS = osName.startsWith("windows") || osName.startsWith("linux"); //$NON-NLS-1$ //$NON-NLS-2$ + } + return flagOS; + } + +} Index: src/org/eclipse/equinox/bidi/complexp/CxpFeatures.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/CxpFeatures.java diff -N src/org/eclipse/equinox/bidi/complexp/CxpFeatures.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/complexp/CxpFeatures.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2010 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.complexp; + +/** + * 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 CxpFeatures instance can be associated with a + * CxpHelper instance using + * the {@link CxpHelper#setFeatures setFeatures} method. + * + *

Code Samples

+ *

Example 1 (set all features) + *

+ *
+ *    CxpFeatures myFeatures = new CxpFeatures("+-=", 0, -1, -1, false, false);
+ *    CxpHelper myHelper = new CxpHelper(IProcessorTypes.FILE, myEnv);
+ *    myHelper.setFeatures(myFeatures);
+ *
+ *  
+ *

Example 2 (change only the operators) + *

+ *
+ *    CxpFeatures f1 = myHelper.getFeatures();
+ *    CxpFeatures f2 = new CxpFeatures("[]|()", f1.specialsCount,
+ *                                     f1.dirArabic, f1.dirHebrew,
+ *                                     f1.ignoreArabic, f1.ignoreHebrew);
+ *    myHelper.setFeatures(f2);
+ *
+ *  
+ * + * @see CxpHelper#getFeatures CxpHelper.getFeatures + * @see CxpHelper#setFeatures CxpHelper.setFeatures + * @see ICxpProcessor#init ICxpProcessor.init + * @see ICxpProcessor#init2 ICxpProcessor.init2 + * + * @author Matitiahu Allouche + */ +public class CxpFeatures { + + /** + * Constant specifying that the base direction of a complex expression is LTR. + * The base direction may depend on whether the GUI is + * {@link CxpEnv#mirrored mirrored} and may + * may be different for Arabic and for Hebrew. + * This constant can appear as dirArabic + * or dirHebrew argument for + * {@link CxpFeatures#CxpFeatures CxpFeatures constructor} and as value + * for the {@link #dirArabic} or {@link #dirHebrew} members of + * CxpFeatures. + */ + 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 CxpEnv#mirrored mirrored} and may + * may be different for Arabic and for Hebrew. + * This constant can appear as dirArabic + * or dirHebrew argument for + * {@link CxpFeatures#CxpFeatures CxpFeatures constructor} and as value + * for the {@link #dirArabic} or {@link #dirHebrew} members of + * CxpFeatures. + */ + public static final int DIR_RTL = 1; + + /** + * Pre-defined CxpFeatures 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 CxpHelper#CxpHelper() CxpHelper} + * instantiated with no arguments. + */ + public static final CxpFeatures DEFAULT = new CxpFeatures(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 ICxpProcessor#indexOfSpecial indexOfSpecial} and + * {@link ICxpProcessor#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 CxpFeatures(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/complexp/CxpHelper.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/CxpHelper.java diff -N src/org/eclipse/equinox/bidi/complexp/CxpHelper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/complexp/CxpHelper.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,570 @@ +/******************************************************************************* + * Copyright (c) 2010 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.complexp; + +import org.eclipse.equinox.bidi.internal.complexp.CxpDoer; + +/** + * 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 CxpHelper 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. + * + *

+ *
+ *    CxpHelper helper = new CxpHelper(IProcessorTypes.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 CxpDoer}. Users of the API need not be concerned by, and + * should not depend upon, details of the implementation by + * CxpDoer. + * + * @author Matitiahu Allouche + * + */ +public class CxpHelper { + /** + * 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 CxpDoer} instance which accomplishes + * most of the work. This member should be accessed only by + * complex expression processors (implementing {@link ICxpProcessor}). + */ + public CxpDoer ced; + + /** + * Create a CxpHelper instance which does nothing tangible + * but does it quickly. We will call it a no-op helper. + * The {@link #CxpHelper() 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 CxpHelper() { + // let ced stay null + } + + /** + * Create a CxpHelper instance to process expressions + * of type type with a + * {@link CxpEnv#DEFAULT DEFAULT} environment. + * + * @param type represents the type of the complex expression. It must + * be one of the values in {@link IProcessorTypes}, or a type + * added in a plug-in extension. + * + * @throws IllegalArgumentException if the type is not + * supported. + */ + public CxpHelper(String type) { + this(type, null); + } + + /** + * Create a CxpHelper instance to process expressions + * of type type operating under the environment + * {@link CxpEnv env}. + * + * @param type represents the type of the complex expression. It must + * be one of the values in {@link IProcessorTypes}, or a type + * added in a plug-in extension. + * + * @param env represents the environment where the complex expression + * will be displayed. It is better to specify the environment + * when instantiating a CxpHelper than to specify + * it later using {@link #setEnvironment setEnvironment}.
+ * null can be specified here for a + * {@link CxpEnv#DEFAULT DEFAULT} environment. + * + * @throws IllegalArgumentException if the type is not + * supported. + */ + public CxpHelper(String type, CxpEnv env) { + ICxpProcessor proc = StringProcessor.getProcessor(type); + if (proc == null) { + throw new IllegalArgumentException("Invalid processor type!"); //$NON-NLS-1$ + } + ced = new CxpDoer(this, proc, env); + } + + /** + * Create a CxpHelper instance to process complex + * expressions by means of a given processor proc, + * operating under the environment {@link CxpEnv env}. + * + * @param proc is a complex expression processor. + * + * @param env represents the environment where the complex expression + * will be displayed. It is better to specify the environment + * when instantiating a CxpHelper than to specify + * it later using {@link #setEnvironment setEnvironment}.
+ * null can be specified here for a + * {@link CxpEnv#DEFAULT DEFAULT} environment. + */ + public CxpHelper(ICxpProcessor proc, CxpEnv env) { + ced = new CxpDoer(this, proc, env); + } + + /** 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 #CxpHelper() 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 #CxpHelper() no-op helper} returns text. + * + * @see #getFinalState getFinalState + */ + public String leanToFullText(String text, int initState) { + if (ced == null) + return text; + return ced.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 CxpEnv#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 #CxpHelper() no-op helper} returns an array of 0 elements. + */ + public int[] leanBidiCharOffsets() { + if (ced == null) + return EMPTY_INT_ARRAY; + return ced.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 CxpEnv#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 #CxpHelper() no-op helper} returns an array of 0 elements. + */ + public int[] fullBidiCharOffsets() { + if (ced == null) + return EMPTY_INT_ARRAY; + return ced.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 #CxpHelper() 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 #CxpHelper() no-op helper} returns text + * + * @see #getFinalState getFinalState + */ + public String fullToLeanText(String text, int initState) { + if (ced == null) + return text; + return ced.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 #CxpHelper() no-op helper} returns {@link #STATE_NOTHING_GOING}. + */ + public int getFinalState() { + if (ced == null) + return STATE_NOTHING_GOING; + return ced.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 pos 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 #CxpHelper() no-op helper} returns pos. + */ + public int leanToFullPos(int pos) { + if (ced == null) + return pos; + return ced.leanToFullPos(pos); + } + + /** + * 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 pos 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 pos 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 #CxpHelper() no-op helper} returns pos. + */ + public int fullToLeanPos(int pos) { + if (ced == null) + return pos; + return ced.fullToLeanPos(pos); + } + + /** + * 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 CxpEnv#mirrored mirrored}. + * + * @return the base direction of the last submitted complex + * expression. It must be one of the values + * {@link CxpFeatures#DIR_LTR} or {@link CxpFeatures#DIR_RTL}.
+ * The {@link #CxpHelper() no-op helper} returns DIR_LTR. + */ + public int getCurDirection() { + if (ced == null) + return CxpFeatures.DIR_LTR; + return ced.getCurDirection(); + } + + /** + * Get the current environment under which the CxpHelper + * operates. + * This environment may have been specified in the constructor or + * specified later using {@link #setEnvironment setEnvironment}.
+ * + * @return the current environment.
+ * The {@link #CxpHelper() no-op helper} returns a {@link CxpEnv#DEFAULT DEFAULT} + * environment. + * + * @see #setEnvironment setEnvironment + */ + public CxpEnv getEnvironment() { + if (ced == null) + return CxpEnv.DEFAULT; + return ced.getEnvironment(); + } + + /** + * Specify the environment under which the CxpHelper + * must operate. + *

+ * Note that calling this method causes the processor + * associated with this instance of CxpHelper + * to re-initialize its features. The effect of a previous call + * to {@link #setFeatures(CxpFeatures) setFeatures} is lost.
+ * The {@link #CxpHelper() no-op helper} does nothing. + * + * @see #getEnvironment getEnvironment + * @see ICxpProcessor#init2 ICxpProcessor.init2 + */ + public void setEnvironment(CxpEnv environment) { + if (ced == null) { + return; // do nothing + } + ced.setEnvironment(environment); + } + + /** + * Get the current features of the processor associated with this + * CxpHelper instance. + * + * @return the current features.
+ * The {@link #CxpHelper() no-op helper} returns {@link CxpFeatures#DEFAULT DEFAULT} + * features. + * + * @see #setFeatures setFeatures + */ + public CxpFeatures getFeatures() { + if (ced == null) + return CxpFeatures.DEFAULT; + return ced.getFeatures(); + } + + /** + * Specify the features to be applied to the processor associated with this + * CxpHelper instance. + * Note that the value of {@link CxpFeatures#specialsCount specialsCount} + * cannot be changed (the new value will be ignored).
+ * The {@link #CxpHelper() no-op helper} does nothing. + * + * @see #getFeatures getFeatures + */ + public void setFeatures(CxpFeatures features) { + if (ced == null) { + return; // do nothing + } + ced.setFeatures(features); + } + + /** + * This method can be called from within + * {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or + * {@link ICxpProcessor#processSpecial processSpecial} in implementations + * of {@link ICxpProcessor} 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 #CxpHelper() no-op helper} returns + * Character.DIRECTIONALITY_UNDEFINED. + */ + public byte getDirProp(int index) { + if (ced == null) + return Character.DIRECTIONALITY_UNDEFINED; + return ced.getDirProp(index); + } + + /** + * This method can be called from within + * {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or + * {@link ICxpProcessor#processSpecial processSpecial} in implementations + * of {@link ICxpProcessor} 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 #CxpHelper() no-op helper} does nothing. + */ + public void setDirProp(int index, byte dirProp) { + if (ced != null) + ced.getDirProp(index); + } + + /** + * This method can be called from within + * {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or + * {@link ICxpProcessor#processSpecial processSpecial} in implementations + * of {@link ICxpProcessor} + * 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 #CxpHelper() no-op helper} does nothing. + */ + public void insertMark(int offset) { + if (ced != null) + ced.insertMark(offset); + } + + /** + * This method can be called from within + * {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or + * {@link ICxpProcessor#processSpecial processSpecial} in + * implementations of {@link ICxpProcessor} 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 #CxpHelper() 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 (ced != null) + ced.processOperator(operLocation); + } + + /** + * This method can be called from within + * {@link ICxpProcessor#indexOfSpecial indexOfSpecial} or + * {@link ICxpProcessor#processSpecial processSpecial} in + * implementations of {@link ICxpProcessor} to + * set the final state which should be used for the next call to + * {@link #leanToFullText(java.lang.String, int)}.
+ * The {@link #CxpHelper() no-op helper} does nothing. + */ + public void setFinalState(int newState) { + if (ced != null) + ced.setFinalState(newState); + } + +} Index: src/org/eclipse/equinox/bidi/complexp/CxpProcessor.java =================================================================== RCS file: src/org/eclipse/equinox/bidi/complexp/CxpProcessor.java diff -N src/org/eclipse/equinox/bidi/complexp/CxpProcessor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/equinox/bidi/complexp/CxpProcessor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2010 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.complexp; + +import org.eclipse.equinox.bidi.internal.complexp.CxpDoer; + +/** + * Generic processor which can be used as superclass (base class) + * for specific complex expression processors. + *

+ * Here are some guidelines about how to write complex expression + * processors. + *