intl/icu/source/common/ubidiwrt.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 ******************************************************************************
michael@0 3 *
michael@0 4 * Copyright (C) 2000-2011, International Business Machines
michael@0 5 * Corporation and others. All Rights Reserved.
michael@0 6 *
michael@0 7 ******************************************************************************
michael@0 8 * file name: ubidiwrt.c
michael@0 9 * encoding: US-ASCII
michael@0 10 * tab size: 8 (not used)
michael@0 11 * indentation:4
michael@0 12 *
michael@0 13 * created on: 1999aug06
michael@0 14 * created by: Markus W. Scherer, updated by Matitiahu Allouche
michael@0 15 *
michael@0 16 * This file contains implementations for BiDi functions that use
michael@0 17 * the core algorithm and core API to write reordered text.
michael@0 18 */
michael@0 19
michael@0 20 /* set import/export definitions */
michael@0 21 #ifndef U_COMMON_IMPLEMENTATION
michael@0 22 # define U_COMMON_IMPLEMENTATION
michael@0 23 #endif
michael@0 24
michael@0 25 #include "unicode/utypes.h"
michael@0 26 #include "unicode/ustring.h"
michael@0 27 #include "unicode/uchar.h"
michael@0 28 #include "unicode/ubidi.h"
michael@0 29 #include "unicode/utf16.h"
michael@0 30 #include "cmemory.h"
michael@0 31 #include "ustr_imp.h"
michael@0 32 #include "ubidiimp.h"
michael@0 33
michael@0 34 /*
michael@0 35 * The function implementations in this file are designed
michael@0 36 * for UTF-16 and UTF-32, not for UTF-8.
michael@0 37 *
michael@0 38 * Assumptions that are not true for UTF-8:
michael@0 39 * - Any code point always needs the same number of code units
michael@0 40 * ("minimum-length-problem" of UTF-8)
michael@0 41 * - The BiDi control characters need only one code unit each
michael@0 42 *
michael@0 43 * Further assumptions for all UTFs:
michael@0 44 * - u_charMirror(c) needs the same number of code units as c
michael@0 45 */
michael@0 46 #if UTF_SIZE==8
michael@0 47 # error reimplement ubidi_writeReordered() for UTF-8, see comment above
michael@0 48 #endif
michael@0 49
michael@0 50 #define IS_COMBINING(type) ((1UL<<(type))&(1UL<<U_NON_SPACING_MARK|1UL<<U_COMBINING_SPACING_MARK|1UL<<U_ENCLOSING_MARK))
michael@0 51
michael@0 52 /*
michael@0 53 * When we have UBIDI_OUTPUT_REVERSE set on ubidi_writeReordered(), then we
michael@0 54 * semantically write RTL runs in reverse and later reverse them again.
michael@0 55 * Instead, we actually write them in forward order to begin with.
michael@0 56 * However, if the RTL run was to be mirrored, we need to mirror here now
michael@0 57 * since the implicit second reversal must not do it.
michael@0 58 * It looks strange to do mirroring in LTR output, but it is only because
michael@0 59 * we are writing RTL output in reverse.
michael@0 60 */
michael@0 61 static int32_t
michael@0 62 doWriteForward(const UChar *src, int32_t srcLength,
michael@0 63 UChar *dest, int32_t destSize,
michael@0 64 uint16_t options,
michael@0 65 UErrorCode *pErrorCode) {
michael@0 66 /* optimize for several combinations of options */
michael@0 67 switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING)) {
michael@0 68 case 0: {
michael@0 69 /* simply copy the LTR run to the destination */
michael@0 70 int32_t length=srcLength;
michael@0 71 if(destSize<length) {
michael@0 72 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 73 return srcLength;
michael@0 74 }
michael@0 75 do {
michael@0 76 *dest++=*src++;
michael@0 77 } while(--length>0);
michael@0 78 return srcLength;
michael@0 79 }
michael@0 80 case UBIDI_DO_MIRRORING: {
michael@0 81 /* do mirroring */
michael@0 82 int32_t i=0, j=0;
michael@0 83 UChar32 c;
michael@0 84
michael@0 85 if(destSize<srcLength) {
michael@0 86 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 87 return srcLength;
michael@0 88 }
michael@0 89 do {
michael@0 90 U16_NEXT(src, i, srcLength, c);
michael@0 91 c=u_charMirror(c);
michael@0 92 U16_APPEND_UNSAFE(dest, j, c);
michael@0 93 } while(i<srcLength);
michael@0 94 return srcLength;
michael@0 95 }
michael@0 96 case UBIDI_REMOVE_BIDI_CONTROLS: {
michael@0 97 /* copy the LTR run and remove any BiDi control characters */
michael@0 98 int32_t remaining=destSize;
michael@0 99 UChar c;
michael@0 100 do {
michael@0 101 c=*src++;
michael@0 102 if(!IS_BIDI_CONTROL_CHAR(c)) {
michael@0 103 if(--remaining<0) {
michael@0 104 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 105
michael@0 106 /* preflight the length */
michael@0 107 while(--srcLength>0) {
michael@0 108 c=*src++;
michael@0 109 if(!IS_BIDI_CONTROL_CHAR(c)) {
michael@0 110 --remaining;
michael@0 111 }
michael@0 112 }
michael@0 113 return destSize-remaining;
michael@0 114 }
michael@0 115 *dest++=c;
michael@0 116 }
michael@0 117 } while(--srcLength>0);
michael@0 118 return destSize-remaining;
michael@0 119 }
michael@0 120 default: {
michael@0 121 /* remove BiDi control characters and do mirroring */
michael@0 122 int32_t remaining=destSize;
michael@0 123 int32_t i, j=0;
michael@0 124 UChar32 c;
michael@0 125 do {
michael@0 126 i=0;
michael@0 127 U16_NEXT(src, i, srcLength, c);
michael@0 128 src+=i;
michael@0 129 srcLength-=i;
michael@0 130 if(!IS_BIDI_CONTROL_CHAR(c)) {
michael@0 131 remaining-=i;
michael@0 132 if(remaining<0) {
michael@0 133 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 134
michael@0 135 /* preflight the length */
michael@0 136 while(srcLength>0) {
michael@0 137 c=*src++;
michael@0 138 if(!IS_BIDI_CONTROL_CHAR(c)) {
michael@0 139 --remaining;
michael@0 140 }
michael@0 141 --srcLength;
michael@0 142 }
michael@0 143 return destSize-remaining;
michael@0 144 }
michael@0 145 c=u_charMirror(c);
michael@0 146 U16_APPEND_UNSAFE(dest, j, c);
michael@0 147 }
michael@0 148 } while(srcLength>0);
michael@0 149 return j;
michael@0 150 }
michael@0 151 } /* end of switch */
michael@0 152 }
michael@0 153
michael@0 154 static int32_t
michael@0 155 doWriteReverse(const UChar *src, int32_t srcLength,
michael@0 156 UChar *dest, int32_t destSize,
michael@0 157 uint16_t options,
michael@0 158 UErrorCode *pErrorCode) {
michael@0 159 /*
michael@0 160 * RTL run -
michael@0 161 *
michael@0 162 * RTL runs need to be copied to the destination in reverse order
michael@0 163 * of code points, not code units, to keep Unicode characters intact.
michael@0 164 *
michael@0 165 * The general strategy for this is to read the source text
michael@0 166 * in backward order, collect all code units for a code point
michael@0 167 * (and optionally following combining characters, see below),
michael@0 168 * and copy all these code units in ascending order
michael@0 169 * to the destination for this run.
michael@0 170 *
michael@0 171 * Several options request whether combining characters
michael@0 172 * should be kept after their base characters,
michael@0 173 * whether BiDi control characters should be removed, and
michael@0 174 * whether characters should be replaced by their mirror-image
michael@0 175 * equivalent Unicode characters.
michael@0 176 */
michael@0 177 int32_t i, j;
michael@0 178 UChar32 c;
michael@0 179
michael@0 180 /* optimize for several combinations of options */
michael@0 181 switch(options&(UBIDI_REMOVE_BIDI_CONTROLS|UBIDI_DO_MIRRORING|UBIDI_KEEP_BASE_COMBINING)) {
michael@0 182 case 0:
michael@0 183 /*
michael@0 184 * With none of the "complicated" options set, the destination
michael@0 185 * run will have the same length as the source run,
michael@0 186 * and there is no mirroring and no keeping combining characters
michael@0 187 * with their base characters.
michael@0 188 */
michael@0 189 if(destSize<srcLength) {
michael@0 190 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 191 return srcLength;
michael@0 192 }
michael@0 193 destSize=srcLength;
michael@0 194
michael@0 195 /* preserve character integrity */
michael@0 196 do {
michael@0 197 /* i is always after the last code unit known to need to be kept in this segment */
michael@0 198 i=srcLength;
michael@0 199
michael@0 200 /* collect code units for one base character */
michael@0 201 U16_BACK_1(src, 0, srcLength);
michael@0 202
michael@0 203 /* copy this base character */
michael@0 204 j=srcLength;
michael@0 205 do {
michael@0 206 *dest++=src[j++];
michael@0 207 } while(j<i);
michael@0 208 } while(srcLength>0);
michael@0 209 break;
michael@0 210 case UBIDI_KEEP_BASE_COMBINING:
michael@0 211 /*
michael@0 212 * Here, too, the destination
michael@0 213 * run will have the same length as the source run,
michael@0 214 * and there is no mirroring.
michael@0 215 * We do need to keep combining characters with their base characters.
michael@0 216 */
michael@0 217 if(destSize<srcLength) {
michael@0 218 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 219 return srcLength;
michael@0 220 }
michael@0 221 destSize=srcLength;
michael@0 222
michael@0 223 /* preserve character integrity */
michael@0 224 do {
michael@0 225 /* i is always after the last code unit known to need to be kept in this segment */
michael@0 226 i=srcLength;
michael@0 227
michael@0 228 /* collect code units and modifier letters for one base character */
michael@0 229 do {
michael@0 230 U16_PREV(src, 0, srcLength, c);
michael@0 231 } while(srcLength>0 && IS_COMBINING(u_charType(c)));
michael@0 232
michael@0 233 /* copy this "user character" */
michael@0 234 j=srcLength;
michael@0 235 do {
michael@0 236 *dest++=src[j++];
michael@0 237 } while(j<i);
michael@0 238 } while(srcLength>0);
michael@0 239 break;
michael@0 240 default:
michael@0 241 /*
michael@0 242 * With several "complicated" options set, this is the most
michael@0 243 * general and the slowest copying of an RTL run.
michael@0 244 * We will do mirroring, remove BiDi controls, and
michael@0 245 * keep combining characters with their base characters
michael@0 246 * as requested.
michael@0 247 */
michael@0 248 if(!(options&UBIDI_REMOVE_BIDI_CONTROLS)) {
michael@0 249 i=srcLength;
michael@0 250 } else {
michael@0 251 /* we need to find out the destination length of the run,
michael@0 252 which will not include the BiDi control characters */
michael@0 253 int32_t length=srcLength;
michael@0 254 UChar ch;
michael@0 255
michael@0 256 i=0;
michael@0 257 do {
michael@0 258 ch=*src++;
michael@0 259 if(!IS_BIDI_CONTROL_CHAR(ch)) {
michael@0 260 ++i;
michael@0 261 }
michael@0 262 } while(--length>0);
michael@0 263 src-=srcLength;
michael@0 264 }
michael@0 265
michael@0 266 if(destSize<i) {
michael@0 267 *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
michael@0 268 return i;
michael@0 269 }
michael@0 270 destSize=i;
michael@0 271
michael@0 272 /* preserve character integrity */
michael@0 273 do {
michael@0 274 /* i is always after the last code unit known to need to be kept in this segment */
michael@0 275 i=srcLength;
michael@0 276
michael@0 277 /* collect code units for one base character */
michael@0 278 U16_PREV(src, 0, srcLength, c);
michael@0 279 if(options&UBIDI_KEEP_BASE_COMBINING) {
michael@0 280 /* collect modifier letters for this base character */
michael@0 281 while(srcLength>0 && IS_COMBINING(u_charType(c))) {
michael@0 282 U16_PREV(src, 0, srcLength, c);
michael@0 283 }
michael@0 284 }
michael@0 285
michael@0 286 if(options&UBIDI_REMOVE_BIDI_CONTROLS && IS_BIDI_CONTROL_CHAR(c)) {
michael@0 287 /* do not copy this BiDi control character */
michael@0 288 continue;
michael@0 289 }
michael@0 290
michael@0 291 /* copy this "user character" */
michael@0 292 j=srcLength;
michael@0 293 if(options&UBIDI_DO_MIRRORING) {
michael@0 294 /* mirror only the base character */
michael@0 295 int32_t k=0;
michael@0 296 c=u_charMirror(c);
michael@0 297 U16_APPEND_UNSAFE(dest, k, c);
michael@0 298 dest+=k;
michael@0 299 j+=k;
michael@0 300 }
michael@0 301 while(j<i) {
michael@0 302 *dest++=src[j++];
michael@0 303 }
michael@0 304 } while(srcLength>0);
michael@0 305 break;
michael@0 306 } /* end of switch */
michael@0 307
michael@0 308 return destSize;
michael@0 309 }
michael@0 310
michael@0 311 U_CAPI int32_t U_EXPORT2
michael@0 312 ubidi_writeReverse(const UChar *src, int32_t srcLength,
michael@0 313 UChar *dest, int32_t destSize,
michael@0 314 uint16_t options,
michael@0 315 UErrorCode *pErrorCode) {
michael@0 316 int32_t destLength;
michael@0 317
michael@0 318 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 319 return 0;
michael@0 320 }
michael@0 321
michael@0 322 /* more error checking */
michael@0 323 if( src==NULL || srcLength<-1 ||
michael@0 324 destSize<0 || (destSize>0 && dest==NULL))
michael@0 325 {
michael@0 326 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 327 return 0;
michael@0 328 }
michael@0 329
michael@0 330 /* do input and output overlap? */
michael@0 331 if( dest!=NULL &&
michael@0 332 ((src>=dest && src<dest+destSize) ||
michael@0 333 (dest>=src && dest<src+srcLength)))
michael@0 334 {
michael@0 335 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 336 return 0;
michael@0 337 }
michael@0 338
michael@0 339 if(srcLength==-1) {
michael@0 340 srcLength=u_strlen(src);
michael@0 341 }
michael@0 342 if(srcLength>0) {
michael@0 343 destLength=doWriteReverse(src, srcLength, dest, destSize, options, pErrorCode);
michael@0 344 } else {
michael@0 345 /* nothing to do */
michael@0 346 destLength=0;
michael@0 347 }
michael@0 348
michael@0 349 return u_terminateUChars(dest, destSize, destLength, pErrorCode);
michael@0 350 }
michael@0 351
michael@0 352 U_CAPI int32_t U_EXPORT2
michael@0 353 ubidi_writeReordered(UBiDi *pBiDi,
michael@0 354 UChar *dest, int32_t destSize,
michael@0 355 uint16_t options,
michael@0 356 UErrorCode *pErrorCode) {
michael@0 357 const UChar *text;
michael@0 358 UChar *saveDest;
michael@0 359 int32_t length, destCapacity;
michael@0 360 int32_t run, runCount, logicalStart, runLength;
michael@0 361
michael@0 362 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
michael@0 363 return 0;
michael@0 364 }
michael@0 365
michael@0 366 /* more error checking */
michael@0 367 if( pBiDi==NULL ||
michael@0 368 (text=pBiDi->text)==NULL || (length=pBiDi->length)<0 ||
michael@0 369 destSize<0 || (destSize>0 && dest==NULL))
michael@0 370 {
michael@0 371 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 372 return 0;
michael@0 373 }
michael@0 374
michael@0 375 /* do input and output overlap? */
michael@0 376 if( dest!=NULL &&
michael@0 377 ((text>=dest && text<dest+destSize) ||
michael@0 378 (dest>=text && dest<text+pBiDi->originalLength)))
michael@0 379 {
michael@0 380 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
michael@0 381 return 0;
michael@0 382 }
michael@0 383
michael@0 384 if(length==0) {
michael@0 385 /* nothing to do */
michael@0 386 return u_terminateUChars(dest, destSize, 0, pErrorCode);
michael@0 387 }
michael@0 388
michael@0 389 runCount=ubidi_countRuns(pBiDi, pErrorCode);
michael@0 390 if(U_FAILURE(*pErrorCode)) {
michael@0 391 return 0;
michael@0 392 }
michael@0 393
michael@0 394 /* destSize shrinks, later destination length=destCapacity-destSize */
michael@0 395 saveDest=dest;
michael@0 396 destCapacity=destSize;
michael@0 397
michael@0 398 /*
michael@0 399 * Option "insert marks" implies UBIDI_INSERT_LRM_FOR_NUMERIC if the
michael@0 400 * reordering mode (checked below) is appropriate.
michael@0 401 */
michael@0 402 if(pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
michael@0 403 options|=UBIDI_INSERT_LRM_FOR_NUMERIC;
michael@0 404 options&=~UBIDI_REMOVE_BIDI_CONTROLS;
michael@0 405 }
michael@0 406 /*
michael@0 407 * Option "remove controls" implies UBIDI_REMOVE_BIDI_CONTROLS
michael@0 408 * and cancels UBIDI_INSERT_LRM_FOR_NUMERIC.
michael@0 409 */
michael@0 410 if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
michael@0 411 options|=UBIDI_REMOVE_BIDI_CONTROLS;
michael@0 412 options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
michael@0 413 }
michael@0 414 /*
michael@0 415 * If we do not perform the "inverse BiDi" algorithm, then we
michael@0 416 * don't need to insert any LRMs, and don't need to test for it.
michael@0 417 */
michael@0 418 if((pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_NUMBERS_AS_L) &&
michael@0 419 (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_LIKE_DIRECT) &&
michael@0 420 (pBiDi->reorderingMode != UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL) &&
michael@0 421 (pBiDi->reorderingMode != UBIDI_REORDER_RUNS_ONLY)) {
michael@0 422 options&=~UBIDI_INSERT_LRM_FOR_NUMERIC;
michael@0 423 }
michael@0 424 /*
michael@0 425 * Iterate through all visual runs and copy the run text segments to
michael@0 426 * the destination, according to the options.
michael@0 427 *
michael@0 428 * The tests for where to insert LRMs ignore the fact that there may be
michael@0 429 * BN codes or non-BMP code points at the beginning and end of a run;
michael@0 430 * they may insert LRMs unnecessarily but the tests are faster this way
michael@0 431 * (this would have to be improved for UTF-8).
michael@0 432 *
michael@0 433 * Note that the only errors that are set by doWriteXY() are buffer overflow
michael@0 434 * errors. Ignore them until the end, and continue for preflighting.
michael@0 435 */
michael@0 436 if(!(options&UBIDI_OUTPUT_REVERSE)) {
michael@0 437 /* forward output */
michael@0 438 if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
michael@0 439 /* do not insert BiDi controls */
michael@0 440 for(run=0; run<runCount; ++run) {
michael@0 441 if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
michael@0 442 runLength=doWriteForward(text+logicalStart, runLength,
michael@0 443 dest, destSize,
michael@0 444 (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
michael@0 445 } else {
michael@0 446 runLength=doWriteReverse(text+logicalStart, runLength,
michael@0 447 dest, destSize,
michael@0 448 options, pErrorCode);
michael@0 449 }
michael@0 450 if(dest!=NULL) {
michael@0 451 dest+=runLength;
michael@0 452 }
michael@0 453 destSize-=runLength;
michael@0 454 }
michael@0 455 } else {
michael@0 456 /* insert BiDi controls for "inverse BiDi" */
michael@0 457 const DirProp *dirProps=pBiDi->dirProps;
michael@0 458 const UChar *src;
michael@0 459 UChar uc;
michael@0 460 UBiDiDirection dir;
michael@0 461 int32_t markFlag;
michael@0 462
michael@0 463 for(run=0; run<runCount; ++run) {
michael@0 464 dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
michael@0 465 src=text+logicalStart;
michael@0 466 /* check if something relevant in insertPoints */
michael@0 467 markFlag=pBiDi->runs[run].insertRemove;
michael@0 468 if(markFlag<0) { /* BiDi controls count */
michael@0 469 markFlag=0;
michael@0 470 }
michael@0 471
michael@0 472 if(UBIDI_LTR==dir) {
michael@0 473 if((pBiDi->isInverse) &&
michael@0 474 (/*run>0 &&*/ dirProps[logicalStart]!=L)) {
michael@0 475 markFlag |= LRM_BEFORE;
michael@0 476 }
michael@0 477 if (markFlag & LRM_BEFORE) {
michael@0 478 uc=LRM_CHAR;
michael@0 479 }
michael@0 480 else if (markFlag & RLM_BEFORE) {
michael@0 481 uc=RLM_CHAR;
michael@0 482 }
michael@0 483 else uc=0;
michael@0 484 if(uc) {
michael@0 485 if(destSize>0) {
michael@0 486 *dest++=uc;
michael@0 487 }
michael@0 488 --destSize;
michael@0 489 }
michael@0 490
michael@0 491 runLength=doWriteForward(src, runLength,
michael@0 492 dest, destSize,
michael@0 493 (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
michael@0 494 if(dest!=NULL) {
michael@0 495 dest+=runLength;
michael@0 496 }
michael@0 497 destSize-=runLength;
michael@0 498
michael@0 499 if((pBiDi->isInverse) &&
michael@0 500 (/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L)) {
michael@0 501 markFlag |= LRM_AFTER;
michael@0 502 }
michael@0 503 if (markFlag & LRM_AFTER) {
michael@0 504 uc=LRM_CHAR;
michael@0 505 }
michael@0 506 else if (markFlag & RLM_AFTER) {
michael@0 507 uc=RLM_CHAR;
michael@0 508 }
michael@0 509 else uc=0;
michael@0 510 if(uc) {
michael@0 511 if(destSize>0) {
michael@0 512 *dest++=uc;
michael@0 513 }
michael@0 514 --destSize;
michael@0 515 }
michael@0 516 } else { /* RTL run */
michael@0 517 if((pBiDi->isInverse) &&
michael@0 518 (/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1])))) {
michael@0 519 markFlag |= RLM_BEFORE;
michael@0 520 }
michael@0 521 if (markFlag & LRM_BEFORE) {
michael@0 522 uc=LRM_CHAR;
michael@0 523 }
michael@0 524 else if (markFlag & RLM_BEFORE) {
michael@0 525 uc=RLM_CHAR;
michael@0 526 }
michael@0 527 else uc=0;
michael@0 528 if(uc) {
michael@0 529 if(destSize>0) {
michael@0 530 *dest++=uc;
michael@0 531 }
michael@0 532 --destSize;
michael@0 533 }
michael@0 534
michael@0 535 runLength=doWriteReverse(src, runLength,
michael@0 536 dest, destSize,
michael@0 537 options, pErrorCode);
michael@0 538 if(dest!=NULL) {
michael@0 539 dest+=runLength;
michael@0 540 }
michael@0 541 destSize-=runLength;
michael@0 542
michael@0 543 if((pBiDi->isInverse) &&
michael@0 544 (/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart])))) {
michael@0 545 markFlag |= RLM_AFTER;
michael@0 546 }
michael@0 547 if (markFlag & LRM_AFTER) {
michael@0 548 uc=LRM_CHAR;
michael@0 549 }
michael@0 550 else if (markFlag & RLM_AFTER) {
michael@0 551 uc=RLM_CHAR;
michael@0 552 }
michael@0 553 else uc=0;
michael@0 554 if(uc) {
michael@0 555 if(destSize>0) {
michael@0 556 *dest++=uc;
michael@0 557 }
michael@0 558 --destSize;
michael@0 559 }
michael@0 560 }
michael@0 561 }
michael@0 562 }
michael@0 563 } else {
michael@0 564 /* reverse output */
michael@0 565 if(!(options&UBIDI_INSERT_LRM_FOR_NUMERIC)) {
michael@0 566 /* do not insert BiDi controls */
michael@0 567 for(run=runCount; --run>=0;) {
michael@0 568 if(UBIDI_LTR==ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength)) {
michael@0 569 runLength=doWriteReverse(text+logicalStart, runLength,
michael@0 570 dest, destSize,
michael@0 571 (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
michael@0 572 } else {
michael@0 573 runLength=doWriteForward(text+logicalStart, runLength,
michael@0 574 dest, destSize,
michael@0 575 options, pErrorCode);
michael@0 576 }
michael@0 577 if(dest!=NULL) {
michael@0 578 dest+=runLength;
michael@0 579 }
michael@0 580 destSize-=runLength;
michael@0 581 }
michael@0 582 } else {
michael@0 583 /* insert BiDi controls for "inverse BiDi" */
michael@0 584 const DirProp *dirProps=pBiDi->dirProps;
michael@0 585 const UChar *src;
michael@0 586 UBiDiDirection dir;
michael@0 587
michael@0 588 for(run=runCount; --run>=0;) {
michael@0 589 /* reverse output */
michael@0 590 dir=ubidi_getVisualRun(pBiDi, run, &logicalStart, &runLength);
michael@0 591 src=text+logicalStart;
michael@0 592
michael@0 593 if(UBIDI_LTR==dir) {
michael@0 594 if(/*run<runCount-1 &&*/ dirProps[logicalStart+runLength-1]!=L) {
michael@0 595 if(destSize>0) {
michael@0 596 *dest++=LRM_CHAR;
michael@0 597 }
michael@0 598 --destSize;
michael@0 599 }
michael@0 600
michael@0 601 runLength=doWriteReverse(src, runLength,
michael@0 602 dest, destSize,
michael@0 603 (uint16_t)(options&~UBIDI_DO_MIRRORING), pErrorCode);
michael@0 604 if(dest!=NULL) {
michael@0 605 dest+=runLength;
michael@0 606 }
michael@0 607 destSize-=runLength;
michael@0 608
michael@0 609 if(/*run>0 &&*/ dirProps[logicalStart]!=L) {
michael@0 610 if(destSize>0) {
michael@0 611 *dest++=LRM_CHAR;
michael@0 612 }
michael@0 613 --destSize;
michael@0 614 }
michael@0 615 } else {
michael@0 616 if(/*run<runCount-1 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart]))) {
michael@0 617 if(destSize>0) {
michael@0 618 *dest++=RLM_CHAR;
michael@0 619 }
michael@0 620 --destSize;
michael@0 621 }
michael@0 622
michael@0 623 runLength=doWriteForward(src, runLength,
michael@0 624 dest, destSize,
michael@0 625 options, pErrorCode);
michael@0 626 if(dest!=NULL) {
michael@0 627 dest+=runLength;
michael@0 628 }
michael@0 629 destSize-=runLength;
michael@0 630
michael@0 631 if(/*run>0 &&*/ !(MASK_R_AL&DIRPROP_FLAG(dirProps[logicalStart+runLength-1]))) {
michael@0 632 if(destSize>0) {
michael@0 633 *dest++=RLM_CHAR;
michael@0 634 }
michael@0 635 --destSize;
michael@0 636 }
michael@0 637 }
michael@0 638 }
michael@0 639 }
michael@0 640 }
michael@0 641
michael@0 642 return u_terminateUChars(saveDest, destCapacity, destCapacity-destSize, pErrorCode);
michael@0 643 }

mercurial