]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ushape.cpp
ICU-551.24.tar.gz
[apple/icu.git] / icuSources / common / ushape.cpp
index c09c13228f4a9df6d0122af202d32dfe7e5361af..eeae57f3d4370ec9489776caed09363d75ac8666 100644 (file)
@@ -1,7 +1,7 @@
 /*
  ******************************************************************************
  *
- *   Copyright (C) 2000-2012, International Business Machines
+ *   Copyright (C) 2000-2014, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *
  ******************************************************************************
@@ -26,8 +26,6 @@
 #include "ubidi_props.h"
 #include "uassert.h"
 
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
-
 /*
  * This implementation is designed for 16-bit Unicode strings.
  * The main assumption is that the Arabic characters and their
@@ -44,6 +42,7 @@
  *   as a glyph fragment of wide-glyph letters
  *   + IBM Unicode conversion tables map it to U+200B (ZWSP)
  *   + IBM Egypt has proposed to encode the tail in Unicode among Arabic Presentation Forms
+ *   + Unicode 3.2 added U+FE73 ARABIC TAIL FRAGMENT
  */
 
 /* definitions for Arabic letter shaping ------------------------------------ */
 #define SHADDA_CHAR        0xFE7C
 #define TATWEEL_CHAR       0x0640
 #define SHADDA_TATWEEL_CHAR  0xFE7D
+#define SHADDA06_CHAR      0x0651
 
 #define SHAPE_MODE   0
 #define DESHAPE_MODE 1
 
-static UChar tailChar = OLD_TAIL_CHAR;
-static uint32_t uShapeLamalefBegin = U_SHAPE_LAMALEF_BEGIN;
-static uint32_t uShapeLamalefEnd    = U_SHAPE_LAMALEF_END;
-static uint32_t uShapeTashkeelBegin = U_SHAPE_TASHKEEL_BEGIN;
-static uint32_t uShapeTashkeelEnd = U_SHAPE_TASHKEEL_END;
-static int spacesRelativeToTextBeginEnd = 0;
+struct uShapeVariables {
+     UChar tailChar;
+     uint32_t uShapeLamalefBegin;
+     uint32_t uShapeLamalefEnd;
+     uint32_t uShapeTashkeelBegin;
+     uint32_t uShapeTashkeelEnd;
+     int spacesRelativeToTextBeginEnd;
+};
 
 static const uint8_t tailFamilyIsolatedFinal[] = {
     /* FEB1 */ 1,
@@ -208,10 +210,20 @@ static const UChar araLink[178]=
   0,                            /*0x0674*/
   1            + 32,            /*0x0675*/
   1, 1,                         /*0x0676-0x0677*/
-  1+2, 1+2, 1+2, 1+2, 1+2, 1+2, /*0x0678-0x067D*/
+  1 + 2,                        /*0x0678*/
+  1 + 2 + 8        + 256 * 0x16,/*0x0679*/
+  1 + 2 + 8        + 256 * 0x0E,/*0x067A*/
+  1 + 2 + 8        + 256 * 0x02,/*0x067B*/
+  1+2, 1+2,                     /*0x67C-0x067D*/
   1+2+8+256 * 0x06, 1+2, 1+2, 1+2, 1+2, 1+2, /*0x067E-0x0683*/
   1+2, 1+2, 1+2+8+256 * 0x2A, 1+2,           /*0x0684-0x0687*/
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*0x0688-0x0691*/
+  1     + 8        + 256 * 0x38,/*0x0688*/
+  1, 1, 1,                      /*0x0689-0x068B*/
+  1     + 8        + 256 * 0x34,/*0x068C*/
+  1     + 8        + 256 * 0x32,/*0x068D*/
+  1     + 8        + 256 * 0x36,/*0x068E*/
+  1, 1,                         /*0x068F-0x0690*/
+  1     + 8        + 256 * 0x3C,/*0x0691*/
   1, 1, 1, 1, 1, 1, 1+8+256 * 0x3A, 1,       /*0x0692-0x0699*/
   1+2, 1+2, 1+2, 1+2, 1+2, 1+2, /*0x069A-0x06A3*/
   1+2, 1+2, 1+2, 1+2,           /*0x069A-0x06A3*/
@@ -219,15 +231,29 @@ static const UChar araLink[178]=
   1+2, 1+2, 1+2, 1+2,           /*0x06A4-0x06AD*/
   1+2, 1+2+8+256 * 0x42, 1+2, 1+2, 1+2, 1+2, /*0x06AE-0x06B7*/
   1+2, 1+2, 1+2, 1+2,           /*0x06AE-0x06B7*/
-  1+2, 1+2, 1+2, 1+2, 1+2, 1+2, /*0x06B8-0x06BF*/
-  1+2, 1+2,                     /*0x06B8-0x06BF*/
-  1,                            /*0x06C0*/
-  1+2,                          /*0x06C1*/
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*0x06C2-0x06CB*/
-  1+2+8+256 * 0xAC,             /*0x06CC*/
+  1+2, 1+2,                     /*0x06B8-0x06B9*/
+  1     + 8        + 256 * 0x4E,/*0x06BA*/
+  1 + 2 + 8        + 256 * 0x50,/*0x06BB*/
+  1+2, 1+2,                     /*0x06BC-0x06BD*/
+  1 + 2 + 8        + 256 * 0x5A,/*0x06BE*/
+  1+2,                          /*0x06BF*/
+  1     + 8        + 256 * 0x54,/*0x06C0*/
+  1 + 2 + 8        + 256 * 0x56,/*0x06C1*/
+  1, 1, 1,                      /*0x06C2-0x06C4*/
+  1     + 8        + 256 * 0x90,/*0x06C5*/
+  1     + 8        + 256 * 0x89,/*0x06C6*/
+  1     + 8        + 256 * 0x87,/*0x06C7*/
+  1     + 8        + 256 * 0x8B,/*0x06C8*/
+  1     + 8        + 256 * 0x92,/*0x06C9*/
+  1,                            /*0x06CA*/
+  1     + 8        + 256 * 0x8E,/*0x06CB*/
+  1 + 2 + 8        + 256 * 0xAC,/*0x06CC*/
   1,                            /*0x06CD*/
-  1+2, 1+2, 1+2, 1+2,           /*0x06CE-0x06D1*/
-  1, 1                          /*0x06D2-0x06D3*/
+  1+2, 1+2,                     /*0x06CE-0x06CF*/
+  1 + 2 + 8        + 256 * 0x94,/*0x06D0*/
+  1+2,                          /*0x06D1*/
+  1     + 8        + 256 * 0x5E,/*0x06D2*/
+  1     + 8        + 256 * 0x60 /*0x06D3*/
 };
 
 static const uint8_t presALink[] = {
@@ -269,16 +295,16 @@ static const uint8_t presBLink[]=
 static const UChar convertFBto06[] =
 {
 /***********0******1******2******3******4******5******6******7******8******9******A******B******C******D******E******F***/
-/*FB5*/   0x671, 0x671,     0,     0,     0,     0, 0x07E, 0x07E, 0x07E, 0x07E,     0,     0,     0,     0,     0,     0,
-/*FB6*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+/*FB5*/   0x671, 0x671, 0x67B, 0x67B, 0x67B, 0x67B, 0x67E, 0x67E, 0x67E, 0x67E,     0,     0,     0,     0, 0x67A, 0x67A,
+/*FB6*/   0x67A, 0x67A,     0,     0,     0,     0, 0x679, 0x679, 0x679, 0x679,     0,     0,     0,     0,     0,     0,
 /*FB7*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0, 0x686, 0x686, 0x686, 0x686,     0,     0,
-/*FB8*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0, 0x698, 0x698,     0,     0, 0x6A9, 0x6A9,
-/*FB9*/   0x6A9, 0x6A9, 0x6AF, 0x6AF, 0x6AF, 0x6AF,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-/*FBA*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-/*FBB*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+/*FB8*/       0,     0, 0x68D, 0x68D, 0x68C, 0x68C, 0x68E, 0x68E, 0x688, 0x688, 0x698, 0x698, 0x691, 0x691, 0x6A9, 0x6A9,
+/*FB9*/   0x6A9, 0x6A9, 0x6AF, 0x6AF, 0x6AF, 0x6AF,     0,     0,     0,     0,     0,     0,     0,     0, 0x6BA, 0x6BA,
+/*FBA*/   0x6BB, 0x6BB, 0x6BB, 0x6BB, 0x6C0, 0x6C0, 0x6C1, 0x6C1, 0x6C1, 0x6C1, 0x6BE, 0x6BE, 0x6BE, 0x6BE, 0x6d2, 0x6D2,
+/*FBB*/   0x6D3, 0x6D3,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
 /*FBC*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-/*FBD*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-/*FBE*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+/*FBD*/       0,     0,     0,     0,     0,     0,     0, 0x6C7, 0x6C7, 0x6C6, 0x6C6, 0x6C8, 0x6C8,     0, 0x6CB, 0x6CB,
+/*FBE*/   0x6C5, 0x6C5, 0x6C9, 0x6C9, 0x6D0, 0x6D0, 0x6D0, 0x6D0,     0,     0,     0,     0,     0,     0,     0,     0,
 /*FBF*/       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0, 0x6CC, 0x6CC, 0x6CC, 0x6CC
 };
 
@@ -702,7 +728,7 @@ static int32_t
 handleGeneratedSpaces(UChar *dest, int32_t sourceLength,
                     int32_t destSize,
                     uint32_t options,
-                    UErrorCode *pErrorCode ) {
+                    UErrorCode *pErrorCode,struct uShapeVariables shapeVars ) {
 
     int32_t i = 0, j = 0;
     int32_t count = 0;
@@ -721,14 +747,15 @@ handleGeneratedSpaces(UChar *dest, int32_t sourceLength,
         }
     }
 
-    if (lamAlefOption || tashkeelOption){
-        tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR);
-        /* Test for NULL */
-        if(tempbuffer == NULL) {
-            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
-            return 0;
-        }
+    tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR);
+    /* Test for NULL */
+    if(tempbuffer == NULL) {
+        *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
+        return 0;
+    }
+
 
+    if (lamAlefOption || tashkeelOption){
         uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR);
 
         i = j = 0; count = 0;
@@ -777,27 +804,21 @@ handleGeneratedSpaces(UChar *dest, int32_t sourceLength,
     tashkeelOption = 0;
 
     if (shapingMode == 0) {
-        if ( ((options&U_SHAPE_LAMALEF_MASK) == uShapeLamalefBegin) ||
+        if ( ((options&U_SHAPE_LAMALEF_MASK) == shapeVars.uShapeLamalefBegin) ||
               (((options&U_SHAPE_LAMALEF_MASK) == U_SHAPE_LAMALEF_AUTO )
-              && (spacesRelativeToTextBeginEnd==1)) ) {
+              && (shapeVars.spacesRelativeToTextBeginEnd==1)) ) {
             lamAlefOption = 1;
         }
-        if ( (options&U_SHAPE_TASHKEEL_MASK) == uShapeTashkeelBegin ) {
+        if ( (options&U_SHAPE_TASHKEEL_MASK) == shapeVars.uShapeTashkeelBegin ) {
             tashkeelOption = 1;
         }
     }
 
     if(lamAlefOption || tashkeelOption){
-        tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR);
-
-        /* Test for NULL */
-        if(tempbuffer == NULL) {
-            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
-            return 0;
-        }
-
         uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR);
+        
         i = j = sourceLength; count = 0;
+        
         while(i >= 0) {
             if ( (lamAlefOption && dest[i] == LAMALEF_SPACE_SUB) ||
                  (tashkeelOption && dest[i] == TASHKEEL_SPACE_SUB) ){
@@ -824,24 +845,17 @@ handleGeneratedSpaces(UChar *dest, int32_t sourceLength,
     tashkeelOption = 0;
 
     if (shapingMode == 0) {
-        if ( ((options&U_SHAPE_LAMALEF_MASK) == uShapeLamalefEnd) ||
+        if ( ((options&U_SHAPE_LAMALEF_MASK) == shapeVars.uShapeLamalefEnd) ||
               (((options&U_SHAPE_LAMALEF_MASK) == U_SHAPE_LAMALEF_AUTO )
-              && (spacesRelativeToTextBeginEnd==0)) ) {
+              && (shapeVars.spacesRelativeToTextBeginEnd==0)) ) {
             lamAlefOption = 1;
         }
-        if ( (options&U_SHAPE_TASHKEEL_MASK) == uShapeTashkeelEnd ){
+        if ( (options&U_SHAPE_TASHKEEL_MASK) == shapeVars.uShapeTashkeelEnd ){
             tashkeelOption = 1;
         }
     }
 
     if(lamAlefOption || tashkeelOption){
-        tempbuffer = (UChar *)uprv_malloc((sourceLength+1)*U_SIZEOF_UCHAR);
-       /* Test for NULL */
-        if(tempbuffer == NULL) {
-            *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
-            return 0;
-        }
-
         uprv_memset(tempbuffer, 0, (sourceLength+1)*U_SIZEOF_UCHAR);
 
         i = j = 0; count = 0;
@@ -1014,7 +1028,7 @@ expandCompositCharAtEnd(UChar *dest, int32_t sourceLength, int32_t destSize,UErr
 
 static int32_t
 expandCompositCharAtNear(UChar *dest, int32_t sourceLength, int32_t destSize,UErrorCode *pErrorCode,
-                         int yehHamzaOption, int seenTailOption, int lamAlefOption) {
+                         int yehHamzaOption, int seenTailOption, int lamAlefOption, struct uShapeVariables shapeVars) {
     int32_t      i = 0;
 
 
@@ -1023,7 +1037,7 @@ expandCompositCharAtNear(UChar *dest, int32_t sourceLength, int32_t destSize,UEr
     for(i = 0 ;i<=sourceLength-1;i++) {
             if (seenTailOption && isSeenTailFamilyChar(dest[i])) {
                 if ((i>0) && (dest[i-1] == SPACE_CHAR) ) {
-                    dest[i-1] = tailChar;
+                    dest[i-1] = shapeVars.tailChar;
                 }else {
                     *pErrorCode=U_NO_SPACE_AVAILABLE;
                 }
@@ -1068,7 +1082,7 @@ expandCompositCharAtNear(UChar *dest, int32_t sourceLength, int32_t destSize,UEr
 static int32_t
 expandCompositChar(UChar *dest, int32_t sourceLength,
               int32_t destSize,uint32_t options,
-              UErrorCode *pErrorCode, int shapingMode) {
+              UErrorCode *pErrorCode, int shapingMode,struct uShapeVariables shapeVars) {
 
     int32_t      i = 0,j = 0;
 
@@ -1080,7 +1094,7 @@ expandCompositChar(UChar *dest, int32_t sourceLength,
     if (shapingMode == 1){
         if ( (options&U_SHAPE_LAMALEF_MASK) == U_SHAPE_LAMALEF_AUTO){
 
-            if(spacesRelativeToTextBeginEnd == 0) {
+            if(shapeVars.spacesRelativeToTextBeginEnd == 0) {
                 destSize = expandCompositCharAtEnd(dest, sourceLength, destSize, pErrorCode);
 
                 if(*pErrorCode == U_NO_SPACE_AVAILABLE) {
@@ -1099,19 +1113,19 @@ expandCompositChar(UChar *dest, int32_t sourceLength,
             if(*pErrorCode == U_NO_SPACE_AVAILABLE) {
                 *pErrorCode = U_ZERO_ERROR;
                 destSize = expandCompositCharAtNear(dest, sourceLength, destSize, pErrorCode, yehHamzaOption,
-                                                seenTailOption, 1);
+                                                seenTailOption, 1,shapeVars);
             }
         }
     }
 
     if (shapingMode == 1){
-        if ( (options&U_SHAPE_LAMALEF_MASK) == uShapeLamalefEnd){
+        if ( (options&U_SHAPE_LAMALEF_MASK) == shapeVars.uShapeLamalefEnd){
             destSize = expandCompositCharAtEnd(dest, sourceLength, destSize, pErrorCode);
         }
     }
 
     if (shapingMode == 1){
-        if ( (options&U_SHAPE_LAMALEF_MASK) == uShapeLamalefBegin){
+        if ( (options&U_SHAPE_LAMALEF_MASK) == shapeVars.uShapeLamalefBegin){
             destSize = expandCompositCharAtBegin(dest, sourceLength, destSize, pErrorCode);
         }
     }
@@ -1133,7 +1147,7 @@ expandCompositChar(UChar *dest, int32_t sourceLength,
 
     if (yehHamzaOption || seenTailOption || lamAlefOption){
         destSize = expandCompositCharAtNear(dest, sourceLength, destSize, pErrorCode, yehHamzaOption,
-                                            seenTailOption,lamAlefOption);
+                                            seenTailOption,lamAlefOption,shapeVars);
     }
 
 
@@ -1182,7 +1196,7 @@ static int32_t
 shapeUnicode(UChar *dest, int32_t sourceLength,
              int32_t destSize,uint32_t options,
              UErrorCode *pErrorCode,
-             int tashkeelFlag) {
+             int tashkeelFlag, struct uShapeVariables shapeVars) {
 
     int32_t          i, iend;
     int32_t          step;
@@ -1260,20 +1274,20 @@ shapeUnicode(UChar *dest, int32_t sourceLength,
                 currLink = getLink(wLamalef);    /* LAMALEF_SPACE_SUB is added here and is replaced by spaces   */
             }                                    /* in removeLamAlefSpaces()                         */
 
-                       if ((i > 0) && (dest[i-1] == SPACE_CHAR)){
-             if ( isSeenFamilyChar(dest[i])){
+            if ((i > 0) && (dest[i-1] == SPACE_CHAR)){
+                if ( isSeenFamilyChar(dest[i])) {
                     seenfamFound = 1;
                 } else if (dest[i] == YEH_HAMZA_CHAR) {
                     yehhamzaFound = 1;
                 }
-                       }
-                       else if(i==0){
-                               if ( isSeenFamilyChar(dest[i])){
+            }
+            else if(i==0){
+                if ( isSeenFamilyChar(dest[i])){
                     seenfamFound = 1;
                 } else if (dest[i] == YEH_HAMZA_CHAR) {
                     yehhamzaFound = 1;
                 }
-                       }
+            }
 
             /*
              * get the proper shape according to link ability of neighbors
@@ -1294,14 +1308,15 @@ shapeUnicode(UChar *dest, int32_t sourceLength,
                     if( (nextLink&ALEFTYPE) == ALEFTYPE && (lastLink&LAMTYPE) == LAMTYPE ) {
                         Shape = 0;
                     }
-                }
-                else {
+                } else if(tashkeelFlag == 2 && dest[i] == SHADDA06_CHAR){
+                    Shape = 1;
+                } else {
                     Shape = 0;
                 }
             }
             if ((dest[i] ^ 0x0600) < 0x100) {
                 if ( isTashkeelChar(dest[i]) ){
-                    if (tashkeelFlag == 2){
+                    if (tashkeelFlag == 2  && dest[i] != SHADDA06_CHAR){
                         dest[i] = TASHKEEL_SPACE_SUB;
                         tashkeelFound  = 1;
                     } else {
@@ -1335,11 +1350,11 @@ shapeUnicode(UChar *dest, int32_t sourceLength,
     }
     destSize = sourceLength;
     if ( (lamalef_found != 0 ) || (tashkeelFound  != 0) ){
-        destSize = handleGeneratedSpaces(dest,sourceLength,destSize,options,pErrorCode);
+        destSize = handleGeneratedSpaces(dest,sourceLength,destSize,options,pErrorCode, shapeVars);
     }
 
     if ( (seenfamFound != 0) || (yehhamzaFound != 0) ) {
-        destSize = expandCompositChar(dest, sourceLength,destSize,options,pErrorCode, SHAPE_MODE);
+        destSize = expandCompositChar(dest, sourceLength,destSize,options,pErrorCode, SHAPE_MODE,shapeVars);
     }
     return destSize;
 }
@@ -1352,7 +1367,7 @@ shapeUnicode(UChar *dest, int32_t sourceLength,
 static int32_t
 deShapeUnicode(UChar *dest, int32_t sourceLength,
                int32_t destSize,uint32_t options,
-               UErrorCode *pErrorCode) {
+               UErrorCode *pErrorCode, struct uShapeVariables shapeVars) {
     int32_t i = 0;
     int32_t lamalef_found = 0;
     int32_t yehHamzaComposeEnabled = 0;
@@ -1391,7 +1406,7 @@ deShapeUnicode(UChar *dest, int32_t sourceLength,
 
    destSize = sourceLength;
    if (lamalef_found != 0){
-          destSize = expandCompositChar(dest,sourceLength,destSize,options,pErrorCode,DESHAPE_MODE);
+          destSize = expandCompositChar(dest,sourceLength,destSize,options,pErrorCode,DESHAPE_MODE, shapeVars);
    }
    return destSize;
 }
@@ -1409,12 +1424,7 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
               UErrorCode *pErrorCode) {
 
     int32_t destLength;
-
-    spacesRelativeToTextBeginEnd = 0;
-    uShapeLamalefBegin = U_SHAPE_LAMALEF_BEGIN;
-    uShapeLamalefEnd = U_SHAPE_LAMALEF_END;
-    uShapeTashkeelBegin = U_SHAPE_TASHKEEL_BEGIN;
-    uShapeTashkeelEnd = U_SHAPE_TASHKEEL_END;
+    struct  uShapeVariables shapeVars = { OLD_TAIL_CHAR,U_SHAPE_LAMALEF_BEGIN,U_SHAPE_LAMALEF_END,U_SHAPE_TASHKEEL_BEGIN,U_SHAPE_TASHKEEL_END,0};
 
     /* usual error checking */
     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
@@ -1438,27 +1448,27 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
-       /* Validate  lamalef options */
-       if(((options&U_SHAPE_LAMALEF_MASK) > 0)&&
+    /* Validate  lamalef options */
+    if(((options&U_SHAPE_LAMALEF_MASK) > 0)&&
               !(((options & U_SHAPE_LAMALEF_MASK)==U_SHAPE_LAMALEF_BEGIN) ||
                 ((options & U_SHAPE_LAMALEF_MASK)==U_SHAPE_LAMALEF_END ) ||
                 ((options & U_SHAPE_LAMALEF_MASK)==U_SHAPE_LAMALEF_RESIZE )||
                  ((options & U_SHAPE_LAMALEF_MASK)==U_SHAPE_LAMALEF_AUTO) ||
                  ((options & U_SHAPE_LAMALEF_MASK)==U_SHAPE_LAMALEF_NEAR)))
-       {
-                *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+    {
+         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
-       }
-       /* Validate  Tashkeel options */
-       if(((options&U_SHAPE_TASHKEEL_MASK) > 0)&&
+    }
+    /* Validate  Tashkeel options */
+    if(((options&U_SHAPE_TASHKEEL_MASK) > 0)&&
                    !(((options & U_SHAPE_TASHKEEL_MASK)==U_SHAPE_TASHKEEL_BEGIN) ||
                      ((options & U_SHAPE_TASHKEEL_MASK)==U_SHAPE_TASHKEEL_END )
                     ||((options & U_SHAPE_TASHKEEL_MASK)==U_SHAPE_TASHKEEL_RESIZE )||
-                                       ((options & U_SHAPE_TASHKEEL_MASK)==U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL)))
-       {
-                *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
+                    ((options & U_SHAPE_TASHKEEL_MASK)==U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL)))
+    {
+         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
-       }
+    }
     /* determine the source length */
     if(sourceLength==-1) {
         sourceLength=u_strlen(source);
@@ -1477,9 +1487,9 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
 
     /* Does Options contain the new Seen Tail Unicode code point option */
     if ( (options&U_SHAPE_TAIL_TYPE_MASK) == U_SHAPE_TAIL_NEW_UNICODE){
-        tailChar = NEW_TAIL_CHAR;
+        shapeVars.tailChar = NEW_TAIL_CHAR;
     }else {
-        tailChar = OLD_TAIL_CHAR;
+        shapeVars.tailChar = OLD_TAIL_CHAR;
     }
 
     if((options&U_SHAPE_LETTERS_MASK)!=U_SHAPE_LETTERS_NOOP) {
@@ -1548,8 +1558,8 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
         }
 
         /* Start of Arabic letter shaping part */
-        if(outputSize<=LENGTHOF(buffer)) {
-            outputSize=LENGTHOF(buffer);
+        if(outputSize<=UPRV_LENGTHOF(buffer)) {
+            outputSize=UPRV_LENGTHOF(buffer);
             tempbuffer=buffer;
         } else {
             tempbuffer = (UChar *)uprv_malloc(outputSize*U_SIZEOF_UCHAR);
@@ -1577,12 +1587,11 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
 
         if((options&U_SHAPE_TEXT_DIRECTION_MASK) == U_SHAPE_TEXT_DIRECTION_VISUAL_LTR) {
             if((options&U_SHAPE_SPACES_RELATIVE_TO_TEXT_MASK) == U_SHAPE_SPACES_RELATIVE_TO_TEXT_BEGIN_END) {
-                spacesRelativeToTextBeginEnd = 1;
-                uShapeLamalefBegin = U_SHAPE_LAMALEF_END;
-                uShapeLamalefEnd = U_SHAPE_LAMALEF_BEGIN;
-
-                uShapeTashkeelBegin = U_SHAPE_TASHKEEL_END;
-                uShapeTashkeelEnd = U_SHAPE_TASHKEEL_BEGIN;
+                shapeVars.spacesRelativeToTextBeginEnd = 1;
+                shapeVars.uShapeLamalefBegin = U_SHAPE_LAMALEF_END;
+                shapeVars.uShapeLamalefEnd = U_SHAPE_LAMALEF_BEGIN;
+                shapeVars.uShapeTashkeelBegin = U_SHAPE_TASHKEEL_END;
+                shapeVars.uShapeTashkeelEnd = U_SHAPE_TASHKEEL_BEGIN;
             }
         }
 
@@ -1591,10 +1600,10 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
              if( (options&U_SHAPE_TASHKEEL_MASK)> 0
                  && ((options&U_SHAPE_TASHKEEL_MASK) !=U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL)) {
                 /* Call the shaping function with tashkeel flag == 2 for removal of tashkeel */
-                destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,2);
+                destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,2,shapeVars);
              }else {
                 /* default Call the shaping function with tashkeel flag == 1 */
-                destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,1);
+                destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,1,shapeVars);
 
                 /*After shaping text check if user wants to remove tashkeel and replace it with tatweel*/
                 if( (options&U_SHAPE_TASHKEEL_MASK) == U_SHAPE_TASHKEEL_REPLACE_BY_TATWEEL){
@@ -1604,12 +1613,12 @@ u_shapeArabic(const UChar *source, int32_t sourceLength,
             break;
         case U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED :
             /* Call the shaping function with tashkeel flag == 0 */
-            destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,0);
+            destLength = shapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,0,shapeVars);
             break;
 
         case U_SHAPE_LETTERS_UNSHAPE :
             /* Call the deshaping function */
-            destLength = deShapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode);
+            destLength = deShapeUnicode(tempbuffer,sourceLength,destCapacity,options,pErrorCode,shapeVars);
             break;
         default :
             /* will never occur because of validity checks above */