ICU-5732 a few fixes to match those in ICU4J
X-SVN-Rev: 22304
This commit is contained in:
parent
a7a26cd51d
commit
f3ffdb5afc
@ -1,18 +1,18 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidi.c
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999jul27
|
||||
* created by: Markus W. Scherer
|
||||
*/
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidi.c
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999jul27
|
||||
* created by: Markus W. Scherer, updated by Matitiahu Allouche
|
||||
*/
|
||||
|
||||
#include "cmemory.h"
|
||||
#include "unicode/utypes.h"
|
||||
@ -114,6 +114,14 @@ static const Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
|
||||
|
||||
/* UBiDi object management -------------------------------------------------- */
|
||||
|
||||
static void
|
||||
crash()
|
||||
{
|
||||
char ** pc;
|
||||
pc = NULL;
|
||||
*pc = "make it crash!";
|
||||
}
|
||||
|
||||
U_CAPI UBiDi * U_EXPORT2
|
||||
ubidi_open(void)
|
||||
{
|
||||
@ -281,7 +289,7 @@ ubidi_isInverse(UBiDi *pBiDi) {
|
||||
* concept of RUNS_ONLY which is a double operation.
|
||||
* It could be advantageous to divide this into 3 concepts:
|
||||
* a) Operation: direct / inverse / RUNS_ONLY
|
||||
* b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_L
|
||||
* b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_R
|
||||
* c) Inverse algorithm: default / INVERSE_LIKE_DIRECT / NUMBERS_SPECIAL
|
||||
* This would allow combinations not possible today like RUNS_ONLY with
|
||||
* NUMBERS_SPECIAL.
|
||||
@ -293,7 +301,7 @@ ubidi_isInverse(UBiDi *pBiDi) {
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
ubidi_setReorderingMode(UBiDi *pBiDi, UBiDiReorderingMode reorderingMode) {
|
||||
if ((pBiDi != NULL) && (reorderingMode >= UBIDI_REORDER_DEFAULT)
|
||||
if ((pBiDi!=NULL) && (reorderingMode >= UBIDI_REORDER_DEFAULT)
|
||||
&& (reorderingMode < UBIDI_REORDER_COUNT)) {
|
||||
pBiDi->reorderingMode = reorderingMode;
|
||||
pBiDi->isInverse = reorderingMode == UBIDI_REORDER_INVERSE_NUMBERS_AS_L;
|
||||
@ -302,7 +310,7 @@ ubidi_setReorderingMode(UBiDi *pBiDi, UBiDiReorderingMode reorderingMode) {
|
||||
|
||||
U_CAPI UBiDiReorderingMode U_EXPORT2
|
||||
ubidi_getReorderingMode(UBiDi *pBiDi) {
|
||||
if (pBiDi != NULL) {
|
||||
if (pBiDi!=NULL) {
|
||||
return pBiDi->reorderingMode;
|
||||
} else {
|
||||
return UBIDI_REORDER_DEFAULT;
|
||||
@ -314,14 +322,14 @@ ubidi_setReorderingOptions(UBiDi *pBiDi, uint32_t reorderingOptions) {
|
||||
if (reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
|
||||
reorderingOptions&=~UBIDI_OPTION_INSERT_MARKS;
|
||||
}
|
||||
if (pBiDi != NULL) {
|
||||
pBiDi->reorderingOptions = reorderingOptions;
|
||||
if (pBiDi!=NULL) {
|
||||
pBiDi->reorderingOptions=reorderingOptions;
|
||||
}
|
||||
}
|
||||
|
||||
U_CAPI uint32_t U_EXPORT2
|
||||
ubidi_getReorderingOptions(UBiDi *pBiDi) {
|
||||
if (pBiDi != NULL) {
|
||||
if (pBiDi!=NULL) {
|
||||
return pBiDi->reorderingOptions;
|
||||
} else {
|
||||
return 0;
|
||||
@ -1372,8 +1380,7 @@ processPropertySeq(UBiDi *pBiDi, LevState *pLevState, uint8_t _prop,
|
||||
break;
|
||||
|
||||
default: /* we should never get here */
|
||||
start=start0+25;
|
||||
start/=(start-start0-25); /* force program crash */
|
||||
crash();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1487,8 +1494,7 @@ resolveImplicitLevels(UBiDi *pBiDi,
|
||||
start2=i;
|
||||
break;
|
||||
default: /* we should never get here */
|
||||
start=start1+25;
|
||||
start/=(start-start1-25); /* force program crash */
|
||||
crash();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1552,8 +1558,11 @@ setParaRunsOnly(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
void *runsOnlyMemory;
|
||||
int32_t *visualMap;
|
||||
UChar *visualText;
|
||||
int32_t saveLength, saveTrailingWSStart;
|
||||
const UBiDiLevel *levels;
|
||||
UBiDiLevel *saveLevels;
|
||||
UBiDiDirection saveDirection;
|
||||
UBool saveMayAllocateText;
|
||||
Run *runs;
|
||||
int32_t visualLength, i, j, visualStart, logicalStart,
|
||||
runCount, runLength, addedRuns, insertRemove,
|
||||
@ -1580,8 +1589,17 @@ setParaRunsOnly(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
pBiDi->reorderingOptions&=~UBIDI_OPTION_INSERT_MARKS;
|
||||
pBiDi->reorderingOptions|=UBIDI_OPTION_REMOVE_CONTROLS;
|
||||
}
|
||||
paraLevel&=1; /* accept only 0 or 1 */
|
||||
ubidi_setPara(pBiDi, text, length, paraLevel, NULL, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
goto cleanup3;
|
||||
}
|
||||
/* we cannot access directly pBiDi->levels since it is not yet set if
|
||||
* direction is not MIXED
|
||||
*/
|
||||
levels=ubidi_getLevels(pBiDi, pErrorCode);
|
||||
uprv_memcpy(saveLevels, levels, pBiDi->length*sizeof(UBiDiLevel));
|
||||
saveTrailingWSStart=pBiDi->trailingWSStart;
|
||||
|
||||
/* FOOD FOR THOUGHT: instead of writing the visual text, we could use
|
||||
* the visual map and the dirProps array to drive the second call
|
||||
@ -1591,20 +1609,31 @@ setParaRunsOnly(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
*/
|
||||
visualLength=ubidi_writeReordered(pBiDi, visualText, length,
|
||||
UBIDI_DO_MIRRORING, pErrorCode);
|
||||
pBiDi->reorderingOptions=saveOptions;
|
||||
ubidi_getVisualMap(pBiDi, visualMap, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
goto cleanup2;
|
||||
}
|
||||
uprv_memcpy(saveLevels, levels, length*sizeof(UBiDiLevel));
|
||||
pBiDi->reorderingOptions=saveOptions;
|
||||
saveLength=pBiDi->length;
|
||||
saveDirection=pBiDi->direction;
|
||||
|
||||
pBiDi->reorderingMode=UBIDI_REORDER_INVERSE_LIKE_DIRECT;
|
||||
paraLevel=pBiDi->paraLevel^1;
|
||||
paraLevel^=1;
|
||||
/* Because what we did with reorderingOptions, visualText may be shorter
|
||||
* than the original text. But we don't want the levels memory to be
|
||||
* reallocated shorter than the original length, since we need to restore
|
||||
* the levels as after the first call to ubidi_setpara() before returning.
|
||||
* We will force mayAllocateText to FALSE before the second call to
|
||||
* ubidi_setpara(), and will restore it afterwards.
|
||||
*/
|
||||
saveMayAllocateText=pBiDi->mayAllocateText;
|
||||
pBiDi->mayAllocateText=FALSE;
|
||||
ubidi_setPara(pBiDi, visualText, visualLength, paraLevel, NULL, pErrorCode);
|
||||
pBiDi->mayAllocateText=saveMayAllocateText;
|
||||
ubidi_getRuns(pBiDi, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
goto cleanup1;
|
||||
}
|
||||
ubidi_getRuns(pBiDi, pErrorCode);
|
||||
/* check if some runs must be split, count how many splits */
|
||||
addedRuns=0;
|
||||
runCount=pBiDi->runCount;
|
||||
@ -1691,13 +1720,22 @@ setParaRunsOnly(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
cleanup2:
|
||||
/* restore real text */
|
||||
pBiDi->text=text;
|
||||
pBiDi->length=saveLength;
|
||||
pBiDi->originalLength=length;
|
||||
pBiDi->direction=saveDirection;
|
||||
/* the saved levels should never excess levelsSize, but we check anyway */
|
||||
if(saveLength>pBiDi->levelsSize) {
|
||||
saveLength=pBiDi->levelsSize;
|
||||
}
|
||||
uprv_memcpy(pBiDi->levels, saveLevels, saveLength*sizeof(UBiDiLevel));
|
||||
pBiDi->trailingWSStart=saveTrailingWSStart;
|
||||
/* free memory for mapping table and visual text */
|
||||
uprv_free(runsOnlyMemory);
|
||||
cleanup3:
|
||||
pBiDi->reorderingMode=UBIDI_REORDER_RUNS_ONLY;
|
||||
if(pBiDi->runCount>1) {
|
||||
pBiDi->direction=UBIDI_MIXED;
|
||||
}
|
||||
cleanup3:
|
||||
pBiDi->reorderingMode=UBIDI_REORDER_RUNS_ONLY;
|
||||
}
|
||||
|
||||
/* ubidi_setPara ------------------------------------------------------------ */
|
||||
@ -1709,12 +1747,11 @@ ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
UBiDiDirection direction;
|
||||
|
||||
/* check the argument values */
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return;
|
||||
} else if(pBiDi==NULL || text==NULL ||
|
||||
((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
|
||||
length<-1
|
||||
) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
if(!IS_DEFAULT_LEVEL(paraLevel)) {
|
||||
RETURN_IF_BAD_RANGE(paraLevel, 0, UBIDI_MAX_EXPLICIT_LEVEL+1, *pErrorCode, );
|
||||
}
|
||||
if(pBiDi==NULL || text==NULL || length<-1) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
@ -1771,6 +1808,7 @@ ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
}
|
||||
|
||||
pBiDi->runCount=0;
|
||||
pBiDi->paraCount=0;
|
||||
pBiDi->pParaBiDi=pBiDi; /* mark successful setPara */
|
||||
return;
|
||||
}
|
||||
@ -1862,8 +1900,7 @@ ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
break;
|
||||
case UBIDI_REORDER_RUNS_ONLY:
|
||||
/* we should never get here */
|
||||
pBiDi=NULL;
|
||||
pBiDi->text=NULL; /* make the program crash! */
|
||||
crash();
|
||||
break;
|
||||
case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
|
||||
pBiDi->pImpTabPair=&impTab_INVERSE_NUMBERS_AS_L;
|
||||
@ -1882,9 +1919,6 @@ ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
pBiDi->pImpTabPair=&impTab_INVERSE_FOR_NUMBERS_SPECIAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pBiDi->pImpTabPair=&impTab_DEFAULT;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If there are no external levels specified and there
|
||||
@ -1969,6 +2003,39 @@ ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
|
||||
adjustWSLevels(pBiDi);
|
||||
break;
|
||||
}
|
||||
/* add RLM for inverse Bidi with contextual orientation resolving
|
||||
* to RTL which would not round-trip otherwise
|
||||
*/
|
||||
if((pBiDi->defaultParaLevel>0) &&
|
||||
(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) &&
|
||||
((pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT) ||
|
||||
(pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL))) {
|
||||
int32_t i, j, start, last;
|
||||
DirProp dirProp;
|
||||
for(i=0; i<pBiDi->paraCount; i++) {
|
||||
last=pBiDi->paras[i]-1;
|
||||
if((pBiDi->dirProps[last] & CONTEXT_RTL)==0) {
|
||||
continue; /* LTR paragraph */
|
||||
}
|
||||
start= i==0 ? 0 : pBiDi->paras[i - 1];
|
||||
for(j=last; j>=start; j--) {
|
||||
dirProp=NO_CONTEXT_RTL(pBiDi->dirProps[j]);
|
||||
if(dirProp==L) {
|
||||
if(j<last) {
|
||||
while(NO_CONTEXT_RTL(pBiDi->dirProps[last])==B) {
|
||||
last--;
|
||||
}
|
||||
}
|
||||
addPoint(pBiDi, last, RLM_BEFORE);
|
||||
break;
|
||||
}
|
||||
if(DIRPROP_FLAG(dirProp) & MASK_R_AL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
|
||||
pBiDi->resultLength -= pBiDi->controlCount;
|
||||
} else {
|
||||
@ -2065,13 +2132,10 @@ ubidi_getParagraphByIndex(const UBiDi *pBiDi, int32_t paraIndex,
|
||||
int32_t paraStart;
|
||||
|
||||
/* check the argument values */
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return;
|
||||
} else if( !IS_VALID_PARA_OR_LINE(pBiDi) || /* no valid setPara/setLine */
|
||||
paraIndex<0 || paraIndex>=pBiDi->paraCount ) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, );
|
||||
RETURN_IF_BAD_RANGE(paraIndex, 0, pBiDi->paraCount, *pErrorCode, );
|
||||
|
||||
pBiDi=pBiDi->pParaBiDi; /* get Para object if Line object */
|
||||
if(paraIndex) {
|
||||
paraStart=pBiDi->paras[paraIndex-1];
|
||||
@ -2098,15 +2162,11 @@ ubidi_getParagraph(const UBiDi *pBiDi, int32_t charIndex,
|
||||
|
||||
/* check the argument values */
|
||||
/* pErrorCode will be checked by the call to ubidi_getParagraphByIndex */
|
||||
if( !IS_VALID_PARA_OR_LINE(pBiDi)) {/* no valid setPara/setLine */
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
|
||||
pBiDi=pBiDi->pParaBiDi; /* get Para object if Line object */
|
||||
if( charIndex<0 || charIndex>=pBiDi->length ) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
RETURN_IF_BAD_RANGE(charIndex, 0, pBiDi->length, *pErrorCode, -1);
|
||||
|
||||
for(paraIndex=0; charIndex>=pBiDi->paras[paraIndex]; paraIndex++);
|
||||
ubidi_getParagraphByIndex(pBiDi, paraIndex, pParaStart, pParaLimit, pParaLevel, pErrorCode);
|
||||
return paraIndex;
|
||||
@ -2117,9 +2177,8 @@ ubidi_setClassCallback(UBiDi *pBiDi, UBiDiClassCallback *newFn,
|
||||
const void *newContext, UBiDiClassCallback **oldFn,
|
||||
const void **oldContext, UErrorCode *pErrorCode)
|
||||
{
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return;
|
||||
} else if(pBiDi==NULL) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
if(pBiDi==NULL) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
@ -2138,6 +2197,9 @@ ubidi_setClassCallback(UBiDi *pBiDi, UBiDiClassCallback *newFn,
|
||||
U_CAPI void U_EXPORT2
|
||||
ubidi_getClassCallback(UBiDi *pBiDi, UBiDiClassCallback **fn, const void **context)
|
||||
{
|
||||
if(pBiDi==NULL) {
|
||||
return;
|
||||
}
|
||||
if( fn )
|
||||
{
|
||||
*fn = pBiDi->fnClassCallback;
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidiimp.h
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999aug06
|
||||
* created by: Markus W. Scherer
|
||||
*/
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidiimp.h
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999aug06
|
||||
* created by: Markus W. Scherer, updated by Matitiahu Allouche
|
||||
*/
|
||||
|
||||
#ifndef UBIDIIMP_H
|
||||
#define UBIDIIMP_H
|
||||
@ -70,6 +70,7 @@ enum {
|
||||
/* are there any characters that are LTR or RTL? */
|
||||
#define MASK_LTR (DIRPROP_FLAG(L)|DIRPROP_FLAG(EN)|DIRPROP_FLAG(AN)|DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
|
||||
#define MASK_RTL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)|DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO))
|
||||
#define MASK_R_AL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL))
|
||||
|
||||
/* explicit embedding codes */
|
||||
#define MASK_LRX (DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
|
||||
@ -299,7 +300,6 @@ struct UBiDi {
|
||||
};
|
||||
|
||||
#define IS_VALID_PARA(x) ((x) && ((x)->pParaBiDi==(x)))
|
||||
#define IS_VALID_LINE(x) ((x) && ((x)->pParaBiDi) && ((x)->pParaBiDi->pParaBiDi==(x)->pParaBiDi))
|
||||
#define IS_VALID_PARA_OR_LINE(x) ((x) && ((x)->pParaBiDi==(x) || (((x)->pParaBiDi) && (x)->pParaBiDi->pParaBiDi==(x)->pParaBiDi)))
|
||||
|
||||
typedef union {
|
||||
@ -309,6 +309,25 @@ typedef union {
|
||||
Run *runsMemory;
|
||||
} BidiMemoryForAllocation;
|
||||
|
||||
/* Macros for initial checks at function entry */
|
||||
#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) \
|
||||
if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue
|
||||
#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) \
|
||||
if(!IS_VALID_PARA(bidi)) { \
|
||||
errcode=U_INVALID_STATE_ERROR; \
|
||||
return retvalue; \
|
||||
}
|
||||
#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) \
|
||||
if(!IS_VALID_PARA_OR_LINE(bidi)) { \
|
||||
errcode=U_INVALID_STATE_ERROR; \
|
||||
return retvalue; \
|
||||
}
|
||||
#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) \
|
||||
if((arg)<(start) || (arg)>=(limit)) { \
|
||||
(errcode)=U_ILLEGAL_ARGUMENT_ERROR; \
|
||||
return retvalue; \
|
||||
}
|
||||
|
||||
/* helper function to (re)allocate memory if allowed */
|
||||
U_CFUNC UBool
|
||||
ubidi_getMemory(BidiMemoryForAllocation *pMemory, int32_t *pSize, UBool mayAllocate, int32_t sizeNeeded);
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidiln.c
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999aug06
|
||||
* created by: Markus W. Scherer
|
||||
*/
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
* file name: ubidiln.c
|
||||
* encoding: US-ASCII
|
||||
* tab size: 8 (not used)
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999aug06
|
||||
* created by: Markus W. Scherer, updated by Matitiahu Allouche
|
||||
*/
|
||||
|
||||
/* set import/export definitions */
|
||||
#ifndef U_COMMON_IMPLEMENTATION
|
||||
@ -133,16 +133,16 @@ ubidi_setLine(const UBiDi *pParaBiDi,
|
||||
int32_t length;
|
||||
|
||||
/* check the argument values */
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return;
|
||||
} else if(!IS_VALID_PARA(pParaBiDi) || pLineBiDi==NULL) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
RETURN_IF_NOT_VALID_PARA(pParaBiDi, *pErrorCode, );
|
||||
RETURN_IF_BAD_RANGE(start, 0, limit, *pErrorCode, );
|
||||
RETURN_IF_BAD_RANGE(limit, 0, pParaBiDi->length+1, *pErrorCode, );
|
||||
if(pLineBiDi==NULL) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
} else if(start<0 || start>limit || limit>pParaBiDi->length) {
|
||||
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
return;
|
||||
} else if(ubidi_getParagraph(pParaBiDi, start, NULL, NULL, NULL, pErrorCode) !=
|
||||
ubidi_getParagraph(pParaBiDi, limit-1, NULL, NULL, NULL, pErrorCode)) {
|
||||
}
|
||||
if(ubidi_getParagraph(pParaBiDi, start, NULL, NULL, NULL, pErrorCode) !=
|
||||
ubidi_getParagraph(pParaBiDi, limit-1, NULL, NULL, NULL, pErrorCode)) {
|
||||
/* the line crosses a paragraph boundary */
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
@ -167,92 +167,84 @@ ubidi_setLine(const UBiDi *pParaBiDi,
|
||||
pLineBiDi->controlCount++;
|
||||
}
|
||||
}
|
||||
pLineBiDi->resultLength-=pLineBiDi->controlCount;
|
||||
}
|
||||
|
||||
if(length>0) {
|
||||
pLineBiDi->dirProps=pParaBiDi->dirProps+start;
|
||||
pLineBiDi->levels=pParaBiDi->levels+start;
|
||||
pLineBiDi->runCount=-1;
|
||||
pLineBiDi->dirProps=pParaBiDi->dirProps+start;
|
||||
pLineBiDi->levels=pParaBiDi->levels+start;
|
||||
pLineBiDi->runCount=-1;
|
||||
|
||||
if(pParaBiDi->direction!=UBIDI_MIXED) {
|
||||
/* the parent is already trivial */
|
||||
pLineBiDi->direction=pParaBiDi->direction;
|
||||
if(pParaBiDi->direction!=UBIDI_MIXED) {
|
||||
/* the parent is already trivial */
|
||||
pLineBiDi->direction=pParaBiDi->direction;
|
||||
|
||||
/*
|
||||
* The parent's levels are all either
|
||||
* implicitly or explicitly ==paraLevel;
|
||||
* do the same here.
|
||||
*/
|
||||
if(pParaBiDi->trailingWSStart<=start) {
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
} else if(pParaBiDi->trailingWSStart<limit) {
|
||||
pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start;
|
||||
} else {
|
||||
pLineBiDi->trailingWSStart=length;
|
||||
}
|
||||
/*
|
||||
* The parent's levels are all either
|
||||
* implicitly or explicitly ==paraLevel;
|
||||
* do the same here.
|
||||
*/
|
||||
if(pParaBiDi->trailingWSStart<=start) {
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
} else if(pParaBiDi->trailingWSStart<limit) {
|
||||
pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start;
|
||||
} else {
|
||||
const UBiDiLevel *levels=pLineBiDi->levels;
|
||||
int32_t i, trailingWSStart;
|
||||
UBiDiLevel level;
|
||||
|
||||
setTrailingWSStart(pLineBiDi);
|
||||
trailingWSStart=pLineBiDi->trailingWSStart;
|
||||
|
||||
/* recalculate pLineBiDi->direction */
|
||||
if(trailingWSStart==0) {
|
||||
/* all levels are at paraLevel */
|
||||
pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1);
|
||||
} else {
|
||||
/* get the level of the first character */
|
||||
level=(UBiDiLevel)(levels[0]&1);
|
||||
|
||||
/* if there is anything of a different level, then the line is mixed */
|
||||
if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) {
|
||||
/* the trailing WS is at paraLevel, which differs from levels[0] */
|
||||
pLineBiDi->direction=UBIDI_MIXED;
|
||||
} else {
|
||||
/* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */
|
||||
i=1;
|
||||
for(;;) {
|
||||
if(i==trailingWSStart) {
|
||||
/* the direction values match those in level */
|
||||
pLineBiDi->direction=(UBiDiDirection)level;
|
||||
break;
|
||||
} else if((levels[i]&1)!=level) {
|
||||
pLineBiDi->direction=UBIDI_MIXED;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(pLineBiDi->direction) {
|
||||
case UBIDI_LTR:
|
||||
/* make sure paraLevel is even */
|
||||
pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1);
|
||||
|
||||
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
break;
|
||||
case UBIDI_RTL:
|
||||
/* make sure paraLevel is odd */
|
||||
pLineBiDi->paraLevel|=1;
|
||||
|
||||
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pLineBiDi->trailingWSStart=length;
|
||||
}
|
||||
} else {
|
||||
/* create an object for a zero-length line */
|
||||
pLineBiDi->direction=pLineBiDi->paraLevel&1 ? UBIDI_RTL : UBIDI_LTR;
|
||||
pLineBiDi->trailingWSStart=pLineBiDi->runCount=0;
|
||||
const UBiDiLevel *levels=pLineBiDi->levels;
|
||||
int32_t i, trailingWSStart;
|
||||
UBiDiLevel level;
|
||||
|
||||
pLineBiDi->dirProps=NULL;
|
||||
pLineBiDi->levels=NULL;
|
||||
setTrailingWSStart(pLineBiDi);
|
||||
trailingWSStart=pLineBiDi->trailingWSStart;
|
||||
|
||||
/* recalculate pLineBiDi->direction */
|
||||
if(trailingWSStart==0) {
|
||||
/* all levels are at paraLevel */
|
||||
pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1);
|
||||
} else {
|
||||
/* get the level of the first character */
|
||||
level=(UBiDiLevel)(levels[0]&1);
|
||||
|
||||
/* if there is anything of a different level, then the line is mixed */
|
||||
if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) {
|
||||
/* the trailing WS is at paraLevel, which differs from levels[0] */
|
||||
pLineBiDi->direction=UBIDI_MIXED;
|
||||
} else {
|
||||
/* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */
|
||||
i=1;
|
||||
for(;;) {
|
||||
if(i==trailingWSStart) {
|
||||
/* the direction values match those in level */
|
||||
pLineBiDi->direction=(UBiDiDirection)level;
|
||||
break;
|
||||
} else if((levels[i]&1)!=level) {
|
||||
pLineBiDi->direction=UBIDI_MIXED;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(pLineBiDi->direction) {
|
||||
case UBIDI_LTR:
|
||||
/* make sure paraLevel is even */
|
||||
pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1);
|
||||
|
||||
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
break;
|
||||
case UBIDI_RTL:
|
||||
/* make sure paraLevel is odd */
|
||||
pLineBiDi->paraLevel|=1;
|
||||
|
||||
/* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
|
||||
pLineBiDi->trailingWSStart=0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pLineBiDi->pParaBiDi=pParaBiDi; /* mark successful setLine */
|
||||
return;
|
||||
@ -274,13 +266,12 @@ U_CAPI const UBiDiLevel * U_EXPORT2
|
||||
ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
int32_t start, length;
|
||||
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return NULL;
|
||||
} else if(!IS_VALID_PARA_OR_LINE(pBiDi) || (length=pBiDi->length)<=0) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, NULL);
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, NULL);
|
||||
if((length=pBiDi->length)<=0) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((start=pBiDi->trailingWSStart)==length) {
|
||||
/* the current levels array reflects the WS run */
|
||||
return pBiDi->levels;
|
||||
@ -293,7 +284,6 @@ ubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
* This must be a UBiDi object for a line, and
|
||||
* we need to create a new levels array.
|
||||
*/
|
||||
|
||||
if(getLevelsMemory(pBiDi, length)) {
|
||||
UBiDiLevel *levels=pBiDi->levelsMemory;
|
||||
|
||||
@ -321,18 +311,16 @@ ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
|
||||
int32_t length, runCount, visualStart, logicalLimit, logicalFirst, i;
|
||||
Run iRun;
|
||||
|
||||
if(!IS_VALID_PARA_OR_LINE(pBiDi) || logicalStart<0 ||
|
||||
(length=pBiDi->length)<=logicalStart) {
|
||||
errorCode=U_ZERO_ERROR;
|
||||
RETURN_IF_BAD_RANGE(logicalStart, 0, pBiDi->length, errorCode, );
|
||||
/* ubidi_countRuns will check VALID_PARA_OR_LINE */
|
||||
runCount=ubidi_countRuns((UBiDi *)pBiDi, &errorCode);
|
||||
if(U_FAILURE(errorCode)) {
|
||||
return;
|
||||
}
|
||||
/* this is done based on runs rather than on levels since levels have
|
||||
a special interpretation when UBIDI_REORDER_RUNS_ONLY
|
||||
*/
|
||||
errorCode=U_ZERO_ERROR;
|
||||
runCount=ubidi_countRuns((UBiDi *)pBiDi, &errorCode);
|
||||
if(U_FAILURE(errorCode)) {
|
||||
return;
|
||||
}
|
||||
visualStart=logicalLimit=0;
|
||||
|
||||
for(i=0; i<runCount; i++) {
|
||||
@ -349,7 +337,10 @@ ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
|
||||
*pLogicalLimit=logicalLimit;
|
||||
}
|
||||
if(pLevel) {
|
||||
if(pBiDi->direction!=UBIDI_MIXED || logicalStart>=pBiDi->trailingWSStart) {
|
||||
if(pBiDi->reorderingMode==UBIDI_REORDER_RUNS_ONLY) {
|
||||
*pLevel=GET_ODD_BIT(iRun.logicalStart);
|
||||
}
|
||||
else if(pBiDi->direction!=UBIDI_MIXED || logicalStart>=pBiDi->trailingWSStart) {
|
||||
*pLevel=GET_PARALEVEL(pBiDi, logicalStart);
|
||||
} else {
|
||||
*pLevel=pBiDi->levels[logicalStart];
|
||||
@ -361,42 +352,41 @@ ubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalStart,
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
|
||||
ubidi_getRuns(pBiDi, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
return -1;
|
||||
} else if(!IS_VALID_PARA_OR_LINE(pBiDi) ||
|
||||
(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi, pErrorCode))) {
|
||||
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
return -1;
|
||||
} else {
|
||||
return pBiDi->runCount;
|
||||
}
|
||||
return pBiDi->runCount;
|
||||
}
|
||||
|
||||
U_CAPI UBiDiDirection U_EXPORT2
|
||||
ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
|
||||
int32_t *pLogicalStart, int32_t *pLength)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if( !IS_VALID_PARA_OR_LINE(pBiDi) || runIndex<0 ||
|
||||
(pBiDi->runCount==-1 && !ubidi_getRuns(pBiDi, &status)) ||
|
||||
runIndex>=pBiDi->runCount
|
||||
) {
|
||||
int32_t start;
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, errorCode, UBIDI_LTR);
|
||||
ubidi_getRuns(pBiDi, &errorCode);
|
||||
if(U_FAILURE(errorCode)) {
|
||||
return UBIDI_LTR;
|
||||
} else {
|
||||
int32_t start=pBiDi->runs[runIndex].logicalStart;
|
||||
if(pLogicalStart!=NULL) {
|
||||
*pLogicalStart=GET_INDEX(start);
|
||||
}
|
||||
if(pLength!=NULL) {
|
||||
if(runIndex>0) {
|
||||
*pLength=pBiDi->runs[runIndex].visualLimit-
|
||||
pBiDi->runs[runIndex-1].visualLimit;
|
||||
} else {
|
||||
*pLength=pBiDi->runs[0].visualLimit;
|
||||
}
|
||||
}
|
||||
return (UBiDiDirection)GET_ODD_BIT(start);
|
||||
}
|
||||
RETURN_IF_BAD_RANGE(runIndex, 0, pBiDi->runCount, errorCode, UBIDI_LTR);
|
||||
|
||||
start=pBiDi->runs[runIndex].logicalStart;
|
||||
if(pLogicalStart!=NULL) {
|
||||
*pLogicalStart=GET_INDEX(start);
|
||||
}
|
||||
if(pLength!=NULL) {
|
||||
if(runIndex>0) {
|
||||
*pLength=pBiDi->runs[runIndex].visualLimit-
|
||||
pBiDi->runs[runIndex-1].visualLimit;
|
||||
} else {
|
||||
*pLength=pBiDi->runs[0].visualLimit;
|
||||
}
|
||||
}
|
||||
return (UBiDiDirection)GET_ODD_BIT(start);
|
||||
}
|
||||
|
||||
/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */
|
||||
@ -529,7 +519,7 @@ reorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
|
||||
|
||||
/* compute the runs array --------------------------------------------------- */
|
||||
|
||||
static int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *status) {
|
||||
static int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) {
|
||||
Run *runs=pBiDi->runs;
|
||||
int32_t runCount=pBiDi->runCount, visualStart=0, i, length, logicalStart;
|
||||
|
||||
@ -543,7 +533,7 @@ static int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UError
|
||||
}
|
||||
/* we should never get here */
|
||||
U_ASSERT(FALSE);
|
||||
*status = U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
*pErrorCode = U_INVALID_STATE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -560,6 +550,14 @@ static int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UError
|
||||
*/
|
||||
U_CFUNC UBool
|
||||
ubidi_getRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
/*
|
||||
* This method returns immediately if the runs are already set. This
|
||||
* includes the case of length==0 (handled in setPara)..
|
||||
*/
|
||||
if (pBiDi->runCount>=0) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(pBiDi->direction!=UBIDI_MIXED) {
|
||||
/* simple, single-run case - this covers length==0 */
|
||||
/* pBiDi->paraLevel is ok even for contextual multiple paragraphs */
|
||||
@ -567,7 +565,9 @@ ubidi_getRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
} else /* UBIDI_MIXED, length>0 */ {
|
||||
/* mixed directionality */
|
||||
int32_t length=pBiDi->length, limit;
|
||||
|
||||
UBiDiLevel *levels=pBiDi->levels;
|
||||
int32_t i, runCount;
|
||||
UBiDiLevel level=UBIDI_DEFAULT_LTR; /* initialize with no valid level */
|
||||
/*
|
||||
* If there are WS characters at the end of the line
|
||||
* and the run preceding them has a level different from
|
||||
@ -580,114 +580,105 @@ ubidi_getRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
|
||||
* levels[]!=paraLevel but we have to treat it like it were so.
|
||||
*/
|
||||
limit=pBiDi->trailingWSStart;
|
||||
if(limit==0) {
|
||||
/* there is only WS on this line */
|
||||
getSingleRun(pBiDi, GET_PARALEVEL(pBiDi, 0));
|
||||
} else {
|
||||
UBiDiLevel *levels=pBiDi->levels;
|
||||
int32_t i, runCount;
|
||||
UBiDiLevel level=UBIDI_DEFAULT_LTR; /* initialize with no valid level */
|
||||
/* count the runs, there is at least one non-WS run, and limit>0 */
|
||||
runCount=0;
|
||||
for(i=0; i<limit; ++i) {
|
||||
/* increment runCount at the start of each run */
|
||||
if(levels[i]!=level) {
|
||||
++runCount;
|
||||
level=levels[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* count the runs, there is at least one non-WS run, and limit>0 */
|
||||
runCount=0;
|
||||
for(i=0; i<limit; ++i) {
|
||||
/* increment runCount at the start of each run */
|
||||
if(levels[i]!=level) {
|
||||
++runCount;
|
||||
level=levels[i];
|
||||
/*
|
||||
* We don't need to see if the last run can be merged with a trailing
|
||||
* WS run because setTrailingWSStart() would have done that.
|
||||
*/
|
||||
if(runCount==1 && limit==length) {
|
||||
/* There is only one non-WS run and no trailing WS-run. */
|
||||
getSingleRun(pBiDi, levels[0]);
|
||||
} else /* runCount>1 || limit<length */ {
|
||||
/* allocate and set the runs */
|
||||
Run *runs;
|
||||
int32_t runIndex, start;
|
||||
UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0;
|
||||
|
||||
/* now, count a (non-mergeable) WS run */
|
||||
if(limit<length) {
|
||||
++runCount;
|
||||
}
|
||||
|
||||
/* runCount>1 */
|
||||
if(getRunsMemory(pBiDi, runCount)) {
|
||||
runs=pBiDi->runsMemory;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* set the runs */
|
||||
/* FOOD FOR THOUGHT: this could be optimized, e.g.:
|
||||
* 464->444, 484->444, 575->555, 595->555
|
||||
* However, that would take longer. Check also how it would
|
||||
* interact with BiDi control removal and inserting Marks.
|
||||
*/
|
||||
runIndex=0;
|
||||
|
||||
/* search for the run limits and initialize visualLimit values with the run lengths */
|
||||
i=0;
|
||||
do {
|
||||
/* prepare this run */
|
||||
start=i;
|
||||
level=levels[i];
|
||||
if(level<minLevel) {
|
||||
minLevel=level;
|
||||
}
|
||||
if(level>maxLevel) {
|
||||
maxLevel=level;
|
||||
}
|
||||
|
||||
/* look for the run limit */
|
||||
while(++i<limit && levels[i]==level) {}
|
||||
|
||||
/* i is another run limit */
|
||||
runs[runIndex].logicalStart=start;
|
||||
runs[runIndex].visualLimit=i-start;
|
||||
runs[runIndex].insertRemove=0;
|
||||
++runIndex;
|
||||
} while(i<limit);
|
||||
|
||||
if(limit<length) {
|
||||
/* there is a separate WS run */
|
||||
runs[runIndex].logicalStart=limit;
|
||||
runs[runIndex].visualLimit=length-limit;
|
||||
/* For the trailing WS run, pBiDi->paraLevel is ok even
|
||||
if contextual multiple paragraphs. */
|
||||
if(pBiDi->paraLevel<minLevel) {
|
||||
minLevel=pBiDi->paraLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't need to see if the last run can be merged with a trailing
|
||||
* WS run because setTrailingWSStart() would have done that.
|
||||
*/
|
||||
if(runCount==1 && limit==length) {
|
||||
/* There is only one non-WS run and no trailing WS-run. */
|
||||
getSingleRun(pBiDi, levels[0]);
|
||||
} else /* runCount>1 || limit<length */ {
|
||||
/* allocate and set the runs */
|
||||
Run *runs;
|
||||
int32_t runIndex, start;
|
||||
UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0;
|
||||
/* set the object fields */
|
||||
pBiDi->runs=runs;
|
||||
pBiDi->runCount=runCount;
|
||||
|
||||
/* now, count a (non-mergeable) WS run */
|
||||
if(limit<length) {
|
||||
++runCount;
|
||||
}
|
||||
reorderLine(pBiDi, minLevel, maxLevel);
|
||||
|
||||
/* runCount>1 */
|
||||
if(getRunsMemory(pBiDi, runCount)) {
|
||||
runs=pBiDi->runsMemory;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
/* now add the direction flags and adjust the visualLimit's to be just that */
|
||||
/* this loop will also handle the trailing WS run */
|
||||
limit=0;
|
||||
for(i=0; i<runCount; ++i) {
|
||||
ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]);
|
||||
limit=runs[i].visualLimit+=limit;
|
||||
}
|
||||
|
||||
/* set the runs */
|
||||
/* FOOD FOR THOUGHT: this could be optimized, e.g.:
|
||||
* 464->444, 484->444, 575->555, 595->555
|
||||
* However, that would take longer. Check also how it would
|
||||
* interact with BiDi control removal and inserting Marks.
|
||||
*/
|
||||
runIndex=0;
|
||||
/* Set the "odd" bit for the trailing WS run. */
|
||||
/* For a RTL paragraph, it will be the *first* run in visual order. */
|
||||
/* For the trailing WS run, pBiDi->paraLevel is ok even if
|
||||
contextual multiple paragraphs. */
|
||||
if(runIndex<runCount) {
|
||||
int32_t trailingRun = ((pBiDi->paraLevel & 1) != 0)? 0 : runIndex;
|
||||
|
||||
/* search for the run limits and initialize visualLimit values with the run lengths */
|
||||
i=0;
|
||||
do {
|
||||
/* prepare this run */
|
||||
start=i;
|
||||
level=levels[i];
|
||||
if(level<minLevel) {
|
||||
minLevel=level;
|
||||
}
|
||||
if(level>maxLevel) {
|
||||
maxLevel=level;
|
||||
}
|
||||
|
||||
/* look for the run limit */
|
||||
while(++i<limit && levels[i]==level) {}
|
||||
|
||||
/* i is another run limit */
|
||||
runs[runIndex].logicalStart=start;
|
||||
runs[runIndex].visualLimit=i-start;
|
||||
runs[runIndex].insertRemove=0;
|
||||
++runIndex;
|
||||
} while(i<limit);
|
||||
|
||||
if(limit<length) {
|
||||
/* there is a separate WS run */
|
||||
runs[runIndex].logicalStart=limit;
|
||||
runs[runIndex].visualLimit=length-limit;
|
||||
/* For the trailing WS run, pBiDi->paraLevel is ok even
|
||||
if contextual multiple paragraphs. */
|
||||
if(pBiDi->paraLevel<minLevel) {
|
||||
minLevel=pBiDi->paraLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/* set the object fields */
|
||||
pBiDi->runs=runs;
|
||||
pBiDi->runCount=runCount;
|
||||
|
||||
reorderLine(pBiDi, minLevel, maxLevel);
|
||||
|
||||
/* now add the direction flags and adjust the visualLimit's to be just that */
|
||||
/* this loop will also handle the trailing WS run */
|
||||
limit=0;
|
||||
for(i=0; i<runCount; ++i) {
|
||||
ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]);
|
||||
limit=runs[i].visualLimit+=limit;
|
||||
}
|
||||
|
||||
/* Set the "odd" bit for the trailing WS run. */
|
||||
/* For a RTL paragraph, it will be the *first* run in visual order. */
|
||||
/* For the trailing WS run, pBiDi->paraLevel is ok even if
|
||||
contextual multiple paragraphs. */
|
||||
if(runIndex<runCount) {
|
||||
int32_t trailingRun = ((pBiDi->paraLevel & 1) != 0)? 0 : runIndex;
|
||||
|
||||
ADD_ODD_BIT_FROM_LEVEL(runs[trailingRun].logicalStart, pBiDi->paraLevel);
|
||||
}
|
||||
ADD_ODD_BIT_FROM_LEVEL(runs[trailingRun].logicalStart, pBiDi->paraLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -885,51 +876,45 @@ ubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap)
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
ubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) {
|
||||
int32_t visualIndex;
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return 0;
|
||||
} else if(!IS_VALID_PARA_OR_LINE(pBiDi)) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
} else if(logicalIndex<0 || pBiDi->length<=logicalIndex) {
|
||||
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
return 0;
|
||||
} else {
|
||||
/* we can do the trivial cases without the runs array */
|
||||
switch(pBiDi->direction) {
|
||||
case UBIDI_LTR:
|
||||
visualIndex=logicalIndex;
|
||||
break;
|
||||
case UBIDI_RTL:
|
||||
visualIndex=pBiDi->length-logicalIndex-1;
|
||||
break;
|
||||
default:
|
||||
if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi, pErrorCode)) {
|
||||
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
return 0;
|
||||
} else {
|
||||
Run *runs=pBiDi->runs;
|
||||
int32_t i, visualStart=0, offset, length;
|
||||
int32_t visualIndex=UBIDI_MAP_NOWHERE;
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
|
||||
RETURN_IF_BAD_RANGE(logicalIndex, 0, pBiDi->length, *pErrorCode, -1);
|
||||
|
||||
/* linear search for the run, search on the visual runs */
|
||||
for(i=0; i<pBiDi->runCount; ++i) {
|
||||
length=runs[i].visualLimit-visualStart;
|
||||
offset=logicalIndex-GET_INDEX(runs[i].logicalStart);
|
||||
if(offset>=0 && offset<length) {
|
||||
if(IS_EVEN_RUN(runs[i].logicalStart)) {
|
||||
/* LTR */
|
||||
visualIndex=visualStart+offset;
|
||||
} else {
|
||||
/* RTL */
|
||||
visualIndex=visualStart+length-offset-1;
|
||||
}
|
||||
break; /* exit for loop */
|
||||
/* we can do the trivial cases without the runs array */
|
||||
switch(pBiDi->direction) {
|
||||
case UBIDI_LTR:
|
||||
visualIndex=logicalIndex;
|
||||
break;
|
||||
case UBIDI_RTL:
|
||||
visualIndex=pBiDi->length-logicalIndex-1;
|
||||
break;
|
||||
default:
|
||||
if(!ubidi_getRuns(pBiDi, pErrorCode)) {
|
||||
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
return -1;
|
||||
} else {
|
||||
Run *runs=pBiDi->runs;
|
||||
int32_t i, visualStart=0, offset, length;
|
||||
|
||||
/* linear search for the run, search on the visual runs */
|
||||
for(i=0; i<pBiDi->runCount; ++i) {
|
||||
length=runs[i].visualLimit-visualStart;
|
||||
offset=logicalIndex-GET_INDEX(runs[i].logicalStart);
|
||||
if(offset>=0 && offset<length) {
|
||||
if(IS_EVEN_RUN(runs[i].logicalStart)) {
|
||||
/* LTR */
|
||||
visualIndex=visualStart+offset;
|
||||
} else {
|
||||
/* RTL */
|
||||
visualIndex=visualStart+length-offset-1;
|
||||
}
|
||||
visualStart+=length;
|
||||
}
|
||||
if(i>=pBiDi->runCount) {
|
||||
return UBIDI_MAP_NOWHERE;
|
||||
break; /* exit for loop */
|
||||
}
|
||||
visualStart+=length;
|
||||
}
|
||||
if(i>=pBiDi->runCount) {
|
||||
return UBIDI_MAP_NOWHERE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -984,7 +969,7 @@ ubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode)
|
||||
} else {
|
||||
/* RTL: check from logical index to run end */
|
||||
start=logicalIndex+1;
|
||||
limit=runs[i].logicalStart+length;
|
||||
limit=GET_INDEX(runs[i].logicalStart)+length;
|
||||
}
|
||||
for(j=start; j<limit; j++) {
|
||||
uchar=pBiDi->text[j];
|
||||
@ -1003,15 +988,9 @@ U_CAPI int32_t U_EXPORT2
|
||||
ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode) {
|
||||
Run *runs;
|
||||
int32_t i, runCount, start;
|
||||
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
|
||||
return 0;
|
||||
} else if(!IS_VALID_PARA_OR_LINE(pBiDi)) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
} else if(visualIndex<0 || pBiDi->resultLength<=visualIndex) {
|
||||
*pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
|
||||
return 0;
|
||||
}
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
|
||||
RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
|
||||
RETURN_IF_BAD_RANGE(visualIndex, 0, pBiDi->resultLength, *pErrorCode, -1);
|
||||
/* we can do the trivial cases without the runs array */
|
||||
if(pBiDi->insertPoints.size==0 && pBiDi->controlCount==0) {
|
||||
if(pBiDi->direction==UBIDI_LTR) {
|
||||
@ -1021,9 +1000,9 @@ ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode)
|
||||
return pBiDi->length-visualIndex-1;
|
||||
}
|
||||
}
|
||||
if(pBiDi->runCount<0 && !ubidi_getRuns(pBiDi, pErrorCode)) {
|
||||
if(!ubidi_getRuns(pBiDi, pErrorCode)) {
|
||||
*pErrorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
runs=pBiDi->runs;
|
||||
@ -1132,7 +1111,8 @@ ubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode)
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
/* ubidi_countRuns() checks all of its and our arguments */
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
/* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
|
||||
ubidi_countRuns(pBiDi, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
/* no op */
|
||||
@ -1141,10 +1121,13 @@ ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
} else {
|
||||
/* fill a logical-to-visual index map using the runs[] */
|
||||
int32_t visualStart, visualLimit, i, j, k;
|
||||
int32_t logicalStart, logicalEnd;
|
||||
int32_t logicalStart, logicalLimit;
|
||||
Run *runs=pBiDi->runs;
|
||||
if (pBiDi->length<=0) {
|
||||
return;
|
||||
}
|
||||
if (pBiDi->length>pBiDi->resultLength) {
|
||||
uprv_memset(indexMap, 0xFF, pBiDi->resultLength*sizeof(int32_t));
|
||||
uprv_memset(indexMap, 0xFF, pBiDi->length*sizeof(int32_t));
|
||||
}
|
||||
|
||||
visualStart=0;
|
||||
@ -1176,10 +1159,10 @@ ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
markFound++;
|
||||
}
|
||||
if(markFound>0) {
|
||||
int32_t limit;
|
||||
int32_t logicalLimit;
|
||||
logicalStart=GET_INDEX(runs[i].logicalStart);
|
||||
limit=logicalStart+length;
|
||||
for(j=logicalStart; j<limit; j++) {
|
||||
logicalLimit=logicalStart+length;
|
||||
for(j=logicalStart; j<logicalLimit; j++) {
|
||||
indexMap[j]+=markFound;
|
||||
}
|
||||
}
|
||||
@ -1205,16 +1188,16 @@ ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
logicalStart=runs[i].logicalStart;
|
||||
evenRun=IS_EVEN_RUN(logicalStart);
|
||||
REMOVE_ODD_BIT(logicalStart);
|
||||
logicalEnd=logicalStart+length-1;
|
||||
logicalLimit=logicalStart+length;
|
||||
/* if no control within this run */
|
||||
if(insertRemove==0) {
|
||||
for(j=logicalStart; j<=logicalEnd; j++) {
|
||||
for(j=logicalStart; j<logicalLimit; j++) {
|
||||
indexMap[j]-=controlFound;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for(j=0; j<length; j++) {
|
||||
k= evenRun ? logicalStart+j : logicalEnd-j;
|
||||
k= evenRun ? logicalStart+j : logicalLimit-j-1;
|
||||
uchar=pBiDi->text[k];
|
||||
if(IS_BIDI_CONTROL_CHAR(uchar)) {
|
||||
controlFound++;
|
||||
@ -1230,8 +1213,10 @@ ubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
/* ubidi_countRuns() checks all of its and our arguments */
|
||||
if(ubidi_countRuns(pBiDi, pErrorCode)<=0) {
|
||||
RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, );
|
||||
/* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
|
||||
ubidi_countRuns(pBiDi, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
/* no op */
|
||||
} else if(indexMap==NULL) {
|
||||
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
|
||||
@ -1240,6 +1225,9 @@ ubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
|
||||
Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
|
||||
int32_t logicalStart, visualStart, visualLimit, *pi=indexMap;
|
||||
|
||||
if (pBiDi->resultLength<=0) {
|
||||
return;
|
||||
}
|
||||
visualStart=0;
|
||||
for(; runs<runsLimit; ++runs) {
|
||||
logicalStart=runs->logicalStart;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2000-2006, International Business Machines
|
||||
* Copyright (C) 2000-2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
@ -11,7 +11,7 @@
|
||||
* indentation:4
|
||||
*
|
||||
* created on: 1999aug06
|
||||
* created by: Markus W. Scherer
|
||||
* created by: Markus W. Scherer, updated by Matitiahu Allouche
|
||||
*
|
||||
* This file contains implementations for BiDi functions that use
|
||||
* the core algorithm and core API to write reordered text.
|
||||
@ -348,8 +348,6 @@ ubidi_writeReverse(const UChar *src, int32_t srcLength,
|
||||
return u_terminateUChars(dest, destSize, destLength, pErrorCode);
|
||||
}
|
||||
|
||||
#define MASK_R_AL (1UL<<U_RIGHT_TO_LEFT|1UL<<U_RIGHT_TO_LEFT_ARABIC)
|
||||
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
ubidi_writeReordered(UBiDi *pBiDi,
|
||||
UChar *dest, int32_t destSize,
|
||||
@ -464,7 +462,7 @@ ubidi_writeReordered(UBiDi *pBiDi,
|
||||
src=text+logicalStart;
|
||||
/* check if something relevant in insertPoints */
|
||||
markFlag=pBiDi->runs[run].insertRemove;
|
||||
if(markFlag<0) { /* insert count */
|
||||
if(markFlag<0) { /* BiDi controls count */
|
||||
markFlag=0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user