00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef U_COMMON_IMPLEMENTATION
00019 # define U_COMMON_IMPLEMENTATION
00020 #endif
00021
00022 #include "cmemory.h"
00023 #include "unicode/utypes.h"
00024 #include "unicode/ustring.h"
00025 #include "unicode/uchar.h"
00026 #include "unicode/ubidi.h"
00027 #include "ubidiimp.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static void
00113 getDirProps(UBiDi *pBiDi, const UChar *text);
00114
00115 static UBiDiDirection
00116 resolveExplicitLevels(UBiDi *pBiDi);
00117
00118 static UBiDiDirection
00119 checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode);
00120
00121 static UBiDiDirection
00122 directionFromFlags(Flags flags);
00123
00124 static void
00125 resolveImplicitLevels(UBiDi *pBiDi,
00126 UTextOffset start, UTextOffset limit,
00127 DirProp sor, DirProp eor);
00128
00129 static void
00130 adjustWSLevels(UBiDi *pBiDi);
00131
00132
00133 static Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) };
00134 static Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) };
00135 static Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
00136
00137 #define DIRPROP_FLAG_LR(level) flagLR[(level)&1]
00138 #define DIRPROP_FLAG_E(level) flagE[(level)&1]
00139 #define DIRPROP_FLAG_O(level) flagO[(level)&1]
00140
00141
00142
00143 U_CAPI UBiDi * U_EXPORT2
00144 ubidi_open(void)
00145 {
00146 UErrorCode errorCode=U_ZERO_ERROR;
00147 return ubidi_openSized(0, 0, &errorCode);
00148 }
00149
00150 U_CAPI UBiDi * U_EXPORT2
00151 ubidi_openSized(UTextOffset maxLength, UTextOffset maxRunCount, UErrorCode *pErrorCode) {
00152 UBiDi *pBiDi;
00153
00154
00155 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00156 return NULL;
00157 } else if(maxLength<0 || maxRunCount<0) {
00158 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00159 return NULL;
00160 }
00161
00162
00163 pBiDi=(UBiDi *)uprv_malloc(sizeof(UBiDi));
00164 if(pBiDi==NULL) {
00165 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00166 return NULL;
00167 }
00168
00169
00170 uprv_memset(pBiDi, 0, sizeof(UBiDi));
00171
00172
00173 if(maxLength>0) {
00174 if( !getInitialDirPropsMemory(pBiDi, maxLength) ||
00175 !getInitialLevelsMemory(pBiDi, maxLength)
00176 ) {
00177 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00178 }
00179 } else {
00180 pBiDi->mayAllocateText=TRUE;
00181 }
00182
00183 if(maxRunCount>0) {
00184 if(maxRunCount==1) {
00185
00186 pBiDi->runsSize=sizeof(Run);
00187 } else if(!getInitialRunsMemory(pBiDi, maxRunCount)) {
00188 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00189 }
00190 } else {
00191 pBiDi->mayAllocateRuns=TRUE;
00192 }
00193
00194 if(U_SUCCESS(*pErrorCode)) {
00195 return pBiDi;
00196 } else {
00197 ubidi_close(pBiDi);
00198 return NULL;
00199 }
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 extern UBool
00216 getMemory(void **pMemory, UTextOffset *pSize, UBool mayAllocate, UTextOffset sizeNeeded) {
00217
00218 if(*pMemory==NULL) {
00219
00220 if(mayAllocate && (*pMemory=uprv_malloc(sizeNeeded))!=NULL) {
00221 *pSize=sizeNeeded;
00222 return TRUE;
00223 } else {
00224 return FALSE;
00225 }
00226 } else {
00227
00228 if(sizeNeeded>*pSize && !mayAllocate) {
00229
00230 return FALSE;
00231 } else if(sizeNeeded!=*pSize && mayAllocate) {
00232
00233 void *memory;
00234
00235 if((memory=uprv_realloc(*pMemory, sizeNeeded))!=NULL) {
00236 *pMemory=memory;
00237 *pSize=sizeNeeded;
00238 return TRUE;
00239 } else {
00240
00241 return FALSE;
00242 }
00243 } else {
00244
00245 return TRUE;
00246 }
00247 }
00248 }
00249
00250 U_CAPI void U_EXPORT2
00251 ubidi_close(UBiDi *pBiDi) {
00252 if(pBiDi!=NULL) {
00253 if(pBiDi->dirPropsMemory!=NULL) {
00254 uprv_free(pBiDi->dirPropsMemory);
00255 }
00256 if(pBiDi->levelsMemory!=NULL) {
00257 uprv_free(pBiDi->levelsMemory);
00258 }
00259 if(pBiDi->runsMemory!=NULL) {
00260 uprv_free(pBiDi->runsMemory);
00261 }
00262 uprv_free(pBiDi);
00263 }
00264 }
00265
00266
00267
00268 U_CAPI void U_EXPORT2
00269 ubidi_setInverse(UBiDi *pBiDi, UBool isInverse) {
00270 if(pBiDi!=NULL) {
00271 pBiDi->isInverse=isInverse;
00272 }
00273 }
00274
00275 U_CAPI UBool U_EXPORT2
00276 ubidi_isInverse(UBiDi *pBiDi) {
00277 if(pBiDi!=NULL) {
00278 return pBiDi->isInverse;
00279 } else {
00280 return FALSE;
00281 }
00282 }
00283
00284
00285
00286 U_CAPI void U_EXPORT2
00287 ubidi_setPara(UBiDi *pBiDi, const UChar *text, UTextOffset length,
00288 UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
00289 UErrorCode *pErrorCode) {
00290 UBiDiDirection direction;
00291
00292
00293 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
00294 return;
00295 } else if(pBiDi==NULL || text==NULL ||
00296 ((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
00297 length<-1
00298 ) {
00299 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00300 return;
00301 }
00302
00303 if(length==-1) {
00304 length=u_strlen(text);
00305 }
00306
00307
00308 pBiDi->text=text;
00309 pBiDi->length=length;
00310 pBiDi->paraLevel=paraLevel;
00311 pBiDi->direction=UBIDI_LTR;
00312 pBiDi->trailingWSStart=length;
00313
00314 pBiDi->dirProps=NULL;
00315 pBiDi->levels=NULL;
00316 pBiDi->runs=NULL;
00317
00318 if(length==0) {
00319
00320
00321
00322
00323
00324 if(IS_DEFAULT_LEVEL(paraLevel)) {
00325 pBiDi->paraLevel&=1;
00326 }
00327 if(paraLevel&1) {
00328 pBiDi->flags=DIRPROP_FLAG(R);
00329 pBiDi->direction=UBIDI_RTL;
00330 } else {
00331 pBiDi->flags=DIRPROP_FLAG(L);
00332 pBiDi->direction=UBIDI_LTR;
00333 }
00334
00335 pBiDi->runCount=0;
00336 return;
00337 }
00338
00339 pBiDi->runCount=-1;
00340
00341
00342
00343
00344
00345
00346 if(getDirPropsMemory(pBiDi, length)) {
00347 pBiDi->dirProps=pBiDi->dirPropsMemory;
00348 getDirProps(pBiDi, text);
00349 } else {
00350 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00351 return;
00352 }
00353
00354
00355 if(embeddingLevels==NULL) {
00356 \
00357 if(getLevelsMemory(pBiDi, length)) {
00358 pBiDi->levels=pBiDi->levelsMemory;
00359 direction=resolveExplicitLevels(pBiDi);
00360 } else {
00361 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00362 return;
00363 }
00364 } else {
00365
00366 pBiDi->levels=embeddingLevels;
00367 direction=checkExplicitLevels(pBiDi, pErrorCode);
00368 if(U_FAILURE(*pErrorCode)) {
00369 return;
00370 }
00371 }
00372
00373
00374
00375
00376
00377 pBiDi->direction=direction;
00378 switch(direction) {
00379 case UBIDI_LTR:
00380
00381 pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
00382
00383
00384 pBiDi->trailingWSStart=0;
00385 break;
00386 case UBIDI_RTL:
00387
00388 pBiDi->paraLevel|=1;
00389
00390
00391 pBiDi->trailingWSStart=0;
00392 break;
00393 default:
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 if(embeddingLevels==NULL && !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
00406 resolveImplicitLevels(pBiDi, 0, length,
00407 GET_LR_FROM_LEVEL(pBiDi->paraLevel),
00408 GET_LR_FROM_LEVEL(pBiDi->paraLevel));
00409 } else {
00410
00411 UBiDiLevel *levels=pBiDi->levels;
00412 UTextOffset start, limit=0;
00413 UBiDiLevel level, nextLevel;
00414 DirProp sor, eor;
00415
00416
00417 level=pBiDi->paraLevel;
00418 nextLevel=levels[0];
00419 if(level<nextLevel) {
00420 eor=GET_LR_FROM_LEVEL(nextLevel);
00421 } else {
00422 eor=GET_LR_FROM_LEVEL(level);
00423 }
00424
00425 do {
00426
00427
00428
00429 sor=eor;
00430 start=limit;
00431 level=nextLevel;
00432
00433
00434 while(++limit<length && levels[limit]==level) {}
00435
00436
00437 if(limit<length) {
00438 nextLevel=levels[limit];
00439 } else {
00440 nextLevel=pBiDi->paraLevel;
00441 }
00442
00443
00444 if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
00445 eor=GET_LR_FROM_LEVEL(nextLevel);
00446 } else {
00447 eor=GET_LR_FROM_LEVEL(level);
00448 }
00449
00450
00451
00452 if(!(level&UBIDI_LEVEL_OVERRIDE)) {
00453 resolveImplicitLevels(pBiDi, start, limit, sor, eor);
00454 } else {
00455
00456 do {
00457 levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
00458 } while(start<limit);
00459 }
00460 } while(limit<length);
00461 }
00462
00463
00464 adjustWSLevels(pBiDi);
00465
00466
00467 if(pBiDi->isInverse) {
00468 if(!ubidi_getRuns(pBiDi)) {
00469 *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
00470 return;
00471 }
00472 }
00473 break;
00474 }
00475 }
00476
00477
00478
00479
00480
00481
00482
00483
00484 static void
00485 getDirProps(UBiDi *pBiDi, const UChar *text) {
00486 DirProp *dirProps=pBiDi->dirPropsMemory;
00487
00488 UTextOffset i=0, i0, i1, length=pBiDi->length;
00489 Flags flags=0;
00490 UChar32 uchar;
00491 DirProp dirProp;
00492
00493 if(IS_DEFAULT_LEVEL(pBiDi->paraLevel)) {
00494
00495 for(;;) {
00496 i0=i;
00497 UTF_NEXT_CHAR(text, i, length, uchar);
00498 i1=i-1;
00499 flags|=DIRPROP_FLAG(dirProps[i1]=dirProp=u_charDirection(uchar));
00500 if(i1>i0) {
00501 flags|=DIRPROP_FLAG(BN);
00502 do {
00503 dirProps[--i1]=BN;
00504 } while(i1>i0);
00505 }
00506
00507 if(dirProp==L) {
00508 pBiDi->paraLevel=0;
00509 break;
00510 } else if(dirProp==R || dirProp==AL) {
00511 pBiDi->paraLevel=1;
00512 break;
00513 } else if(i>=length) {
00514
00515
00516
00517
00518
00519 pBiDi->paraLevel&=1;
00520 break;
00521 }
00522 }
00523 }
00524
00525
00526 while(i<length) {
00527 i0=i;
00528 UTF_NEXT_CHAR(text, i, length, uchar);
00529 i1=i-1;
00530 flags|=DIRPROP_FLAG(dirProps[i1]=dirProp=u_charDirection(uchar));
00531 if(i1>i0) {
00532 flags|=DIRPROP_FLAG(BN);
00533 do {
00534 dirProps[--i1]=BN;
00535 } while(i1>i0);
00536 }
00537 }
00538 if(flags&MASK_EMBEDDING) {
00539 flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
00540 }
00541
00542 pBiDi->flags=flags;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 static UBiDiDirection
00601 resolveExplicitLevels(UBiDi *pBiDi) {
00602 const DirProp *dirProps=pBiDi->dirProps;
00603 UBiDiLevel *levels=pBiDi->levels;
00604
00605 UTextOffset i=0, length=pBiDi->length;
00606 Flags flags=pBiDi->flags;
00607 DirProp dirProp;
00608 UBiDiLevel level=pBiDi->paraLevel;
00609
00610 UBiDiDirection direction;
00611
00612
00613 direction=directionFromFlags(flags);
00614
00615
00616 if(direction!=UBIDI_MIXED) {
00617
00618 } else if(!(flags&MASK_EXPLICIT) || pBiDi->isInverse) {
00619
00620
00621
00622 for(i=0; i<length; ++i) {
00623 levels[i]=level;
00624 }
00625 } else {
00626
00627
00628
00629
00630 UBiDiLevel embeddingLevel=level, newLevel, stackTop=0;
00631
00632 UBiDiLevel stack[UBIDI_MAX_EXPLICIT_LEVEL];
00633 uint32_t countOver60=0, countOver61=0;
00634
00635
00636 flags=0;
00637
00638
00639 for(i=0; i<length; ++i) {
00640 dirProp=dirProps[i];
00641 switch(dirProp) {
00642 case LRE:
00643 case LRO:
00644
00645 newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1));
00646 if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
00647 stack[stackTop]=embeddingLevel;
00648 ++stackTop;
00649 embeddingLevel=newLevel;
00650 if(dirProp==LRO) {
00651 embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
00652 } else {
00653 embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
00654 }
00655 } else if((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL) {
00656 ++countOver61;
00657 } else {
00658 ++countOver60;
00659 }
00660 flags|=DIRPROP_FLAG(BN);
00661 break;
00662 case RLE:
00663 case RLO:
00664
00665 newLevel=(UBiDiLevel)(((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)+1)|1);
00666 if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
00667 stack[stackTop]=embeddingLevel;
00668 ++stackTop;
00669 embeddingLevel=newLevel;
00670 if(dirProp==RLO) {
00671 embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
00672 } else {
00673 embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
00674 }
00675 } else {
00676 ++countOver61;
00677 }
00678 flags|=DIRPROP_FLAG(BN);
00679 break;
00680 case PDF:
00681
00682
00683 if(countOver61>0) {
00684 --countOver61;
00685 } else if(countOver60>0 && (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)!=UBIDI_MAX_EXPLICIT_LEVEL) {
00686
00687 --countOver60;
00688 } else if(stackTop>0) {
00689
00690 --stackTop;
00691 embeddingLevel=stack[stackTop];
00692
00693 }
00694 flags|=DIRPROP_FLAG(BN);
00695 break;
00696 case B:
00697
00698
00699
00700
00701
00702 stackTop=0;
00703 countOver60=countOver61=0;
00704 embeddingLevel=level=pBiDi->paraLevel;
00705 flags|=DIRPROP_FLAG(B);
00706 break;
00707 case BN:
00708
00709
00710 flags|=DIRPROP_FLAG(BN);
00711 break;
00712 default:
00713
00714 if(level!=embeddingLevel) {
00715 level=embeddingLevel;
00716 if(level&UBIDI_LEVEL_OVERRIDE) {
00717 flags|=DIRPROP_FLAG_O(level)|DIRPROP_FLAG_MULTI_RUNS;
00718 } else {
00719 flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG_MULTI_RUNS;
00720 }
00721 }
00722 if(!(level&UBIDI_LEVEL_OVERRIDE)) {
00723 flags|=DIRPROP_FLAG(dirProp);
00724 }
00725 break;
00726 }
00727
00728
00729
00730
00731
00732 levels[i]=level;
00733 }
00734 if(flags&MASK_EMBEDDING) {
00735 flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
00736 }
00737
00738
00739
00740
00741 pBiDi->flags=flags;
00742 direction=directionFromFlags(flags);
00743 }
00744 return direction;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 static UBiDiDirection
00758 checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
00759 const DirProp *dirProps=pBiDi->dirProps;
00760 UBiDiLevel *levels=pBiDi->levels;
00761
00762 UTextOffset i, length=pBiDi->length;
00763 Flags flags=0;
00764 UBiDiLevel level, paraLevel=pBiDi->paraLevel;
00765
00766 for(i=0; i<length; ++i) {
00767 level=levels[i];
00768 if(level&UBIDI_LEVEL_OVERRIDE) {
00769
00770 level&=~UBIDI_LEVEL_OVERRIDE;
00771 flags|=DIRPROP_FLAG_O(level);
00772 } else {
00773
00774 flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProps[i]);
00775 }
00776 if(level<paraLevel || UBIDI_MAX_EXPLICIT_LEVEL<level) {
00777
00778 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
00779 return UBIDI_LTR;
00780 }
00781 }
00782 if(flags&MASK_EMBEDDING) {
00783 flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
00784 }
00785
00786
00787 pBiDi->flags=flags;
00788 return directionFromFlags(flags);
00789 }
00790
00791
00792 static UBiDiDirection
00793 directionFromFlags(Flags flags) {
00794
00795 if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
00796 return UBIDI_LTR;
00797 } else if(!(flags&MASK_LTR)) {
00798 return UBIDI_RTL;
00799 } else {
00800 return UBIDI_MIXED;
00801 }
00802 }
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 #define EN_SHIFT 2
00830 #define EN_AFTER_W2 1
00831 #define EN_AFTER_W4 2
00832 #define EN_ALL 3
00833 #define PREV_EN_AFTER_W2 4
00834 #define PREV_EN_AFTER_W4 8
00835
00836 static void
00837 resolveImplicitLevels(UBiDi *pBiDi,
00838 UTextOffset start, UTextOffset limit,
00839 DirProp sor, DirProp eor) {
00840 const DirProp *dirProps=pBiDi->dirProps;
00841 UBiDiLevel *levels=pBiDi->levels;
00842
00843 UTextOffset i, next, neutralStart=-1;
00844 DirProp prevDirProp, dirProp, nextDirProp, lastStrong, beforeNeutral=L;
00845 UBiDiLevel numberLevel;
00846 uint8_t historyOfEN;
00847
00848
00849 next=start;
00850 dirProp=lastStrong=sor;
00851 nextDirProp=dirProps[next];
00852 historyOfEN=0;
00853
00854 if(pBiDi->isInverse) {
00855
00856
00857
00858
00859
00860 numberLevel=levels[start];
00861 if(numberLevel&1) {
00862 ++numberLevel;
00863 }
00864 } else {
00865
00866 numberLevel=(UBiDiLevel)((levels[start]+2)&~1);
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876 while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT) {
00877 if(++next<limit) {
00878 nextDirProp=dirProps[next];
00879 } else {
00880 nextDirProp=eor;
00881 break;
00882 }
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 while(next<limit) {
00895
00896 prevDirProp=dirProp;
00897 dirProp=nextDirProp;
00898 i=next;
00899 do {
00900 if(++next<limit) {
00901 nextDirProp=dirProps[next];
00902 } else {
00903 nextDirProp=eor;
00904 break;
00905 }
00906 } while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT);
00907 historyOfEN<<=EN_SHIFT;
00908
00909
00910 switch(dirProp) {
00911 case L:
00912 lastStrong=L;
00913 break;
00914 case R:
00915 lastStrong=R;
00916 break;
00917 case AL:
00918
00919 lastStrong=AL;
00920 dirProp=R;
00921 break;
00922 case EN:
00923
00924 if(lastStrong==AL) {
00925
00926 dirProp=AN;
00927 } else {
00928 if(lastStrong==L) {
00929
00930 dirProp=L;
00931 }
00932
00933 historyOfEN|=EN_ALL;
00934 }
00935 break;
00936 case ES:
00937 if( historyOfEN&PREV_EN_AFTER_W2 &&
00938 nextDirProp==EN && lastStrong!=AL
00939 ) {
00940
00941 if(lastStrong!=L) {
00942 dirProp=EN;
00943 } else {
00944
00945 dirProp=L;
00946 }
00947 historyOfEN|=EN_AFTER_W4;
00948 } else {
00949
00950 dirProp=ON;
00951 }
00952 break;
00953 case CS:
00954 if( historyOfEN&PREV_EN_AFTER_W2 &&
00955 nextDirProp==EN && lastStrong!=AL
00956 ) {
00957
00958 if(lastStrong!=L) {
00959 dirProp=EN;
00960 } else {
00961
00962 dirProp=L;
00963 }
00964 historyOfEN|=EN_AFTER_W4;
00965 } else if(prevDirProp==AN &&
00966 (nextDirProp==AN ||
00967 (nextDirProp==EN && lastStrong==AL))
00968 ) {
00969
00970 dirProp=AN;
00971 } else {
00972
00973 dirProp=ON;
00974 }
00975 break;
00976 case ET:
00977
00978 if(next<limit) {
00979 while(DIRPROP_FLAG(nextDirProp)&MASK_ET_NSM_BN ) {
00980 if(++next<limit) {
00981 nextDirProp=dirProps[next];
00982 } else {
00983 nextDirProp=eor;
00984 break;
00985 }
00986 }
00987 }
00988
00989
00990 if((historyOfEN&PREV_EN_AFTER_W4) ||
00991 (nextDirProp==EN && lastStrong!=AL)
00992 ) {
00993
00994 if(lastStrong!=L) {
00995 dirProp=EN;
00996 } else {
00997
00998 dirProp=L;
00999 }
01000 } else {
01001
01002 dirProp=ON;
01003 }
01004
01005
01006 break;
01007 case NSM:
01008
01009 dirProp=prevDirProp;
01010
01011 historyOfEN>>=EN_SHIFT;
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 break;
01023 default:
01024 break;
01025 }
01026
01027
01028
01029
01030
01031
01032 if(DIRPROP_FLAG(dirProp)&MASK_N) {
01033 if(neutralStart<0) {
01034
01035 neutralStart=i;
01036 beforeNeutral=prevDirProp;
01037 }
01038 } else {
01039
01040
01041
01042
01043
01044
01045 UBiDiLevel level=levels[i];
01046
01047 if(neutralStart>=0) {
01048 UBiDiLevel final;
01049
01050 if(!(pBiDi->isInverse)) {
01051 if(beforeNeutral==L) {
01052 if(dirProp==L) {
01053 final=0;
01054 } else {
01055 final=level;
01056 }
01057 } else {
01058 if(dirProp==L) {
01059 final=level;
01060 } else {
01061 final=1;
01062 }
01063 }
01064 } else {
01065
01066 if(beforeNeutral!=R) {
01067 if(dirProp!=R) {
01068 final=0;
01069 } else {
01070 final=level;
01071 }
01072 } else {
01073 if(dirProp!=R) {
01074 final=level;
01075 } else {
01076 final=1;
01077 }
01078 }
01079 }
01080
01081 if((level^final)&1) {
01082
01083 do {
01084 ++levels[neutralStart];
01085 } while(++neutralStart<i);
01086 }
01087 neutralStart=-1;
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097 if(dirProp==L) {
01098 if(level&1) {
01099 ++level;
01100 } else {
01101 i=next;
01102 }
01103 } else if(dirProp==R) {
01104 if(!(level&1)) {
01105 ++level;
01106 } else {
01107 i=next;
01108 }
01109 } else {
01110
01111 level=numberLevel;
01112 }
01113
01114
01115 while(i<next) {
01116 levels[i++]=level;
01117 }
01118 }
01119 }
01120
01121
01122
01123
01124 if(neutralStart>=0) {
01125
01126
01127
01128
01129
01130
01131 UBiDiLevel level=levels[neutralStart], final;
01132
01133
01134 if(!(pBiDi->isInverse)) {
01135 if(beforeNeutral==L) {
01136 if(eor==L) {
01137 final=0;
01138 } else {
01139 final=level;
01140 }
01141 } else {
01142 if(eor==L) {
01143 final=level;
01144 } else {
01145 final=1;
01146 }
01147 }
01148 } else {
01149
01150 if(beforeNeutral!=R) {
01151 if(eor!=R) {
01152 final=0;
01153 } else {
01154 final=level;
01155 }
01156 } else {
01157 if(eor!=R) {
01158 final=level;
01159 } else {
01160 final=1;
01161 }
01162 }
01163 }
01164
01165 if((level^final)&1) {
01166
01167 do {
01168 ++levels[neutralStart];
01169 } while(++neutralStart<limit);
01170 }
01171 }
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 static void
01183 adjustWSLevels(UBiDi *pBiDi) {
01184 const DirProp *dirProps=pBiDi->dirProps;
01185 UBiDiLevel *levels=pBiDi->levels;
01186 UTextOffset i;
01187
01188 if(pBiDi->flags&MASK_WS) {
01189 UBiDiLevel paraLevel=pBiDi->paraLevel;
01190 Flags flag;
01191
01192 i=pBiDi->trailingWSStart;
01193 while(i>0) {
01194
01195 while(i>0 && DIRPROP_FLAG(dirProps[--i])&MASK_WS) {
01196 levels[i]=paraLevel;
01197 }
01198
01199
01200
01201 while(i>0) {
01202 flag=DIRPROP_FLAG(dirProps[--i]);
01203 if(flag&MASK_BN_EXPLICIT) {
01204 levels[i]=levels[i+1];
01205 } else if(flag&MASK_B_S) {
01206 levels[i]=paraLevel;
01207 break;
01208 }
01209 }
01210 }
01211 }
01212 }
01213
01214
01215
01216 U_CAPI UBiDiDirection U_EXPORT2
01217 ubidi_getDirection(const UBiDi *pBiDi) {
01218 if(pBiDi!=NULL) {
01219 return pBiDi->direction;
01220 } else {
01221 return UBIDI_LTR;
01222 }
01223 }
01224
01225 U_CAPI const UChar * U_EXPORT2
01226 ubidi_getText(const UBiDi *pBiDi) {
01227 if(pBiDi!=NULL) {
01228 return pBiDi->text;
01229 } else {
01230 return NULL;
01231 }
01232 }
01233
01234 U_CAPI UTextOffset U_EXPORT2
01235 ubidi_getLength(const UBiDi *pBiDi) {
01236 if(pBiDi!=NULL) {
01237 return pBiDi->length;
01238 } else {
01239 return 0;
01240 }
01241 }
01242
01243 U_CAPI UBiDiLevel U_EXPORT2
01244 ubidi_getParaLevel(const UBiDi *pBiDi) {
01245 if(pBiDi!=NULL) {
01246 return pBiDi->paraLevel;
01247 } else {
01248 return 0;
01249 }
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259 #if 0
01260
01261
01262
01263
01264
01265
01266
01267 #define MASK_W_TABLE (FLAG(L)|FLAG(R)|FLAG(AL)|FLAG(EN)|FLAG(ES)|FLAG(CS)|FLAG(ET)|FLAG(AN))
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280 enum { _L, _R, _AL, _EN, _ES, _CS, _ET, _AN, _OTHER };
01281 enum { __EN, __AN, __OTHER };
01282
01283 #define LAST_STRONG_SHIFT 3
01284 #define DIR_PROP_SHIFT 5
01285 #define NEXT_DIR_PROP_SHIFT 8
01286
01287
01288 #define LAST_STRONG_MASK 3
01289 #define DIR_PROP_MASK 7
01290 #define STATE_MASK 0x1f
01291
01292
01293 static DirProp inputDirProp[dirPropCount]={ _X<<DIR_PROP_SHIFT, ... };
01294
01295
01296 static DirProp inputNextDirProp[dirPropCount]={ __X<<NEXT_DIR_PROP_SHIFT, ... };
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 enum { ___L, ___R, ___EN, ___AN, ___ON, ___count };
01311
01312
01313 static DirProp outputDirProp[___count]={ X, ... };
01314
01315
01316 static uint8_t wnTable[1024]={ };
01317
01318 static void
01319 resolveImplicitLevels(BiDi *pBiDi,
01320 Index start, Index end,
01321 DirProp sor, DirProp eor) {
01322
01323 uint8_t state;
01324
01325
01326
01327
01328 state= sor==L ? 0 : _R<<LAST_STRONG_SHIFT;
01329
01330 while(next<limit) {
01331
01332 prevDirProp=dirProp;
01333 dirProp=nextDirProp;
01334 i=next;
01335 do {
01336 if(++next<limit) {
01337 nextDirProp=dirProps[next];
01338 } else {
01339 nextDirProp=eor;
01340 break;
01341 }
01342 } while(FLAG(nextDirProp)&MASK_BN_EXPLICIT);
01343
01344
01345
01346 if(FLAG(dirProp)&MASK_W_TABLE) {
01347 state=wnTable[
01348 ((int)state)|
01349 inputDirProp[dirProp]|
01350 inputNextDirProp[nextDirProp]
01351 ];
01352 dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
01353 state&=STATE_MASK;
01354 } else if(dirProp==ET) {
01355
01356 while(next<limit && FLAG(nextDirProp)&MASK_ET_NSM_BN ) {
01357 if(++next<limit) {
01358 nextDirProp=dirProps[next];
01359 } else {
01360 nextDirProp=eor;
01361 break;
01362 }
01363 }
01364
01365 state=wnTable[
01366 ((int)state)|
01367 _ET<<DIR_PROP_SHIFT|
01368 inputNextDirProp[nextDirProp]
01369 ];
01370 dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
01371 state&=STATE_MASK;
01372
01373
01374 } else if(dirProp==NSM) {
01375
01376 dirProp=prevDirProp;
01377
01378 } else {
01379
01380 state&=LAST_STRONG_MASK<<LAST_STRONG_SHIFT;
01381 }
01382
01383
01384 }
01385
01386 }
01387 #endif