1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
427f654740f2a26ad62a5c155af9199af9e69b889claireho*   Copyright (C) 1999-2010, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   file name:  ubidiln.c
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   encoding:   US-ASCII
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   tab size:   8 (not used)
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   indentation:4
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created on: 1999aug06
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created by: Markus W. Scherer, updated by Matitiahu Allouche
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchar.h"
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ubidi.h"
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ubidiimp.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * General remarks about the functions in this file:
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * These functions deal with the aspects of potentially mixed-directional
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * text in a single paragraph or in a line of a single paragraph
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * which has already been processed according to
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the Unicode 3.0 BiDi algorithm as defined in
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * http://www.unicode.org/unicode/reports/tr9/ , version 13,
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * also described in The Unicode Standard, Version 4.0.1 .
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This means that there is a UBiDi object with a levels
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and a dirProps array.
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * paraLevel and direction are also set.
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Only if the length of the text is zero, then levels==dirProps==NULL.
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The overall directionality of the paragraph
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * or line is used to bypass the reordering steps if possible.
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Even purely RTL text does not need reordering there because
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the ubidi_getLogical/VisualIndex() functions can compute the
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * index on the fly in such a case.
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The implementation of the access to same-level-runs and of the reordering
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * do attempt to provide better performance and less memory usage compared to
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * a direct implementation of especially rule (L2) with an array of
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * one (32-bit) integer per text character.
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Here, the levels array is scanned as soon as necessary, and a vector of
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * same-level-runs is created. Reordering then is done on this vector.
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * For each run of text positions that were resolved to the same level,
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * only 8 bytes are stored: the first text position of the run and the visual
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * position behind the run after reordering.
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * One sign bit is used to hold the directionality of the run.
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is inefficient if there are many very short runs. If the average run
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * length is <2, then this uses more memory.
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * In a further attempt to save memory, the levels array is never changed
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * after all the resolution rules (Xn, Wn, Nn, In).
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Many functions have to consider the field trailingWSStart:
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * if it is less than length, then there is an implicit trailing run
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * at the paraLevel,
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * which is not reflected in the levels array.
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This allows a line UBiDi object to use the same levels array as
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * its paragraph parent object.
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * When a UBiDi object is created for a line of a paragraph, then the
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * paragraph's levels and dirProps arrays are reused by way of setting
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * a pointer into them, not by copying. This again saves memory and forbids to
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * change the now shared levels for (L1).
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* handle trailing WS (L1) -------------------------------------------------- */
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * setTrailingWSStart() sets the start index for a trailing
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * run of WS in the line. This is necessary because we do not modify
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the paragraph's levels array that we just point into.
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Using trailingWSStart is another form of performing (L1).
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * To make subsequent operations easier, we also include the run
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * before the WS if it is at the paraLevel - we merge the two here.
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This function is called only from ubidi_setLine(), so pBiDi->paraLevel is
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * set correctly for the line even when contextual multiple paragraphs.
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerusetTrailingWSStart(UBiDi *pBiDi) {
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* pBiDi->direction!=UBIDI_MIXED */
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const DirProp *dirProps=pBiDi->dirProps;
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiLevel *levels=pBiDi->levels;
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start=pBiDi->length;
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiLevel paraLevel=pBiDi->paraLevel;
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* If the line is terminated by a block separator, all preceding WS etc...
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       are already set to paragraph level.
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       Setting trailingWSStart to pBidi->length will avoid changing the
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       level of B chars from 0 to paraLevel in ubidi_getLevels when
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       orderParagraphsLTR==TRUE.
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(NO_CONTEXT_RTL(dirProps[start-1])==B) {
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pBiDi->trailingWSStart=start;   /* currently == pBiDi->length */
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* go backwards across all WS, BN, explicit codes */
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(start>0 && DIRPROP_FLAG_NC(dirProps[start-1])&MASK_WS) {
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --start;
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if the WS run can be merged with the previous run then do so here */
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(start>0 && levels[start-1]==paraLevel) {
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --start;
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->trailingWSStart=start;
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* ubidi_setLine ------------------------------------------------------------ */
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_setLine(const UBiDi *pParaBiDi,
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              int32_t start, int32_t limit,
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UBiDi *pLineBiDi,
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru              UErrorCode *pErrorCode) {
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length;
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check the argument values */
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_NOT_VALID_PARA(pParaBiDi, *pErrorCode);
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_BAD_RANGE(start, 0, limit, *pErrorCode);
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_BAD_RANGE(limit, 0, pParaBiDi->length+1, *pErrorCode);
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pLineBiDi==NULL) {
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(ubidi_getParagraph(pParaBiDi, start, NULL, NULL, NULL, pErrorCode) !=
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       ubidi_getParagraph(pParaBiDi, limit-1, NULL, NULL, NULL, pErrorCode)) {
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the line crosses a paragraph boundary */
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* set the values in pLineBiDi from its pParaBiDi parent */
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->pParaBiDi=NULL;          /* mark unfinished setLine */
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->text=pParaBiDi->text+start;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    length=pLineBiDi->length=limit-start;
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->resultLength=pLineBiDi->originalLength=length;
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->paraLevel=GET_PARALEVEL(pParaBiDi, start);
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->paraCount=pParaBiDi->paraCount;
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->runs=NULL;
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->flags=0;
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->reorderingMode=pParaBiDi->reorderingMode;
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->reorderingOptions=pParaBiDi->reorderingOptions;
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->controlCount=0;
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pParaBiDi->controlCount>0) {
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t j;
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(j=start; j<limit; j++) {
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(IS_BIDI_CONTROL_CHAR(pParaBiDi->text[j])) {
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pLineBiDi->controlCount++;
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pLineBiDi->resultLength-=pLineBiDi->controlCount;
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->dirProps=pParaBiDi->dirProps+start;
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->levels=pParaBiDi->levels+start;
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->runCount=-1;
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pParaBiDi->direction!=UBIDI_MIXED) {
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the parent is already trivial */
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pLineBiDi->direction=pParaBiDi->direction;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * The parent's levels are all either
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * implicitly or explicitly ==paraLevel;
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * do the same here.
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pParaBiDi->trailingWSStart<=start) {
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->trailingWSStart=0;
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if(pParaBiDi->trailingWSStart<limit) {
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->trailingWSStart=pParaBiDi->trailingWSStart-start;
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->trailingWSStart=length;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UBiDiLevel *levels=pLineBiDi->levels;
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i, trailingWSStart;
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel level;
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        setTrailingWSStart(pLineBiDi);
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        trailingWSStart=pLineBiDi->trailingWSStart;
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* recalculate pLineBiDi->direction */
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(trailingWSStart==0) {
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* all levels are at paraLevel */
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->direction=(UBiDiDirection)(pLineBiDi->paraLevel&1);
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* get the level of the first character */
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            level=(UBiDiLevel)(levels[0]&1);
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* if there is anything of a different level, then the line is mixed */
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(trailingWSStart<length && (pLineBiDi->paraLevel&1)!=level) {
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* the trailing WS is at paraLevel, which differs from levels[0] */
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pLineBiDi->direction=UBIDI_MIXED;
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* see if levels[1..trailingWSStart-1] have the same direction as levels[0] and paraLevel */
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                i=1;
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(;;) {
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(i==trailingWSStart) {
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        /* the direction values match those in level */
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pLineBiDi->direction=(UBiDiDirection)level;
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else if((levels[i]&1)!=level) {
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        pLineBiDi->direction=UBIDI_MIXED;
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        break;
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ++i;
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        switch(pLineBiDi->direction) {
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case UBIDI_LTR:
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* make sure paraLevel is even */
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->paraLevel=(UBiDiLevel)((pLineBiDi->paraLevel+1)&~1);
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->trailingWSStart=0;
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case UBIDI_RTL:
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* make sure paraLevel is odd */
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->paraLevel|=1;
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pLineBiDi->trailingWSStart=0;
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default:
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pLineBiDi->pParaBiDi=pParaBiDi;     /* mark successful setLine */
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return;
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBiDiLevel U_EXPORT2
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getLevelAt(const UBiDi *pBiDi, int32_t charIndex) {
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* return paraLevel if in the trailing WS run, otherwise the real level */
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!IS_VALID_PARA_OR_LINE(pBiDi) || charIndex<0 || pBiDi->length<=charIndex) {
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(pBiDi->direction!=UBIDI_MIXED || charIndex>=pBiDi->trailingWSStart) {
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return GET_PARALEVEL(pBiDi, charIndex);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return pBiDi->levels[charIndex];
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI const UBiDiLevel * U_EXPORT2
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start, length;
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, NULL);
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, NULL);
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((length=pBiDi->length)<=0) {
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((start=pBiDi->trailingWSStart)==length) {
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the current levels array reflects the WS run */
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return pBiDi->levels;
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * After the previous if(), we know that the levels array
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * has an implicit trailing WS run and therefore does not fully
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * reflect itself all the levels.
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * This must be a UBiDi object for a line, and
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * we need to create a new levels array.
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(getLevelsMemory(pBiDi, length)) {
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel *levels=pBiDi->levelsMemory;
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(start>0 && levels!=pBiDi->levels) {
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memcpy(levels, pBiDi->levels, start);
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* pBiDi->paraLevel is ok even if contextual multiple paragraphs,
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           since pBidi is a line object                                     */
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        uprv_memset(levels+start, pBiDi->paraLevel, length-start);
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* this new levels array is set for the line and reflects the WS run */
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pBiDi->trailingWSStart=length;
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return pBiDi->levels=levels;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* out of memory */
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getLogicalRun(const UBiDi *pBiDi, int32_t logicalPosition,
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    int32_t *pLogicalLimit, UBiDiLevel *pLevel) {
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode;
306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t runCount, visualStart, logicalLimit, logicalFirst, i;
307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Run iRun;
308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    errorCode=U_ZERO_ERROR;
310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_BAD_RANGE(logicalPosition, 0, pBiDi->length, errorCode);
311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* ubidi_countRuns will check VALID_PARA_OR_LINE */
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runCount=ubidi_countRuns((UBiDi *)pBiDi, &errorCode);
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* this is done based on runs rather than on levels since levels have
317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       a special interpretation when UBIDI_REORDER_RUNS_ONLY
318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    visualStart=logicalLimit=0;
320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    iRun=pBiDi->runs[0];
321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<runCount; i++) {
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        iRun = pBiDi->runs[i];
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logicalFirst=GET_INDEX(iRun.logicalStart);
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logicalLimit=logicalFirst+iRun.visualLimit-visualStart;
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((logicalPosition>=logicalFirst) &&
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru           (logicalPosition<logicalLimit)) {
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualStart = iRun.visualLimit;
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pLogicalLimit) {
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pLogicalLimit=logicalLimit;
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pLevel) {
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pBiDi->reorderingMode==UBIDI_REORDER_RUNS_ONLY) {
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pLevel=(UBiDiLevel)GET_ODD_BIT(iRun.logicalStart);
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(pBiDi->direction!=UBIDI_MIXED || logicalPosition>=pBiDi->trailingWSStart) {
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pLevel=GET_PARALEVEL(pBiDi, logicalPosition);
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pLevel=pBiDi->levels[logicalPosition];
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* runs API functions ------------------------------------------------------- */
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_getRuns(pBiDi, pErrorCode);
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return pBiDi->runCount;
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI UBiDiDirection U_EXPORT2
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   int32_t *pLogicalStart, int32_t *pLength)
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, errorCode, UBIDI_LTR);
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_getRuns(pBiDi, &errorCode);
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(errorCode)) {
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return UBIDI_LTR;
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_BAD_RANGE(runIndex, 0, pBiDi->runCount, errorCode, UBIDI_LTR);
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    start=pBiDi->runs[runIndex].logicalStart;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pLogicalStart!=NULL) {
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pLogicalStart=GET_INDEX(start);
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pLength!=NULL) {
378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(runIndex>0) {
379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pLength=pBiDi->runs[runIndex].visualLimit-
380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                     pBiDi->runs[runIndex-1].visualLimit;
381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pLength=pBiDi->runs[0].visualLimit;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBiDiDirection)GET_ODD_BIT(start);
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* in trivial cases there is only one trivial run; called by ubidi_getRuns() */
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerugetSingleRun(UBiDi *pBiDi, UBiDiLevel level) {
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* simple, single-run case */
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->runs=pBiDi->simpleRuns;
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->runCount=1;
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* fill and reorder the single run */
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->runs[0].logicalStart=MAKE_INDEX_ODD_PAIR(0, level);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->runs[0].visualLimit=pBiDi->length;
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pBiDi->runs[0].insertRemove=0;
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* reorder the runs array (L2) ---------------------------------------------- */
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Reorder the same-level runs in the runs array.
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Here, runCount>1 and maxLevel>=minLevel>=paraLevel.
406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * All the visualStart fields=logical start before reordering.
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The "odd" bits are not set yet.
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Reordering with this data structure lends itself to some handy shortcuts:
410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Since each run is moved but not modified, and since at the initial maxLevel
412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * each sequence of same-level runs consists of only one run each, we
413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * don't need to do anything there and can predecrement maxLevel.
414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * In many simple cases, the reordering is thus done entirely in the
415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * index mapping.
416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Also, reordering occurs only down to the lowest odd level that occurs,
417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * which is minLevel|1. However, if the lowest level itself is odd, then
418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * in the last reordering the sequence of the runs at this level or higher
419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * will be all runs, and we don't need the elaborate loop to search for them.
420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is covered by ++minLevel instead of minLevel|=1 followed
421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * by an extra reorder-all after the reorder-some loop.
422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * About a trailing WS run:
423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Such a run would need special treatment because its level is not
424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * reflected in levels[] if this is not a paragraph object.
425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Instead, all characters from trailingWSStart on are implicitly at
426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * paraLevel.
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * However, for all maxLevel>paraLevel, this run will never be reordered
428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and does not need to be taken into account. maxLevel==paraLevel is only reordered
429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * if minLevel==paraLevel is odd, which is done in the extra segment.
430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This means that for the main reordering loop we don't need to consider
431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * this run and can --runCount. If it is later part of the all-runs
432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * reordering, then runCount is adjusted accordingly.
433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerureorderLine(UBiDi *pBiDi, UBiDiLevel minLevel, UBiDiLevel maxLevel) {
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Run *runs, tempRun;
437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiLevel *levels;
438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t firstRun, endRun, limitRun, runCount;
439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* nothing to do? */
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(maxLevel<=(minLevel|1)) {
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Reorder only down to the lowest odd level
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * and reorder at an odd minLevel in a separate, simpler loop.
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * See comments above for why minLevel is always incremented.
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ++minLevel;
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runs=pBiDi->runs;
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    levels=pBiDi->levels;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runCount=pBiDi->runCount;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* do not include the WS run at paraLevel<=old minLevel except in the simple loop */
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->trailingWSStart<pBiDi->length) {
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --runCount;
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(--maxLevel>=minLevel) {
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        firstRun=0;
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* loop for all sequences of runs */
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for a sequence of runs that are all at >=maxLevel */
467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the first run of such a sequence */
468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(firstRun<runCount && levels[runs[firstRun].logicalStart]<maxLevel) {
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++firstRun;
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(firstRun>=runCount) {
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such runs */
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the limit run of such a sequence (the run behind it) */
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(limitRun=firstRun; ++limitRun<runCount && levels[runs[limitRun].logicalStart]>=maxLevel;) {}
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Swap the entire sequence of runs from firstRun to limitRun-1. */
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            endRun=limitRun-1;
480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(firstRun<endRun) {
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                tempRun = runs[firstRun];
482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[firstRun]=runs[endRun];
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[endRun]=tempRun;
484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++firstRun;
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --endRun;
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(limitRun==runCount) {
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such runs */
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                firstRun=limitRun+1;
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* now do maxLevel==old minLevel (==odd!), see above */
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!(minLevel&1)) {
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        firstRun=0;
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* include the trailing WS run in this complete reordering */
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pBiDi->trailingWSStart==pBiDi->length) {
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            --runCount;
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* Swap the entire sequence of all runs. (endRun==runCount) */
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(firstRun<runCount) {
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tempRun=runs[firstRun];
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runs[firstRun]=runs[runCount];
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runs[runCount]=tempRun;
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++firstRun;
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            --runCount;
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* compute the runs array --------------------------------------------------- */
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t getRunFromLogicalIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) {
519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Run *runs=pBiDi->runs;
520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t runCount=pBiDi->runCount, visualStart=0, i, length, logicalStart;
521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(i=0; i<runCount; i++) {
523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length=runs[i].visualLimit-visualStart;
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logicalStart=GET_INDEX(runs[i].logicalStart);
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if((logicalIndex>=logicalStart) && (logicalIndex<(logicalStart+length))) {
526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return i;
527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualStart+=length;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* we should never get here */
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_ASSERT(FALSE);
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *pErrorCode = U_INVALID_STATE_ERROR;
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Compute the runs array from the levels array.
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * After ubidi_getRuns() returns TRUE, runCount is guaranteed to be >0
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and the runs are reordered.
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Odd-level runs have visualStart on their visual right edge and
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * they progress visually to the left.
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If option UBIDI_OPTION_INSERT_MARKS is set, insertRemove will contain the
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * sum of appropriate LRM/RLM_BEFORE/AFTER flags.
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * If option UBIDI_OPTION_REMOVE_CONTROLS is set, insertRemove will contain the
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * negative number of BiDi control characters within this run.
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC UBool
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getRuns(UBiDi *pBiDi, UErrorCode *pErrorCode) {
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * This method returns immediately if the runs are already set. This
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * includes the case of length==0 (handled in setPara)..
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (pBiDi->runCount>=0) {
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return TRUE;
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->direction!=UBIDI_MIXED) {
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* simple, single-run case - this covers length==0 */
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* pBiDi->paraLevel is ok even for contextual multiple paragraphs */
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        getSingleRun(pBiDi, pBiDi->paraLevel);
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else /* UBIDI_MIXED, length>0 */ {
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* mixed directionality */
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t length=pBiDi->length, limit;
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel *levels=pBiDi->levels;
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i, runCount;
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBiDiLevel level=UBIDI_DEFAULT_LTR;   /* initialize with no valid level */
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * If there are WS characters at the end of the line
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * and the run preceding them has a level different from
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * paraLevel, then they will form their own run at paraLevel (L1).
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * Count them separately.
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * We need some special treatment for this in order to not
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * modify the levels array which a line UBiDi object shares
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * with its paragraph parent and its other line siblings.
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * In other words, for the trailing WS, it may be
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * levels[]!=paraLevel but we have to treat it like it were so.
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        limit=pBiDi->trailingWSStart;
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* count the runs, there is at least one non-WS run, and limit>0 */
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runCount=0;
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; i<limit; ++i) {
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* increment runCount at the start of each run */
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(levels[i]!=level) {
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++runCount;
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                level=levels[i];
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /*
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * We don't need to see if the last run can be merged with a trailing
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         * WS run because setTrailingWSStart() would have done that.
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru         */
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(runCount==1 && limit==length) {
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* There is only one non-WS run and no trailing WS-run. */
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            getSingleRun(pBiDi, levels[0]);
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else /* runCount>1 || limit<length */ {
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* allocate and set the runs */
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Run *runs;
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t runIndex, start;
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBiDiLevel minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1, maxLevel=0;
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* now, count a (non-mergeable) WS run */
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(limit<length) {
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++runCount;
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* runCount>1 */
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(getRunsMemory(pBiDi, runCount)) {
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs=pBiDi->runsMemory;
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return FALSE;
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* set the runs */
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* FOOD FOR THOUGHT: this could be optimized, e.g.:
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * 464->444, 484->444, 575->555, 595->555
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * However, that would take longer. Check also how it would
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * interact with BiDi control removal and inserting Marks.
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runIndex=0;
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* search for the run limits and initialize visualLimit values with the run lengths */
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i=0;
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            do {
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* prepare this run */
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start=i;
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                level=levels[i];
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(level<minLevel) {
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    minLevel=level;
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(level>maxLevel) {
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    maxLevel=level;
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* look for the run limit */
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                while(++i<limit && levels[i]==level) {}
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* i is another run limit */
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[runIndex].logicalStart=start;
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[runIndex].visualLimit=i-start;
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[runIndex].insertRemove=0;
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++runIndex;
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } while(i<limit);
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(limit<length) {
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* there is a separate WS run */
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[runIndex].logicalStart=limit;
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                runs[runIndex].visualLimit=length-limit;
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* For the trailing WS run, pBiDi->paraLevel is ok even
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                   if contextual multiple paragraphs.                   */
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(pBiDi->paraLevel<minLevel) {
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    minLevel=pBiDi->paraLevel;
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* set the object fields */
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pBiDi->runs=runs;
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pBiDi->runCount=runCount;
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            reorderLine(pBiDi, minLevel, maxLevel);
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* now add the direction flags and adjust the visualLimit's to be just that */
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* this loop will also handle the trailing WS run */
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit=0;
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<runCount; ++i) {
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ADD_ODD_BIT_FROM_LEVEL(runs[i].logicalStart, levels[runs[i].logicalStart]);
66727f654740f2a26ad62a5c155af9199af9e69b889claireho                limit+=runs[i].visualLimit;
66827f654740f2a26ad62a5c155af9199af9e69b889claireho                runs[i].visualLimit=limit;
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* Set the "odd" bit for the trailing WS run. */
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* For a RTL paragraph, it will be the *first* run in visual order. */
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* For the trailing WS run, pBiDi->paraLevel is ok even if
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               contextual multiple paragraphs.                          */
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(runIndex<runCount) {
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t trailingRun = ((pBiDi->paraLevel & 1) != 0)? 0 : runIndex;
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ADD_ODD_BIT_FROM_LEVEL(runs[trailingRun].logicalStart, pBiDi->paraLevel);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* handle insert LRM/RLM BEFORE/AFTER run */
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->insertPoints.size>0) {
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Point *point, *start=pBiDi->insertPoints.points,
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                      *limit=start+pBiDi->insertPoints.size;
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t runIndex;
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(point=start; point<limit; point++) {
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runIndex=getRunFromLogicalIndex(pBiDi, point->pos, pErrorCode);
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pBiDi->runs[runIndex].insertRemove|=point->flag;
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* handle remove BiDi control characters */
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->controlCount>0) {
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t runIndex;
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar *start=pBiDi->text, *limit=start+pBiDi->length, *pu;
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(pu=start; pu<limit; pu++) {
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(IS_BIDI_CONTROL_CHAR(*pu)) {
70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                runIndex=getRunFromLogicalIndex(pBiDi, (int32_t)(pu-start), pErrorCode);
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pBiDi->runs[runIndex].insertRemove--;
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruprepareReorder(const UBiDiLevel *levels, int32_t length,
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               int32_t *indexMap,
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru               UBiDiLevel *pMinLevel, UBiDiLevel *pMaxLevel) {
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start;
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBiDiLevel level, minLevel, maxLevel;
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(levels==NULL || length<=0) {
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return FALSE;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* determine minLevel and maxLevel */
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLevel=UBIDI_MAX_EXPLICIT_LEVEL+1;
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    maxLevel=0;
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(start=length; start>0;) {
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        level=levels[--start];
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(level>UBIDI_MAX_EXPLICIT_LEVEL+1) {
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return FALSE;
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(level<minLevel) {
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            minLevel=level;
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(level>maxLevel) {
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            maxLevel=level;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *pMinLevel=minLevel;
736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    *pMaxLevel=maxLevel;
737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* initialize the index map */
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for(start=length; start>0;) {
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        --start;
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexMap[start]=start;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* reorder a line based on a levels array (L2) ------------------------------ */
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_reorderLogical(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) {
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start, limit, sumOfSosEos;
75250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UBiDiLevel minLevel = 0, maxLevel = 0;
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* nothing to do? */
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(minLevel==maxLevel && (minLevel&1)==0) {
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* reorder only down to the lowest odd level */
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLevel|=1;
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* loop maxLevel..minLevel */
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        start=0;
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* loop for all sequences of levels to reorder at the current maxLevel */
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for a sequence of levels that are all at >=maxLevel */
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the first index of such a sequence */
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(start<length && levels[start]<maxLevel) {
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++start;
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(start>=length) {
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such sequences */
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the limit of such a sequence (the index behind it) */
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * sos=start of sequence, eos=end of sequence
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             *
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * The closed (inclusive) interval from sos to eos includes all the logical
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * and visual indexes within this sequence. They are logically and
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * visually contiguous and in the same range.
790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             *
791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * For each run, the new visual index=sos+eos-old visual index;
792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * we pre-add sos+eos into sumOfSosEos ->
793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * new visual index=sumOfSosEos-old visual index;
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            sumOfSosEos=start+limit-1;
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* reorder each index in the sequence */
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            do {
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                indexMap[start]=sumOfSosEos-indexMap[start];
800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } while(++start<limit);
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* start==limit */
803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(limit==length) {
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such sequences */
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start=limit+1;
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while(--maxLevel>=minLevel);
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_reorderVisual(const UBiDiLevel *levels, int32_t length, int32_t *indexMap) {
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start, end, limit, temp;
81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UBiDiLevel minLevel = 0, maxLevel = 0;
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(indexMap==NULL || !prepareReorder(levels, length, indexMap, &minLevel, &maxLevel)) {
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* nothing to do? */
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(minLevel==maxLevel && (minLevel&1)==0) {
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* reorder only down to the lowest odd level */
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    minLevel|=1;
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* loop maxLevel..minLevel */
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    do {
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        start=0;
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* loop for all sequences of levels to reorder at the current maxLevel */
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for a sequence of levels that are all at >=maxLevel */
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the first index of such a sequence */
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(start<length && levels[start]<maxLevel) {
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++start;
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(start>=length) {
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such runs */
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* look for the limit of such a sequence (the index behind it) */
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(limit=start; ++limit<length && levels[limit]>=maxLevel;) {}
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * Swap the entire interval of indexes from start to limit-1.
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * We don't need to swap the levels for the purpose of this
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * algorithm: the sequence of levels that we look at does not
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * move anyway.
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            end=limit-1;
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(start<end) {
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                temp=indexMap[start];
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                indexMap[start]=indexMap[end];
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                indexMap[end]=temp;
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ++start;
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --end;
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(limit==length) {
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;  /* no more such sequences */
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start=limit+1;
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } while(--maxLevel>=minLevel);
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* API functions for logical<->visual mapping ------------------------------- */
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getVisualIndex(UBiDi *pBiDi, int32_t logicalIndex, UErrorCode *pErrorCode) {
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t visualIndex=UBIDI_MAP_NOWHERE;
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_BAD_RANGE(logicalIndex, 0, pBiDi->length, *pErrorCode, -1);
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* we can do the trivial cases without the runs array */
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch(pBiDi->direction) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UBIDI_LTR:
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualIndex=logicalIndex;
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case UBIDI_RTL:
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualIndex=pBiDi->length-logicalIndex-1;
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(!ubidi_getRuns(pBiDi, pErrorCode)) {
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return -1;
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Run *runs=pBiDi->runs;
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i, visualStart=0, offset, length;
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* linear search for the run, search on the visual runs */
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<pBiDi->runCount; ++i) {
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length=runs[i].visualLimit-visualStart;
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                offset=logicalIndex-GET_INDEX(runs[i].logicalStart);
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(offset>=0 && offset<length) {
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(IS_EVEN_RUN(runs[i].logicalStart)) {
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        /* LTR */
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        visualIndex=visualStart+offset;
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    } else {
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        /* RTL */
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        visualIndex=visualStart+length-offset-1;
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;          /* exit for loop */
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                visualStart+=length;
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(i>=pBiDi->runCount) {
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return UBIDI_MAP_NOWHERE;
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->insertPoints.size>0) {
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* add the number of added marks until the calculated visual index */
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Run *runs=pBiDi->runs;
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i, length, insertRemove;
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t visualStart=0, markFound=0;
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; ; i++, visualStart+=length) {
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=runs[i].visualLimit-visualStart;
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            insertRemove=runs[i].insertRemove;
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove & (LRM_BEFORE|RLM_BEFORE)) {
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                markFound++;
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* is it the run containing the visual index? */
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(visualIndex<runs[i].visualLimit) {
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return visualIndex+markFound;
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove & (LRM_AFTER|RLM_AFTER)) {
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                markFound++;
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if(pBiDi->controlCount>0) {
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* subtract the number of controls until the calculated visual index */
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Run *runs=pBiDi->runs;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t i, j, start, limit, length, insertRemove;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t visualStart=0, controlFound=0;
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar uchar=pBiDi->text[logicalIndex];
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* is the logical index pointing to a control ? */
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(IS_BIDI_CONTROL_CHAR(uchar)) {
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return UBIDI_MAP_NOWHERE;
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* loop on runs */
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; ; i++, visualStart+=length) {
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=runs[i].visualLimit-visualStart;
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            insertRemove=runs[i].insertRemove;
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* calculated visual index is beyond this run? */
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(visualIndex>=runs[i].visualLimit) {
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                controlFound-=insertRemove;
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* calculated visual index must be within current run */
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove==0) {
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return visualIndex-controlFound;
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(IS_EVEN_RUN(runs[i].logicalStart)) {
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* LTR: check from run start to logical index */
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start=runs[i].logicalStart;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                limit=logicalIndex;
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* RTL: check from logical index to run end */
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                start=logicalIndex+1;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                limit=GET_INDEX(runs[i].logicalStart)+length;
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(j=start; j<limit; j++) {
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uchar=pBiDi->text[j];
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(IS_BIDI_CONTROL_CHAR(uchar)) {
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    controlFound++;
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return visualIndex-controlFound;
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return visualIndex;
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getLogicalIndex(UBiDi *pBiDi, int32_t visualIndex, UErrorCode *pErrorCode) {
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Run *runs;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t i, runCount, start;
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_IF_BAD_RANGE(visualIndex, 0, pBiDi->resultLength, *pErrorCode, -1);
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* we can do the trivial cases without the runs array */
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->insertPoints.size==0 && pBiDi->controlCount==0) {
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pBiDi->direction==UBIDI_LTR) {
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return visualIndex;
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(pBiDi->direction==UBIDI_RTL) {
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return pBiDi->length-visualIndex-1;
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!ubidi_getRuns(pBiDi, pErrorCode)) {
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runs=pBiDi->runs;
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    runCount=pBiDi->runCount;
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pBiDi->insertPoints.size>0) {
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* handle inserted LRM/RLM */
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t markFound=0, insertRemove;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t visualStart=0, length;
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        runs=pBiDi->runs;
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* subtract number of marks until visual index */
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; ; i++, visualStart+=length) {
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=runs[i].visualLimit-visualStart;
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            insertRemove=runs[i].insertRemove;
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(visualIndex<=(visualStart+markFound)) {
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return UBIDI_MAP_NOWHERE;
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                markFound++;
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* is adjusted visual index within this run? */
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(visualIndex<(runs[i].visualLimit+markFound)) {
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                visualIndex-=markFound;
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(visualIndex==(visualStart+length+markFound)) {
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return UBIDI_MAP_NOWHERE;
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                markFound++;
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    else if(pBiDi->controlCount>0) {
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* handle removed BiDi control characters */
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t controlFound=0, insertRemove, length;
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t logicalStart, logicalEnd, visualStart=0, j, k;
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UChar uchar;
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UBool evenRun;
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* add number of controls until visual index */
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; ; i++, visualStart+=length) {
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length=runs[i].visualLimit-visualStart;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            insertRemove=runs[i].insertRemove;
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* is adjusted visual index beyond current run? */
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(visualIndex>=(runs[i].visualLimit-controlFound+insertRemove)) {
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                controlFound-=insertRemove;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* adjusted visual index is within current run */
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(insertRemove==0) {
1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                visualIndex+=controlFound;
1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* count non-control chars until visualIndex */
1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalStart=runs[i].logicalStart;
1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            evenRun=IS_EVEN_RUN(logicalStart);
1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            REMOVE_ODD_BIT(logicalStart);
1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalEnd=logicalStart+length-1;
1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(j=0; j<length; j++) {
1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                k= evenRun ? logicalStart+j : logicalEnd-j;
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uchar=pBiDi->text[k];
1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(IS_BIDI_CONTROL_CHAR(uchar)) {
1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    controlFound++;
1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if((visualIndex+controlFound)==(visualStart+j)) {
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualIndex+=controlFound;
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* handle all cases */
1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(runCount<=10) {
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* linear search for the run */
1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(i=0; visualIndex>=runs[i].visualLimit; ++i) {}
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* binary search for the run */
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t begin=0, limit=runCount;
1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the middle if() is guaranteed to find the run, we don't need a loop limit */
1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(;;) {
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            i=(begin+limit)/2;
1085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(visualIndex>=runs[i].visualLimit) {
1086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                begin=i+1;
1087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else if(i==0 || visualIndex>=runs[i-1].visualLimit) {
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                limit=i;
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    start=runs[i].logicalStart;
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(IS_EVEN_RUN(start)) {
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* LTR */
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* the offset in runs[i] is visualIndex-runs[i-1].visualLimit */
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(i>0) {
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualIndex-=runs[i-1].visualLimit;
1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return start+visualIndex;
1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* RTL */
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return GET_INDEX(start)+runs[i].visualLimit-visualIndex-1;
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getLogicalMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_countRuns(pBiDi, pErrorCode);
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_FAILURE(*pErrorCode)) {
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* no op */
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if(indexMap==NULL) {
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* fill a logical-to-visual index map using the runs[] */
1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t visualStart, visualLimit, i, j, k;
1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t logicalStart, logicalLimit;
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Run *runs=pBiDi->runs;
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pBiDi->length<=0) {
1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pBiDi->length>pBiDi->resultLength) {
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memset(indexMap, 0xFF, pBiDi->length*sizeof(int32_t));
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualStart=0;
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(j=0; j<pBiDi->runCount; ++j) {
1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalStart=GET_INDEX(runs[j].logicalStart);
1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualLimit=runs[j].visualLimit;
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(IS_EVEN_RUN(runs[j].logicalStart)) {
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do { /* LTR */
1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[logicalStart++]=visualStart++;
1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while(visualStart<visualLimit);
1138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalStart+=visualLimit-visualStart;  /* logicalLimit */
1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do { /* RTL */
1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[--logicalStart]=visualStart++;
1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while(visualStart<visualLimit);
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* visualStart==visualLimit; */
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pBiDi->insertPoints.size>0) {
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t markFound=0, runCount=pBiDi->runCount;
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t length, insertRemove;
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualStart=0;
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* add number of marks found until each index */
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<runCount; i++, visualStart+=length) {
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length=runs[i].visualLimit-visualStart;
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                insertRemove=runs[i].insertRemove;
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound++;
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(markFound>0) {
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    logicalStart=GET_INDEX(runs[i].logicalStart);
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    logicalLimit=logicalStart+length;
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for(j=logicalStart; j<logicalLimit; j++) {
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        indexMap[j]+=markFound;
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound++;
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(pBiDi->controlCount>0) {
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t controlFound=0, runCount=pBiDi->runCount;
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t length, insertRemove;
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool evenRun;
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UChar uchar;
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualStart=0;
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* subtract number of controls found until each index */
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<runCount; i++, visualStart+=length) {
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length=runs[i].visualLimit-visualStart;
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                insertRemove=runs[i].insertRemove;
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* no control found within previous runs nor within this run */
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if((controlFound-insertRemove)==0) {
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    continue;
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalStart=runs[i].logicalStart;
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                evenRun=IS_EVEN_RUN(logicalStart);
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                REMOVE_ODD_BIT(logicalStart);
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalLimit=logicalStart+length;
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* if no control within this run */
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove==0) {
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for(j=logicalStart; j<logicalLimit; j++) {
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        indexMap[j]-=controlFound;
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    continue;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(j=0; j<length; j++) {
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    k= evenRun ? logicalStart+j : logicalLimit-j-1;
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uchar=pBiDi->text[k];
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(IS_BIDI_CONTROL_CHAR(uchar)) {
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        controlFound++;
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        indexMap[k]=UBIDI_MAP_NOWHERE;
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        continue;
1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[k]-=controlFound;
1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_getVisualMap(UBiDi *pBiDi, int32_t *indexMap, UErrorCode *pErrorCode) {
1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(indexMap==NULL) {
1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* ubidi_countRuns() checks for VALID_PARA_OR_LINE */
1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ubidi_countRuns(pBiDi, pErrorCode);
1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(U_SUCCESS(*pErrorCode)) {
1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* fill a visual-to-logical index map using the runs[] */
1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Run *runs=pBiDi->runs, *runsLimit=runs+pBiDi->runCount;
1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t logicalStart, visualStart, visualLimit, *pi=indexMap;
1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pBiDi->resultLength<=0) {
1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        visualStart=0;
1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for(; runs<runsLimit; ++runs) {
1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logicalStart=runs->logicalStart;
1230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualLimit=runs->visualLimit;
1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(IS_EVEN_RUN(logicalStart)) {
1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do { /* LTR */
1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *pi++ = logicalStart++;
1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while(++visualStart<visualLimit);
1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                REMOVE_ODD_BIT(logicalStart);
1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalStart+=visualLimit-visualStart;  /* logicalLimit */
1238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                do { /* RTL */
1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    *pi++ = --logicalStart;
1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } while(++visualStart<visualLimit);
1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* visualStart==visualLimit; */
1243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(pBiDi->insertPoints.size>0) {
1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t markFound=0, runCount=pBiDi->runCount;
1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t insertRemove, i, j, k;
1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runs=pBiDi->runs;
1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* count all inserted marks */
1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<runCount; i++) {
1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                insertRemove=runs[i].insertRemove;
1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound++;
1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound++;
1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* move back indexes by number of preceding marks */
1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            k=pBiDi->resultLength;
1261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=runCount-1; i>=0 && markFound>0; i--) {
1262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                insertRemove=runs[i].insertRemove;
1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_AFTER|RLM_AFTER)) {
1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[--k]= UBIDI_MAP_NOWHERE;
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound--;
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                visualStart= i>0 ? runs[i-1].visualLimit : 0;
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(j=runs[i].visualLimit-1; j>=visualStart && markFound>0; j--) {
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[--k]=indexMap[j];
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove&(LRM_BEFORE|RLM_BEFORE)) {
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    indexMap[--k]= UBIDI_MAP_NOWHERE;
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    markFound--;
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else if(pBiDi->controlCount>0) {
1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t runCount=pBiDi->runCount, logicalEnd;
1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t insertRemove, length, i, j, k, m;
1280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UChar uchar;
1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UBool evenRun;
1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            runs=pBiDi->runs;
1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            visualStart=0;
1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* move forward indexes by number of preceding controls */
1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            k=0;
1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<runCount; i++, visualStart+=length) {
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                length=runs[i].visualLimit-visualStart;
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                insertRemove=runs[i].insertRemove;
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* if no control found yet, nothing to do in this run */
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if((insertRemove==0)&&(k==visualStart)) {
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    k+=length;
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    continue;
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* if no control in this run */
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(insertRemove==0) {
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    visualLimit=runs[i].visualLimit;
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    for(j=visualStart; j<visualLimit; j++) {
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        indexMap[k++]=indexMap[j];
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    continue;
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalStart=runs[i].logicalStart;
1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                evenRun=IS_EVEN_RUN(logicalStart);
1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                REMOVE_ODD_BIT(logicalStart);
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                logicalEnd=logicalStart+length-1;
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(j=0; j<length; j++) {
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    m= evenRun ? logicalStart+j : logicalEnd-j;
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uchar=pBiDi->text[m];
1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if(!IS_BIDI_CONTROL_CHAR(uchar)) {
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        indexMap[k++]=m;
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruubidi_invertMap(const int32_t *srcMap, int32_t *destMap, int32_t length) {
1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(srcMap!=NULL && destMap!=NULL && length>0) {
1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const int32_t *pi;
1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t destLength=-1, count=0;
1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* find highest value and count positive indexes in srcMap */
1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pi=srcMap+length;
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(pi>srcMap) {
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(*--pi>destLength) {
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                destLength=*pi;
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(*pi>=0) {
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                count++;
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        destLength++;           /* add 1 for origin 0 */
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(count<destLength) {
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* we must fill unmatched destMap entries with -1 */
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memset(destMap, 0xFF, destLength*sizeof(int32_t));
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pi=srcMap+length;
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        while(length>0) {
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(*--pi>=0) {
1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                destMap[*pi]=--length;
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                --length;
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1348