1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/ubidiwrt.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,643 @@ 1.4 +/* 1.5 +****************************************************************************** 1.6 +* 1.7 +* Copyright (C) 2000-2011, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +****************************************************************************** 1.11 +* file name: ubidiwrt.c 1.12 +* encoding: US-ASCII 1.13 +* tab size: 8 (not used) 1.14 +* indentation:4 1.15 +* 1.16 +* created on: 1999aug06 1.17 +* created by: Markus W. Scherer, updated by Matitiahu Allouche 1.18 +* 1.19 +* This file contains implementations for BiDi functions that use 1.20 +* the core algorithm and core API to write reordered text. 1.21 +*/ 1.22 + 1.23 +/* set import/export definitions */ 1.24 +#ifndef U_COMMON_IMPLEMENTATION 1.25 +# define U_COMMON_IMPLEMENTATION 1.26 +#endif 1.27 + 1.28 +#include "unicode/utypes.h" 1.29 +#include "unicode/ustring.h" 1.30 +#include "unicode/uchar.h" 1.31 +#include "unicode/ubidi.h" 1.32 +#include "unicode/utf16.h" 1.33 +#include "cmemory.h" 1.34 +#include "ustr_imp.h" 1.35 +#include "ubidiimp.h" 1.36 + 1.37 +/* 1.38 + * The function implementations in this file are designed 1.39 + * for UTF-16 and UTF-32, not for UTF-8. 1.40 + * 1.41 + * Assumptions that are not true for UTF-8: 1.42 + * - Any code point always needs the same number of code units 1.43 + * ("minimum-length-problem" of UTF-8) 1.44 + * - The BiDi control characters need only one code unit each 1.45 + * 1.46 + * Further assumptions for all UTFs: 1.47 + * - u_charMirror(c) needs the same number of code units as c 1.48 + */ 1.49 +#if UTF_SIZE==8 1.50 +# error reimplement ubidi_writeReordered() for UTF-8, see comment above 1.51 +#endif 1.52 + 1.53 +#define IS_COMBINING(type) ((1UL<<(type))&(1UL<<U_NON_SPACING_MARK|1UL<<U_COMBINING_SPACING_MARK|1UL<<U_ENCLOSING_MARK)) 1.54 + 1.55 +/* 1.56 + * When we have UBIDI_OUTPUT_REVERSE set on ubidi_writeReordered(), then we 1.57 + * semantically write RTL runs in reverse and later reverse them again. 1.58 + * Instead, we actually write them in forward order to begin with. 1.59 + * However, if the RTL run was to be mirrored, we need to mirror here now 1.60 + * since the implicit second reversal must not do it. 1.61 + * It looks strange to do mirroring in LTR output, but it is only because 1.62 + * we are writing RTL output in reverse. 1.63 + */ 1.64 +static int32_t 1.65 +doWriteForward(const UChar *src, int32_t srcLength, 1.66 + UChar *dest, int32_t destSize, 1.67 + uint16_t options, 1.68 + UErrorCode *pErrorCode) { 1.69 + /* optimize for several combinations of options */ 1.70 + switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING)) { 1.71 + case 0: { 1.72 + /* simply copy the LTR run to the destination */ 1.73 + int32_t length=srcLength; 1.74 + if(destSize<length) { 1.75 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.76 + return srcLength; 1.77 + } 1.78 + do { 1.79 + *dest++=*src++; 1.80 + } while(--length>0); 1.81 + return srcLength; 1.82 + } 1.83 + case UBIDI_DO_MIRRORING: { 1.84 + /* do mirroring */ 1.85 + int32_t i=0, j=0; 1.86 + UChar32 c; 1.87 + 1.88 + if(destSize<srcLength) { 1.89 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.90 + return srcLength; 1.91 + } 1.92 + do { 1.93 + U16_NEXT(src, i, srcLength, c); 1.94 + c=u_charMirror(c); 1.95 + U16_APPEND_UNSAFE(dest, j, c); 1.96 + } while(i<srcLength); 1.97 + return srcLength; 1.98 + } 1.99 + case UBIDI_REMOVE_BIDI_CONTROLS: { 1.100 + /* copy the LTR run and remove any BiDi control characters */ 1.101 + int32_t remaining=destSize; 1.102 + UChar c; 1.103 + do { 1.104 + c=*src++; 1.105 + if(!IS_BIDI_CONTROL_CHAR(c)) { 1.106 + if(--remaining<0) { 1.107 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.108 + 1.109 + /* preflight the length */ 1.110 + while(--srcLength>0) { 1.111 + c=*src++; 1.112 + if(!IS_BIDI_CONTROL_CHAR(c)) { 1.113 + --remaining; 1.114 + } 1.115 + } 1.116 + return destSize-remaining; 1.117 + } 1.118 + *dest++=c; 1.119 + } 1.120 + } while(--srcLength>0); 1.121 + return destSize-remaining; 1.122 + } 1.123 + default: { 1.124 + /* remove BiDi control characters and do mirroring */ 1.125 + int32_t remaining=destSize; 1.126 + int32_t i, j=0; 1.127 + UChar32 c; 1.128 + do { 1.129 + i=0; 1.130 + U16_NEXT(src, i, srcLength, c); 1.131 + src+=i; 1.132 + srcLength-=i; 1.133 + if(!IS_BIDI_CONTROL_CHAR(c)) { 1.134 + remaining-=i; 1.135 + if(remaining<0) { 1.136 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.137 + 1.138 + /* preflight the length */ 1.139 + while(srcLength>0) { 1.140 + c=*src++; 1.141 + if(!IS_BIDI_CONTROL_CHAR(c)) { 1.142 + --remaining; 1.143 + } 1.144 + --srcLength; 1.145 + } 1.146 + return destSize-remaining; 1.147 + } 1.148 + c=u_charMirror(c); 1.149 + U16_APPEND_UNSAFE(dest, j, c); 1.150 + } 1.151 + } while(srcLength>0); 1.152 + return j; 1.153 + } 1.154 + } /* end of switch */ 1.155 +} 1.156 + 1.157 +static int32_t 1.158 +doWriteReverse(const UChar *src, int32_t srcLength, 1.159 + UChar *dest, int32_t destSize, 1.160 + uint16_t options, 1.161 + UErrorCode *pErrorCode) { 1.162 + /* 1.163 + * RTL run - 1.164 + * 1.165 + * RTL runs need to be copied to the destination in reverse order 1.166 + * of code points, not code units, to keep Unicode characters intact. 1.167 + * 1.168 + * The general strategy for this is to read the source text 1.169 + * in backward order, collect all code units for a code point 1.170 + * (and optionally following combining characters, see below), 1.171 + * and copy all these code units in ascending order 1.172 + * to the destination for this run. 1.173 + * 1.174 + * Several options request whether combining characters 1.175 + * should be kept after their base characters, 1.176 + * whether BiDi control characters should be removed, and 1.177 + * whether characters should be replaced by their mirror-image 1.178 + * equivalent Unicode characters. 1.179 + */ 1.180 + int32_t i, j; 1.181 + UChar32 c; 1.182 + 1.183 + /* optimize for several combinations of options */ 1.184 + switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING)) { 1.185 + case 0: 1.186 + /* 1.187 + * With none of the "complicated" options set, the destination 1.188 + * run will have the same length as the source run, 1.189 + * and there is no mirroring and no keeping combining characters 1.190 + * with their base characters. 1.191 + */ 1.192 + if(destSize<srcLength) { 1.193 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.194 + return srcLength; 1.195 + } 1.196 + destSize=srcLength; 1.197 + 1.198 + /* preserve character integrity */ 1.199 + do { 1.200 + /* i is always after the last code unit known to need to be kept in this segment */ 1.201 + i=srcLength; 1.202 + 1.203 + /* collect code units for one base character */ 1.204 + U16_BACK_1(src, 0, srcLength); 1.205 + 1.206 + /* copy this base character */ 1.207 + j=srcLength; 1.208 + do { 1.209 + *dest++=src[j++]; 1.210 + } while(j<i); 1.211 + } while(srcLength>0); 1.212 + break; 1.213 + case UBIDI_KEEP_BASE_COMBINING: 1.214 + /* 1.215 + * Here, too, the destination 1.216 + * run will have the same length as the source run, 1.217 + * and there is no mirroring. 1.218 + * We do need to keep combining characters with their base characters. 1.219 + */ 1.220 + if(destSize<srcLength) { 1.221 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.222 + return srcLength; 1.223 + } 1.224 + destSize=srcLength; 1.225 + 1.226 + /* preserve character integrity */ 1.227 + do { 1.228 + /* i is always after the last code unit known to need to be kept in this segment */ 1.229 + i=srcLength; 1.230 + 1.231 + /* collect code units and modifier letters for one base character */ 1.232 + do { 1.233 + U16_PREV(src, 0, srcLength, c); 1.234 + } while(srcLength>0 && IS_COMBINING(u_charType(c))); 1.235 + 1.236 + /* copy this "user character" */ 1.237 + j=srcLength; 1.238 + do { 1.239 + *dest++=src[j++]; 1.240 + } while(j<i); 1.241 + } while(srcLength>0); 1.242 + break; 1.243 + default: 1.244 + /* 1.245 + * With several "complicated" options set, this is the most 1.246 + * general and the slowest copying of an RTL run. 1.247 + * We will do mirroring, remove BiDi controls, and 1.248 + * keep combining characters with their base characters 1.249 + * as requested. 1.250 + */ 1.251 + if(!(options&UBIDI_REMOVE_BIDI_CONTROLS)) { 1.252 + i=srcLength; 1.253 + } else { 1.254 + /* we need to find out the destination length of the run, 1.255 + which will not include the BiDi control characters */ 1.256 + int32_t length=srcLength; 1.257 + UChar ch; 1.258 + 1.259 + i=0; 1.260 + do { 1.261 + ch=*src++; 1.262 + if(!IS_BIDI_CONTROL_CHAR(ch)) { 1.263 + ++i; 1.264 + } 1.265 + } while(--length>0); 1.266 + src-=srcLength; 1.267 + } 1.268 + 1.269 + if(destSize<i) { 1.270 + *pErrorCode=U_BUFFER_OVERFLOW_ERROR; 1.271 + return i; 1.272 + } 1.273 + destSize=i; 1.274 + 1.275 + /* preserve character integrity */ 1.276 + do { 1.277 + /* i is always after the last code unit known to need to be kept in this segment */ 1.278 + i=srcLength; 1.279 + 1.280 + /* collect code units for one base character */ 1.281 + U16_PREV(src, 0, srcLength, c); 1.282 + if(options&UBIDI_KEEP_BASE_COMBINING) { 1.283 + /* collect modifier letters for this base character */ 1.284 + while(srcLength>0 && IS_COMBINING(u_charType(c))) { 1.285 + U16_PREV(src, 0, srcLength, c); 1.286 + } 1.287 + } 1.288 + 1.289 + if(options&UBIDI_REMOVE_BIDI_CONTROLS && IS_BIDI_CONTROL_CHAR(c)) { 1.290 + /* do not copy this BiDi control character */ 1.291 + continue; 1.292 + } 1.293 + 1.294 + /* copy this "user character" */ 1.295 + j=srcLength; 1.296 + if(options&UBIDI_DO_MIRRORING) { 1.297 + /* mirror only the base character */ 1.298 + int32_t k=0; 1.299 + c=u_charMirror(c); 1.300 + U16_APPEND_UNSAFE(dest, k, c); 1.301 + dest+=k; 1.302 + j+=k; 1.303 + } 1.304 + while(j<i) { 1.305 + *dest++=src[j++]; 1.306 + } 1.307 + } while(srcLength>0); 1.308 + break; 1.309 + } /* end of switch */ 1.310 + 1.311 + return destSize; 1.312 +} 1.313 + 1.314 +U_CAPI int32_t U_EXPORT2 1.315 +ubidi_writeReverse(const UChar *src, int32_t srcLength, 1.316 + UChar *dest, int32_t destSize, 1.317 + uint16_t options, 1.318 + UErrorCode *pErrorCode) { 1.319 + int32_t destLength; 1.320 + 1.321 + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 1.322 + return 0; 1.323 + } 1.324 + 1.325 + /* more error checking */ 1.326 + if( src==NULL || srcLength<-1 || 1.327 + destSize<0 || (destSize>0 && dest==NULL)) 1.328 + { 1.329 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.330 + return 0; 1.331 + } 1.332 + 1.333 + /* do input and output overlap? */ 1.334 + if( dest!=NULL && 1.335 + ((src>=dest && src<dest+destSize) || 1.336 + (dest>=src && dest<src+srcLength))) 1.337 + { 1.338 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.339 + return 0; 1.340 + } 1.341 + 1.342 + if(srcLength==-1) { 1.343 + srcLength=u_strlen(src); 1.344 + } 1.345 + if(srcLength>0) { 1.346 + destLength=doWriteReverse(src, srcLength, dest, destSize, options, pErrorCode); 1.347 + } else { 1.348 + /* nothing to do */ 1.349 + destLength=0; 1.350 + } 1.351 + 1.352 + return u_terminateUChars(dest, destSize, destLength, pErrorCode); 1.353 +} 1.354 + 1.355 +U_CAPI int32_t U_EXPORT2 1.356 +ubidi_writeReordered(UBiDi *pBiDi, 1.357 + UChar *dest, int32_t destSize, 1.358 + uint16_t options, 1.359 + UErrorCode *pErrorCode) { 1.360 + const UChar *text; 1.361 + UChar *saveDest; 1.362 + int32_t length, destCapacity; 1.363 + int32_t run, runCount, logicalStart, runLength; 1.364 + 1.365 + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { 1.366 + return 0; 1.367 + } 1.368 + 1.369 + /* more error checking */ 1.370 + if( pBiDi==NULL || 1.371 + (text=pBiDi->text)==NULL || (length=pBiDi->length)<0 || 1.372 + destSize<0 || (destSize>0 && dest==NULL)) 1.373 + { 1.374 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.375 + return 0; 1.376 + } 1.377 + 1.378 + /* do input and output overlap? */ 1.379 + if( dest!=NULL && 1.380 + ((text>=dest && text<dest+destSize) || 1.381 + (dest>=text && dest<text+pBiDi->originalLength))) 1.382 + { 1.383 + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 1.384 + return 0; 1.385 + } 1.386 + 1.387 + if(length==0) { 1.388 + /* nothing to do */ 1.389 + return u_terminateUChars(dest, destSize, 0, pErrorCode); 1.390 + } 1.391 + 1.392 + runCount=ubidi_countRuns(pBiDi, pErrorCode); 1.393 + if(U_FAILURE(*pErrorCode)) { 1.394 + return 0; 1.395 + } 1.396 + 1.397 + /* destSize shrinks, later destination length=destCapacity-destSize */ 1.398 + saveDest=dest; 1.399 + destCapacity=destSize; 1.400 + 1.401 + /* 1.402 + * Option "insert marks" implies UBIDI_INSERT_LRM_FOR_NUMERIC if the 1.403 + * reordering mode (checked below) is appropriate. 1.404 + */ 1.405 + if(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) { 1.406 + options|=UBIDI_INSERT_LRM_FOR_NUMERIC; 1.407 + options&=~UBIDI_REMOVE_BIDI_CONTROLS; 1.408 + } 1.409 + /* 1.410 + * Option "remove controls" implies UBIDI_REMOVE_BIDI_CONTROLS 1.411 + * and cancels UBIDI_INSERT_LRM_FOR_NUMERIC. 1.412 + */ 1.413 + if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) { 1.414 + options|=UBIDI_REMOVE_BIDI_CONTROLS; 1.415 + options&=~UBIDI_INSERT_LRM_FOR_NUMERIC; 1.416 + } 1.417 + /* 1.418 + * If we do not perform the "inverse BiDi" algorithm, then we 1.419 + * don't need to insert any LRMs, and don't need to test for it. 1.420 + */ 1.421 + if((pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_NUMBERS_AS_L) && 1.422 + (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_LIKE_DIRECT) && 1.423 + (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) && 1.424 + (pBiDi->reorderingMode != UBIDI_REORDER_RUNS_ONLY)) { 1.425 + options&=~UBIDI_INSERT_LRM_FOR_NUMERIC; 1.426 + } 1.427 + /* 1.428 + * Iterate through all visual runs and copy the run text segments to 1.429 + * the destination, according to the options. 1.430 + * 1.431 + * The tests for where to insert LRMs ignore the fact that there may be 1.432 + * BN codes or non-BMP code points at the beginning and end of a run; 1.433 + * they may insert LRMs unnecessarily but the tests are faster this way 1.434 + * (this would have to be improved for UTF-8). 1.435 + * 1.436 + * Note that the only errors that are set by doWriteXY() are buffer overflow 1.437 + * errors. Ignore them until the end, and continue for preflighting. 1.438 + */ 1.439 + if(!(options&UBIDI_OUTPUT_REVERSE)) { 1.440 + /* forward output */ 1.441 + if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) { 1.442 + /* do not insert BiDi controls */ 1.443 + for(run=0; run<runCount; ++run) { 1.444 + if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) { 1.445 + runLength=doWriteForward(text+logicalStart, runLength, 1.446 + dest, destSize, 1.447 + (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode); 1.448 + } else { 1.449 + runLength=doWriteReverse(text+logicalStart, runLength, 1.450 + dest, destSize, 1.451 + options, pErrorCode); 1.452 + } 1.453 + if(dest!=NULL) { 1.454 + dest+=runLength; 1.455 + } 1.456 + destSize-=runLength; 1.457 + } 1.458 + } else { 1.459 + /* insert BiDi controls for "inverse BiDi" */ 1.460 + const DirProp *dirProps=pBiDi->dirProps; 1.461 + const UChar *src; 1.462 + UChar uc; 1.463 + UBiDiDirection dir; 1.464 + int32_t markFlag; 1.465 + 1.466 + for(run=0; run<runCount; ++run) { 1.467 + dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength); 1.468 + src=text+logicalStart; 1.469 + /* check if something relevant in insertPoints */ 1.470 + markFlag=pBiDi->runs[run].insertRemove; 1.471 + if(markFlag<0) { /* BiDi controls count */ 1.472 + markFlag=0; 1.473 + } 1.474 + 1.475 + if(UBIDI_LTR==dir) { 1.476 + if((pBiDi->isInverse) && 1.477 + (/*run>0 &&*/ dirProps[logicalStart]!=L)) { 1.478 + markFlag |= LRM_BEFORE; 1.479 + } 1.480 + if (markFlag & LRM_BEFORE) { 1.481 + uc=LRM_CHAR; 1.482 + } 1.483 + else if (markFlag & RLM_BEFORE) { 1.484 + uc=RLM_CHAR; 1.485 + } 1.486 + else uc=0; 1.487 + if(uc) { 1.488 + if(destSize>0) { 1.489 + *dest++=uc; 1.490 + } 1.491 + --destSize; 1.492 + } 1.493 + 1.494 + runLength=doWriteForward(src, runLength, 1.495 + dest, destSize, 1.496 + (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode); 1.497 + if(dest!=NULL) { 1.498 + dest+=runLength; 1.499 + } 1.500 + destSize-=runLength; 1.501 + 1.502 + if((pBiDi->isInverse) && 1.503 + (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) { 1.504 + markFlag |= LRM_AFTER; 1.505 + } 1.506 + if (markFlag & LRM_AFTER) { 1.507 + uc=LRM_CHAR; 1.508 + } 1.509 + else if (markFlag & RLM_AFTER) { 1.510 + uc=RLM_CHAR; 1.511 + } 1.512 + else uc=0; 1.513 + if(uc) { 1.514 + if(destSize>0) { 1.515 + *dest++=uc; 1.516 + } 1.517 + --destSize; 1.518 + } 1.519 + } else { /* RTL run */ 1.520 + if((pBiDi->isInverse) && 1.521 + (/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1])))) { 1.522 + markFlag |= RLM_BEFORE; 1.523 + } 1.524 + if (markFlag & LRM_BEFORE) { 1.525 + uc=LRM_CHAR; 1.526 + } 1.527 + else if (markFlag & RLM_BEFORE) { 1.528 + uc=RLM_CHAR; 1.529 + } 1.530 + else uc=0; 1.531 + if(uc) { 1.532 + if(destSize>0) { 1.533 + *dest++=uc; 1.534 + } 1.535 + --destSize; 1.536 + } 1.537 + 1.538 + runLength=doWriteReverse(src, runLength, 1.539 + dest, destSize, 1.540 + options, pErrorCode); 1.541 + if(dest!=NULL) { 1.542 + dest+=runLength; 1.543 + } 1.544 + destSize-=runLength; 1.545 + 1.546 + if((pBiDi->isInverse) && 1.547 + (/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart])))) { 1.548 + markFlag |= RLM_AFTER; 1.549 + } 1.550 + if (markFlag & LRM_AFTER) { 1.551 + uc=LRM_CHAR; 1.552 + } 1.553 + else if (markFlag & RLM_AFTER) { 1.554 + uc=RLM_CHAR; 1.555 + } 1.556 + else uc=0; 1.557 + if(uc) { 1.558 + if(destSize>0) { 1.559 + *dest++=uc; 1.560 + } 1.561 + --destSize; 1.562 + } 1.563 + } 1.564 + } 1.565 + } 1.566 + } else { 1.567 + /* reverse output */ 1.568 + if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) { 1.569 + /* do not insert BiDi controls */ 1.570 + for(run=runCount; --run>=0;) { 1.571 + if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) { 1.572 + runLength=doWriteReverse(text+logicalStart, runLength, 1.573 + dest, destSize, 1.574 + (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode); 1.575 + } else { 1.576 + runLength=doWriteForward(text+logicalStart, runLength, 1.577 + dest, destSize, 1.578 + options, pErrorCode); 1.579 + } 1.580 + if(dest!=NULL) { 1.581 + dest+=runLength; 1.582 + } 1.583 + destSize-=runLength; 1.584 + } 1.585 + } else { 1.586 + /* insert BiDi controls for "inverse BiDi" */ 1.587 + const DirProp *dirProps=pBiDi->dirProps; 1.588 + const UChar *src; 1.589 + UBiDiDirection dir; 1.590 + 1.591 + for(run=runCount; --run>=0;) { 1.592 + /* reverse output */ 1.593 + dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength); 1.594 + src=text+logicalStart; 1.595 + 1.596 + if(UBIDI_LTR==dir) { 1.597 + if(/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L) { 1.598 + if(destSize>0) { 1.599 + *dest++=LRM_CHAR; 1.600 + } 1.601 + --destSize; 1.602 + } 1.603 + 1.604 + runLength=doWriteReverse(src, runLength, 1.605 + dest, destSize, 1.606 + (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode); 1.607 + if(dest!=NULL) { 1.608 + dest+=runLength; 1.609 + } 1.610 + destSize-=runLength; 1.611 + 1.612 + if(/*run>0 &&*/ dirProps[logicalStart]!=L) { 1.613 + if(destSize>0) { 1.614 + *dest++=LRM_CHAR; 1.615 + } 1.616 + --destSize; 1.617 + } 1.618 + } else { 1.619 + if(/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart]))) { 1.620 + if(destSize>0) { 1.621 + *dest++=RLM_CHAR; 1.622 + } 1.623 + --destSize; 1.624 + } 1.625 + 1.626 + runLength=doWriteForward(src, runLength, 1.627 + dest, destSize, 1.628 + options, pErrorCode); 1.629 + if(dest!=NULL) { 1.630 + dest+=runLength; 1.631 + } 1.632 + destSize-=runLength; 1.633 + 1.634 + if(/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) { 1.635 + if(destSize>0) { 1.636 + *dest++=RLM_CHAR; 1.637 + } 1.638 + --destSize; 1.639 + } 1.640 + } 1.641 + } 1.642 + } 1.643 + } 1.644 + 1.645 + return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode); 1.646 +}