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