+#define RETURN_IF_BAD_ERRCODE(x) \
+ if (U_FAILURE(errorCode)) { \
+ log_err("\nbad errorCode %d at %s\n", errorCode, (x)); \
+ return; \
+ } \
+
+#define STRING_TEST_CASE(s) { (s), LENGTHOF(s) }
+
+static void testGetBaseDirection(void) {
+ UBiDiDirection dir;
+ int i;
+
+/* Test Data */
+ static const UChar
+/*Mixed Start with L*/
+ stringMixedEnglishFirst[]={ 0x61, 0x627, 0x32, 0x6f3, 0x61, 0x34, 0 },
+/*Mixed Start with AL*/
+ stringMixedArabicFirst[]={ 0x661, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
+/*Mixed Start with R*/
+ stringMixedHebrewFirst[]={ 0x05EA, 0x627, 0x662, 0x6f3, 0x61, 0x664, 0 },
+/*All AL (Arabic. Persian)*/
+ stringPersian[]={0x0698, 0x067E, 0x0686, 0x06AF, 0},
+/*All R (Hebrew etc.)*/
+ stringHebrew[]={0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
+/*All L (English)*/
+ stringEnglish[]={0x71, 0x61, 0x66, 0},
+/*Mixed Start with weak AL an then L*/
+ stringStartWeakAL[]={ 0x0663, 0x71, 0x61, 0x66, 0},
+/*Mixed Start with weak L and then AL*/
+ stringStartWeakL[]={0x31, 0x0698, 0x067E, 0x0686, 0x06AF, 0},
+/*Empty*/
+ stringEmpty[]={0},
+/*Surrogate Char.*/
+ stringSurrogateChar[]={0xD800, 0xDC00, 0},
+/*Invalid UChar*/
+ stringInvalidUchar[]={-1},
+/*All weak L (English Digits)*/
+ stringAllEnglishDigits[]={0x31, 0x32, 0x33, 0},
+/*All weak AL (Arabic Digits)*/
+ stringAllArabicDigits[]={0x0663, 0x0664, 0x0665, 0},
+/*First L (English) others are R (Hebrew etc.) */
+ stringFirstL[] = {0x71, 0x0590, 0x05D5, 0x05EA, 0x05F1, 0},
+/*Last R (Hebrew etc.) others are weak L (English Digits)*/
+ stringLastR[] = {0x31, 0x32, 0x33, 0x05F1, 0};
+
+ static const struct {
+ const UChar *s;
+ int32_t length;
+ } testCases[]={
+ STRING_TEST_CASE(stringMixedEnglishFirst),
+ STRING_TEST_CASE(stringMixedArabicFirst),
+ STRING_TEST_CASE(stringMixedHebrewFirst),
+ STRING_TEST_CASE(stringPersian),
+ STRING_TEST_CASE(stringHebrew),
+ STRING_TEST_CASE(stringEnglish),
+ STRING_TEST_CASE(stringStartWeakAL),
+ STRING_TEST_CASE(stringStartWeakL),
+ STRING_TEST_CASE(stringEmpty),
+ STRING_TEST_CASE(stringSurrogateChar),
+ STRING_TEST_CASE(stringInvalidUchar),
+ STRING_TEST_CASE(stringAllEnglishDigits),
+ STRING_TEST_CASE(stringAllArabicDigits),
+ STRING_TEST_CASE(stringFirstL),
+ STRING_TEST_CASE(stringLastR),
+ };
+
+/* Expected results */
+ static const UBiDiDirection expectedDir[] ={
+ UBIDI_LTR, UBIDI_RTL, UBIDI_RTL,
+ UBIDI_RTL, UBIDI_RTL, UBIDI_LTR,
+ UBIDI_LTR, UBIDI_RTL, UBIDI_NEUTRAL,
+ UBIDI_LTR, UBIDI_NEUTRAL, UBIDI_NEUTRAL,
+ UBIDI_NEUTRAL, UBIDI_LTR, UBIDI_RTL
+ };
+
+ log_verbose("testGetBaseDirection() with %u test cases ---\n",
+ LENGTHOF(testCases));
+/* Run Tests */
+ for(i=0; i<LENGTHOF(testCases); ++i) {
+ dir = ubidi_getBaseDirection(testCases[i].s, testCases[i].length );
+ log_verbose("Testing case %d\tReceived dir %d\n", i, dir);
+ if (dir != expectedDir[i])
+ log_err("\nFailed getBaseDirection case %d Expected %d \tReceived %d\n",
+ i, expectedDir[i], dir);
+ }
+
+/* Misc. tests */
+/* NULL string */
+ dir = ubidi_getBaseDirection(NULL, 3);
+ if (dir != UBIDI_NEUTRAL )
+ log_err("\nFailed getBaseDirection for NULL string " ,
+ "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
+/*All L- English string and length=-3 */
+ dir = ubidi_getBaseDirection( stringEnglish, -3);
+ if (dir != UBIDI_NEUTRAL )
+ log_err("\nFailed getBaseDirection for string w length= -3 ",
+ "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
+/*All L- English string and length=-1 */
+ dir = ubidi_getBaseDirection( stringEnglish, -1);
+ if (dir != UBIDI_LTR )
+ log_err("\nFailed getBaseDirection for English string w length= -1 ",
+ "\nExpected %d \nReceived %d", UBIDI_LTR, dir);
+/*All AL- Persian string and length=-1 */
+ dir = ubidi_getBaseDirection( stringPersian, -1);
+ if (dir != UBIDI_RTL )
+ log_err("\nFailed getBaseDirection for Persian string w length= -1 ",
+ "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
+/*All R- Hebrew string and length=-1 */
+ dir = ubidi_getBaseDirection( stringHebrew, -1);
+ if (dir != UBIDI_RTL )
+ log_err("\nFailed getBaseDirection for Hebrew string w length= -1 ",
+ "\nExpected %d \nReceived %d", UBIDI_RTL, dir);
+/*All weak L- English digits string and length=-1 */
+ dir = ubidi_getBaseDirection(stringAllEnglishDigits, -1);
+ if (dir != UBIDI_NEUTRAL )
+ log_err("\nFailed getBaseDirection for English digits string w length= -1 ",
+ "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
+/*All weak AL- Arabic digits string and length=-1 */
+ dir = ubidi_getBaseDirection(stringAllArabicDigits, -1);
+ if (dir != UBIDI_NEUTRAL )
+ log_err("\nFailed getBaseDirection for Arabic string w length= -1 ",
+ "\nExpected %d \nReceived %d", UBIDI_NEUTRAL, dir);
+
+}
+
+
+static void doMisc(void) {
+/* Miscellaneous tests to exercize less popular code paths */
+ UBiDi *bidi, *bidiLine;
+ UChar src[MAXLEN], dest[MAXLEN];
+ int32_t srcLen, destLen, runCount, i;
+ UBiDiLevel level;
+ UBiDiDirection dir;
+ int32_t map[MAXLEN];
+ UErrorCode errorCode=U_ZERO_ERROR;
+ static const int32_t srcMap[6] = {0,1,-1,5,4};
+ static const int32_t dstMap[6] = {0,1,-1,-1,4,3};
+
+ bidi = ubidi_openSized(120, 66, &errorCode);
+ if (bidi == NULL) {
+ log_err("Error with openSized(120, 66)\n");
+ return;
+ }
+ bidiLine = ubidi_open();
+ if (bidi == NULL) {
+ log_err("Error with open()\n");
+ return;
+ }
+
+ destLen = ubidi_writeReverse(src, 0, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nwriteReverse should return zero length, ",
+ "returned %d instead\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#1#");
+
+ ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nwriteReordered should return zero length, ",
+ "returned %d instead\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#2#");
+
+ srcLen = u_unescape("abc ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != UBIDI_RTL) {
+ log_err("\nTrailing space at index %d should get paragraph level"
+ "%d, got %d instead\n", i, UBIDI_RTL, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#3#");
+
+ srcLen = u_unescape("abc def", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != UBIDI_RTL) {
+ log_err("\nTrailing space at index %d should get paragraph level"
+ "%d, got %d instead\n", i, UBIDI_RTL, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#4#");
+
+ srcLen = u_unescape("abcdefghi ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ for (i = 3; i < 6; i++) {
+ level = ubidi_getLevelAt(bidiLine, i);
+ if (level != 2) {
+ log_err("\nTrailing char at index %d should get level 2, "
+ "got %d instead\n", i, level);
+ }
+ }
+ RETURN_IF_BAD_ERRCODE("#5#");
+
+ ubidi_setReorderingOptions(bidi, UBIDI_OPTION_REMOVE_CONTROLS);
+ srcLen = u_unescape("\\u200eabc def", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ destLen = ubidi_getResultLength(bidiLine);
+ if (destLen != 5) {
+ log_err("\nWrong result length, should be 5, got %d\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#6#");
+
+ srcLen = u_unescape("abcdefghi", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ dir = ubidi_getDirection(bidiLine);
+ if (dir != UBIDI_LTR) {
+ log_err("\nWrong direction #1, should be %d, got %d\n",
+ UBIDI_LTR, dir);
+ }
+ RETURN_IF_BAD_ERRCODE("#7#");
+
+ ubidi_setPara(bidi, src, 0, UBIDI_LTR, NULL, &errorCode);
+ runCount = ubidi_countRuns(bidi, &errorCode);
+ if (runCount != 0) {
+ log_err("\nWrong number of runs #1, should be 0, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#8#");
+
+ srcLen = u_unescape(" ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ runCount = ubidi_countRuns(bidiLine, &errorCode);
+ if (runCount != 1) {
+ log_err("\nWrong number of runs #2, should be 1, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#9#");
+
+ srcLen = u_unescape("a\\u05d0 bc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ ubidi_setLine(bidi, 0, 6, bidiLine, &errorCode);
+ dir = ubidi_getDirection(bidi);
+ if (dir != UBIDI_MIXED) {
+ log_err("\nWrong direction #2, should be %d, got %d\n",
+ UBIDI_MIXED, dir);
+ }
+ dir = ubidi_getDirection(bidiLine);
+ if (dir != UBIDI_MIXED) {
+ log_err("\nWrong direction #3, should be %d, got %d\n",
+ UBIDI_MIXED, dir);
+ }
+ runCount = ubidi_countRuns(bidiLine, &errorCode);
+ if (runCount != 2) {
+ log_err("\nWrong number of runs #3, should be 2, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#10#");
+
+ ubidi_invertMap(srcMap, map, 5);
+ if (memcmp(dstMap, map, sizeof(dstMap))) {
+ log_err("\nUnexpected inverted Map, got ");
+ for (i = 0; i < 6; i++) {
+ log_err("%d ", map[i]);
+ }
+ log_err("\n");
+ }
+
+ /* test REMOVE_BIDI_CONTROLS together with DO_MIRRORING */
+ srcLen = u_unescape("abc\\u200e", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN,
+ UBIDI_REMOVE_BIDI_CONTROLS | UBIDI_DO_MIRRORING, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, 3 * sizeof(UChar))) {
+ log_err("\nWrong result #1, should be 'abc', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#11#");
+
+ /* test inverse Bidi with marks and contextual orientation */
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_INVERSE_LIKE_DIRECT);
+ ubidi_setReorderingOptions(bidi, UBIDI_OPTION_INSERT_MARKS);
+ ubidi_setPara(bidi, src, 0, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 0) {
+ log_err("\nWrong result #2, length should be 0, got %d\n", destLen);
+ }
+ RETURN_IF_BAD_ERRCODE("#12#");
+ srcLen = u_unescape(" ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #3, should be ' ', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#13#");
+ srcLen = u_unescape("abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ if (destLen != 3 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #4, should be 'abc', got '%s'\n",
+ aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#14#");
+ srcLen = u_unescape("\\u05d0\\u05d1", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 2 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #5, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#15#");
+ srcLen = u_unescape("abc \\u05d0\\u05d1", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d1\\u05d0 abc", src, MAXLEN);
+ if (destLen != 6 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #6, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#16#");
+ srcLen = u_unescape("\\u05d0\\u05d1 abc", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200fabc \\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 7 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #7, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#17#");
+ srcLen = u_unescape("\\u05d0\\u05d1 abc .-=", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200f=-. abc \\u05d1\\u05d0", src, MAXLEN);
+ if (destLen != 11 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #8, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#18#");
+ ubidi_orderParagraphsLTR(bidi, TRUE);
+ srcLen = u_unescape("\n\r \n\rabc\n\\u05d0\\u05d1\rabc \\u05d2\\u05d3\n\r"
+ "\\u05d4\\u05d5 abc\n\\u05d6\\u05d7 abc .-=\r\n"
+ "-* \\u05d8\\u05d9 abc .-=", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_DEFAULT_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\n\r \n\rabc\n\\u05d1\\u05d0\r\\u05d3\\u05d2 abc\n\r"
+ "\\u200fabc \\u05d5\\u05d4\n\\u200f=-. abc \\u05d7\\u05d6\r\n"
+ "\\u200f=-. abc \\u05d9\\u05d8 *-", src, MAXLEN);
+ if (destLen != 57 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #9, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#19#");
+ srcLen = u_unescape("\\u05d0 \t", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05D0\\u200e \t", src, MAXLEN);
+ if (destLen != 4 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #10, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#20#");
+ srcLen = u_unescape("\\u05d0 123 \t\\u05d1 123 \\u05d2", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d0 \\u200e123\\u200e \t\\u05d2 123 \\u05d1", src, MAXLEN);
+ if (destLen != 16 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #11, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#21#");
+ srcLen = u_unescape("\\u05d0 123 \\u0660\\u0661 ab", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u05d0 \\u200e123 \\u200e\\u0660\\u0661 ab", src, MAXLEN);
+ if (destLen != 13 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #12, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#22#");
+ srcLen = u_unescape("ab \t", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_RTL, NULL, &errorCode);
+ destLen = ubidi_writeReordered(bidi, dest, MAXLEN, 0, &errorCode);
+ srcLen = u_unescape("\\u200f\t ab", src, MAXLEN);
+ if (destLen != 5 || memcmp(dest, src, destLen * sizeof(UChar))) {
+ log_err("\nWrong result #13, should be '%s', got '%s'\n",
+ aescstrdup(src, srcLen), aescstrdup(dest, destLen));
+ }
+ RETURN_IF_BAD_ERRCODE("#23#");
+
+ /* check exceeding para level */
+ ubidi_close(bidi);
+ bidi = ubidi_open();
+ srcLen = u_unescape("A\\u202a\\u05d0\\u202aC\\u202c\\u05d1\\u202cE", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_MAX_EXPLICIT_LEVEL - 1, NULL, &errorCode);
+ level = ubidi_getLevelAt(bidi, 2);
+ if (level != 61) {
+ log_err("\nWrong level at index 2\n, should be 61, got %d\n", level);
+ }
+ RETURN_IF_BAD_ERRCODE("#24#");
+
+ /* check 1-char runs with RUNS_ONLY */
+ ubidi_setReorderingMode(bidi, UBIDI_REORDER_RUNS_ONLY);
+ srcLen = u_unescape("a \\u05d0 b \\u05d1 c \\u05d2 d ", src, MAXLEN);
+ ubidi_setPara(bidi, src, srcLen, UBIDI_LTR, NULL, &errorCode);
+ runCount = ubidi_countRuns(bidi, &errorCode);
+ if (runCount != 14) {
+ log_err("\nWrong number of runs #3, should be 14, got %d\n", runCount);
+ }
+ RETURN_IF_BAD_ERRCODE("#25#");
+
+ ubidi_close(bidi);
+ ubidi_close(bidiLine);
+}
+
+static void
+testFailureRecovery(void) {
+ UErrorCode errorCode;
+ UBiDi *bidi, *bidiLine;
+ UChar src[MAXLEN];
+ int32_t srcLen;
+ UBiDiLevel level;
+ UBiDiReorderingMode rm;
+ static UBiDiLevel myLevels[3] = {6,5,4};