U_CAPI void U_EXPORT2 ubidi_setLine(const UBiDi *pParaBiDi, int32_t start, int32_t limit, UBiDi *pLineBiDi, UErrorCode *pErrorCode) { int32_t length; /* check the argument values */ RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode); RETURN_VOID_IF_NOT_VALID_PARA(pParaBiDi, *pErrorCode); RETURN_VOID_IF_BAD_RANGE(start, 0, limit, *pErrorCode); RETURN_VOID_IF_BAD_RANGE(limit, 0, pParaBiDi->length+1, *pErrorCode); if(pLineBiDi==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } 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; } /* set the values in pLineBiDi from its pParaBiDi parent */ pLineBiDi->pParaBiDi=NULL; /* mark unfinished setLine */ pLineBiDi->text=pParaBiDi->text+start; length=pLineBiDi->length=limit-start; pLineBiDi->resultLength=pLineBiDi->originalLength=length; pLineBiDi->paraLevel=GET_PARALEVEL(pParaBiDi, start); pLineBiDi->paraCount=pParaBiDi->paraCount; pLineBiDi->runs=NULL; pLineBiDi->flags=0; pLineBiDi->reorderingMode=pParaBiDi->reorderingMode; pLineBiDi->reorderingOptions=pParaBiDi->reorderingOptions; pLineBiDi->controlCount=0; if(pParaBiDi->controlCount>0) { int32_t j; for(j=start; j<limit; j++) { if(IS_BIDI_CONTROL_CHAR(pParaBiDi->text[j])) { pLineBiDi->controlCount++; } } pLineBiDi->resultLength-=pLineBiDi->controlCount; } 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; /* * 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; } } 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->pParaBiDi=pParaBiDi; /* mark successful setLine */ return; }
U_CAPI void U_EXPORT2 ubidi_setLine(const UBiDi *pParaBiDi, int32_t start, int32_t limit, UBiDi *pLineBiDi, UErrorCode *pErrorCode) { int32_t length; /* check the argument values */ if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return; } else if(pParaBiDi==NULL || pLineBiDi==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return; } else if(start<0 || start>limit || limit>pParaBiDi->length) { *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; return; } /* set the values in pLineBiDi from its pParaBiDi parent */ pLineBiDi->text=pParaBiDi->text+start; length=pLineBiDi->length=limit-start; pLineBiDi->paraLevel=pParaBiDi->paraLevel; pLineBiDi->runs=NULL; pLineBiDi->flags=0; if(length>0) { 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; /* * 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; } } 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; } } } else { /* create an object for a zero-length line */ pLineBiDi->direction=pLineBiDi->paraLevel&1 ? UBIDI_RTL : UBIDI_LTR; pLineBiDi->trailingWSStart=pLineBiDi->runCount=0; pLineBiDi->dirProps=NULL; pLineBiDi->levels=NULL; } return; }