Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 160698 Details for
Bug 183164
[Implementation for] Display of Complex Expressions Containing Bidirectional Text
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Fix compiler warnings and some line formatting
patch_tests_20100302.txt (text/plain), 118.08 KB, created by
Matitiahu Allouche
on 2010-03-02 17:01:40 EST
(
hide
)
Description:
Fix compiler warnings and some line formatting
Filename:
MIME Type:
Creator:
Matitiahu Allouche
Created:
2010-03-02 17:01:40 EST
Size:
118.08 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.equinox.bidi >Index: .settings/org.eclipse.jdt.core.prefs >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/.settings/org.eclipse.jdt.core.prefs,v >retrieving revision 1.2 >diff -u -r1.2 org.eclipse.jdt.core.prefs >--- .settings/org.eclipse.jdt.core.prefs 22 Feb 2010 14:41:30 -0000 1.2 >+++ .settings/org.eclipse.jdt.core.prefs 2 Mar 2010 21:33:42 -0000 >@@ -1,4 +1,4 @@ >-#Mon Feb 22 08:40:30 CST 2010 >+#Tue Mar 02 21:27:03 GMT 2010 > eclipse.preferences.version=1 > org.eclipse.jdt.core.builder.cleanOutputFolder=clean > org.eclipse.jdt.core.builder.duplicateResourceTask=warning >Index: src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java,v >retrieving revision 1.2 >diff -u -r1.2 ComplExpUtil.java >--- src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java 3 Feb 2010 20:00:58 -0000 1.2 >+++ src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java 2 Mar 2010 21:33:42 -0000 >@@ -126,19 +126,19 @@ > public static String insertMarks(String text, int[] offsets, int direction, boolean affix) { > int textLen = text.length(); > if (textLen == 0) >- return ""; >+ return ""; //$NON-NLS-1$ > > String curPrefix, curSuffix, full; > char curMark, c; > char[] fullChars; > if (direction == IComplExpProcessor.DIRECTION_LTR) { > curMark = LRM; >- curPrefix = "\u202a\u200e"; >- curSuffix = "\u200e\u202c"; >+ curPrefix = "\u202a\u200e"; /* LRE+LRM *///$NON-NLS-1$ >+ curSuffix = "\u200e\u202c"; /* LRM+PDF *///$NON-NLS-1$ > } else { > curMark = RLM; >- curPrefix = "\u202b\u200f"; >- curSuffix = "\u200f\u202c"; >+ 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)) { >@@ -170,7 +170,7 @@ > /*************************************************************************/ > > // The default set of delimiters to use to segment a string. >- private static final String defaultDelimiters = ".:/\\"; >+ private static final String defaultDelimiters = ".:/\\"; //$NON-NLS-1$ > // left to right mark > private static final char LRM = '\u200e'; > // left to right mark >@@ -193,12 +193,12 @@ > // TBD use OSGi service > Locale locale = Locale.getDefault(); > String lang = locale.getLanguage(); >- if ("iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || "fa".equals(lang) || "ur".equals(lang)) >+ if ("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$ > PROCESSING_NEEDED_SCORE++; > > // TBD use bundle properties >- String osName = System.getProperty("os.name").toLowerCase(); >- if (osName.startsWith("windows") || osName.startsWith("linux")) >+ String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ >+ if (osName.startsWith("windows") || osName.startsWith("linux")) //$NON-NLS-1$ //$NON-NLS-2$ > PROCESSING_NEEDED_SCORE += 2; > > return PROCESSING_NEEDED_SCORE; >Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java,v >retrieving revision 1.2 >diff -u -r1.2 ComplExpBasic.java >--- src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java 24 Feb 2010 14:59:37 -0000 1.2 >+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java 2 Mar 2010 21:33:42 -0000 >@@ -29,956 +29,956 @@ > */ > public class ComplExpBasic implements IComplExpProcessor { > >- final private static String EMPTY_STRING = ""; //$NON-NLS-1$ >+ final private static String EMPTY_STRING = ""; //$NON-NLS-1$ > >- /** >- * Flag specifying that a specific instance of complex expression should >- * assume that the GUI is mirrored (globally going from right to left). >- * This flag overrides the default flag <code>mirroredDefault</code> >- * for the parent complex expression instance. >- * @see #assumeMirrored >- * @see #isMirrored >- * @see ComplExpUtil#mirroredDefault >- */ >- protected boolean mirrored = ComplExpUtil.isMirroredDefault(); >- >- /** >- * Orientation that should be assumed for the text component where the >- * complex expression will be displayed. It can be specified using >- * {@link #assumeOrientation}. >- * It must be one of the values >- * {@link IComplExpProcessor#ORIENT_LTR ORIENT_LTR}, >- * {@link IComplExpProcessor#ORIENT_LTR ORIENT_RTL}, >- * {@link IComplExpProcessor#ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR} or >- * {@link IComplExpProcessor#ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL}. >- * {@link IComplExpProcessor#ORIENT_UNKNOWN ORIENT_UNKNOWN}. >- * {@link IComplExpProcessor#ORIENT_IGNORE ORIENT_IGNORE}. >- * The default is <code>ORIENT_LTR</code>. >- * <p> >- * The orientation affects the addition of directional formatting >- * characters as prefix and/or suffix when generating the <i>full</i> >- * text of the complex expression. >- * >- * @see #assumeOrientation >- * @see #recallOrientation >- * @see #leanToFullText >- */ >- protected int orientation; >- >- /** >- * Type of the complex expression processor specified when calling >- * {@link ComplExpUtil#create} >- */ >- protected String type; >- >- /** >- * Base direction of the complex expression. This is an array such that >- * <ul> >- * <li><code>direction[0][0]</code> represents the base direction >- * for Arabic when the GUI is not mirrored. >- * <li><code>direction[0][1]</code> represents the base direction >- * for Arabic when the GUI is mirrored. >- * <li><code>direction[1][0]</code> represents the base direction >- * for Hebrew when the GUI is not mirrored. >- * <li><code>direction[1][1]</code> represents the base direction >- * for Hebrew when the GUI is mirrored. >- * </ul> >- * Each of the elements in the array must be one of the values >- * {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_LTR}, >- * {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_RTL}. >- * The default is <code>DIRECTION_LTR</code>. >- * >- * @see #setDirection(int) setDirection >- * @see #getDirection getDirection >- */ >- protected int[][] direction = new int[2][2]; >- >- /** >- * This field represents the final state achieved in a previous call to >- * {@link IComplExpProcessor#leanToFullText leanToFullText} or >- * {@link IComplExpProcessor#fullToLeanText fullToLeanText}, >- * {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text)} or >- * {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text, int initState)}. >- * The <code>state</code> is an opaque value which makes sense only >- * within calls to a same complex expression processor. >- * The only externalized value is >- * {@link IComplExpProcessor#STATE_NOTHING_GOING} which means that >- * there is nothing to remember from the last call. >- * <p> >- * <code>state</code> should be used only for complex expressions >- * which span more than one line, when the user makes a separate call to >- * <code>leanToFullText</code>, <code>fullToLeanText</code> or >- * <code>leanBidiCharOffsets</code> 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. >- * <p> >- * If a line within a complex expression has already been processed by >- * <code>leanToFullText</code> and the <i>lean</i> version of that line has >- * not changed, and its initial state has not changed either, the user >- * can be sure that the <i>full</i> version of that line is also >- * identical to the result of the previous processing. >- * >- * @see IComplExpProcessor#getFinalState >- * @see IComplExpProcessor#leanToFullText(String text, int initState) >- * @see IComplExpProcessor#fullToLeanText(String text, int initState) >- * @see IComplExpProcessor#leanBidiCharOffsets(String text, int initState) >- */ >- protected int state = STATE_NOTHING_GOING; >- >- private boolean ignoreArabic, ignoreHebrew; >- >- public static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR; >- public static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; >- public static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; >- public static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; >- public static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER; >- public static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER; >- public static final char LRM = 0x200E; >- public static final char RLM = 0x200F; >- public static final char LRE = 0x202A; >- public static final char RLE = 0x202B; >- public static final char PDF = 0x202C; >- public static final char[] MARKS = {LRM, RLM}; >- public static final char[] EMBEDS = {LRE, RLE}; >- public static final byte[] STRONGS = {L, R}; >- public static final int PREFIX_LENGTH = 2; >- public static final int SUFFIX_LENGTH = 2; >- public static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH; >- >- private byte curStrong = -1; >- private char curMark; >- private char curEmbed; >- private int prefixLength; >- char[] operators; >- int operCount; >- int[] locations; >- int specialsCount; >- int nextLocation; >- int len; >- private String leanText; >- private int idxLocation; >- private int[] offsets; >- private int count, countLimit; >- private int curPos; >- // 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. >- private byte[] dirProps; >- // current UI orientation (after resolution if contextual) >- private int curOrient = -1; >- // Current expression base direction (after resolution if depending on >- // script and/or on GUI mirroring (0=LTR, 1=RTL)) >- private int curDirection = -1; >- >- /** >- * Constructor specifying operators. The processor will add directional >- * formatting characters to <i>lean</i> text to generate a <i>full</i> >- * text so that the operators and the segments of text between operators >- * are displayed from left to right, while each segment is displayed >- * according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>. >- * >- * @param operators string grouping one-character operators which >- * separate the text of the complex expression into segments. >- */ >- public ComplExpBasic(String operators) { >- this.operators = operators.toCharArray(); >- operCount = this.operators.length; >- locations = new int[operCount]; >- } >- >- public void setOperators(String operators) { >- this.operators = operators.toCharArray(); >- operCount = this.operators.length; >- locations = new int[operCount + specialsCount]; >- } >- >- public String getOperators() { >- return new String(operators); >- } >- >- /** >- * Constructor specifying operators and a number of special cases. >- * In <code>ComplExpBasic</code> the special cases are implemented as >- * doing nothing. Subclasses of <code>ComplExpBasic</code> may override >- * methods <code>indexOfSpecial</code> and <code>processSpecial</code> >- * to provide specific handling for the special cases. >- * Examples of special cases are comments, literals, or anything which >- * is not identified by a one-character operator. >- * <p> >- * Independently of the special cases, the processor will add directional >- * formatting characters to <i>lean</i> text to generate a <i>full</i> >- * text so that the operators and the segments of text between operators >- * are displayed from left to right, while each segment is displayed >- * according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>. >- * >- * @param operators string grouping one-character operators which >- * separate the text of the complex expression into segments. >- * >- * @param specialsCount number of special cases supported by this >- * class. Handling of the special cases is implemented with >- * methods <code>indexOfSpecial</code> and >- * <code>processSpecial</code>. >- * >- * @see #indexOfSpecial indexOfSpecial >- * @see #processSpecial processSpecial >- */ >- public ComplExpBasic(String operators, int specialsCount) { >- this.operators = operators.toCharArray(); >- operCount = this.operators.length; >- this.specialsCount = specialsCount; >- locations = new int[operCount + specialsCount]; >- } >- >- public void selectBidiScript(boolean arabic, boolean hebrew) { >- ignoreArabic = !arabic; >- ignoreHebrew = !hebrew; >- } >- >- public boolean handlesArabicScript() { >- return !ignoreArabic; >- } >- >- public boolean handlesHebrewScript() { >- return !ignoreHebrew; >- } >- >- void computeNextLocation() { >- nextLocation = len; >- // Start with special sequences to give them precedence over simple >- // operators. This may apply to cases like slash+asterisk versus slash. >- for (int i = 0; i < specialsCount; i++) { >- int loc = locations[operCount + i]; >- if (loc < curPos) { >- loc = indexOfSpecial(i, leanText, curPos); >- if (loc < 0) >- loc = len; >- locations[operCount + i] = loc; >- } >- if (loc < nextLocation) { >- nextLocation = loc; >- idxLocation = operCount + i; >- } >- } >- for (int i = 0; i < operCount; i++) { >- int loc = locations[i]; >- if (loc < curPos) { >- loc = leanText.indexOf(operators[i], curPos); >- if (loc < 0) >- loc = len; >- locations[i] = loc; >- } >- if (loc < nextLocation) { >- nextLocation = loc; >- idxLocation = i; >- } >- } >- } >- >- /** >- * This method is called repeatedly by <code>leanToFullText</code> to >- * locate all special cases specified in the constructor >- * (see {@link #ComplExpBasic(String operators, int specialsCount)}), >- * varying <code>whichSpecial</code> from zero to >- * <code>specialsCount - 1</code>. It is meant to be overridden in >- * subclasses of <code>ComplExpBasic</code>. >- * Those subclasses may use methods >- * {@link #getDirProp getDirProp}, >- * {@link #setDirProp setDirProp} and >- * {@link #insertMark insertMark} within <code>indexOfSpecial</code>. >- * >- * @param whichSpecial number of the special case to locate. The meaning >- * of this number is internal to the class implementing >- * <code>indexOfSpecial</code>. >- * >- * @param leanText text of the complex expression before addition of any >- * directional formatting characters. >- * >- * @param fromIndex the index within <code>leanText</code> to start >- * the search from. >- * >- * @return the position where the start of the special case was located. >- * The method must return the first occurrence of whatever >- * identifies the start of the special case after >- * <code>fromIndex</code>. The method does not have to check if >- * this occurrence appears within the scope of another special >- * case (e.g. a comment starting delimiter within the scope of >- * a literal or vice-versa). >- * If no occurrence is found, the method must return -1. >- * <p> >- * In <code>ComplExpBasic</code> this method always returns -1. >- * >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- // This method must be overridden by all subclasses with special cases. >- return -1; >- } >- >- /** >- * This method is called by <code>leanToFullText</code> >- * when a special case occurrence is located by >- * {@link #indexOfSpecial indexOfSpecial}. >- * It is meant to be overridden in subclasses of <code>ComplExpBasic</code>. >- * Those subclasses may use methods >- * {@link #getDirProp getDirProp}, >- * {@link #setDirProp setDirProp} and >- * {@link #insertMark insertMark} within <code>processSpecial</code>. >- * <p> >- * If a special processing cannot be completed within a current call to >- * <code>processSpecial</code> (for instance, a comment has been started >- * in the current line but its end appears in a following line), >- * <code>processSpecial</code> should put in the {@link #state} >- * member of the class instance a number which characterizes this >- * situation. On a later call to >- * {@link IComplExpProcessor#leanToFullText(String text, int initState)} >- * specifying that state value, <code>processSpecial</code> will be >- * called with that value for parameter <code>whichSpecial</code> and >- * <code>-1</code> for parameter <code>operLocation</code> and should >- * perform whatever initializations are required depending on the state. >- * >- * @param whichSpecial number of the special case to handle. >- * >- * @param text text of the complex expression. >- * >- * @param operLocation the position returned by <code>indexOfSpecial</code>. >- * In calls to <code>leanToFullText</code> or >- * <code>fullToLeanText</code> specifying an <code>initState</code> >- * parameter, <code>processSpecial</code> is called when initializing >- * the processing with the value of <code>whichSpecial</code> >- * equal to <code>initState</code> and the value of >- * <code>operLocation</code> equal to <code>-1</code>. >- * >- * @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. >- * <p> >- * In <code>ComplExpBasic</code> this method always returns >- * <code>operLocation + 1</code> (but it should never be called). >- * >- */ >- protected int processSpecial(int whichSpecial, String text, int operLocation) { >- // This method must be overridden by all subclasses with any special case. >- return operLocation + 1; >- } >- >- private int getCurOrient() { >- if (curOrient >= 0) >- return curOrient; >- >- if ((orientation & ORIENT_CONTEXTUAL_LTR) == 0) { >- // absolute orientation >- curOrient = orientation; >- return curOrient; >- } >- // contextual orientation >- byte dirProp; >- for (int i = 0; i < len; i++) { >- dirProp = dirProps[i]; >- if (dirProp == 0) { >- dirProp = Character.getDirectionality(leanText.charAt(i)); >- if (dirProp == B) // B char resolves to L or R depending on orientation >- continue; >- dirProps[i] = (byte) (dirProp + 2); >- } else { >- dirProp -= 2; >- } >- if (dirProp == L) { >- curOrient = ORIENT_LTR; >- return curOrient; >- } >- if (dirProp == R || dirProp == AL) { >- curOrient = ORIENT_RTL; >- return curOrient; >- } >- } >- curOrient = orientation & 1; >- return curOrient; >- } >- >- public int getCurDirection() { >- if (curDirection >= 0) >- return curDirection; >- >- curStrong = -1; >- int idx2 = mirrored ? 1 : 0; >- // same direction for Arabic and Hebrew? >- if (direction[0][idx2] == direction[1][idx2]) { >- curDirection = direction[0][idx2]; >- return curDirection; >- } >- // check if Arabic or Hebrew letter comes first >- byte dirProp; >- for (int i = 0; i < len; i++) { >- dirProp = getDirProp(i); >- if (dirProp == AL) { >- curDirection = direction[0][idx2]; >- return curDirection; >- } >- if (dirProp == R) { >- curDirection = direction[1][idx2]; >- return curDirection; >- } >- } >- // found no Arabic or Hebrew character >- curDirection = DIRECTION_LTR; >- return curDirection; >- } >- >- private void setMarkAndFixes() { >- int dir = getCurDirection(); >- if (curStrong == STRONGS[dir]) >- return; >- curStrong = STRONGS[dir]; >- curMark = MARKS[dir]; >- curEmbed = EMBEDS[dir]; >- } >- >- /** >- * This method can be called from within {@link #indexOfSpecial indexOfSpecial} >- * or {@link #processSpecial processSpecial} in subclasses of >- * <code>ComplExpBasic</code> to retrieve the bidirectional class of >- * characters in <code>leanText</code>. >- * >- * @param index position of the character in <code>leanText</code>. >- * >- * @return the bidirectional class of the character. It is one of the >- * values which can be returned by >- * <code>java.lang.Character#getDirectionality</code>. >- * However, it is recommended to use <code>getDirProp</code> >- * rather than <code>java.lang.Character.getDirectionality</code> >- * since <code>getDirProp</code> manages a cache of character >- * properties and so can be more efficient than calling the >- * java.lang.Character method. >- * >- */ >- protected byte getDirProp(int index) { >- byte dirProp = dirProps[index]; >- if (dirProp == 0) { >- dirProp = Character.getDirectionality(leanText.charAt(index)); >- if (dirProp == B) >- dirProp = getCurOrient() == ORIENT_RTL ? R : L; >- dirProps[index] = (byte) (dirProp + 2); >- return dirProp; >- } >- return (byte) (dirProp - 2); >- } >- >- /** >- * This method can be called from within {@link #indexOfSpecial indexOfSpecial} >- * or {@link #processSpecial processSpecial} in subclasses of >- * <code>ComplExpBasic</code> to set or override the bidirectional >- * class of characters in <code>leanText</code>. >- * >- * @param index position of the character in <code>leanText</code>. >- * >- * @param dirProp bidirectional class of the character. It is one of the >- * values which can be returned by >- * <code>java.lang.Character.getDirectionality</code>. >- * >- */ >- protected void setDirProp(int index, byte dirProp) { >- dirProps[index] = (byte) (dirProp + 2); >- } >- >- /** >- * This method can be called from within >- * {@link #processSpecial processSpecial} in subclasses of >- * <code>ComplExpBasic</code> 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 <code>leanText</code> preceding and following >- * the operator itself. >- * >- * @param operLocation offset of the operator in <code>leanText</code>. >- * >- */ >- protected void processOperator(int operLocation) { >- boolean doneAN = false; >- >- if (getCurDirection() == DIRECTION_RTL) { >- // the expression base direction is RTL >- for (int i = operLocation - 1; i >= 0; i--) { >- byte dirProp = getDirProp(i); >- if (dirProp == R || dirProp == AL) >- return; >- >- if (dirProp == L) { >- for (int j = operLocation; j < len; j++) { >- dirProp = getDirProp(j); >- if (dirProp == R || dirProp == AL) >- return; >- if (dirProp == L || dirProp == EN) { >- insertMark(operLocation); >- return; >- } >- } >- return; >- } >- } >- return; >- } >- >- // the expression base direction is LTR >- if (ignoreArabic) { >- if (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; >- } >- } >- } else { >- if (ignoreHebrew) { /* process Arabic, not Hebrew */ >- for (int i = operLocation - 1; i >= 0; i--) { >- byte dirProp = getDirProp(i); >- 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; >- } >- } >- 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); >- 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; >- } >- } >- 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; >- } >- } >- } >- } >- } >- >- public int getFinalState() { >- return state; >- } >- >- public String leanToFullText(String text) { >- return leanToFullText(text, STATE_NOTHING_GOING); >- } >- >- public String leanToFullText(String text, int initState) { >- if (text.length() == 0) >- return text; >- leanToFullTextNofix(text, initState); >- return addMarks(true); >- } >- >- void leanToFullTextNofix(String text, int initState) { >- leanText = text; >- len = leanText.length(); >- offsets = new int[20]; >- count = 0; >- countLimit = offsets.length - 1; >- dirProps = new byte[len]; >- curOrient = -1; >- curDirection = -1; >- curPos = 0; >- // initialize locations >- int k = locations.length; >- for (int i = 0; i < k; i++) { >- locations[i] = -1; >- } >- state = STATE_NOTHING_GOING; >- nextLocation = -1; >- if (initState != STATE_NOTHING_GOING) >- curPos = processSpecial(initState, leanText, -1); >- >- while (true) { >- computeNextLocation(); >- if (nextLocation >= len) >- break; >- if (idxLocation < operCount) { >- processOperator(nextLocation); >- curPos = nextLocation + 1; >- } else { >- curPos = processSpecial(idxLocation - operCount, leanText, nextLocation); >- } >- } >- } >- >- public int[] leanBidiCharOffsets(String text) { >- return leanBidiCharOffsets(text, STATE_NOTHING_GOING); >- } >- >- public int[] leanBidiCharOffsets(String text, int initState) { >- leanToFullTextNofix(text, initState); >- return leanBidiCharOffsets(); >- } >- >- public int[] leanBidiCharOffsets() { >- int[] result = new int[count]; >- System.arraycopy(offsets, 0, result, 0, count); >- return result; >- } >- >- public int[] fullBidiCharOffsets() { >- int lim = count; >- if (prefixLength > 0) { >- if (prefixLength == 1) >- lim++; >- else >- lim += FIXES_LENGTH; >- } >- int[] fullOffsets = new int[lim]; >- for (int i = 0; i < prefixLength; i++) { >- fullOffsets[i] = i; >- } >- int added = prefixLength; >- for (int i = 0; i < count; i++) { >- fullOffsets[prefixLength + i] = offsets[i] + added; >- added++; >- } >- if (prefixLength > 1) { >- fullOffsets[lim - 2] = len + lim - 2; >- fullOffsets[lim - 1] = len + lim - 1; >- } >- return fullOffsets; >- } >- >- public String fullToLeanText(String text) { >- return fullToLeanText(text, STATE_NOTHING_GOING); >- } >- >- public String fullToLeanText(String text, int initState) { >- int i; // TBD this variable is used for multiple unrelated tasks >- setMarkAndFixes(); >- // remove any prefix and leading mark >- int lenText = text.length(); >- for (i = 0; i < lenText; i++) { >- char c = text.charAt(i); >- if (c != curEmbed && c != curMark) >- break; >- } >- if (i > 0) { >- text = text.substring(i); >- lenText = text.length(); >- } >- // remove any suffix and trailing mark >- for (i = lenText - 1; i >= 0; i--) { >- char c = text.charAt(i); >- if (c != PDF && c != curMark) >- break; >- } >- if (i < 0) { >- leanText = EMPTY_STRING; >- len = 0; >- return leanText; >- } >- if (i < (lenText - 1)) { >- text = text.substring(0, i + 1); >- lenText = text.length(); >- } >- char[] chars = text.toCharArray(); >- // remove marks from chars >- int cnt = 0; >- for (i = 0; i < lenText; i++) { >- char c = chars[i]; >- if (c == curMark) >- cnt++; >- else if (cnt > 0) >- chars[i - cnt] = c; >- } >- String lean = new String(chars, 0, lenText - cnt); >- leanToFullTextNofix(lean, initState); >- String full = addMarks(false); /* only marks, no prefix/suffix */ >- if (full.equals(text)) >- return lean; >- >- // There are some marks in full which are not in text and/or vice versa. >- // We need to add to lean any mark appearing in text and not in full. >- // 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 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 */ >- idxText++; >- idxFull++; >- continue; >- } >- if (cFull == curMark) { /* extra Mark in full text */ >- idxFull++; >- continue; >- } >- if (cText == curMark) { /* extra Mark in source full text */ >- idxText++; >- // 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 */ >- 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; >- len = leanText.length(); >- return lean; >- } >- >- public int leanToFullPos(int pos) { >- int added = prefixLength; >- for (int i = 0; i < count; i++) { >- if (offsets[i] <= pos) >- added++; >- else >- return pos + added; >- } >- return pos + added; >- } >- >- public int fullToLeanPos(int pos) { >- pos -= prefixLength; >- int added = 0; >- for (int i = 0; i < count; i++) { >- if ((offsets[i] + added) < pos) >- added++; >- else >- break; >- } >- pos -= added; >- if (pos < 0) >- pos = 0; >- else if (pos > len) >- pos = len; >- return pos; >- } >- >- /** >- * This method can be called from within {@link #indexOfSpecial} or >- * {@link #processSpecial} in subclasses of <code>ComplExpBasic</code> >- * to specify that a mark character must be added before the character >- * at the specified position of the <i>lean</i> text when generating the >- * <i>full</i> 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 <i>full</i> text. >- * >- * @param offset position of the character in <code>leanText</code>. >- * It must be a non-negative number smaller than the length >- * of the <i>lean</i> text. >- * For the benefit of efficiency, it is better to insert >- * multiple marks in ascending order of the offsets. >- * >- */ >- protected void insertMark(int offset) { >- int index = count - 1; // index of greatest member <= offset >- // look up after which member the new offset should be inserted >- while (index >= 0) { >- int wrkOffset = offsets[index]; >- if (offset > wrkOffset) >- break; >- if (offset == wrkOffset) >- return; // avoid duplicates >- index--; >- } >- index++; // index now points at where to insert >- // check if we have an available slot for new member >- if (count >= countLimit) { >- int[] newOffsets = new int[offsets.length * 2]; >- System.arraycopy(offsets, 0, newOffsets, 0, count); >- offsets = newOffsets; >- countLimit = offsets.length - 1; >- } >- >- 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++; >- // if the offset is 0, adding a mark does not change anything >- if (offset < 1) >- return; >- >- byte dirProp = getDirProp(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 >- if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN) >- index = offset - 1; >- else >- // if the current char is a neutral, we change its own dirProp >- index = offset; >- setMarkAndFixes(); >- setDirProp(index, curStrong); >- } >- >- private String addMarks(boolean addFixes) { >- // add prefix/suffix only if addFixes is true >- if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == ORIENT_IGNORE))) { >- prefixLength = 0; >- return leanText; >- } >- int newLen = len + count; >- if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == ORIENT_UNKNOWN))) { >- if ((orientation & 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); >- } >- >- public void assumeMirrored(boolean shouldBeMirrored) { >- mirrored = shouldBeMirrored; >- curDirection = -1; >- } >- >- public boolean isMirrored() { >- return mirrored; >- } >- >- public void assumeOrientation(int componentOrientation) { >- if (componentOrientation < ORIENT_LTR || componentOrientation > ORIENT_IGNORE) >- orientation = ORIENT_UNKNOWN; // TBD should throw new IllegalArgumentException()? >- else >- orientation = componentOrientation; >- } >- >- public int recallOrientation() { >- return orientation; >- } >- >- public void setArabicDirection(int not_mirrored, int mirrored) { >- direction[0][0] = not_mirrored & 1; >- direction[0][1] = mirrored & 1; >- curDirection = -1; >- } >- >- public void setArabicDirection(int direction) { >- setArabicDirection(direction, direction); >- } >- >- public void setHebrewDirection(int not_mirrored, int mirrored) { >- direction[1][0] = not_mirrored & 1; >- direction[1][1] = mirrored & 1; >- curDirection = -1; >- } >- >- public void setHebrewDirection(int direction) { >- setHebrewDirection(direction, direction); >- } >- >- public void setDirection(int not_mirrored, int mirrored) { >- setArabicDirection(not_mirrored, mirrored); >- setHebrewDirection(not_mirrored, mirrored); >- } >- >- public void setDirection(int direction) { >- setDirection(direction, direction); >- } >- >- public int[][] getDirection() { >- return direction; >- } >+ /** >+ * Flag specifying that a specific instance of complex expression should >+ * assume that the GUI is mirrored (globally going from right to left). >+ * This flag overrides the default flag <code>mirroredDefault</code> >+ * for the parent complex expression instance. >+ * @see #assumeMirrored >+ * @see #isMirrored >+ * @see ComplExpUtil#mirroredDefault >+ */ >+ protected boolean mirrored = ComplExpUtil.isMirroredDefault(); >+ >+ /** >+ * Orientation that should be assumed for the text component where the >+ * complex expression will be displayed. It can be specified using >+ * {@link #assumeOrientation}. >+ * It must be one of the values >+ * {@link IComplExpProcessor#ORIENT_LTR ORIENT_LTR}, >+ * {@link IComplExpProcessor#ORIENT_LTR ORIENT_RTL}, >+ * {@link IComplExpProcessor#ORIENT_CONTEXTUAL_LTR ORIENT_CONTEXTUAL_LTR} or >+ * {@link IComplExpProcessor#ORIENT_CONTEXTUAL_RTL ORIENT_CONTEXTUAL_RTL}. >+ * {@link IComplExpProcessor#ORIENT_UNKNOWN ORIENT_UNKNOWN}. >+ * {@link IComplExpProcessor#ORIENT_IGNORE ORIENT_IGNORE}. >+ * The default is <code>ORIENT_LTR</code>. >+ * <p> >+ * The orientation affects the addition of directional formatting >+ * characters as prefix and/or suffix when generating the <i>full</i> >+ * text of the complex expression. >+ * >+ * @see #assumeOrientation >+ * @see #recallOrientation >+ * @see #leanToFullText >+ */ >+ protected int orientation; >+ >+ /** >+ * Type of the complex expression processor specified when calling >+ * {@link ComplExpUtil#create} >+ */ >+ protected String type; >+ >+ /** >+ * Base direction of the complex expression. This is an array such that >+ * <ul> >+ * <li><code>direction[0][0]</code> represents the base direction >+ * for Arabic when the GUI is not mirrored. >+ * <li><code>direction[0][1]</code> represents the base direction >+ * for Arabic when the GUI is mirrored. >+ * <li><code>direction[1][0]</code> represents the base direction >+ * for Hebrew when the GUI is not mirrored. >+ * <li><code>direction[1][1]</code> represents the base direction >+ * for Hebrew when the GUI is mirrored. >+ * </ul> >+ * Each of the elements in the array must be one of the values >+ * {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_LTR}, >+ * {@link IComplExpProcessor#DIRECTION_LTR DIRECTION_RTL}. >+ * The default is <code>DIRECTION_LTR</code>. >+ * >+ * @see #setDirection(int) setDirection >+ * @see #getDirection getDirection >+ */ >+ protected int[][] direction = new int[2][2]; >+ >+ /** >+ * This field represents the final state achieved in a previous call to >+ * {@link IComplExpProcessor#leanToFullText leanToFullText} or >+ * {@link IComplExpProcessor#fullToLeanText fullToLeanText}, >+ * {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text)} or >+ * {@link IComplExpProcessor#leanBidiCharOffsets(java.lang.String text, int initState)}. >+ * The <code>state</code> is an opaque value which makes sense only >+ * within calls to a same complex expression processor. >+ * The only externalized value is >+ * {@link IComplExpProcessor#STATE_NOTHING_GOING} which means that >+ * there is nothing to remember from the last call. >+ * <p> >+ * <code>state</code> should be used only for complex expressions >+ * which span more than one line, when the user makes a separate call to >+ * <code>leanToFullText</code>, <code>fullToLeanText</code> or >+ * <code>leanBidiCharOffsets</code> 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. >+ * <p> >+ * If a line within a complex expression has already been processed by >+ * <code>leanToFullText</code> and the <i>lean</i> version of that line has >+ * not changed, and its initial state has not changed either, the user >+ * can be sure that the <i>full</i> version of that line is also >+ * identical to the result of the previous processing. >+ * >+ * @see IComplExpProcessor#getFinalState >+ * @see IComplExpProcessor#leanToFullText(String text, int initState) >+ * @see IComplExpProcessor#fullToLeanText(String text, int initState) >+ * @see IComplExpProcessor#leanBidiCharOffsets(String text, int initState) >+ */ >+ protected int state = STATE_NOTHING_GOING; >+ >+ private boolean ignoreArabic, ignoreHebrew; >+ >+ public static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR; >+ public static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT; >+ public static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT; >+ public static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC; >+ public static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER; >+ public static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER; >+ public static final char LRM = 0x200E; >+ public static final char RLM = 0x200F; >+ public static final char LRE = 0x202A; >+ public static final char RLE = 0x202B; >+ public static final char PDF = 0x202C; >+ public static final char[] MARKS = {LRM, RLM}; >+ public static final char[] EMBEDS = {LRE, RLE}; >+ public static final byte[] STRONGS = {L, R}; >+ public static final int PREFIX_LENGTH = 2; >+ public static final int SUFFIX_LENGTH = 2; >+ public static final int FIXES_LENGTH = PREFIX_LENGTH + SUFFIX_LENGTH; >+ >+ private byte curStrong = -1; >+ private char curMark; >+ private char curEmbed; >+ private int prefixLength; >+ char[] operators; >+ int operCount; >+ int[] locations; >+ int specialsCount; >+ int nextLocation; >+ int len; >+ private String leanText; >+ private int idxLocation; >+ private int[] offsets; >+ private int count, countLimit; >+ private int curPos; >+ // 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. >+ private byte[] dirProps; >+ // current UI orientation (after resolution if contextual) >+ private int curOrient = -1; >+ // Current expression base direction (after resolution if depending on >+ // script and/or on GUI mirroring (0=LTR, 1=RTL)) >+ private int curDirection = -1; >+ >+ /** >+ * Constructor specifying operators. The processor will add directional >+ * formatting characters to <i>lean</i> text to generate a <i>full</i> >+ * text so that the operators and the segments of text between operators >+ * are displayed from left to right, while each segment is displayed >+ * according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>. >+ * >+ * @param operators string grouping one-character operators which >+ * separate the text of the complex expression into segments. >+ */ >+ public ComplExpBasic(String operators) { >+ this.operators = operators.toCharArray(); >+ operCount = this.operators.length; >+ locations = new int[operCount]; >+ } >+ >+ public void setOperators(String operators) { >+ this.operators = operators.toCharArray(); >+ operCount = this.operators.length; >+ locations = new int[operCount + specialsCount]; >+ } >+ >+ public String getOperators() { >+ return new String(operators); >+ } >+ >+ /** >+ * Constructor specifying operators and a number of special cases. >+ * In <code>ComplExpBasic</code> the special cases are implemented as >+ * doing nothing. Subclasses of <code>ComplExpBasic</code> may override >+ * methods <code>indexOfSpecial</code> and <code>processSpecial</code> >+ * to provide specific handling for the special cases. >+ * Examples of special cases are comments, literals, or anything which >+ * is not identified by a one-character operator. >+ * <p> >+ * Independently of the special cases, the processor will add directional >+ * formatting characters to <i>lean</i> text to generate a <i>full</i> >+ * text so that the operators and the segments of text between operators >+ * are displayed from left to right, while each segment is displayed >+ * according to the <a href="http://www.unicode.org/reports/tr9/">UBA</a>. >+ * >+ * @param operators string grouping one-character operators which >+ * separate the text of the complex expression into segments. >+ * >+ * @param specialsCount number of special cases supported by this >+ * class. Handling of the special cases is implemented with >+ * methods <code>indexOfSpecial</code> and >+ * <code>processSpecial</code>. >+ * >+ * @see #indexOfSpecial indexOfSpecial >+ * @see #processSpecial processSpecial >+ */ >+ public ComplExpBasic(String operators, int specialsCount) { >+ this.operators = operators.toCharArray(); >+ operCount = this.operators.length; >+ this.specialsCount = specialsCount; >+ locations = new int[operCount + specialsCount]; >+ } >+ >+ public void selectBidiScript(boolean arabic, boolean hebrew) { >+ ignoreArabic = !arabic; >+ ignoreHebrew = !hebrew; >+ } >+ >+ public boolean handlesArabicScript() { >+ return !ignoreArabic; >+ } >+ >+ public boolean handlesHebrewScript() { >+ return !ignoreHebrew; >+ } >+ >+ void computeNextLocation() { >+ nextLocation = len; >+ // Start with special sequences to give them precedence over simple >+ // operators. This may apply to cases like slash+asterisk versus slash. >+ for (int i = 0; i < specialsCount; i++) { >+ int loc = locations[operCount + i]; >+ if (loc < curPos) { >+ loc = indexOfSpecial(i, leanText, curPos); >+ if (loc < 0) >+ loc = len; >+ locations[operCount + i] = loc; >+ } >+ if (loc < nextLocation) { >+ nextLocation = loc; >+ idxLocation = operCount + i; >+ } >+ } >+ for (int i = 0; i < operCount; i++) { >+ int loc = locations[i]; >+ if (loc < curPos) { >+ loc = leanText.indexOf(operators[i], curPos); >+ if (loc < 0) >+ loc = len; >+ locations[i] = loc; >+ } >+ if (loc < nextLocation) { >+ nextLocation = loc; >+ idxLocation = i; >+ } >+ } >+ } >+ >+ /** >+ * This method is called repeatedly by <code>leanToFullText</code> to >+ * locate all special cases specified in the constructor >+ * (see {@link #ComplExpBasic(String operators, int specialsCount)}), >+ * varying <code>whichSpecial</code> from zero to >+ * <code>specialsCount - 1</code>. It is meant to be overridden in >+ * subclasses of <code>ComplExpBasic</code>. >+ * Those subclasses may use methods >+ * {@link #getDirProp getDirProp}, >+ * {@link #setDirProp setDirProp} and >+ * {@link #insertMark insertMark} within <code>indexOfSpecial</code>. >+ * >+ * @param whichSpecial number of the special case to locate. The meaning >+ * of this number is internal to the class implementing >+ * <code>indexOfSpecial</code>. >+ * >+ * @param srcText text of the complex expression before addition of any >+ * directional formatting characters. >+ * >+ * @param fromIndex the index within <code>srcText</code> to start >+ * the search from. >+ * >+ * @return the position where the start of the special case was located. >+ * The method must return the first occurrence of whatever >+ * identifies the start of the special case after >+ * <code>fromIndex</code>. The method does not have to check if >+ * this occurrence appears within the scope of another special >+ * case (e.g. a comment starting delimiter within the scope of >+ * a literal or vice-versa). >+ * If no occurrence is found, the method must return -1. >+ * <p> >+ * In <code>ComplExpBasic</code> this method always returns -1. >+ * >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ // This method must be overridden by all subclasses with special cases. >+ return -1; >+ } >+ >+ /** >+ * This method is called by <code>leanToFullText</code> >+ * when a special case occurrence is located by >+ * {@link #indexOfSpecial indexOfSpecial}. >+ * It is meant to be overridden in subclasses of <code>ComplExpBasic</code>. >+ * Those subclasses may use methods >+ * {@link #getDirProp getDirProp}, >+ * {@link #setDirProp setDirProp} and >+ * {@link #insertMark insertMark} within <code>processSpecial</code>. >+ * <p> >+ * If a special processing cannot be completed within a current call to >+ * <code>processSpecial</code> (for instance, a comment has been started >+ * in the current line but its end appears in a following line), >+ * <code>processSpecial</code> should put in the {@link #state} >+ * member of the class instance a number which characterizes this >+ * situation. On a later call to >+ * {@link IComplExpProcessor#leanToFullText(String text, int initState)} >+ * specifying that state value, <code>processSpecial</code> will be >+ * called with that value for parameter <code>whichSpecial</code> and >+ * <code>-1</code> for parameter <code>operLocation</code> and should >+ * perform whatever initializations are required depending on the state. >+ * >+ * @param whichSpecial number of the special case to handle. >+ * >+ * @param srcText text of the complex expression. >+ * >+ * @param operLocation the position returned by <code>indexOfSpecial</code>. >+ * In calls to <code>leanToFullText</code> or >+ * <code>fullToLeanText</code> specifying an <code>initState</code> >+ * parameter, <code>processSpecial</code> is called when initializing >+ * the processing with the value of <code>whichSpecial</code> >+ * equal to <code>initState</code> and the value of >+ * <code>operLocation</code> equal to <code>-1</code>. >+ * >+ * @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. >+ * <p> >+ * In <code>ComplExpBasic</code> this method always returns >+ * <code>operLocation + 1</code> (but it should never be called). >+ * >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ // This method must be overridden by all subclasses with any special case. >+ return operLocation + 1; >+ } >+ >+ private int getCurOrient() { >+ if (curOrient >= 0) >+ return curOrient; >+ >+ if ((orientation & ORIENT_CONTEXTUAL_LTR) == 0) { >+ // absolute orientation >+ curOrient = orientation; >+ return curOrient; >+ } >+ // contextual orientation >+ byte dirProp; >+ for (int i = 0; i < len; i++) { >+ dirProp = dirProps[i]; >+ if (dirProp == 0) { >+ dirProp = Character.getDirectionality(leanText.charAt(i)); >+ if (dirProp == B) // B char resolves to L or R depending on orientation >+ continue; >+ dirProps[i] = (byte) (dirProp + 2); >+ } else { >+ dirProp -= 2; >+ } >+ if (dirProp == L) { >+ curOrient = ORIENT_LTR; >+ return curOrient; >+ } >+ if (dirProp == R || dirProp == AL) { >+ curOrient = ORIENT_RTL; >+ return curOrient; >+ } >+ } >+ curOrient = orientation & 1; >+ return curOrient; >+ } >+ >+ public int getCurDirection() { >+ if (curDirection >= 0) >+ return curDirection; >+ >+ curStrong = -1; >+ int idx2 = mirrored ? 1 : 0; >+ // same direction for Arabic and Hebrew? >+ if (direction[0][idx2] == direction[1][idx2]) { >+ curDirection = direction[0][idx2]; >+ return curDirection; >+ } >+ // check if Arabic or Hebrew letter comes first >+ byte dirProp; >+ for (int i = 0; i < len; i++) { >+ dirProp = getDirProp(i); >+ if (dirProp == AL) { >+ curDirection = direction[0][idx2]; >+ return curDirection; >+ } >+ if (dirProp == R) { >+ curDirection = direction[1][idx2]; >+ return curDirection; >+ } >+ } >+ // found no Arabic or Hebrew character >+ curDirection = DIRECTION_LTR; >+ return curDirection; >+ } >+ >+ private void setMarkAndFixes() { >+ int dir = getCurDirection(); >+ if (curStrong == STRONGS[dir]) >+ return; >+ curStrong = STRONGS[dir]; >+ curMark = MARKS[dir]; >+ curEmbed = EMBEDS[dir]; >+ } >+ >+ /** >+ * This method can be called from within {@link #indexOfSpecial indexOfSpecial} >+ * or {@link #processSpecial processSpecial} in subclasses of >+ * <code>ComplExpBasic</code> to retrieve the bidirectional class of >+ * characters in <code>leanText</code>. >+ * >+ * @param index position of the character in <code>leanText</code>. >+ * >+ * @return the bidirectional class of the character. It is one of the >+ * values which can be returned by >+ * <code>java.lang.Character#getDirectionality</code>. >+ * However, it is recommended to use <code>getDirProp</code> >+ * rather than <code>java.lang.Character.getDirectionality</code> >+ * since <code>getDirProp</code> manages a cache of character >+ * properties and so can be more efficient than calling the >+ * java.lang.Character method. >+ * >+ */ >+ protected byte getDirProp(int index) { >+ byte dirProp = dirProps[index]; >+ if (dirProp == 0) { >+ dirProp = Character.getDirectionality(leanText.charAt(index)); >+ if (dirProp == B) >+ dirProp = getCurOrient() == ORIENT_RTL ? R : L; >+ dirProps[index] = (byte) (dirProp + 2); >+ return dirProp; >+ } >+ return (byte) (dirProp - 2); >+ } >+ >+ /** >+ * This method can be called from within {@link #indexOfSpecial indexOfSpecial} >+ * or {@link #processSpecial processSpecial} in subclasses of >+ * <code>ComplExpBasic</code> to set or override the bidirectional >+ * class of characters in <code>leanText</code>. >+ * >+ * @param index position of the character in <code>leanText</code>. >+ * >+ * @param dirProp bidirectional class of the character. It is one of the >+ * values which can be returned by >+ * <code>java.lang.Character.getDirectionality</code>. >+ * >+ */ >+ protected void setDirProp(int index, byte dirProp) { >+ dirProps[index] = (byte) (dirProp + 2); >+ } >+ >+ /** >+ * This method can be called from within >+ * {@link #processSpecial processSpecial} in subclasses of >+ * <code>ComplExpBasic</code> 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 <code>leanText</code> preceding and following >+ * the operator itself. >+ * >+ * @param operLocation offset of the operator in <code>leanText</code>. >+ * >+ */ >+ protected void processOperator(int operLocation) { >+ boolean doneAN = false; >+ >+ if (getCurDirection() == DIRECTION_RTL) { >+ // the expression base direction is RTL >+ for (int i = operLocation - 1; i >= 0; i--) { >+ byte dirProp = getDirProp(i); >+ if (dirProp == R || dirProp == AL) >+ return; >+ >+ if (dirProp == L) { >+ for (int j = operLocation; j < len; j++) { >+ dirProp = getDirProp(j); >+ if (dirProp == R || dirProp == AL) >+ return; >+ if (dirProp == L || dirProp == EN) { >+ insertMark(operLocation); >+ return; >+ } >+ } >+ return; >+ } >+ } >+ return; >+ } >+ >+ // the expression base direction is LTR >+ if (ignoreArabic) { >+ if (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; >+ } >+ } >+ } else { >+ if (ignoreHebrew) { /* process Arabic, not Hebrew */ >+ for (int i = operLocation - 1; i >= 0; i--) { >+ byte dirProp = getDirProp(i); >+ 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; >+ } >+ } >+ 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); >+ 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; >+ } >+ } >+ 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; >+ } >+ } >+ } >+ } >+ } >+ >+ public int getFinalState() { >+ return state; >+ } >+ >+ public String leanToFullText(String text) { >+ return leanToFullText(text, STATE_NOTHING_GOING); >+ } >+ >+ public String leanToFullText(String text, int initState) { >+ if (text.length() == 0) >+ return text; >+ leanToFullTextNofix(text, initState); >+ return addMarks(true); >+ } >+ >+ void leanToFullTextNofix(String text, int initState) { >+ leanText = text; >+ len = leanText.length(); >+ offsets = new int[20]; >+ count = 0; >+ countLimit = offsets.length - 1; >+ dirProps = new byte[len]; >+ curOrient = -1; >+ curDirection = -1; >+ curPos = 0; >+ // initialize locations >+ int k = locations.length; >+ for (int i = 0; i < k; i++) { >+ locations[i] = -1; >+ } >+ state = STATE_NOTHING_GOING; >+ nextLocation = -1; >+ if (initState != STATE_NOTHING_GOING) >+ curPos = processSpecial(initState, leanText, -1); >+ >+ while (true) { >+ computeNextLocation(); >+ if (nextLocation >= len) >+ break; >+ if (idxLocation < operCount) { >+ processOperator(nextLocation); >+ curPos = nextLocation + 1; >+ } else { >+ curPos = processSpecial(idxLocation - operCount, leanText, nextLocation); >+ } >+ } >+ } >+ >+ public int[] leanBidiCharOffsets(String text) { >+ return leanBidiCharOffsets(text, STATE_NOTHING_GOING); >+ } >+ >+ public int[] leanBidiCharOffsets(String text, int initState) { >+ leanToFullTextNofix(text, initState); >+ return leanBidiCharOffsets(); >+ } >+ >+ public int[] leanBidiCharOffsets() { >+ int[] result = new int[count]; >+ System.arraycopy(offsets, 0, result, 0, count); >+ return result; >+ } >+ >+ public int[] fullBidiCharOffsets() { >+ int lim = count; >+ if (prefixLength > 0) { >+ if (prefixLength == 1) >+ lim++; >+ else >+ lim += FIXES_LENGTH; >+ } >+ int[] fullOffsets = new int[lim]; >+ for (int i = 0; i < prefixLength; i++) { >+ fullOffsets[i] = i; >+ } >+ int added = prefixLength; >+ for (int i = 0; i < count; i++) { >+ fullOffsets[prefixLength + i] = offsets[i] + added; >+ added++; >+ } >+ if (prefixLength > 1) { >+ fullOffsets[lim - 2] = len + lim - 2; >+ fullOffsets[lim - 1] = len + lim - 1; >+ } >+ return fullOffsets; >+ } >+ >+ public String fullToLeanText(String text) { >+ return fullToLeanText(text, STATE_NOTHING_GOING); >+ } >+ >+ public String fullToLeanText(String text, int initState) { >+ int i; // TBD this variable is used for multiple unrelated tasks >+ setMarkAndFixes(); >+ // remove any prefix and leading mark >+ int lenText = text.length(); >+ for (i = 0; i < lenText; i++) { >+ char c = text.charAt(i); >+ if (c != curEmbed && c != curMark) >+ break; >+ } >+ if (i > 0) { >+ text = text.substring(i); >+ lenText = text.length(); >+ } >+ // remove any suffix and trailing mark >+ for (i = lenText - 1; i >= 0; i--) { >+ char c = text.charAt(i); >+ if (c != PDF && c != curMark) >+ break; >+ } >+ if (i < 0) { >+ leanText = EMPTY_STRING; >+ len = 0; >+ return leanText; >+ } >+ if (i < (lenText - 1)) { >+ text = text.substring(0, i + 1); >+ lenText = text.length(); >+ } >+ char[] chars = text.toCharArray(); >+ // remove marks from chars >+ int cnt = 0; >+ for (i = 0; i < lenText; i++) { >+ char c = chars[i]; >+ if (c == curMark) >+ cnt++; >+ else if (cnt > 0) >+ chars[i - cnt] = c; >+ } >+ String lean = new String(chars, 0, lenText - cnt); >+ leanToFullTextNofix(lean, initState); >+ String full = addMarks(false); /* only marks, no prefix/suffix */ >+ if (full.equals(text)) >+ return lean; >+ >+ // There are some marks in full which are not in text and/or vice versa. >+ // We need to add to lean any mark appearing in text and not in full. >+ // 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 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 */ >+ idxText++; >+ idxFull++; >+ continue; >+ } >+ if (cFull == curMark) { /* extra Mark in full text */ >+ idxFull++; >+ continue; >+ } >+ if (cText == curMark) { /* extra Mark in source full text */ >+ idxText++; >+ // 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 */ >+ 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; >+ len = leanText.length(); >+ return lean; >+ } >+ >+ public int leanToFullPos(int pos) { >+ int added = prefixLength; >+ for (int i = 0; i < count; i++) { >+ if (offsets[i] <= pos) >+ added++; >+ else >+ return pos + added; >+ } >+ return pos + added; >+ } >+ >+ public int fullToLeanPos(int pos) { >+ pos -= prefixLength; >+ int added = 0; >+ for (int i = 0; i < count; i++) { >+ if ((offsets[i] + added) < pos) >+ added++; >+ else >+ break; >+ } >+ pos -= added; >+ if (pos < 0) >+ pos = 0; >+ else if (pos > len) >+ pos = len; >+ return pos; >+ } >+ >+ /** >+ * This method can be called from within {@link #indexOfSpecial} or >+ * {@link #processSpecial} in subclasses of <code>ComplExpBasic</code> >+ * to specify that a mark character must be added before the character >+ * at the specified position of the <i>lean</i> text when generating the >+ * <i>full</i> 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 <i>full</i> text. >+ * >+ * @param offset position of the character in <code>leanText</code>. >+ * It must be a non-negative number smaller than the length >+ * of the <i>lean</i> text. >+ * For the benefit of efficiency, it is better to insert >+ * multiple marks in ascending order of the offsets. >+ * >+ */ >+ protected void insertMark(int offset) { >+ int index = count - 1; // index of greatest member <= offset >+ // look up after which member the new offset should be inserted >+ while (index >= 0) { >+ int wrkOffset = offsets[index]; >+ if (offset > wrkOffset) >+ break; >+ if (offset == wrkOffset) >+ return; // avoid duplicates >+ index--; >+ } >+ index++; // index now points at where to insert >+ // check if we have an available slot for new member >+ if (count >= countLimit) { >+ int[] newOffsets = new int[offsets.length * 2]; >+ System.arraycopy(offsets, 0, newOffsets, 0, count); >+ offsets = newOffsets; >+ countLimit = offsets.length - 1; >+ } >+ >+ 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++; >+ // if the offset is 0, adding a mark does not change anything >+ if (offset < 1) >+ return; >+ >+ byte dirProp = getDirProp(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 >+ if (dirProp == L || dirProp == R || dirProp == AL || dirProp == EN || dirProp == AN) >+ index = offset - 1; >+ else >+ // if the current char is a neutral, we change its own dirProp >+ index = offset; >+ setMarkAndFixes(); >+ setDirProp(index, curStrong); >+ } >+ >+ private String addMarks(boolean addFixes) { >+ // add prefix/suffix only if addFixes is true >+ if ((count == 0) && (!addFixes || (getCurOrient() == getCurDirection()) || (curOrient == ORIENT_IGNORE))) { >+ prefixLength = 0; >+ return leanText; >+ } >+ int newLen = len + count; >+ if (addFixes && ((getCurOrient() != getCurDirection()) || (curOrient == ORIENT_UNKNOWN))) { >+ if ((orientation & 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); >+ } >+ >+ public void assumeMirrored(boolean shouldBeMirrored) { >+ mirrored = shouldBeMirrored; >+ curDirection = -1; >+ } >+ >+ public boolean isMirrored() { >+ return mirrored; >+ } >+ >+ public void assumeOrientation(int componentOrientation) { >+ if (componentOrientation < ORIENT_LTR || componentOrientation > ORIENT_IGNORE) >+ orientation = ORIENT_UNKNOWN; // TBD should throw new IllegalArgumentException()? >+ else >+ orientation = componentOrientation; >+ } >+ >+ public int recallOrientation() { >+ return orientation; >+ } >+ >+ public void setArabicDirection(int not_mirrored, int mirrored) { >+ direction[0][0] = not_mirrored & 1; >+ direction[0][1] = mirrored & 1; >+ curDirection = -1; >+ } >+ >+ public void setArabicDirection(int direction) { >+ setArabicDirection(direction, direction); >+ } >+ >+ public void setHebrewDirection(int not_mirrored, int mirrored) { >+ direction[1][0] = not_mirrored & 1; >+ direction[1][1] = mirrored & 1; >+ curDirection = -1; >+ } >+ >+ public void setHebrewDirection(int direction) { >+ setHebrewDirection(direction, direction); >+ } >+ >+ public void setDirection(int not_mirrored, int mirrored) { >+ setArabicDirection(not_mirrored, mirrored); >+ setHebrewDirection(not_mirrored, mirrored); >+ } >+ >+ public void setDirection(int direction) { >+ setDirection(direction, direction); >+ } >+ >+ public int[][] getDirection() { >+ return direction; >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpDelims.java >--- src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java 3 Feb 2010 20:01:02 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java 2 Mar 2010 21:33:42 -0000 >@@ -24,52 +24,52 @@ > * @author Matitiahu Allouche > */ > public class ComplExpDelims extends ComplExpBasic { >- char[] delims; >+ char[] delims; > >- /** >- * Constructor for a complex expressions processor with support for >- * operators and delimiters. >- * >- * @param operators string grouping one-character operators which >- * separate the text of the complex expression into segments. >- * >- * @param delims delimiters implemented in this class instance. >- * This parameter is a string which must include an even >- * number of characters. The first 2 characters of a string >- * constitute a pair, the next 2 characters are a second pair, etc... >- * In each pair, the first character is a start delimiter and >- * the second character is an end delimiter. In the <i>lean</i> >- * text, any part starting with a start delimiter and ending with >- * the corresponding end delimiter is a delimited part. Within a >- * delimited part, operators are treated like regular characters, >- * which means that they do not define new segments. >- */ >- public ComplExpDelims(String operators, String delims) { >- super(operators, delims.length() / 2); >- this.delims = delims.toCharArray(); >- } >+ /** >+ * Constructor for a complex expressions processor with support for >+ * operators and delimiters. >+ * >+ * @param operators string grouping one-character operators which >+ * separate the text of the complex expression into segments. >+ * >+ * @param delims delimiters implemented in this class instance. >+ * This parameter is a string which must include an even >+ * number of characters. The first 2 characters of a string >+ * constitute a pair, the next 2 characters are a second pair, etc... >+ * In each pair, the first character is a start delimiter and >+ * the second character is an end delimiter. In the <i>lean</i> >+ * text, any part starting with a start delimiter and ending with >+ * the corresponding end delimiter is a delimited part. Within a >+ * delimited part, operators are treated like regular characters, >+ * which means that they do not define new segments. >+ */ >+ public ComplExpDelims(String operators, String delims) { >+ super(operators, delims.length() / 2); >+ this.delims = delims.toCharArray(); >+ } > >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- char delim = delims[whichSpecial * 2]; >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ char delim = delims[whichSpecial * 2]; > >- return leanText.indexOf(delim, fromIndex); >- } >+ return srcText.indexOf(delim, fromIndex); >+ } > >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- processOperator(operLocation); >- int loc = operLocation + 1; >- char delim = delims[(whichSpecial * 2) + 1]; >- loc = leanText.indexOf(delim, loc); >- if (loc < 0) >- return leanText.length(); >- return loc + 1; >- } >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ processOperator(operLocation); >+ int loc = operLocation + 1; >+ char delim = delims[(whichSpecial * 2) + 1]; >+ loc = srcText.indexOf(delim, loc); >+ if (loc < 0) >+ return srcText.length(); >+ return loc + 1; >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpDelimsEsc.java >--- src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java 3 Feb 2010 20:01:02 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java 2 Mar 2010 21:33:42 -0000 >@@ -32,51 +32,51 @@ > * @author Matitiahu Allouche > */ > public class ComplExpDelimsEsc extends ComplExpDelims { >- /** >- * Constructor for a complex expressions processor with support for >- * operators and delimiters which can be escaped. >- * >- * @param operators string grouping one-character operators which >- * separate the text of the complex expression into segments. >- * >- * @param delims delimiters implemented in this class instance. >- * This parameter is a string which must include an even >- * number of characters. The first 2 characters of a string >- * constitute a pair, the next 2 characters are a second pair, etc... >- * In each pair, the first character is a start delimiter and >- * the second character is an end delimiter. In the <i>lean</i> >- * text, any part starting with a start delimiter and ending with >- * the corresponding end delimiter is a delimited part. Within a >- * delimited part, operators are treated like regular characters, >- * which means that they do not define new segments.<br> >- * <br> >- * Note however that an ending delimiter preceded by an odd >- * number of backslashes is considered as a regular character >- * and does not mark the termination of a delimited part. >- */ >- public ComplExpDelimsEsc(String operators, String delims) { >- super(operators, delims); >- } >+ /** >+ * Constructor for a complex expressions processor with support for >+ * operators and delimiters which can be escaped. >+ * >+ * @param operators string grouping one-character operators which >+ * separate the text of the complex expression into segments. >+ * >+ * @param delims delimiters implemented in this class instance. >+ * This parameter is a string which must include an even >+ * number of characters. The first 2 characters of a string >+ * constitute a pair, the next 2 characters are a second pair, etc... >+ * In each pair, the first character is a start delimiter and >+ * the second character is an end delimiter. In the <i>lean</i> >+ * text, any part starting with a start delimiter and ending with >+ * the corresponding end delimiter is a delimited part. Within a >+ * delimited part, operators are treated like regular characters, >+ * which means that they do not define new segments.<br> >+ * <br> >+ * Note however that an ending delimiter preceded by an odd >+ * number of backslashes is considered as a regular character >+ * and does not mark the termination of a delimited part. >+ */ >+ public ComplExpDelimsEsc(String operators, String delims) { >+ super(operators, delims); >+ } > >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- processOperator(operLocation); >- int loc = operLocation + 1; >- char delim = delims[(whichSpecial * 2) + 1]; >- while (true) { >- loc = leanText.indexOf(delim, loc); >- if (loc < 0) >- return leanText.length(); >- int cnt = 0; >- for (int i = loc - 1; leanText.charAt(i) == '\\'; i--) { >- cnt++; >- } >- loc++; >- if ((cnt & 1) == 0) >- return loc; >- } >- } >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ processOperator(operLocation); >+ int loc = operLocation + 1; >+ char delim = delims[(whichSpecial * 2) + 1]; >+ while (true) { >+ loc = srcText.indexOf(delim, loc); >+ if (loc < 0) >+ return srcText.length(); >+ int cnt = 0; >+ for (int i = loc - 1; srcText.charAt(i) == '\\'; i--) { >+ cnt++; >+ } >+ loc++; >+ if ((cnt & 1) == 0) >+ return loc; >+ } >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpSingle.java >--- src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java 3 Feb 2010 20:01:02 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java 2 Mar 2010 21:33:42 -0000 >@@ -30,36 +30,36 @@ > * @author Matitiahu Allouche > */ > public class ComplExpSingle extends ComplExpBasic { >- char separator; >+ char separator; > >- /** >- * Constructor for a complex expressions processor with support for one >- * operator. >- * >- * @param operators string including at least one character. The >- * first character of the string is the operator which divides >- * the expression into 2 parts. >- * >- */ >- public ComplExpSingle(String operators) { >- super(operators, 1); >- separator = operators.charAt(0); >- } >+ /** >+ * Constructor for a complex expressions processor with support for one >+ * operator. >+ * >+ * @param operators string including at least one character. The >+ * first character of the string is the operator which divides >+ * the expression into 2 parts. >+ * >+ */ >+ public ComplExpSingle(String operators) { >+ super(operators, 1); >+ separator = operators.charAt(0); >+ } > >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- return leanText.indexOf(separator, fromIndex); >- } >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ return srcText.indexOf(separator, fromIndex); >+ } > >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- processOperator(operLocation); >- return leanText.length(); >- } >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ processOperator(operLocation); >+ return srcText.length(); >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpJava.java >--- src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java 3 Feb 2010 20:01:01 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java 2 Mar 2010 21:33:42 -0000 >@@ -10,9 +10,8 @@ > ******************************************************************************/ > package org.eclipse.equinox.bidi.internal.complexp.consumable; > >-import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; >- > import org.eclipse.equinox.bidi.complexp.IComplExpProcessor; >+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; > > /** > * <code>ComplExpJava</code> is a processor for complex expressions >@@ -34,87 +33,87 @@ > * @author Matitiahu Allouche > */ > public class ComplExpJava extends ComplExpBasic { >- private static final byte WS = Character.DIRECTIONALITY_WHITESPACE; >- static final String operators = "[](){}.+-<>=~!&*/%^|?:,;\t"; >- static String lineSep; >- >- /** >- * Constructor for a complex expressions processor with support for >- * Java statements. >- */ >- public ComplExpJava() { >- super(operators, 4); >- // TBD use bundle properties >- if (lineSep == null) >- lineSep = System.getProperty("line.separator", "\n"); >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- switch (whichSpecial) { >- case 0 : /* space */ >- return leanText.indexOf(' ', fromIndex); >- case 1 : /* literal */ >- return leanText.indexOf('"', fromIndex); >- case 2 : /* slash-aster comment */ >- return leanText.indexOf("/*", fromIndex); >- case 3 : /* slash-slash comment */ >- return leanText.indexOf("//", fromIndex); >- } >- // we should never get here >- return -1; >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- int loc, cnt, i; >- >- processOperator(operLocation); >- switch (whichSpecial) { >- case 0 : /* space */ >- operLocation++; >- while (operLocation < leanText.length() && leanText.charAt(operLocation) == ' ') { >- setDirProp(operLocation, WS); >- operLocation++; >- } >- return operLocation; >- case 1 : /* literal */ >- loc = operLocation + 1; >- while (true) { >- loc = leanText.indexOf('"', loc); >- if (loc < 0) >- return leanText.length(); >- for (cnt = 0, i = loc - 1; leanText.charAt(i) == '\\'; i--) { >- cnt++; >- } >- loc++; >- if ((cnt & 1) == 0) >- return loc; >- } >- case 2 : /* slash-aster comment */ >- if (operLocation < 0) >- loc = 0; // initial state from previous line >- else >- loc = operLocation + 2; // skip the opening slash-aster >- loc = leanText.indexOf("*/", loc); >- if (loc < 0) { >- state = 2; >- return leanText.length(); >- } >- return loc + 2; >- case 3 : /* slash-slash comment */ >- loc = leanText.indexOf(lineSep, operLocation + 2); >- if (loc < 0) >- return leanText.length(); >- return loc + lineSep.length(); >- } >- // we should never get here >- return operLocation + 1; >- } >+ private static final byte WS = Character.DIRECTIONALITY_WHITESPACE; >+ static final String operators = "[](){}.+-<>=~!&*/%^|?:,;\t"; //$NON-NLS-1$ >+ static String lineSep; >+ >+ /** >+ * Constructor for a complex expressions processor with support for >+ * Java statements. >+ */ >+ public ComplExpJava() { >+ super(operators, 4); >+ // TBD use bundle properties >+ if (lineSep == null) >+ lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$//$NON-NLS-2$ >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ switch (whichSpecial) { >+ 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$ >+ } >+ // we should never get here >+ return -1; >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ int loc, cnt, i; >+ >+ processOperator(operLocation); >+ switch (whichSpecial) { >+ case 0 : /* space */ >+ operLocation++; >+ while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') { >+ setDirProp(operLocation, WS); >+ operLocation++; >+ } >+ return operLocation; >+ case 1 : /* literal */ >+ loc = operLocation + 1; >+ while (true) { >+ loc = srcText.indexOf('"', loc); >+ if (loc < 0) >+ return srcText.length(); >+ for (cnt = 0, i = loc - 1; srcText.charAt(i) == '\\'; i--) { >+ cnt++; >+ } >+ loc++; >+ if ((cnt & 1) == 0) >+ return loc; >+ } >+ case 2 : /* slash-aster comment */ >+ if (operLocation < 0) >+ loc = 0; // initial state from previous line >+ else >+ loc = operLocation + 2; // skip the opening slash-aster >+ loc = srcText.indexOf("*/", loc); //$NON-NLS-1$ >+ if (loc < 0) { >+ state = 2; >+ return srcText.length(); >+ } >+ return loc + 2; >+ case 3 : /* slash-slash comment */ >+ loc = srcText.indexOf(lineSep, operLocation + 2); >+ if (loc < 0) >+ return srcText.length(); >+ return loc + lineSep.length(); >+ } >+ // we should never get here >+ return operLocation + 1; >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpRegex.java >--- src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java 3 Feb 2010 20:01:00 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java 2 Mar 2010 21:33:42 -0000 >@@ -10,9 +10,8 @@ > ******************************************************************************/ > package org.eclipse.equinox.bidi.internal.complexp.consumable; > >-import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; >- > import org.eclipse.equinox.bidi.complexp.IComplExpProcessor; >+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; > > /** > * <code>ComplExpRegex</code> is a processor for regular expressions. >@@ -33,172 +32,172 @@ > * @author Matitiahu Allouche > */ > public class ComplExpRegex extends ComplExpBasic { >- static final String operators = ""; >- static final String[] startStrings = {"(?#", /* 0 *//* comment (?#...) */ >- "(?<", /* 1 *//* named group (?<name> */ >- "(?'", /* 2 *//* named group (?'name' */ >- "(?(<", /* 3 *//* conditional named back reference (?(<name>) */ >- "(?('", /* 4 *//* conditional named back reference (?('name') */ >- "(?(", /* 5 *//* conditional named back reference (?(name) */ >- "(?&", /* 6 *//* named parentheses reference (?&name) */ >- "(?P<", /* 7 *//* named group (?P<name> */ >- "\\k<", /* 8 *//* named back reference \k<name> */ >- "\\k'", /* 9 *//* named back reference \k'name' */ >- "\\k{", /* 10 *//* named back reference \k{name} */ >- "(?P=", /* 11 *//* named back reference (?P=name) */ >- "\\g{", /* 12 *//* named back reference \g{name} */ >- "\\g<", /* 13 *//* subroutine call \g<name> */ >- "\\g'", /* 14 *//* subroutine call \g'name' */ >- "(?(R&", /* 15 *//* named back reference recursion (?(R&name) */ >- "\\Q" /* 16 *//* quoted sequence \Q...\E */ >- }; >- 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; >- >- /** >- * Constructor for a complex expressions processor with support for >- * regular expressions. >- */ >- public ComplExpRegex() { >- super(operators, maxSpecial); >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- byte dirProp; >- >- if (whichSpecial < numberOfStrings) { >- /* 0 *//* comment (?#...) */ >- /* 1 *//* named group (?<name> */ >- /* 2 *//* named group (?'name' */ >- /* 3 *//* conditional named back reference (?(name) */ >- /* 4 *//* conditional named back reference (?(<name>) */ >- /* 5 *//* conditional named back reference (?('name') */ >- /* 6 *//* named parentheses reference (?&name) */ >- /* 7 *//* named group (?P<name> */ >- /* 8 *//* named back reference \k<name> */ >- /* 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<name> */ >- /* 14 *//* subroutine call \g'name' */ >- /* 15 *//* named back reference recursion (?(R&name) */ >- /* 16 *//* quoted sequence \Q...\E */ >- return leanText.indexOf(startStrings[whichSpecial], fromIndex); >- } >- // look for R, AL, AN, EN which are potentially needing a mark >- for (; fromIndex < leanText.length(); fromIndex++) { >- // there never is a need for a mark before the first char >- if (fromIndex <= 0) >- continue; >- >- dirProp = getDirProp(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 (getDirProp(fromIndex - 1) == dirProp) >- continue; >- >- for (int i = fromIndex - 1; i >= 0; i--) { >- dirProp = getDirProp(i); >- // after a L char, no need for a mark >- if (dirProp == L) >- continue; >- >- // digit after R or AL or AN need a mark, except for EN >- // following AN, but this is a contrived case, so we >- // don't check for it (and calling processOperator() >- // for it will do no harm) >- if (dirProp == R || dirProp == AL || dirProp == AN) >- return fromIndex; >- } >- continue; >- } >- } >- return -1; >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- int loc; >- >- switch (whichSpecial) { >- case 0 : /* comment (?#...) */ >- if (operLocation < 0) { >- // initial state from previous line >- loc = 0; >- } else { >- processOperator(operLocation); >- // skip the opening "(?#" >- loc = operLocation + 3; >- } >- loc = leanText.indexOf(')', loc); >- if (loc < 0) { >- state = whichSpecial; >- return leanText.length(); >- } >- return loc + 1; >- case 1 : /* named group (?<name> */ >- case 2 : /* named group (?'name' */ >- case 3 : /* conditional named back reference (?(name) */ >- case 4 : /* conditional named back reference (?(<name>) */ >- case 5 : /* conditional named back reference (?('name') */ >- case 6 : /* named parentheses reference (?&name) */ >- processOperator(operLocation); >- // no need for calling processOperator() for the following cases >- // since the starting string contains a L char >- case 7 : /* named group (?P<name> */ >- case 8 : /* named back reference \k<name> */ >- 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<name> */ >- case 14 : /* subroutine call \g'name' */ >- case 15 : /* named back reference recursion (?(R&name) */ >- // skip the opening string >- loc = operLocation + startStrings[whichSpecial].length(); >- // look for ending character >- loc = leanText.indexOf(endChars[whichSpecial], loc); >- if (loc < 0) >- return leanText.length(); >- return loc + 1; >- case 16 : /* quoted sequence \Q...\E */ >- if (operLocation < 0) { >- // initial state from previous line >- loc = 0; >- } else { >- processOperator(operLocation); >- // skip the opening "\Q" >- loc = operLocation + 2; >- } >- loc = leanText.indexOf("\\E", loc); >- if (loc < 0) { >- state = whichSpecial; >- return leanText.length(); >- } >- // set the dirProp for the "E" >- setDirProp(loc + 1, L); >- return loc + 2; >- case 17 : /* R, AL, AN, EN */ >- processOperator(operLocation); >- return operLocation + 1; >- >- } >- // we should never get here >- return leanText.length(); >- } >+ static final String operators = ""; //$NON-NLS-1$ >+ static final String[] startStrings = {"(?#", /* 0 *//* comment (?#...) *///$NON-NLS-1$ >+ "(?<", /* 1 *//* named group (?<name> *///$NON-NLS-1$ >+ "(?'", /* 2 *//* named group (?'name' *///$NON-NLS-1$ >+ "(?(<", /* 3 *//* conditional named back reference (?(<name>) *///$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<name> *///$NON-NLS-1$ >+ "\\k<", /* 8 *//* named back reference \k<name> *///$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<name> *///$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 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; >+ >+ /** >+ * Constructor for a complex expressions processor with support for >+ * regular expressions. >+ */ >+ public ComplExpRegex() { >+ super(operators, maxSpecial); >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ byte dirProp; >+ >+ if (whichSpecial < numberOfStrings) { >+ /* 0 *//* comment (?#...) */ >+ /* 1 *//* named group (?<name> */ >+ /* 2 *//* named group (?'name' */ >+ /* 3 *//* conditional named back reference (?(name) */ >+ /* 4 *//* conditional named back reference (?(<name>) */ >+ /* 5 *//* conditional named back reference (?('name') */ >+ /* 6 *//* named parentheses reference (?&name) */ >+ /* 7 *//* named group (?P<name> */ >+ /* 8 *//* named back reference \k<name> */ >+ /* 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<name> */ >+ /* 14 *//* subroutine call \g'name' */ >+ /* 15 *//* named back reference recursion (?(R&name) */ >+ /* 16 *//* quoted sequence \Q...\E */ >+ return srcText.indexOf(startStrings[whichSpecial], fromIndex); >+ } >+ // look for R, AL, AN, EN which are potentially needing a mark >+ for (; fromIndex < srcText.length(); fromIndex++) { >+ // there never is a need for a mark before the first char >+ if (fromIndex <= 0) >+ continue; >+ >+ dirProp = getDirProp(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 (getDirProp(fromIndex - 1) == dirProp) >+ continue; >+ >+ for (int i = fromIndex - 1; i >= 0; i--) { >+ dirProp = getDirProp(i); >+ // after a L char, no need for a mark >+ if (dirProp == L) >+ continue; >+ >+ // digit after R or AL or AN need a mark, except for EN >+ // following AN, but this is a contrived case, so we >+ // don't check for it (and calling processOperator() >+ // for it will do no harm) >+ if (dirProp == R || dirProp == AL || dirProp == AN) >+ return fromIndex; >+ } >+ continue; >+ } >+ } >+ return -1; >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ int loc; >+ >+ switch (whichSpecial) { >+ case 0 : /* comment (?#...) */ >+ if (operLocation < 0) { >+ // initial state from previous line >+ loc = 0; >+ } else { >+ processOperator(operLocation); >+ // skip the opening "(?#" >+ loc = operLocation + 3; >+ } >+ loc = srcText.indexOf(')', loc); >+ if (loc < 0) { >+ state = whichSpecial; >+ return srcText.length(); >+ } >+ return loc + 1; >+ case 1 : /* named group (?<name> */ >+ case 2 : /* named group (?'name' */ >+ case 3 : /* conditional named back reference (?(name) */ >+ case 4 : /* conditional named back reference (?(<name>) */ >+ case 5 : /* conditional named back reference (?('name') */ >+ case 6 : /* named parentheses reference (?&name) */ >+ processOperator(operLocation); >+ // no need for calling processOperator() for the following cases >+ // since the starting string contains a L char >+ case 7 : /* named group (?P<name> */ >+ case 8 : /* named back reference \k<name> */ >+ 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<name> */ >+ case 14 : /* subroutine call \g'name' */ >+ case 15 : /* named back reference recursion (?(R&name) */ >+ // skip the opening string >+ loc = operLocation + startStrings[whichSpecial].length(); >+ // look for ending character >+ loc = srcText.indexOf(endChars[whichSpecial], loc); >+ if (loc < 0) >+ return srcText.length(); >+ return loc + 1; >+ case 16 : /* quoted sequence \Q...\E */ >+ if (operLocation < 0) { >+ // initial state from previous line >+ loc = 0; >+ } else { >+ processOperator(operLocation); >+ // skip the opening "\Q" >+ loc = operLocation + 2; >+ } >+ loc = srcText.indexOf("\\E", loc); //$NON-NLS-1$ >+ if (loc < 0) { >+ state = whichSpecial; >+ return srcText.length(); >+ } >+ // set the dirProp for the "E" >+ setDirProp(loc + 1, L); >+ return loc + 2; >+ case 17 : /* R, AL, AN, EN */ >+ processOperator(operLocation); >+ return operLocation + 1; >+ >+ } >+ // we should never get here >+ return srcText.length(); >+ } > } >Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSql.java >=================================================================== >RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSql.java,v >retrieving revision 1.1 >diff -u -r1.1 ComplExpSql.java >--- src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSql.java 3 Feb 2010 20:01:01 -0000 1.1 >+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSql.java 2 Mar 2010 21:33:42 -0000 >@@ -10,9 +10,8 @@ > ******************************************************************************/ > package org.eclipse.equinox.bidi.internal.complexp.consumable; > >-import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; >- > import org.eclipse.equinox.bidi.complexp.IComplExpProcessor; >+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic; > > /** > * <code>ComplExpSql</code> is a processor for complex expressions >@@ -34,106 +33,106 @@ > * @author Matitiahu Allouche > */ > public class ComplExpSql extends ComplExpBasic { >- private static final byte WS = Character.DIRECTIONALITY_WHITESPACE; >- static final String operators = "\t!#%&()*+,-./:;<=>?|[]{}"; >- static String lineSep; >- >- /** >- * Constructor for a complex expressions processor with support for >- * SQL statements. >- */ >- public ComplExpSql() { >- super(operators, 5); >- // TBD use bundle properties >- if (lineSep == null) >- lineSep = System.getProperty("line.separator", "\n"); >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int indexOfSpecial(int whichSpecial, String leanText, int fromIndex) { >- switch (whichSpecial) { >- case 0 : /* space */ >- return leanText.indexOf(" ", fromIndex); >- case 1 : /* literal */ >- return leanText.indexOf('\'', fromIndex); >- case 2 : /* delimited identifier */ >- return leanText.indexOf('"', fromIndex); >- case 3 : /* slash-aster comment */ >- return leanText.indexOf("/*", fromIndex); >- case 4 : /* hyphen-hyphen comment */ >- return leanText.indexOf("--", fromIndex); >- } >- // we should never get here >- return -1; >- } >- >- /** >- * This method is not supposed to be invoked directly by users of this >- * class. It may be overridden by subclasses of this class. >- */ >- protected int processSpecial(int whichSpecial, String leanText, int operLocation) { >- int loc; >- >- processOperator(operLocation); >- switch (whichSpecial) { >- case 0 : /* space */ >- operLocation++; >- while (operLocation < leanText.length() && leanText.charAt(operLocation) == ' ') { >- setDirProp(operLocation, WS); >- operLocation++; >- } >- return operLocation; >- case 1 : /* literal */ >- loc = operLocation + 1; >- while (true) { >- loc = leanText.indexOf('\'', loc); >- if (loc < 0) { >- state = whichSpecial; >- return leanText.length(); >- } >- if ((loc + 1) < leanText.length() && leanText.charAt(loc + 1) == '\'') { >- loc += 2; >- continue; >- } >- return loc + 1; >- } >- case 2 : /* delimited identifier */ >- loc = operLocation + 1; >- while (true) { >- loc = leanText.indexOf('"', loc); >- if (loc < 0) >- return leanText.length(); >- >- if ((loc + 1) < leanText.length() && leanText.charAt(loc + 1) == '"') { >- loc += 2; >- continue; >- } >- return loc + 1; >- } >- case 3 : /* slash-aster comment */ >- if (operLocation < 0) >- loc = 0; // initial state from previous line >- else >- loc = operLocation + 2; // skip the opening slash-aster >- loc = leanText.indexOf("*/", loc); >- if (loc < 0) { >- state = whichSpecial; >- return leanText.length(); >- } >- // we need to call processOperator since text may follow the >- // end of comment immediately without even a space >- processOperator(loc); >- return loc + 2; >- case 4 : /* hyphen-hyphen comment */ >- loc = leanText.indexOf(lineSep, operLocation + 2); >- if (loc < 0) >- return leanText.length(); >- return loc + lineSep.length(); >- } >- // we should never get here >- return leanText.length(); >- } >+ private static final byte WS = Character.DIRECTIONALITY_WHITESPACE; >+ static final String operators = "\t!#%&()*+,-./:;<=>?|[]{}"; //$NON-NLS-1$ >+ static String lineSep; >+ >+ /** >+ * Constructor for a complex expressions processor with support for >+ * SQL statements. >+ */ >+ public ComplExpSql() { >+ super(operators, 5); >+ // TBD use bundle properties >+ if (lineSep == null) >+ lineSep = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int indexOfSpecial(int whichSpecial, String srcText, int fromIndex) { >+ switch (whichSpecial) { >+ 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$ >+ } >+ // we should never get here >+ return -1; >+ } >+ >+ /** >+ * This method is not supposed to be invoked directly by users of this >+ * class. It may be overridden by subclasses of this class. >+ */ >+ protected int processSpecial(int whichSpecial, String srcText, int operLocation) { >+ int loc; >+ >+ processOperator(operLocation); >+ switch (whichSpecial) { >+ case 0 : /* space */ >+ operLocation++; >+ while (operLocation < srcText.length() && srcText.charAt(operLocation) == ' ') { >+ setDirProp(operLocation, WS); >+ operLocation++; >+ } >+ return operLocation; >+ case 1 : /* literal */ >+ loc = operLocation + 1; >+ while (true) { >+ loc = srcText.indexOf('\'', loc); >+ if (loc < 0) { >+ state = whichSpecial; >+ return srcText.length(); >+ } >+ if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '\'') { >+ loc += 2; >+ continue; >+ } >+ return loc + 1; >+ } >+ case 2 : /* delimited identifier */ >+ loc = operLocation + 1; >+ while (true) { >+ loc = srcText.indexOf('"', loc); >+ if (loc < 0) >+ return srcText.length(); >+ >+ if ((loc + 1) < srcText.length() && srcText.charAt(loc + 1) == '"') { >+ loc += 2; >+ continue; >+ } >+ return loc + 1; >+ } >+ case 3 : /* slash-aster comment */ >+ if (operLocation < 0) >+ loc = 0; // initial state from previous line >+ else >+ loc = operLocation + 2; // skip the opening slash-aster >+ loc = srcText.indexOf("*/", loc); //$NON-NLS-1$ >+ if (loc < 0) { >+ state = whichSpecial; >+ return srcText.length(); >+ } >+ // we need to call processOperator since text may follow the >+ // end of comment immediately without even a space >+ processOperator(loc); >+ return loc + 2; >+ case 4 : /* hyphen-hyphen comment */ >+ loc = srcText.indexOf(lineSep, operLocation + 2); >+ if (loc < 0) >+ return srcText.length(); >+ return loc + lineSep.length(); >+ } >+ // we should never get here >+ return srcText.length(); >+ } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 183164
:
148967
|
157821
|
158092
|
158531
|
160015
|
160017
|
160081
|
160698
|
160858
|
162228
|
162229
|
164476
|
186038
|
186054
|
186488
|
186490
|
188406
|
188407
|
188408
|
188627
|
194078
|
194079
|
195082
|
195084
|
196575
|
196576
|
199068
|
199070
|
199113
|
199855
|
200008
|
200389
|
200629
|
200630
|
200631
|
200742
|
200743
|
200803
|
200805
|
200905
|
200907
|
201464
|
201465
|
201467
|
201468
|
201469
|
201470
|
201676
|
201677
|
201785
|
201787
|
202172
|
202173
|
205767
|
205768
|
206588
|
210657