ComplExpBasic
is a
- * complex expression processor for simple types of complex expressions.
- * Normally, a group of operatorsis specified when creating a new - * instance. - * Lean text which is submitted to this processor is divided into - * segments by the operators. The processor adds directional formatting - * characters into the lean text to generate a full text where - * operators and text segments will be presented in left-to-right sequence. - * - * @see IComplExpProcessor - * - * @author Matitiahu Allouche - */ -public class ComplExpBasic implements IComplExpProcessor { - - 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
mirroredDefault
- * for the parent complex expression instance.
- * @see #assumeMirrored
- * @see #isMirrored
- * @see ComplExpUtil#mirroredDefault
- */
- protected boolean mirrored = ComplExpUtil.mirroredDefault;
-
- /**
- * 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 ORIENT_LTR
.
- * - * The orientation affects the addition of directional formatting - * characters as prefix and/or suffix when generating the full - * 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 int type; - - /** - * Base direction of the complex expression. This is an array such that - *
direction[0][0]
represents the base direction
- * for Arabic when the GUI is not mirrored.
- * direction[0][1]
represents the base direction
- * for Arabic when the GUI is mirrored.
- * direction[1][0]
represents the base direction
- * for Hebrew when the GUI is not mirrored.
- * direction[1][1]
represents the base direction
- * for Hebrew when the GUI is mirrored.
- * DIRECTION_LTR
.
- *
- * @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 state
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.
- *
- * state
should be used only for complex expressions
- * which span more than one line, when the user makes a separate call to
- * leanToFullText
, fullToLeanText
or
- * leanBidiCharOffsets
for each
- * line in the expression. The final state value retrieved after the
- * call for one line should be used as the initial state in the call
- * which processes the next line.
- *
- * If a line within a complex expression has already been processed by
- * leanToFullText
and the lean version of that line has
- * not changed, and its initial state has not changed either, the user
- * can be sure that the full version of that line is also
- * identical to the result of the previous processing.
- *
- * @see 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;
-
- static final byte B = Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR;
- static final byte L = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
- static final byte R = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
- static final byte AL = Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
- static final byte AN = Character.DIRECTIONALITY_ARABIC_NUMBER;
- static final byte EN = Character.DIRECTIONALITY_EUROPEAN_NUMBER;
- static final char LRM = 0x200E;
- static final char RLM = 0x200F;
- static final char LRE = 0x202A;
- static final char RLE = 0x202B;
- static final char PDF = 0x202C;
- static final char[] MARKS = {LRM, RLM};
- static final char[] EMBEDS = {LRE, RLE};
- static final byte[] STRONGS = {L, R};
- static final int PREFIX_LENGTH = 2;
- static final int SUFFIX_LENGTH = 2;
- 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 lean text to generate a full
- * 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 UBA.
- *
- * @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];
- }
-
- /**
- * Constructor specifying operators and a number of special cases.
- * In ComplExpBasic
the special cases are implemented as
- * doing nothing. Subclasses of ComplExpBasic
may override
- * methods indexOfSpecial
and processSpecial
- * 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.
- *
- * Independently of the special cases, the processor will add directional
- * formatting characters to lean text to generate a full
- * 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 UBA.
- *
- * @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 indexOfSpecial
and
- * processSpecial
.
- *
- * @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 leanToFullText
to
- * locate all special cases specified in the constructor
- * (see {@link #ComplExpBasic(String operators, int specialsCount)}),
- * varying whichSpecial
from zero to
- * specialsCount - 1
. It is meant to be overridden in
- * subclasses of ComplExpBasic
.
- * Those subclasses may use methods
- * {@link #getDirProp getDirProp},
- * {@link #setDirProp setDirProp} and
- * {@link #insertMark insertMark} within indexOfSpecial
.
- *
- * @param whichSpecial number of the special case to locate. The meaning
- * of this number is internal to the class implementing
- * indexOfSpecial
.
- *
- * @param text text of the complex expression.
- *
- * @param fromIndex the index within leanText
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
- * fromIndex
. 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.
- *
- * In ComplExpBasic
this method always returns -1.
- *
- */
- protected int indexOfSpecial(int whichSpecial, String text, int fromIndex) {
- // This method must be overridden by all subclasses with special cases.
- return -1;
- }
-
- /**
- * This method is called by leanToFullText
- * when a special case occurrence is located by
- * {@link #indexOfSpecial indexOfSpecial}.
- * It is meant to be overridden in subclasses of ComplExpBasic
.
- * Those subclasses may use methods
- * {@link #getDirProp getDirProp},
- * {@link #setDirProp setDirProp} and
- * {@link #insertMark insertMark} within processSpecial
.
- *
- * If a special processing cannot be completed within a current call to
- * processSpecial
(for instance, a comment has been started
- * in the current line but its end appears in a following line),
- * processSpecial
should 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, processSpecial
will be
- * called with that value for parameter whichSpecial
and
- * -1
for parameter operLocation
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 indexOfSpecial
.
- * In calls to leanToFullText
or
- * fullToLeanText
specifying an initState
- * parameter, processSpecial
is called when initializing
- * the processing with the value of whichSpecial
- * equal to initState
and the value of
- * operLocation
equal to -1
.
- *
- * @return the position after the scope of the special case ends.
- * For instance, the position after the end of a comment,
- * the position after the end of a literal.
- *
- * In ComplExpBasic
this method always returns
- * operLocation + 1
(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
- * ComplExpBasic
to retrieve the bidirectional class of
- * characters in leanText
.
- *
- * @param index position of the character in leanText
.
- *
- * @return the bidirectional class of the character. It is one of the
- * values which can be returned by
- * java.lang.Character#getDirectionality
.
- * However, it is recommended to use getDirProp
- * rather than java.lang.Character.getDirectionality
- * since getDirProp
manages a cache of character
- * properties and so can be more efficient than calling the
- * java.lang.Character method.
- *
- */
- 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
- * ComplExpBasic
to set or override the bidirectional
- * class of characters in leanText
.
- *
- * @param index position of the character in leanText
.
- *
- * @param dirProp bidirectional class of the character. It is one of the
- * values which can be returned by
- * java.lang.Character.getDirectionality
.
- *
- */
- 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
- * ComplExpBasic
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 leanText
preceding and following
- * the operator itself.
- *
- * @param operLocation offset of the operator in leanText
.
- *
- */
- 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 ComplExpBasic
- * to specify that a mark character must be added before the character
- * at the specified position of the lean text when generating the
- * full text. The mark character will be LRM for complex expressions
- * with a LTR base direction, and RLM for complex expressions with RTL
- * base direction. The mark character is not added physically by this
- * method, but its position is noted and will be used when generating
- * the full text.
- *
- * @param offset position of the character in leanText
.
- * It must be a non-negative number smaller than the length
- * of the lean text.
- * For the benefit of efficiency, it is better to insert
- * multiple marks in ascending order of the offsets.
- *
- */
- 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 desiredOrientation) {
- if (desiredOrientation < ORIENT_LTR || desiredOrientation > ORIENT_IGNORE)
- orientation = ORIENT_UNKNOWN; // TBD should throw new IllegalArgumentException()?
- orientation = desiredOrientation;
- }
-
- 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/complexp/ComplExpDelims.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpDelims.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpDelims.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpDelims.java 2 Feb 2010 21:55:25 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,73 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.equinox.bidi.complexp;
-
-/**
- * ComplExpDelims
is a processor for complex expressions
- * composed of text segments separated by operators where the text segments
- * may include delimited parts within which operators are treated like
- * regular characters.
- *
- * @see IComplExpProcessor
- * @see ComplExpBasic
- *
- * @author Matitiahu Allouche
- */
-public class ComplExpDelims extends ComplExpBasic {
- 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 lean
- * 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];
-
- return leanText.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;
- }
-}
Index: src/org/eclipse/equinox/bidi/complexp/ComplExpDelimsEsc.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpDelimsEsc.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpDelimsEsc.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpDelimsEsc.java 2 Feb 2010 21:55:25 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.equinox.bidi.complexp;
-
-/**
- * ComplExpDelims
is a processor for complex expressions
- * composed of text segments separated by operators where the text segments
- * may include delimited parts within which operators are treated like
- * regular characters and the delimiters may be escaped.
- * This is similar to {@link ComplExpDelims} except
- * that delimiters can be escaped using the backslash character.
- *
IComplExpProcessor
interface but does no real processing.
- * Since it is optimized for minimal overhead, it can
- * be used as a low-cost default processor when no complex expression is
- * involved and no processing is needed, but a general framework of
- * handling complex expressions must be preserved.
- *
- * @author Matitiahu Allouche
- */
-
-public class ComplExpDoNothing implements IComplExpProcessor {
-
- private static final int[] EMPTY_INT_ARRAY = new int[0];
- private static final int[][] ALL_LTR = new int[][] { {DIRECTION_LTR, DIRECTION_LTR}, {DIRECTION_LTR, DIRECTION_LTR}};
-
- /**
- * Allocate a ComplExpDoNothing
processor instance.
- * Such a processor does not modify text submitted to it, and can be
- * used as a place holder when the text to process is not a known
- * complex expression.
- */
- public ComplExpDoNothing() {
- return;
- }
-
- /**
- * For class ComplExpDoNothing
- * this method does nothing.
- */
- public void selectBidiScript(boolean arabic, boolean hebrew) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
- * this method always returns false
.
- */
- public boolean handlesArabicScript() {
- return false;
- }
-
- /**
- * For class ComplExpDoNothing
- * this method always returns false
.
- */
- public boolean handlesHebrewScript() {
- return false;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a string identical to the text
parameter.
- */
- public String leanToFullText(String text) {
- return text;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a string identical to the text
parameter.
- */
- public String leanToFullText(String text, int initState) {
- return text;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a zero length array.
- */
- public int[] leanBidiCharOffsets(String text) {
- return EMPTY_INT_ARRAY;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a zero length array.
- */
- public int[] leanBidiCharOffsets(String text, int initState) {
- return EMPTY_INT_ARRAY;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a zero length array.
- */
- public int[] leanBidiCharOffsets() {
- return EMPTY_INT_ARRAY;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a zero length array.
- */
- public int[] fullBidiCharOffsets() {
- return EMPTY_INT_ARRAY;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a string identical to the text
parameter.
- */
- public String fullToLeanText(String text) {
- return text;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns a string identical to the text
parameter.
- */
- public String fullToLeanText(String text, int initState) {
- return text;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns value {@link #STATE_NOTHING_GOING}.
- */
- public int getFinalState() {
- return STATE_NOTHING_GOING;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns an index identical to the pos
parameter.
- */
- public int leanToFullPos(int pos) {
- return pos;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns an index identical to the pos
parameter.
- */
- public int fullToLeanPos(int pos) {
- return pos;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void assumeMirrored(boolean mirrored) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * always returns false
.
- */
- public boolean isMirrored() {
- return false;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void assumeOrientation(int orientation) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * always returns ORIENT_LTR
.
- */
- public int recallOrientation() {
- return ORIENT_LTR;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setArabicDirection(int not_mirrored, int mirrored) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setArabicDirection(int direction) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setHebrewDirection(int not_mirrored, int mirrored) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setHebrewDirection(int direction) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setDirection(int not_mirrored, int mirrored) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * does nothing.
- */
- public void setDirection(int direction) {
- // empty
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns all directions as DIRECTION_LTR
.
- */
- public int[][] getDirection() {
- return ALL_LTR;
- }
-
- /**
- * For class ComplExpDoNothing
this method
- * returns DIRECTION_LTR
.
- */
- public int getCurDirection() {
- return DIRECTION_LTR;
- }
-}
Index: src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/complexp/ComplExpFactory.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.complexp;
+
+import org.eclipse.equinox.bidi.internal.complexp.BiDiTypesCollector;
+
+/**
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+// TBD do we really want to provide individual instances of the text processors?
+final public class ComplExpFactory implements IBiDiProcessor {
+
+ /**
+ * Factory method to create a new instance of the bi-directional text
+ * processor for the specified text type. This method may return null
+ * if it is unable to locate processor for the specified text type.
+ *
+ * @see #PROPERTY
+ * @see #UNDERSCORE
+ * @see #COMMA_DELIMITED
+ * @see #SYSTEM_USER
+ * @see #FILE
+ * @see #EMAIL
+ * @see #URL
+ * @see #REGEXP
+ * @see #XPATH
+ * @see #JAVA
+ * @see #SQL
+ * @see #RTL_ARITHMETIC
+ *
+ * @param type specifies the type of complex expression to process.
+ * @return a IComplExpProcessor
instance capable of handling
+ * the type of complex expression specified. May return null
+ * if the processor not found.
+ */
+ public static IComplExpProcessor create(String type) {
+ return BiDiTypesCollector.getInstance().makeProcessor(type);
+ }
+
+}
Index: src/org/eclipse/equinox/bidi/complexp/ComplExpJava.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpJava.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpJava.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpJava.java 2 Feb 2010 21:55:25 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.equinox.bidi.complexp;
-
-/**
- * ComplExpJava
is a processor for complex expressions
- * composed of Java statements. Such a complex expression may span
- * multiple lines.
- *
- * In applications like an editor where parts of the text might be modified
- * while other parts are not, the user may want to call
- * {@link IComplExpProcessor#leanToFullText leanToFullText}
- * separately on each line and save the initial state of each line (this is
- * the final state of the previous line which can be retrieved using
- * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
- * of a line and its initial state have not changed, the user can be sure that
- * the last full text computed for this line has not changed either.
- *
- * @see IComplExpProcessor
- * @see ComplExpBasic#state
- *
- * @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;
- }
-}
Index: src/org/eclipse/equinox/bidi/complexp/ComplExpRegex.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpRegex.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpRegex.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpRegex.java 2 Feb 2010 21:55:25 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,200 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.equinox.bidi.complexp;
-
-/**
- * ComplExpRegex
is a processor for regular expressions.
- * Such expressions may span multiple lines.
- *
- * In applications like an editor where parts of the text might be modified
- * while other parts are not, the user may want to call
- * {@link IComplExpProcessor#leanToFullText leanToFullText}
- * separately on each line and save the initial state of each line (this is
- * the final state of the previous line which can be retrieved using
- * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
- * of a line and its initial state have not changed, the user can be sure that
- * the last full text computed for this line has not changed either.
- *
- * @see IComplExpProcessor
- * @see ComplExpBasic#state
- *
- * @author Matitiahu Allouche
- */
-public class ComplExpRegex extends ComplExpBasic {
- static final String operators = "";
- static final String[] startStrings = {"(?#", /* 0 *//* comment (?#...) */
- "(?<", /* 1 *//* named group (?
- * In applications like an editor where parts of the text might be modified
- * while other parts are not, the user may want to call
- * {@link IComplExpProcessor#leanToFullText leanToFullText}
- * separately on each line and save the initial state of each line (this is
- * the final state of the previous line which can be retrieved using
- * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
- * of a line and its initial state have not changed, the user can be sure that
- * the last full text computed for this line has not changed either.
- *
- * @see IComplExpProcessor
- * @see ComplExpBasic#state
- *
- * @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();
- }
-}
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.1
diff -u -r1.1 ComplExpUtil.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java 2 Feb 2010 21:55:25 -0000 1.1
+++ src/org/eclipse/equinox/bidi/complexp/ComplExpUtil.java 3 Feb 2010 19:53:44 -0000
@@ -11,6 +11,7 @@
package org.eclipse.equinox.bidi.complexp;
import java.util.Locale;
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
/**
* This class provides a number of convenience functions facilitating the
@@ -40,225 +41,6 @@
* @author Matitiahu Allouche
*/
final public class ComplExpUtil {
- /**
- * Constant indicating a default type of complex expression processor.
- * This type does not add any directional formatting character, it is
- * a "transparent" processor.
- *
- * @see #create
- */
- public static final int DEFAULT = 0;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing property file statements.
- * This type covers expression of the form
+ * The orientation affects the addition of directional formatting
+ * characters as prefix and/or suffix when generating the full
+ * 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 int type;
+
+ /**
+ * Base direction of the complex expression. This is an array such that
+ *
+ *
+ * If a line within a complex expression has already been processed by
+ *
+ * Independently of the special cases, the processor will add directional
+ * formatting characters to lean text to generate a full
+ * 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 UBA.
+ *
+ * @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
+ * In
+ * If a special processing cannot be completed within a current call to
+ *
+ * In
+ * In applications like an editor where parts of the text might be modified
+ * while other parts are not, the user may want to call
+ * {@link IComplExpProcessor#leanToFullText leanToFullText}
+ * separately on each line and save the initial state of each line (this is
+ * the final state of the previous line which can be retrieved using
+ * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
+ * of a line and its initial state have not changed, the user can be sure that
+ * the last full text computed for this line has not changed either.
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic#state
+ *
+ * @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;
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpMath.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpMath.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpMath.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpMath.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+/**
+ * Processor adapted to processing arithmetic expressions with right-to-left
+ * base direction.
+ */
+public class ComplExpMath extends ComplExpBasic {
+ public ComplExpMath() {
+ super("+-/*()="); //$NON-NLS-1$
+ setDirection(DIRECTION_RTL);
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpProperty.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpProperty.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpProperty.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpProperty.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpSingle;
+
+/**
+ * Processor adapted to processing property file statements.
+ * It expects the following string format:
+ *
+ * In applications like an editor where parts of the text might be modified
+ * while other parts are not, the user may want to call
+ * {@link IComplExpProcessor#leanToFullText leanToFullText}
+ * separately on each line and save the initial state of each line (this is
+ * the final state of the previous line which can be retrieved using
+ * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
+ * of a line and its initial state have not changed, the user can be sure that
+ * the last full text computed for this line has not changed either.
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic#state
+ *
+ * @author Matitiahu Allouche
+ */
+public class ComplExpRegex extends ComplExpBasic {
+ static final String operators = "";
+ static final String[] startStrings = {"(?#", /* 0 *//* comment (?#...) */
+ "(?<", /* 1 *//* named group (?
+ * In applications like an editor where parts of the text might be modified
+ * while other parts are not, the user may want to call
+ * {@link IComplExpProcessor#leanToFullText leanToFullText}
+ * separately on each line and save the initial state of each line (this is
+ * the final state of the previous line which can be retrieved using
+ * {@link IComplExpProcessor#getFinalState getFinalState}. If both the content
+ * of a line and its initial state have not changed, the user can be sure that
+ * the last full text computed for this line has not changed either.
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic#state
+ *
+ * @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();
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSystem.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSystem.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSystem.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpSystem.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpSingle;
+
+/**
+ * Processor adapted to processing expressions with the following string format:
+ * ComplExpSingle
is a processor for complex expressions
- * composed of two parts separated by an operator.
- * The first occurrence of the operator delimits the end of the first part
- * and the start of the second part. Further occurrences of the operator,
- * if any, are treated like regular characters of the second text part.
- * The processor makes sure that the expression be presented in the form
- * (assuming that the equal sign is the operator):
- *
- * part1=part2
- *
- *
- * @see IComplExpProcessor
- * @see ComplExpBasic
- *
- * @author Matitiahu Allouche
- */
-public class ComplExpSingle extends ComplExpBasic {
- 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);
- }
-
- /**
- * 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 processSpecial(int whichSpecial, String leanText, int operLocation) {
- processOperator(operLocation);
- return leanText.length();
- }
-}
Index: src/org/eclipse/equinox/bidi/complexp/ComplExpSql.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/ComplExpSql.java
diff -N src/org/eclipse/equinox/bidi/complexp/ComplExpSql.java
--- src/org/eclipse/equinox/bidi/complexp/ComplExpSql.java 2 Feb 2010 21:55:25 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,135 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2010 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- ******************************************************************************/
-package org.eclipse.equinox.bidi.complexp;
-
-/**
- * ComplExpSql
is a processor for complex expressions
- * composed of SQL statements. Such a complex expression may span
- * multiple lines.
- *
- * name=value
- *
- * @see #create
- */
- public static final int PROPERTY = 1;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing compound names.
- * This type covers names made of one or more parts, each one connected
- * to the previous one by one underscore, as below:
- * part1_part2_part3
- *
- * @see #create
- */
- public static final int COMPOUND_NAME = 2;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing comma-delimited lists.
- * This types covers expressions made of one or more parts, each one
- * separated from the previous one by a comma, as below:
- * part1,part2,part3
- *
- * @see #create
- */
- public static final int COMMA_DELIMITED = 3;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing system(user)
constructs.
- * This type covers expression of the form
- * system(user)
- * with a system name immediately followed by a user name within
- * parentheses.
- *
- * @see #create
- */
- public static final int SYSTEM_USER = 4;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing directory and file paths.
- *
- * @see #create
- */
- public static final int PATH = 5;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing e-mail addresses.
- *
- * @see #create
- */
- public static final int EMAIL = 6;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing URLs.
- *
- * @see #create
- */
- public static final int URL = 7;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing regular expressions, possibly spanning more than one
- * line.
- *
- * @see #create
- */
- public static final int REGEXP = 8;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing Xpath expressions.
- *
- * @see #create
- */
- public static final int XPATH = 9;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing Java code, possibly spanning more than one line.
- *
- * @see #create
- */
- public static final int JAVA = 10;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing SQL statements, possibly spanning more than one line.
- *
- * @see #create
- */
- public static final int SQL = 11;
-
- /**
- * Constant indicating a type of complex expression processor adapted
- * to processing arithmetic expressions with a RTL base direction.
- *
- * @see #create
- */
- public static final int RTL_ARITHMETIC = 12;
-
- /** Constant indicating the highest value used in this package for
- * types of complex expressions.
- * @see #create
- */
- public static final int HIGHEST = 12;
-
- /** Constant indicating the base direction of a string representing
- * a left-to-right complex expression.
- * @see #insertMarks
- */
- public static final int DIRECTION_LTR = IComplExpProcessor.DIRECTION_LTR;
-
- /** Constant indicating the base direction of a string representing
- * a right-to-left complex expression.
- * @see #insertMarks
- */
- public static final int DIRECTION_RTL = IComplExpProcessor.DIRECTION_RTL;
-
- /**
- * prevent instantiation
- */
- private ComplExpUtil() {
- // empty
- }
-
- /**
- * Factory method to create specialized implementations
- * of IComplExpProcessor
adapted to specific types of
- * complex expressions.
- *
- * @param type specifies the type of complex expression to process.
- * This must be one of the values
- * {@link #DEFAULT},
- * {@link #PROPERTY},
- * {@link #COMPOUND_NAME},
- * {@link #COMMA_DELIMITED},
- * {@link #SYSTEM_USER},
- * {@link #PATH},
- * {@link #EMAIL},
- * {@link #URL},
- * {@link #REGEXP},
- * {@link #XPATH},
- * {@link #JAVA},
- * {@link #SQL},
- * {@link #RTL_ARITHMETIC}
- *
- * @return a IComplExpProcessor
instance capable of
- * handling the type of complex expression specified.
- * If the type
is not a valid value,
- * null
is returned.
- *
- */
- public static IComplExpProcessor create(int type) {
- IComplExpProcessor complexp;
- if (type == DEFAULT) {
- return new ComplExpDoNothing();
- }
- switch (type) {
- case PROPERTY :
- complexp = new ComplExpSingle("=");
- break;
- case COMPOUND_NAME :
- complexp = new ComplExpBasic("_");
- break;
- case COMMA_DELIMITED :
- complexp = new ComplExpBasic(",");
- break;
- case SYSTEM_USER :
- complexp = new ComplExpSingle("(");
- break;
- case PATH :
- complexp = new ComplExpBasic(":/\\.");
- break;
- case EMAIL :
- complexp = new ComplExpDelimsEsc("<>.:,;@", "()\"\"");
- break;
- case URL :
- complexp = new ComplExpBasic(":?#/@.[]");
- break;
- case REGEXP :
- complexp = new ComplExpRegex();
- break;
- case XPATH :
- complexp = new ComplExpDelims(" /[]<>=!:@.|()+-*", "''\"\"");
- break;
- case JAVA :
- complexp = new ComplExpJava();
- break;
- case SQL :
- complexp = new ComplExpSql();
- break;
- case RTL_ARITHMETIC :
- complexp = new ComplExpBasic("+-/*()=");
- complexp.setDirection(IComplExpProcessor.DIRECTION_RTL);
- break;
- default :
- return null;
- }
- ((ComplExpBasic) complexp).type = type;
- return complexp;
- }
/**
* Flag specifying that all complex expressions should by default assume
@@ -271,6 +53,13 @@
*/
static boolean mirroredDefault;
+ /**
+ * prevents instantiation
+ */
+ private ComplExpUtil() {
+ // empty
+ }
+
/** Specify whether the GUI where the complex expression will be displayed
* is mirrored (is laid out from right to left). The value specified in
* this method sets a default for all complex expressions to be created
@@ -320,8 +109,8 @@
* This argument may be null if there are no marks to add.
*
* @param direction specifies the base direction of the complex expression.
- * It must be one of the values {@link #DIRECTION_LTR} or
- * {@link #DIRECTION_RTL}.
+ * It must be one of the values {@link IComplExpProcessor#DIRECTION_LTR} or
+ * {@link IComplExpProcessor#DIRECTION_RTL}.
*
* @param affix specifies if a prefix and a suffix should be added to
* the result to make sure that the direction
@@ -342,7 +131,7 @@
String curPrefix, curSuffix, full;
char curMark, c;
char[] fullChars;
- if (direction == DIRECTION_LTR) {
+ if (direction == IComplExpProcessor.DIRECTION_LTR) {
curMark = LRM;
curPrefix = "\u202a\u200e";
curSuffix = "\u200e\u202c";
@@ -526,7 +315,7 @@
*
* @return the processed string
*/
- public static String process(String str, int type) {
+ public static String processTyped(String str, String type) {
if ((str == null) || (str.length() <= 1) || (getProcessingNeededScore() != 3))
return str;
@@ -535,7 +324,7 @@
if (((c == LRE) || (c == RLE)) && str.charAt(str.length() - 1) == PDF)
return str;
- IComplExpProcessor processor = create(type);
+ IComplExpProcessor processor = ComplExpFactory.create(type);
if (processor == null) // invalid type
return str;
@@ -588,11 +377,11 @@
* @return string with no directional formatting characters
*
*/
- public static String deprocess(String str, int type) {
+ public static String deprocess(String str, String type) {
if ((str == null) || (str.length() <= 1) || (getProcessingNeededScore() != 3))
return str;
- IComplExpProcessor processor = create(type);
+ IComplExpProcessor processor = ComplExpFactory.create(type);
if (processor == null) // invalid type
return str;
Index: src/org/eclipse/equinox/bidi/complexp/IBiDiProcessor.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/IBiDiProcessor.java
diff -N src/org/eclipse/equinox/bidi/complexp/IBiDiProcessor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/complexp/IBiDiProcessor.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.complexp;
+
+/**
+ * Bi-directional processors supplied in this bundle.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface IBiDiProcessor {
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing property file statements. It expects the following
+ * string format:
+ *
+ * name=value
+ *
+ */
+ public String PROPERTY = "property"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing compound names.
+ * This type covers names made of one or more parts separated by underscores:
+ *
+ * part1_part2_part3
+ *
+ */
+ public String UNDERSCORE = "underscore"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing comma-delimited lists, such as:
+ *
+ * part1,part2,part3
+ *
+ */
+ public String COMMA_DELIMITED = "comma"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing expressions with the following string format:
+ *
+ * system(user)
+ *
+ */
+ public String SYSTEM_USER = "system"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing directory and file paths.
+ */
+ public String FILE = "file"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing e-mail addresses.
+ */
+ public String EMAIL = "email"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing URLs.
+ */
+ public String URL = "url"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing regular expressions, possibly spanning more than one
+ * line.
+ */
+ public String REGEXP = "regex"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing XPath expressions.
+ */
+ public String XPATH = "xpath"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing Java code, possibly spanning more than one line.
+ */
+ public String JAVA = "java"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing SQL statements, possibly spanning more than one line.
+ */
+ public String SQL = "sql"; //$NON-NLS-1$
+
+ /**
+ * Constant indicating a type of complex expression processor adapted
+ * to processing arithmetic expressions with a RTL base direction.
+ */
+ public String RTL_ARITHMETIC = "math"; //$NON-NLS-1$
+}
Index: src/org/eclipse/equinox/bidi/complexp/IComplExpProcessor.java
===================================================================
RCS file: /cvsroot/rt/org.eclipse.equinox/components/bundles/org.eclipse.equinox.bidi/src/org/eclipse/equinox/bidi/complexp/IComplExpProcessor.java,v
retrieving revision 1.1
diff -u -r1.1 IComplExpProcessor.java
--- src/org/eclipse/equinox/bidi/complexp/IComplExpProcessor.java 2 Feb 2010 21:55:25 -0000 1.1
+++ src/org/eclipse/equinox/bidi/complexp/IComplExpProcessor.java 3 Feb 2010 19:53:44 -0000
@@ -10,6 +10,8 @@
******************************************************************************/
package org.eclipse.equinox.bidi.complexp;
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
/**
* This interface provides a generic mechanism to handle
* complex expressions, with as main purpose to ensure that they are
Index: src/org/eclipse/equinox/bidi/complexp/StringProcessor.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/complexp/StringProcessor.java
diff -N src/org/eclipse/equinox/bidi/complexp/StringProcessor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/complexp/StringProcessor.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.complexp;
+
+import org.eclipse.equinox.bidi.internal.complexp.BiDiTypesCollector;
+
+/**
+ * The API part for the TextProcessor replacement.
+ */
+// TBD processors currently are not thread-safe (ComplExpBasic has class variables containing
+// parsing state). This means that either:
+// a) a new instance of the processor needs to be created for every call;
+// b) processors have to be made thread-safe.
+public class StringProcessor {
+
+ static public String[] getKnownTypes() {
+ return BiDiTypesCollector.getInstance().getTypes();
+ }
+
+ static public IComplExpProcessor getProcessor(String type) {
+ return BiDiTypesCollector.getInstance().getProcessor(type);
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/BiDiActivator.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/BiDiActivator.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/BiDiActivator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/BiDiActivator.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class BiDiActivator implements BundleActivator {
+
+ private ServiceTracker logTracker = null;
+ private BundleContext bundleContext;
+
+ private static BiDiActivator instance;
+
+ public BiDiActivator() {
+ instance = this; // there is only one bundle activator
+ }
+
+ public void start(BundleContext context) throws Exception {
+ bundleContext = context;
+ instance = this;
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ if (logTracker != null) {
+ logTracker.close();
+ logTracker = null;
+ }
+ bundleContext = null;
+ }
+
+ private FrameworkLog getFrameworkLog() {
+ if (logTracker == null) {
+ logTracker = new ServiceTracker(bundleContext, FrameworkLog.class.getName(), null);
+ logTracker.open();
+ }
+ return (FrameworkLog) logTracker.getService();
+ }
+
+ static public void logError(String message, Exception e) {
+ FrameworkLog frameworkLog = instance.getFrameworkLog();
+ if (frameworkLog != null) {
+ frameworkLog.log(new FrameworkLogEntry("org.eclipse.equinox.bidi", FrameworkLogEntry.ERROR, 1, message, 0, e, null)); //$NON-NLS-1$
+ return;
+ }
+ System.err.println(message);
+ if (e != null)
+ e.printStackTrace();
+ }
+
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/BiDiTypesCollector.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/BiDiTypesCollector.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/BiDiTypesCollector.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/BiDiTypesCollector.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+public class BiDiTypesCollector implements IRegistryEventListener {
+
+ private static final String EXT_POINT = "org.eclipse.equinox.bidi.bidiTypes"; //$NON-NLS-1$
+
+ private static final String CE_NAME = "typeDescription"; //$NON-NLS-1$
+ private static final String ATTR_TYPE = "type"; //$NON-NLS-1$
+ private static final String ATTR_PROCESSOR = "class"; //$NON-NLS-1$
+
+ private Map types;
+ private Map factories;
+
+ static private BiDiTypesCollector instance = new BiDiTypesCollector();
+
+ private BiDiTypesCollector() {
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ registry.addListener(this, EXT_POINT);
+ }
+
+ static public BiDiTypesCollector getInstance() {
+ return instance;
+ }
+
+ public String[] getTypes() {
+ if (types == null)
+ read();
+ int size = types.size();
+ String[] result = new String[size];
+ types.keySet().toArray(result);
+ return result;
+ }
+
+ public IComplExpProcessor getProcessor(String type) {
+ if (types == null)
+ read();
+ Object processor = types.get(type);
+ if (processor instanceof IComplExpProcessor)
+ return (IComplExpProcessor) processor;
+ return null;
+ }
+
+ public IComplExpProcessor makeProcessor(String type) {
+ if (factories == null)
+ read();
+ IConfigurationElement ce = (IConfigurationElement) factories.get(type);
+ if (ce == null)
+ return null;
+ Object processor;
+ try {
+ processor = ce.createExecutableExtension(ATTR_PROCESSOR);
+ } catch (CoreException e) {
+ BiDiActivator.logError("BiDi types: unable to create processor for " + type, e); //$NON-NLS-1$
+ return null;
+ }
+ if (processor instanceof IComplExpProcessor)
+ return (IComplExpProcessor) processor;
+ return null;
+ }
+
+ private void read() {
+ if (types == null)
+ types = new HashMap();
+ else
+ types.clear();
+
+ if (factories == null)
+ factories = new HashMap();
+ else
+ factories.clear();
+
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ IExtensionPoint extPoint = registry.getExtensionPoint(EXT_POINT);
+ IExtension[] extensions = extPoint.getExtensions();
+
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] confElements = extensions[i].getConfigurationElements();
+ for (int j = 0; j < confElements.length; j++) {
+ if (CE_NAME != confElements[j].getName())
+ BiDiActivator.logError("BiDi types: unexpected element name " + confElements[j].getName(), new IllegalArgumentException()); //$NON-NLS-1$
+ String type = confElements[j].getAttribute(ATTR_TYPE);
+ Object processor;
+ try {
+ processor = confElements[j].createExecutableExtension(ATTR_PROCESSOR);
+ } catch (CoreException e) {
+ BiDiActivator.logError("BiDi types: unable to create processor for " + type, e); //$NON-NLS-1$
+ continue;
+ }
+ types.put(type, processor);
+ factories.put(type, confElements[j]);
+ }
+ }
+ }
+
+ public void added(IExtension[] extensions) {
+ types = null;
+ factories = null;
+ }
+
+ public void removed(IExtension[] extensions) {
+ types = null;
+ factories = null;
+ }
+
+ public void added(IExtensionPoint[] extensionPoints) {
+ types = null;
+ factories = null;
+ }
+
+ public void removed(IExtensionPoint[] extensionPoints) {
+ types = null;
+ factories = null;
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpBasic.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,976 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.equinox.bidi.complexp.ComplExpUtil;
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpBasic
is a
+ * complex expression processor for simple types of complex expressions.
+ * Normally, a group of operators
is specified when creating a new
+ * instance.
+ * Lean text which is submitted to this processor is divided into
+ * segments by the operators. The processor adds directional formatting
+ * characters into the lean text to generate a full text where
+ * operators and text segments will be presented in left-to-right sequence.
+ *
+ * @see IComplExpProcessor
+ *
+ * @author Matitiahu Allouche
+ */
+public class ComplExpBasic implements IComplExpProcessor {
+
+ 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 mirroredDefault
+ * 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 ORIENT_LTR
.
+ *
+ *
+ * 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 direction[0][0]
represents the base direction
+ * for Arabic when the GUI is not mirrored.
+ * direction[0][1]
represents the base direction
+ * for Arabic when the GUI is mirrored.
+ * direction[1][0]
represents the base direction
+ * for Hebrew when the GUI is not mirrored.
+ * direction[1][1]
represents the base direction
+ * for Hebrew when the GUI is mirrored.
+ * DIRECTION_LTR
.
+ *
+ * @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 state
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.
+ * state
should be used only for complex expressions
+ * which span more than one line, when the user makes a separate call to
+ * leanToFullText
, fullToLeanText
or
+ * leanBidiCharOffsets
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.
+ * leanToFullText
and the lean version of that line has
+ * not changed, and its initial state has not changed either, the user
+ * can be sure that the full version of that line is also
+ * identical to the result of the previous processing.
+ *
+ * @see 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 lean text to generate a full
+ * 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 UBA.
+ *
+ * @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 setType(int expressionType) {
+ type = expressionType;
+ }
+
+ /**
+ * Constructor specifying operators and a number of special cases.
+ * In ComplExpBasic
the special cases are implemented as
+ * doing nothing. Subclasses of ComplExpBasic
may override
+ * methods indexOfSpecial
and processSpecial
+ * 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.
+ * indexOfSpecial
and
+ * processSpecial
.
+ *
+ * @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 leanToFullText
to
+ * locate all special cases specified in the constructor
+ * (see {@link #ComplExpBasic(String operators, int specialsCount)}),
+ * varying whichSpecial
from zero to
+ * specialsCount - 1
. It is meant to be overridden in
+ * subclasses of ComplExpBasic
.
+ * Those subclasses may use methods
+ * {@link #getDirProp getDirProp},
+ * {@link #setDirProp setDirProp} and
+ * {@link #insertMark insertMark} within indexOfSpecial
.
+ *
+ * @param whichSpecial number of the special case to locate. The meaning
+ * of this number is internal to the class implementing
+ * indexOfSpecial
.
+ *
+ * @param text text of the complex expression.
+ *
+ * @param fromIndex the index within leanText
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
+ * fromIndex
. 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.
+ * ComplExpBasic
this method always returns -1.
+ *
+ */
+ protected int indexOfSpecial(int whichSpecial, String text, int fromIndex) {
+ // This method must be overridden by all subclasses with special cases.
+ return -1;
+ }
+
+ /**
+ * This method is called by leanToFullText
+ * when a special case occurrence is located by
+ * {@link #indexOfSpecial indexOfSpecial}.
+ * It is meant to be overridden in subclasses of ComplExpBasic
.
+ * Those subclasses may use methods
+ * {@link #getDirProp getDirProp},
+ * {@link #setDirProp setDirProp} and
+ * {@link #insertMark insertMark} within processSpecial
.
+ * processSpecial
(for instance, a comment has been started
+ * in the current line but its end appears in a following line),
+ * processSpecial
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, processSpecial
will be
+ * called with that value for parameter whichSpecial
and
+ * -1
for parameter operLocation
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 indexOfSpecial
.
+ * In calls to leanToFullText
or
+ * fullToLeanText
specifying an initState
+ * parameter, processSpecial
is called when initializing
+ * the processing with the value of whichSpecial
+ * equal to initState
and the value of
+ * operLocation
equal to -1
.
+ *
+ * @return the position after the scope of the special case ends.
+ * For instance, the position after the end of a comment,
+ * the position after the end of a literal.
+ * ComplExpBasic
this method always returns
+ * operLocation + 1
(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
+ * ComplExpBasic
to retrieve the bidirectional class of
+ * characters in leanText
.
+ *
+ * @param index position of the character in leanText
.
+ *
+ * @return the bidirectional class of the character. It is one of the
+ * values which can be returned by
+ * java.lang.Character#getDirectionality
.
+ * However, it is recommended to use getDirProp
+ * rather than java.lang.Character.getDirectionality
+ * since getDirProp
manages a cache of character
+ * properties and so can be more efficient than calling the
+ * java.lang.Character method.
+ *
+ */
+ 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
+ * ComplExpBasic
to set or override the bidirectional
+ * class of characters in leanText
.
+ *
+ * @param index position of the character in leanText
.
+ *
+ * @param dirProp bidirectional class of the character. It is one of the
+ * values which can be returned by
+ * java.lang.Character.getDirectionality
.
+ *
+ */
+ 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
+ * ComplExpBasic
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 leanText
preceding and following
+ * the operator itself.
+ *
+ * @param operLocation offset of the operator in leanText
.
+ *
+ */
+ 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 ComplExpBasic
+ * to specify that a mark character must be added before the character
+ * at the specified position of the lean text when generating the
+ * full text. The mark character will be LRM for complex expressions
+ * with a LTR base direction, and RLM for complex expressions with RTL
+ * base direction. The mark character is not added physically by this
+ * method, but its position is noted and will be used when generating
+ * the full text.
+ *
+ * @param offset position of the character in leanText
.
+ * It must be a non-negative number smaller than the length
+ * of the lean text.
+ * For the benefit of efficiency, it is better to insert
+ * multiple marks in ascending order of the offsets.
+ *
+ */
+ 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 desiredOrientation) {
+ if (desiredOrientation < ORIENT_LTR || desiredOrientation > ORIENT_IGNORE)
+ orientation = ORIENT_UNKNOWN; // TBD should throw new IllegalArgumentException()?
+ orientation = desiredOrientation;
+ }
+
+ 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: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelims.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpDelims
is a processor for complex expressions
+ * composed of text segments separated by operators where the text segments
+ * may include delimited parts within which operators are treated like
+ * regular characters.
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic
+ *
+ * @author Matitiahu Allouche
+ */
+public class ComplExpDelims extends ComplExpBasic {
+ 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 lean
+ * 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];
+
+ return leanText.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;
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDelimsEsc.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpDelims
is a processor for complex expressions
+ * composed of text segments separated by operators where the text segments
+ * may include delimited parts within which operators are treated like
+ * regular characters and the delimiters may be escaped.
+ * This is similar to {@link ComplExpDelims} except
+ * that delimiters can be escaped using the backslash character.
+ *
+ *
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic
+ *
+ * @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 lean
+ * 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.
+ *
+ * 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;
+ }
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDoNothing.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDoNothing.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDoNothing.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpDoNothing.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * This class is a minimal processor which implements the
+ * IComplExpProcessor
interface but does no real processing.
+ * Since it is optimized for minimal overhead, it can
+ * be used as a low-cost default processor when no complex expression is
+ * involved and no processing is needed, but a general framework of
+ * handling complex expressions must be preserved.
+ *
+ * @author Matitiahu Allouche
+ */
+// TBD is this needed?
+public class ComplExpDoNothing implements IComplExpProcessor {
+
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private static final int[][] ALL_LTR = new int[][] { {DIRECTION_LTR, DIRECTION_LTR}, {DIRECTION_LTR, DIRECTION_LTR}};
+
+ /**
+ * Allocate a ComplExpDoNothing
processor instance.
+ * Such a processor does not modify text submitted to it, and can be
+ * used as a place holder when the text to process is not a known
+ * complex expression.
+ */
+ public ComplExpDoNothing() {
+ return;
+ }
+
+ /**
+ * For class ComplExpDoNothing
+ * this method does nothing.
+ */
+ public void selectBidiScript(boolean arabic, boolean hebrew) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
+ * this method always returns false
.
+ */
+ public boolean handlesArabicScript() {
+ return false;
+ }
+
+ /**
+ * For class ComplExpDoNothing
+ * this method always returns false
.
+ */
+ public boolean handlesHebrewScript() {
+ return false;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a string identical to the text
parameter.
+ */
+ public String leanToFullText(String text) {
+ return text;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a string identical to the text
parameter.
+ */
+ public String leanToFullText(String text, int initState) {
+ return text;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a zero length array.
+ */
+ public int[] leanBidiCharOffsets(String text) {
+ return EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a zero length array.
+ */
+ public int[] leanBidiCharOffsets(String text, int initState) {
+ return EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a zero length array.
+ */
+ public int[] leanBidiCharOffsets() {
+ return EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a zero length array.
+ */
+ public int[] fullBidiCharOffsets() {
+ return EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a string identical to the text
parameter.
+ */
+ public String fullToLeanText(String text) {
+ return text;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns a string identical to the text
parameter.
+ */
+ public String fullToLeanText(String text, int initState) {
+ return text;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns value {@link #STATE_NOTHING_GOING}.
+ */
+ public int getFinalState() {
+ return STATE_NOTHING_GOING;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns an index identical to the pos
parameter.
+ */
+ public int leanToFullPos(int pos) {
+ return pos;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns an index identical to the pos
parameter.
+ */
+ public int fullToLeanPos(int pos) {
+ return pos;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void assumeMirrored(boolean mirrored) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * always returns false
.
+ */
+ public boolean isMirrored() {
+ return false;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void assumeOrientation(int orientation) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * always returns ORIENT_LTR
.
+ */
+ public int recallOrientation() {
+ return ORIENT_LTR;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setArabicDirection(int not_mirrored, int mirrored) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setArabicDirection(int direction) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setHebrewDirection(int not_mirrored, int mirrored) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setHebrewDirection(int direction) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setDirection(int not_mirrored, int mirrored) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * does nothing.
+ */
+ public void setDirection(int direction) {
+ // empty
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns all directions as DIRECTION_LTR
.
+ */
+ public int[][] getDirection() {
+ return ALL_LTR;
+ }
+
+ /**
+ * For class ComplExpDoNothing
this method
+ * returns DIRECTION_LTR
.
+ */
+ public int getCurDirection() {
+ return DIRECTION_LTR;
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/ComplExpSingle.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpSingle
is a processor for complex expressions
+ * composed of two parts separated by an operator.
+ * The first occurrence of the operator delimits the end of the first part
+ * and the start of the second part. Further occurrences of the operator,
+ * if any, are treated like regular characters of the second text part.
+ * The processor makes sure that the expression be presented in the form
+ * (assuming that the equal sign is the operator):
+ *
+ * part1=part2
+ *
+ *
+ * @see IComplExpProcessor
+ * @see ComplExpBasic
+ *
+ * @author Matitiahu Allouche
+ */
+public class ComplExpSingle extends ComplExpBasic {
+ 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);
+ }
+
+ /**
+ * 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 processSpecial(int whichSpecial, String leanText, int operLocation) {
+ processOperator(operLocation);
+ return leanText.length();
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpComma.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpComma.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpComma.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpComma.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+/**
+ * Processor adapted to processing comma-delimited lists, such as:
+ *
+ * part1,part2,part3
+ *
+ */
+public class ComplExpComma extends ComplExpBasic {
+ public ComplExpComma() {
+ super(","); //$NON-NLS-1$
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpEmail.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpEmail.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpEmail.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpEmail.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpDelimsEsc;
+
+/**
+ * Processor adapted to processing e-mail addresses.
+ */
+public class ComplExpEmail extends ComplExpDelimsEsc {
+ public ComplExpEmail() {
+ super("<>.:,;@", "()\"\""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpFile.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpFile.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpFile.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpFile.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+/**
+ * Processor adapted to processing directory and file paths.
+ */
+public class ComplExpFile extends ComplExpBasic {
+ public ComplExpFile() {
+ super(":/\\."); //$NON-NLS-1$
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpJava.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpJava
is a processor for complex expressions
+ * composed of Java statements. Such a complex expression may span
+ * multiple lines.
+ *
+ * name=value
+ *
+ */
+public class ComplExpProperty extends ComplExpSingle {
+
+ public ComplExpProperty() {
+ super("="); //$NON-NLS-1$
+ }
+
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpRegex.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+import org.eclipse.equinox.bidi.complexp.IComplExpProcessor;
+
+/**
+ * ComplExpRegex
is a processor for regular expressions.
+ * Such expressions may span multiple lines.
+ * ComplExpSql
is a processor for complex expressions
+ * composed of SQL statements. Such a complex expression may span
+ * multiple lines.
+ *
+ * system(user)
+ *
+ */
+public class ComplExpSystem extends ComplExpSingle {
+
+ public ComplExpSystem() {
+ super("("); //$NON-NLS-1$
+ }
+
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpURL.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpURL.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpURL.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpURL.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+/**
+ * Processor adapted to processing URLs.
+ */
+public class ComplExpURL extends ComplExpBasic {
+ public ComplExpURL() {
+ super(":?#/@.[]"); //$NON-NLS-1$
+ }
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpUnderscore.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpUnderscore.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpUnderscore.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpUnderscore.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpBasic;
+
+/**
+ * Processor adapted to processing compound names.
+ * This type covers names made of one or more parts, separated by underscores:
+ *
+ * part1_part2_part3
+ *
+ */
+public class ComplExpUnderscore extends ComplExpBasic {
+ public ComplExpUnderscore() {
+ super("_"); //$NON-NLS-1$
+ }
+
+}
Index: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpXPath.java
===================================================================
RCS file: src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpXPath.java
diff -N src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpXPath.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/equinox/bidi/internal/complexp/consumable/ComplExpXPath.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2010 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.bidi.internal.complexp.consumable;
+
+import org.eclipse.equinox.bidi.internal.complexp.ComplExpDelims;
+
+/**
+ * Processor adapted to processing XPath expressions.
+ */
+public class ComplExpXPath extends ComplExpDelims {
+ public ComplExpXPath() {
+ super(" /[]<>=!:@.|()+-*", "''\"\""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}