1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   Copyright (C) 1999-2009, International Business Machines
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   Corporation and others.  All Rights Reserved.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   file name:  ubidi.c
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   encoding:   US-ASCII
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   tab size:   8 (not used)
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   indentation:4
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   created on: 1999jul27
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*   created by: Markus W. Scherer, updated by Matitiahu Allouche
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "cmemory.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/utypes.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/ustring.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/uchar.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/ubidi.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "ubidi_props.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "ubidiimp.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "uassert.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * General implementation notes:
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Throughout the implementation, there are comments like (W2) that refer to
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * rules of the BiDi algorithm in its version 5, in this example to the second
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * rule of the resolution of weak types.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * For handling surrogate pairs, where two UChar's form one "abstract" (or UTF-32)
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * character according to UTF-16, the second UChar gets the directional property of
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the entire character assigned, while the first one gets a BN, a boundary
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * neutral, type, which is ignored by most of the algorithm according to
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * rule (X9) and the implementation suggestions of the BiDi algorithm.
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Later, adjustWSLevels() will set the level for each BN to that of the
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * following character (UChar), which results in surrogate pairs getting the
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * same level on each of their surrogates.
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In a UTF-8 implementation, the same thing could be done: the last byte of
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * a multi-byte sequence would get the "real" property, while all previous
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * bytes of that sequence would get BN.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * It is not possible to assign all those parts of a character the same real
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * property because this would fail in the resolution of weak types with rules
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * that look at immediately surrounding types.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * As a related topic, this implementation does not remove Boundary Neutral
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * types from the input, but ignores them wherever this is relevant.
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * For example, the loop for the resolution of the weak types reads
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * types until it finds a non-BN.
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Also, explicit embedding codes are neither changed into BN nor removed.
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * They are only treated the same way real BNs are.
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * As stated before, adjustWSLevels() takes care of them at the end.
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * For the purpose of conformance, the levels of all these codes
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * do not matter.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Note that this implementation never modifies the dirProps
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * after the initial setup.
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In this implementation, the resolution of weak types (Wn),
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * neutrals (Nn), and the assignment of the resolved level (In)
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * are all done in one single loop, in resolveImplicitLevels().
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Changes of dirProp values are done on the fly, without writing
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * them back to the dirProps array.
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This implementation contains code that allows to bypass steps of the
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * algorithm that are not needed on the specific paragraph
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in order to speed up the most common cases considerably,
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * like text that is entirely LTR, or RTL text without numbers.
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Most of this is done by setting a bit for each directional property
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in a flags variable and later checking for whether there are
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * any LTR characters or any RTL characters, or both, whether
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * there are any explicit embedding codes, etc.
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If the (Xn) steps are performed, then the flags are re-evaluated,
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * because they will then not contain the embedding codes any more
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and will be adjusted for override codes, so that subsequently
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * more bypassing may be possible than what the initial flags suggested.
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If the text is not mixed-directional, then the
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * algorithm steps for the weak type resolution are not performed,
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and all levels are set to the paragraph level.
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If there are no explicit embedding codes, then the (Xn) steps
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * are not performed.
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If embedding levels are supplied as a parameter, then all
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * explicit embedding codes are ignored, and the (Xn) steps
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * are not performed.
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * White Space types could get the level of the run they belong to,
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and are checked with a test of (flags&MASK_EMBEDDING) to
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * consider if the paragraph direction should be considered in
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the flags variable.
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If there are no White Space types in the paragraph, then
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (L1) is not necessary in adjustWSLevels().
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* to avoid some conditional statements, use tiny constant arrays */
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) };
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) };
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DIRPROP_FLAG_LR(level) flagLR[(level)&1]
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DIRPROP_FLAG_E(level) flagE[(level)&1]
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define DIRPROP_FLAG_O(level) flagO[(level)&1]
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* UBiDi object management -------------------------------------------------- */
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBiDi * U_EXPORT2
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_open(void)
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UErrorCode errorCode=U_ZERO_ERROR;
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ubidi_openSized(0, 0, &errorCode);
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBiDi * U_EXPORT2
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_openSized(int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode) {
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDi *pBiDi;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check the argument values */
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if(maxLength<0 || maxRunCount<0) {
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;    /* invalid arguments */
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* allocate memory for the object */
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi=(UBiDi *)uprv_malloc(sizeof(UBiDi));
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi==NULL) {
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* reset the object, all pointers NULL, all flags FALSE, all sizes 0 */
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_memset(pBiDi, 0, sizeof(UBiDi));
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* get BiDi properties */
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->bdp=ubidi_getSingleton(pErrorCode);
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(U_FAILURE(*pErrorCode)) {
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        uprv_free(pBiDi);
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* allocate memory for arrays as requested */
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(maxLength>0) {
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if( !getInitialDirPropsMemory(pBiDi, maxLength) ||
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            !getInitialLevelsMemory(pBiDi, maxLength)
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ) {
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->mayAllocateText=TRUE;
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(maxRunCount>0) {
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(maxRunCount==1) {
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* use simpleRuns[] */
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->runsSize=sizeof(Run);
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else if(!getInitialRunsMemory(pBiDi, maxRunCount)) {
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->mayAllocateRuns=TRUE;
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(U_SUCCESS(*pErrorCode)) {
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi;
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ubidi_close(pBiDi);
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We are allowed to allocate memory if memory==NULL or
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * mayAllocate==TRUE for each array that we need.
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * We also try to grow memory as needed if we
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * allocate it.
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Assume sizeNeeded>0.
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * If *pMemory!=NULL, then assume *pSize>0.
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * ### this realloc() may unnecessarily copy the old data,
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * which we know we don't need any more;
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * is this the best way to do this??
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CFUNC UBool
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getMemory(BidiMemoryForAllocation *bidiMem, int32_t *pSize, UBool mayAllocate, int32_t sizeNeeded) {
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void **pMemory = (void **)bidiMem;
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check for existing memory */
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(*pMemory==NULL) {
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* we need to allocate memory */
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(mayAllocate && (*pMemory=uprv_malloc(sizeNeeded))!=NULL) {
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pSize=sizeNeeded;
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return TRUE;
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return FALSE;
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(sizeNeeded<=*pSize) {
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* there is already enough memory */
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return TRUE;
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else if(!mayAllocate) {
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* not enough memory, and we must not allocate */
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return FALSE;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* we try to grow */
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            void *memory;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* in most cases, we do not need the copy-old-data part of
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             * realloc, but it is needed when adding runs using getRunsMemory()
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             * in setParaRunsOnly()
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             */
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if((memory=uprv_realloc(*pMemory, sizeNeeded))!=NULL) {
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                *pMemory=memory;
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                *pSize=sizeNeeded;
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                return TRUE;
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } else {
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* we failed to grow */
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                return FALSE;
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_close(UBiDi *pBiDi) {
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi!=NULL) {
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->pParaBiDi=NULL;          /* in case one tries to reuse this block */
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->dirPropsMemory!=NULL) {
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pBiDi->dirPropsMemory);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->levelsMemory!=NULL) {
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pBiDi->levelsMemory);
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->runsMemory!=NULL) {
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pBiDi->runsMemory);
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->parasMemory!=NULL) {
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pBiDi->parasMemory);
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->insertPoints.points!=NULL) {
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            uprv_free(pBiDi->insertPoints.points);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        uprv_free(pBiDi);
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* set to approximate "inverse BiDi" ---------------------------------------- */
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_setInverse(UBiDi *pBiDi, UBool isInverse) {
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi!=NULL) {
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->isInverse=isInverse;
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->reorderingMode = isInverse ? UBIDI_REORDER_INVERSE_NUMBERS_AS_L
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          : UBIDI_REORDER_DEFAULT;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBool U_EXPORT2
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_isInverse(UBiDi *pBiDi) {
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi!=NULL) {
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->isInverse;
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return FALSE;
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* FOOD FOR THOUGHT: currently the reordering modes are a mixture of
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * algorithm for direct BiDi, algorithm for inverse BiDi and the bizarre
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * concept of RUNS_ONLY which is a double operation.
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * It could be advantageous to divide this into 3 concepts:
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * a) Operation: direct / inverse / RUNS_ONLY
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * b) Direct algorithm: default / NUMBERS_SPECIAL / GROUP_NUMBERS_WITH_R
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * c) Inverse algorithm: default / INVERSE_LIKE_DIRECT / NUMBERS_SPECIAL
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This would allow combinations not possible today like RUNS_ONLY with
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NUMBERS_SPECIAL.
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Also allow to set INSERT_MARKS for the direct step of RUNS_ONLY and
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * REMOVE_CONTROLS for the inverse step.
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Not all combinations would be supported, and probably not all do make sense.
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This would need to document which ones are supported and what are the
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * fallbacks for unsupported combinations.
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_setReorderingMode(UBiDi *pBiDi, UBiDiReorderingMode reorderingMode) {
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ((pBiDi!=NULL) && (reorderingMode >= UBIDI_REORDER_DEFAULT)
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        && (reorderingMode < UBIDI_REORDER_COUNT)) {
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->reorderingMode = reorderingMode;
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->isInverse = (UBool)(reorderingMode == UBIDI_REORDER_INVERSE_NUMBERS_AS_L);
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBiDiReorderingMode U_EXPORT2
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getReorderingMode(UBiDi *pBiDi) {
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pBiDi!=NULL) {
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->reorderingMode;
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return UBIDI_REORDER_DEFAULT;
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_setReorderingOptions(UBiDi *pBiDi, uint32_t reorderingOptions) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        reorderingOptions&=~UBIDI_OPTION_INSERT_MARKS;
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pBiDi!=NULL) {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->reorderingOptions=reorderingOptions;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI uint32_t U_EXPORT2
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getReorderingOptions(UBiDi *pBiDi) {
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pBiDi!=NULL) {
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->reorderingOptions;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* perform (P2)..(P3) ------------------------------------------------------- */
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Get the directional properties for the text,
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * calculate the flags bit-set, and
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * determine the paragraph level if necessary.
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottgetDirProps(UBiDi *pBiDi) {
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const UChar *text=pBiDi->text;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp *dirProps=pBiDi->dirPropsMemory;    /* pBiDi->dirProps is const */
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t i=0, i0, i1, length=pBiDi->originalLength;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Flags flags=0;      /* collect all directionalities in the text */
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UChar32 uchar;
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp dirProp=0, paraDirDefault=0;/* initialize to avoid compiler warnings */
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool isDefaultLevel=IS_DEFAULT_LEVEL(pBiDi->paraLevel);
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* for inverse BiDi, the default para level is set to RTL if there is a
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       strong R or AL character at either end of the text                           */
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool isDefaultLevelInverse=isDefaultLevel && (UBool)
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            (pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT ||
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL);
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t lastArabicPos=-1;
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t controlCount=0;
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool removeBiDiControls = (UBool)(pBiDi->reorderingOptions &
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       UBIDI_OPTION_REMOVE_CONTROLS);
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    typedef enum {
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         NOT_CONTEXTUAL,                /* 0: not contextual paraLevel */
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         LOOKING_FOR_STRONG,            /* 1: looking for first strong char */
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         FOUND_STRONG_CHAR              /* 2: found first strong char       */
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } State;
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    State state;
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t paraStart=0;                /* index of first char in paragraph */
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp paraDir;                    /* == CONTEXT_RTL within paragraphs
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           starting with strong R char      */
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp lastStrongDir=0;            /* for default level & inverse BiDi */
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t lastStrongLTR=0;            /* for STREAMING option             */
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING) {
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->length=0;
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        lastStrongLTR=0;
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(isDefaultLevel) {
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        paraDirDefault=pBiDi->paraLevel&1 ? CONTEXT_RTL : 0;
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        paraDir=paraDirDefault;
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        lastStrongDir=paraDirDefault;
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        state=LOOKING_FOR_STRONG;
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        state=NOT_CONTEXTUAL;
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        paraDir=0;
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* count paragraphs and determine the paragraph level (P2..P3) */
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /*
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * see comment in ubidi.h:
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * the DEFAULT_XXX values are designed so that
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * their bit 0 alone yields the intended default
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for( /* i=0 above */ ; i<length; ) {
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* i is incremented by UTF_NEXT_CHAR */
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        i0=i;           /* index of first code unit */
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        UTF_NEXT_CHAR(text, i, length, uchar);
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        i1=i-1;         /* index of last code unit, gets the directional property */
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        flags|=DIRPROP_FLAG(dirProp=(DirProp)ubidi_getCustomizedClass(pBiDi, uchar));
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        dirProps[i1]=dirProp|paraDir;
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(i1>i0) {     /* set previous code units' properties to BN */
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            flags|=DIRPROP_FLAG(BN);
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            do {
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                dirProps[--i1]=(DirProp)(BN|paraDir);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } while(i1>i0);
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(state==LOOKING_FOR_STRONG) {
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(dirProp==L) {
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                state=FOUND_STRONG_CHAR;
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(paraDir) {
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    paraDir=0;
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    for(i1=paraStart; i1<i; i1++) {
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        dirProps[i1]&=~CONTEXT_RTL;
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                continue;
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(dirProp==R || dirProp==AL) {
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                state=FOUND_STRONG_CHAR;
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(paraDir==0) {
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    paraDir=CONTEXT_RTL;
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    for(i1=paraStart; i1<i; i1++) {
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        dirProps[i1]|=CONTEXT_RTL;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                continue;
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(dirProp==L) {
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            lastStrongDir=0;
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            lastStrongLTR=i;            /* i is index to next character */
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else if(dirProp==R) {
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            lastStrongDir=CONTEXT_RTL;
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else if(dirProp==AL) {
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            lastStrongDir=CONTEXT_RTL;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            lastArabicPos=i-1;
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else if(dirProp==B) {
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING) {
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->length=i;        /* i is index to next character */
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(isDefaultLevelInverse && (lastStrongDir==CONTEXT_RTL) &&(paraDir!=lastStrongDir)) {
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                for( ; paraStart<i; paraStart++) {
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    dirProps[paraStart]|=CONTEXT_RTL;
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(i<length) {              /* B not last char in text */
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(!((uchar==CR) && (text[i]==LF))) {
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    pBiDi->paraCount++;
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(isDefaultLevel) {
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    state=LOOKING_FOR_STRONG;
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    paraStart=i;        /* i is index to next character */
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    paraDir=paraDirDefault;
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    lastStrongDir=paraDirDefault;
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(removeBiDiControls && IS_BIDI_CONTROL_CHAR(uchar)) {
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            controlCount++;
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(isDefaultLevelInverse && (lastStrongDir==CONTEXT_RTL) &&(paraDir!=lastStrongDir)) {
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(i1=paraStart; i1<length; i1++) {
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            dirProps[i1]|=CONTEXT_RTL;
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(isDefaultLevel) {
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->paraLevel=GET_PARALEVEL(pBiDi, 0);
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->reorderingOptions & UBIDI_OPTION_STREAMING) {
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if((lastStrongLTR>pBiDi->length) &&
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           (GET_PARALEVEL(pBiDi, lastStrongLTR)==0)) {
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->length = lastStrongLTR;
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->length<pBiDi->originalLength) {
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->paraCount--;
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* The following line does nothing new for contextual paraLevel, but is
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       needed for absolute paraLevel.                               */
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->orderParagraphsLTR && (flags&DIRPROP_FLAG(B))) {
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        flags|=DIRPROP_FLAG(L);
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->controlCount = controlCount;
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->flags=flags;
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->lastArabicPos=lastArabicPos;
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* perform (X1)..(X9) ------------------------------------------------------- */
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* determine if the text is mixed-directional or single-directional */
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic UBiDiDirection
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottdirectionFromFlags(UBiDi *pBiDi) {
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Flags flags=pBiDi->flags;
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* if the text contains AN and neutrals, then some neutrals may become RTL */
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return UBIDI_LTR;
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if(!(flags&MASK_LTR)) {
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return UBIDI_RTL;
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return UBIDI_MIXED;
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Resolve the explicit levels as specified by explicit embedding codes.
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Recalculate the flags to have them reflect the real properties
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * after taking the explicit embeddings into account.
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The BiDi algorithm is designed to result in the same behavior whether embedding
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * levels are externally specified (from "styled text", supposedly the preferred
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * method) or set by explicit embedding codes (LRx, RLx, PDF) in the plain text.
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * That is why (X9) instructs to remove all explicit codes (and BN).
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * However, in a real implementation, this removal of these codes and their index
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * positions in the plain text is undesirable since it would result in
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * reallocated, reindexed text.
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Instead, this implementation leaves the codes in there and just ignores them
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in the subsequent processing.
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In order to get the same reordering behavior, positions with a BN or an
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * explicit embedding code just get the same level assigned as the last "real"
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * character.
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Some implementations, not this one, then overwrite some of these
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * directionality properties at "real" same-level-run boundaries by
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * L or R codes so that the resolution of weak types can be performed on the
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * entire paragraph at once instead of having to parse it once more and
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * perform that resolution on same-level-runs.
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This limits the scope of the implicit rules in effectively
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the same way as the run limits.
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Instead, this implementation does not modify these codes.
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * On one hand, the paragraph has to be scanned for same-level-runs, but
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * on the other hand, this saves another loop to reset these codes,
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * or saves making and modifying a copy of dirProps[].
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Note that (Pn) and (Xn) changed significantly from version 4 of the BiDi algorithm.
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Handling the stack of explicit levels (Xn):
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * With the BiDi stack of explicit levels,
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * as pushed with each LRE, RLE, LRO, and RLO and popped with each PDF,
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the explicit level must never exceed UBIDI_MAX_EXPLICIT_LEVEL==61.
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In order to have a correct push-pop semantics even in the case of overflows,
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * there are two overflow counters:
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * - countOver60 is incremented with each LRx at level 60
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * - from level 60, one RLx increases the level to 61
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * - countOver61 is incremented with each LRx and RLx at level 61
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Popping levels with PDF must work in the opposite order so that level 61
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * is correct at the correct point. Underflows (too many PDFs) must be checked.
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This implementation assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd.
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic UBiDiDirection
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottresolveExplicitLevels(UBiDi *pBiDi) {
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DirProp *dirProps=pBiDi->dirProps;
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel *levels=pBiDi->levels;
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const UChar *text=pBiDi->text;
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t i=0, length=pBiDi->length;
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Flags flags=pBiDi->flags;       /* collect all directionalities in the text */
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp dirProp;
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel level=GET_PARALEVEL(pBiDi, 0);
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiDirection direction;
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t paraIndex=0;
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* determine if the text is mixed-directional or single-directional */
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    direction=directionFromFlags(pBiDi);
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* we may not need to resolve any explicit levels, but for multiple
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       paragraphs we want to loop on all chars to set the para boundaries */
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if((direction!=UBIDI_MIXED) && (pBiDi->paraCount==1)) {
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if((pBiDi->paraCount==1) &&
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              (!(flags&MASK_EXPLICIT) ||
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               (pBiDi->reorderingMode > UBIDI_REORDER_LAST_LOGICAL_TO_VISUAL))) {
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* mixed, but all characters are at the same embedding level */
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* or we are in "inverse BiDi" */
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* and we don't have contextual multiple paragraphs with some B char */
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* set all levels to the paragraph level */
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(i=0; i<length; ++i) {
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            levels[i]=level;
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* continue to perform (Xn) */
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* both variables may carry the UBIDI_LEVEL_OVERRIDE flag to indicate the override status */
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        UBiDiLevel embeddingLevel=level, newLevel, stackTop=0;
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        UBiDiLevel stack[UBIDI_MAX_EXPLICIT_LEVEL];        /* we never push anything >=UBIDI_MAX_EXPLICIT_LEVEL */
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        uint32_t countOver60=0, countOver61=0;  /* count overflows of explicit levels */
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* recalculate the flags */
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        flags=0;
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(i=0; i<length; ++i) {
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            dirProp=NO_CONTEXT_RTL(dirProps[i]);
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            switch(dirProp) {
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case LRE:
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case LRO:
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* (X3, X5) */
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1)); /* least greater even level */
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    stack[stackTop]=embeddingLevel;
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ++stackTop;
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    embeddingLevel=newLevel;
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(dirProp==LRO) {
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* we don't need to set UBIDI_LEVEL_OVERRIDE off for LRE
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       since this has already been done for newLevel which is
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       the source for embeddingLevel.
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     */
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL) {
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ++countOver61;
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else /* (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL-1 */ {
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ++countOver60;
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flags|=DIRPROP_FLAG(BN);
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case RLE:
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case RLO:
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* (X2, X4) */
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                newLevel=(UBiDiLevel)(((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)+1)|1); /* least greater odd level */
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    stack[stackTop]=embeddingLevel;
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ++stackTop;
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    embeddingLevel=newLevel;
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(dirProp==RLO) {
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* we don't need to set UBIDI_LEVEL_OVERRIDE off for RLE
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       since this has already been done for newLevel which is
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       the source for embeddingLevel.
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     */
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    ++countOver61;
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flags|=DIRPROP_FLAG(BN);
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case PDF:
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* (X7) */
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* handle all the overflow cases first */
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(countOver61>0) {
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    --countOver61;
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if(countOver60>0 && (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)!=UBIDI_MAX_EXPLICIT_LEVEL) {
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* handle LRx overflows from level 60 */
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    --countOver60;
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if(stackTop>0) {
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* this is the pop operation; it also pops level 61 while countOver60>0 */
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    --stackTop;
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    embeddingLevel=stack[stackTop];
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* } else { (underflow) */
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flags|=DIRPROP_FLAG(BN);
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case B:
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                stackTop=0;
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                countOver60=countOver61=0;
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                level=GET_PARALEVEL(pBiDi, i);
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if((i+1)<length) {
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    embeddingLevel=GET_PARALEVEL(pBiDi, i+1);
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(!((text[i]==CR) && (text[i+1]==LF))) {
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        pBiDi->paras[paraIndex++]=i+1;
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flags|=DIRPROP_FLAG(B);
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case BN:
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* they will get their levels set correctly in adjustWSLevels() */
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flags|=DIRPROP_FLAG(BN);
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            default:
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* all other types get the "real" level */
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(level!=embeddingLevel) {
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    level=embeddingLevel;
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(level&UBIDI_LEVEL_OVERRIDE) {
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        flags|=DIRPROP_FLAG_O(level)|DIRPROP_FLAG_MULTI_RUNS;
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    } else {
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG_MULTI_RUNS;
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(!(level&UBIDI_LEVEL_OVERRIDE)) {
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    flags|=DIRPROP_FLAG(dirProp);
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /*
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             * We need to set reasonable levels even on BN codes and
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             * explicit codes because we will later look at same-level runs (X10).
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             */
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            levels[i]=level;
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(flags&MASK_EMBEDDING) {
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(pBiDi->orderParagraphsLTR && (flags&DIRPROP_FLAG(B))) {
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            flags|=DIRPROP_FLAG(L);
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* subsequently, ignore the explicit codes and BN (X9) */
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* again, determine if the text is mixed-directional or single-directional */
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->flags=flags;
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        direction=directionFromFlags(pBiDi);
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return direction;
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Use a pre-specified embedding levels array:
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Adjust the directional properties for overrides (->LEVEL_OVERRIDE),
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * ignore all explicit codes (X9),
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * and check all the preset levels.
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Recalculate the flags to have them reflect the real properties
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * after taking the explicit embeddings into account.
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic UBiDiDirection
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottcheckExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DirProp *dirProps=pBiDi->dirProps;
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp dirProp;
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel *levels=pBiDi->levels;
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const UChar *text=pBiDi->text;
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t i, length=pBiDi->length;
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Flags flags=0;  /* collect all directionalities in the text */
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel level;
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint32_t paraIndex=0;
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for(i=0; i<length; ++i) {
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        level=levels[i];
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        dirProp=NO_CONTEXT_RTL(dirProps[i]);
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(level&UBIDI_LEVEL_OVERRIDE) {
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* keep the override flag in levels[i] but adjust the flags */
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            level&=~UBIDI_LEVEL_OVERRIDE;     /* make the range check below simpler */
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            flags|=DIRPROP_FLAG_O(level);
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* set the flags */
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProp);
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if((level<GET_PARALEVEL(pBiDi, i) &&
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            !((0==level)&&(dirProp==B))) ||
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           (UBIDI_MAX_EXPLICIT_LEVEL<level)) {
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* level out of bounds */
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return UBIDI_LTR;
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if((dirProp==B) && ((i+1)<length)) {
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(!((text[i]==CR) && (text[i+1]==LF))) {
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->paras[paraIndex++]=i+1;
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(flags&MASK_EMBEDDING) {
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* determine if the text is mixed-directional or single-directional */
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->flags=flags;
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return directionFromFlags(pBiDi);
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/******************************************************************
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The Properties state machine table
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott All table cells are 8 bits:
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bits 0..4:  next state
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bits 5..7:  action to perform (if > 0)
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cells may be of format "n" where n represents the next state
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (except for the rightmost column).
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cells may also be of format "s(x,y)" where x represents an action
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott to perform and y represents the next state.
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Definitions and type for properties state table
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define IMPTABPROPS_COLUMNS 14
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define IMPTABPROPS_RES (IMPTABPROPS_COLUMNS - 1)
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GET_STATEPROPS(cell) ((cell)&0x1f)
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GET_ACTIONPROPS(cell) ((cell)>>5)
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define s(action, newState) ((uint8_t)(newState+(action<<5)))
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8_t groupProp[] =          /* dirProp regrouped */
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  L   R   EN  ES  ET  AN  CS  B   S   WS  ON  LRE LRO AL  RLE RLO PDF NSM BN  */
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0,  1,  2,  7,  8,  3,  9,  6,  5,  4,  4,  10, 10, 12, 10, 10, 10, 11, 10
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum { DirProp_L=0, DirProp_R=1, DirProp_EN=2, DirProp_AN=3, DirProp_ON=4, DirProp_S=5, DirProp_B=6 }; /* reduced dirProp */
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/******************************************************************
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PROPERTIES  STATE  TABLE
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott In table impTabProps,
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      - the ON column regroups ON and WS
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      - the BN column regroups BN, LRE, RLE, LRO, RLO, PDF
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      - the Res column is the reduced property assigned to a run
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Action 1: process current run1, init new run1
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        2: init new run2
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        3: process run1, process run2, init new run1
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        4: process run1, set run1=run2, init new run2
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Notes:
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  1) This table is used in resolveImplicitLevels().
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  2) This table triggers actions when there is a change in the Bidi
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     property of incoming characters (action 1).
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  3) Most such property sequences are processed immediately (in
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     fact, passed to processPropertySeq().
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  4) However, numbers are assembled as one sequence. This means
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     that undefined situations (like CS following digits, until
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     it is known if the next char will be a digit) are held until
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     following chars define them.
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     Example: digits followed by CS, then comes another CS or ON;
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              the digits will be processed, then the CS assigned
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              as the start of an ON sequence (action 3).
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  5) There are cases where more than one sequence must be
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     processed, for instance digits followed by CS followed by L:
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     the digits must be processed as one sequence, and the CS
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     must be processed as an ON sequence, all this before starting
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     assembling chars for the opening L sequence.
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8_t impTabProps[][IMPTABPROPS_COLUMNS] =
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                        L ,     R ,    EN ,    AN ,    ON ,     S ,     B ,    ES ,    ET ,    CS ,    BN ,   NSM ,    AL ,  Res */
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 Init        */ {     1 ,     2 ,     4 ,     5 ,     7 ,    15 ,    17 ,     7 ,     9 ,     7 ,     0 ,     7 ,     3 ,  DirProp_ON },
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 L           */ {     1 , s(1,2), s(1,4), s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), s(1,9), s(1,7),     1 ,     1 , s(1,3),   DirProp_L },
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 R           */ { s(1,1),     2 , s(1,4), s(1,5), s(1,7),s(1,15),s(1,17), s(1,7), s(1,9), s(1,7),     2 ,     2 , s(1,3),   DirProp_R },
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 AL          */ { s(1,1), s(1,2), s(1,6), s(1,6), s(1,8),s(1,16),s(1,17), s(1,8), s(1,8), s(1,8),     3 ,     3 ,     3 ,   DirProp_R },
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 EN          */ { s(1,1), s(1,2),     4 , s(1,5), s(1,7),s(1,15),s(1,17),s(2,10),    11 ,s(2,10),     4 ,     4 , s(1,3),  DirProp_EN },
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 AN          */ { s(1,1), s(1,2), s(1,4),     5 , s(1,7),s(1,15),s(1,17), s(1,7), s(1,9),s(2,12),     5 ,     5 , s(1,3),  DirProp_AN },
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 6 AL:EN/AN    */ { s(1,1), s(1,2),     6 ,     6 , s(1,8),s(1,16),s(1,17), s(1,8), s(1,8),s(2,13),     6 ,     6 , s(1,3),  DirProp_AN },
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 7 ON          */ { s(1,1), s(1,2), s(1,4), s(1,5),     7 ,s(1,15),s(1,17),     7 ,s(2,14),     7 ,     7 ,     7 , s(1,3),  DirProp_ON },
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 8 AL:ON       */ { s(1,1), s(1,2), s(1,6), s(1,6),     8 ,s(1,16),s(1,17),     8 ,     8 ,     8 ,     8 ,     8 , s(1,3),  DirProp_ON },
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 9 ET          */ { s(1,1), s(1,2),     4 , s(1,5),     7 ,s(1,15),s(1,17),     7 ,     9 ,     7 ,     9 ,     9 , s(1,3),  DirProp_ON },
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*10 EN+ES/CS    */ { s(3,1), s(3,2),     4 , s(3,5), s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7),    10 , s(4,7), s(3,3),  DirProp_EN },
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*11 EN+ET       */ { s(1,1), s(1,2),     4 , s(1,5), s(1,7),s(1,15),s(1,17), s(1,7),    11 , s(1,7),    11 ,    11 , s(1,3),  DirProp_EN },
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*12 AN+CS       */ { s(3,1), s(3,2), s(3,4),     5 , s(4,7),s(3,15),s(3,17), s(4,7),s(4,14), s(4,7),    12 , s(4,7), s(3,3),  DirProp_AN },
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*13 AL:EN/AN+CS */ { s(3,1), s(3,2),     6 ,     6 , s(4,8),s(3,16),s(3,17), s(4,8), s(4,8), s(4,8),    13 , s(4,8), s(3,3),  DirProp_AN },
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*14 ON+ET       */ { s(1,1), s(1,2), s(4,4), s(1,5),     7 ,s(1,15),s(1,17),     7 ,    14 ,     7 ,    14 ,    14 , s(1,3),  DirProp_ON },
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*15 S           */ { s(1,1), s(1,2), s(1,4), s(1,5), s(1,7),    15 ,s(1,17), s(1,7), s(1,9), s(1,7),    15 , s(1,7), s(1,3),   DirProp_S },
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*16 AL:S        */ { s(1,1), s(1,2), s(1,6), s(1,6), s(1,8),    16 ,s(1,17), s(1,8), s(1,8), s(1,8),    16 , s(1,8), s(1,3),   DirProp_S },
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*17 B           */ { s(1,1), s(1,2), s(1,4), s(1,5), s(1,7),s(1,15),    17 , s(1,7), s(1,9), s(1,7),    17 , s(1,7), s(1,3),   DirProp_B }
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  we must undef macro s because the levels table have a different
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *  structure (4 bits for action and 4 bits for next state.
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#undef s
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/******************************************************************
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The levels state machine tables
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott All table cells are 8 bits:
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bits 0..3:  next state
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bits 4..7:  action to perform (if > 0)
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cells may be of format "n" where n represents the next state
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (except for the rightmost column).
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Cells may also be of format "s(x,y)" where x represents an action
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott to perform and y represents the next state.
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott This format limits each table to 16 states each and to 15 actions.
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Definitions and type for levels state tables
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*******************************************************************
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define IMPTABLEVELS_COLUMNS (DirProp_B + 2)
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define IMPTABLEVELS_RES (IMPTABLEVELS_COLUMNS - 1)
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GET_STATE(cell) ((cell)&0x0f)
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define GET_ACTION(cell) ((cell)>>4)
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define s(action, newState) ((uint8_t)(newState+(action<<4)))
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef uint8_t ImpTab[][IMPTABLEVELS_COLUMNS];
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef uint8_t ImpAct[];
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* FOOD FOR THOUGHT: each ImpTab should have its associated ImpAct,
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * instead of having a pair of ImpTab and a pair of ImpAct.
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef struct ImpTabPair {
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const void * pImpTab[2];
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const void * pImpAct[2];
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} ImpTabPair;
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/******************************************************************
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LEVELS  STATE  TABLES
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott In all levels state tables,
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      - state 0 is the initial state
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      - the Res column is the increment to add to the text level
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for this property sequence.
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The impAct arrays for each table of a pair map the local action
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott numbers of the table to the total list of actions. For instance,
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott action 2 in a given table corresponds to the action number which
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott appears in entry [2] of the impAct array for that table.
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The first entry of all impAct arrays must be 0.
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Action 1: init conditional sequence
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        2: prepend conditional sequence to current sequence
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        3: set ON sequence to new level - 1
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        4: init EN/AN/ON sequence
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        5: fix EN/AN/ON sequence followed by R
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        6: set previous level sequence to level 2
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Notes:
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  1) These tables are used in processPropertySeq(). The input
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     is property sequences as determined by resolveImplicitLevels.
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  2) Most such property sequences are processed immediately
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     (levels are assigned).
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  3) However, some sequences cannot be assigned a final level till
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     one or more following sequences are received. For instance,
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     ON following an R sequence within an even-level paragraph.
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     If the following sequence is R, the ON sequence will be
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     assigned basic run level+1, and so will the R sequence.
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  4) S is generally handled like ON, since its level will be fixed
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     to paragraph level in adjustWSLevels().
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_DEFAULT =   /* Even paragraph level */
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, conditional sequences receive the higher possible level
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven otherwise.
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     0 ,     1 ,     0 ,     2 ,     0 ,     0 ,     0 ,  0 },
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : R          */ {     0 ,     1 ,     3 ,     3 , s(1,4), s(1,4),     0 ,  1 },
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : AN         */ {     0 ,     1 ,     0 ,     2 , s(1,5), s(1,5),     0 ,  2 },
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : R+EN/AN    */ {     0 ,     1 ,     3 ,     3 , s(1,4), s(1,4),     0 ,  2 },
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : R+ON       */ { s(2,0),     1 ,     3 ,     3 ,     4 ,     4 , s(2,0),  1 },
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : AN+ON      */ { s(2,0),     1 , s(2,0),     2 ,     5 ,     5 , s(2,0),  1 }
953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabR_DEFAULT =   /* Odd  paragraph level */
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, conditional sequences receive the lower possible level
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven otherwise.
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     1 ,     0 ,     2 ,     2 ,     0 ,     0 ,     0 ,  0 },
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L          */ {     1 ,     0 ,     1 ,     3 , s(1,4), s(1,4),     0 ,  1 },
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : EN/AN      */ {     1 ,     0 ,     2 ,     2 ,     0 ,     0 ,     0 ,  1 },
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : L+AN       */ {     1 ,     0 ,     1 ,     3 ,     5 ,     5 ,     0 ,  1 },
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : L+ON       */ { s(2,1),     0 , s(2,1),     3 ,     4 ,     4 ,     0 ,  0 },
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : L+AN+ON    */ {     1 ,     0 ,     1 ,     3 ,     5 ,     5 ,     0 ,  0 }
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpAct impAct0 = {0,1,2,3,4,5,6};
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_DEFAULT = {{&impTabL_DEFAULT,
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           &impTabR_DEFAULT},
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          {&impAct0, &impAct0}};
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_NUMBERS_SPECIAL =   /* Even paragraph level */
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, conditional sequences receive the higher possible level
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven otherwise.
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     0 ,     2 ,    1 ,      1 ,     0 ,     0 ,     0 ,  0 },
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L+EN/AN    */ {     0 ,     2 ,    1 ,      1 ,     0 ,     0 ,     0 ,  2 },
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : R          */ {     0 ,     2 ,    4 ,      4 , s(1,3),     0 ,     0 ,  1 },
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : R+ON       */ { s(2,0),     2 ,    4 ,      4 ,     3 ,     3 , s(2,0),  1 },
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : R+EN/AN    */ {     0 ,     2 ,    4 ,      4 , s(1,3), s(1,3),     0 ,  2 }
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_NUMBERS_SPECIAL = {{&impTabL_NUMBERS_SPECIAL,
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                   &impTabR_DEFAULT},
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                  {&impAct0, &impAct0}};
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_GROUP_NUMBERS_WITH_R =
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, EN/AN+ON sequences receive levels as if associated with R
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven that there is L or sor/eor on both sides. AN is handled like EN.
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 init         */ {     0 ,     3 , s(1,1), s(1,1),     0 ,     0 ,     0 ,  0 },
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 EN/AN        */ { s(2,0),     3 ,     1 ,     1 ,     2 , s(2,0), s(2,0),  2 },
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 EN/AN+ON     */ { s(2,0),     3 ,     1 ,     1 ,     2 , s(2,0), s(2,0),  1 },
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 R            */ {     0 ,     3 ,     5 ,     5 , s(1,4),     0 ,     0 ,  1 },
998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 R+ON         */ { s(2,0),     3 ,     5 ,     5 ,     4 , s(2,0), s(2,0),  1 },
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 R+EN/AN      */ {     0 ,     3 ,     5 ,     5 , s(1,4),     0 ,     0 ,  2 }
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabR_GROUP_NUMBERS_WITH_R =
1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, EN/AN+ON sequences receive levels as if associated with R
1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven that there is L on both sides. AN is handled like EN.
1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 init         */ {     2 ,     0 ,     1 ,     1 ,     0 ,     0 ,     0 ,  0 },
1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 EN/AN        */ {     2 ,     0 ,     1 ,     1 ,     0 ,     0 ,     0 ,  1 },
1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 L            */ {     2 ,     0 , s(1,4), s(1,4), s(1,3),     0 ,     0 ,  1 },
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 L+ON         */ { s(2,2),     0 ,     4 ,     4 ,     3 ,     0 ,     0 ,  0 },
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 L+EN/AN      */ { s(2,2),     0 ,     4 ,     4 ,     3 ,     0 ,     0 ,  1 }
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_GROUP_NUMBERS_WITH_R = {
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_GROUP_NUMBERS_WITH_R,
1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_GROUP_NUMBERS_WITH_R},
1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct0}};
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_INVERSE_NUMBERS_AS_L =
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  This table is identical to the Default LTR table except that EN and AN are
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    handled like L.
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     0 ,     1 ,     0 ,     0 ,     0 ,     0 ,     0 ,  0 },
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : R          */ {     0 ,     1 ,     0 ,     0 , s(1,4), s(1,4),     0 ,  1 },
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : AN         */ {     0 ,     1 ,     0 ,     0 , s(1,5), s(1,5),     0 ,  2 },
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : R+EN/AN    */ {     0 ,     1 ,     0 ,     0 , s(1,4), s(1,4),     0 ,  2 },
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : R+ON       */ { s(2,0),     1 , s(2,0), s(2,0),     4 ,     4 , s(2,0),  1 },
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : AN+ON      */ { s(2,0),     1 , s(2,0), s(2,0),     5 ,     5 , s(2,0),  1 }
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabR_INVERSE_NUMBERS_AS_L =
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  This table is identical to the Default RTL table except that EN and AN are
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    handled like L.
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     1 ,     0 ,     1 ,     1 ,     0 ,     0 ,     0 ,  0 },
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L          */ {     1 ,     0 ,     1 ,     1 , s(1,4), s(1,4),     0 ,  1 },
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : EN/AN      */ {     1 ,     0 ,     1 ,     1 ,     0 ,     0 ,     0 ,  1 },
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : L+AN       */ {     1 ,     0 ,     1 ,     1 ,     5 ,     5 ,     0 ,  1 },
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : L+ON       */ { s(2,1),     0 , s(2,1), s(2,1),     4 ,     4 ,     0 ,  0 },
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : L+AN+ON    */ {     1 ,     0 ,     1 ,     1 ,     5 ,     5 ,     0 ,  0 }
1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_INVERSE_NUMBERS_AS_L = {
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_INVERSE_NUMBERS_AS_L,
1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_INVERSE_NUMBERS_AS_L},
1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct0}};
1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabR_INVERSE_LIKE_DIRECT =   /* Odd  paragraph level */
1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  In this table, conditional sequences receive the lower possible level
1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    until proven otherwise.
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     1 ,     0 ,     2 ,     2 ,     0 ,     0 ,     0 ,  0 },
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L          */ {     1 ,     0 ,     1 ,     2 , s(1,3), s(1,3),     0 ,  1 },
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : EN/AN      */ {     1 ,     0 ,     2 ,     2 ,     0 ,     0 ,     0 ,  1 },
1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : L+ON       */ { s(2,1), s(3,0),     6 ,     4 ,     3 ,     3 , s(3,0),  0 },
1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : L+ON+AN    */ { s(2,1), s(3,0),     6 ,     4 ,     5 ,     5 , s(3,0),  3 },
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : L+AN+ON    */ { s(2,1), s(3,0),     6 ,     4 ,     5 ,     5 , s(3,0),  2 },
1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 6 : L+ON+EN    */ { s(2,1), s(3,0),     6 ,     4 ,     3 ,     3 , s(3,0),  1 }
1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpAct impAct1 = {0,1,11,12};
1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* FOOD FOR THOUGHT: in LTR table below, check case "JKL 123abc"
1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_INVERSE_LIKE_DIRECT = {
1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_DEFAULT,
1069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_INVERSE_LIKE_DIRECT},
1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct1}};
1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_INVERSE_LIKE_DIRECT_WITH_MARKS =
1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  The case handled in this table is (visually):  R EN L
1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     0 , s(6,3),     0 ,     1 ,     0 ,     0 ,     0 ,  0 },
1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L+AN       */ {     0 , s(6,3),     0 ,     1 , s(1,2), s(3,0),     0 ,  4 },
1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : L+AN+ON    */ { s(2,0), s(6,3), s(2,0),     1 ,     2 , s(3,0), s(2,0),  3 },
1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : R          */ {     0 , s(6,3), s(5,5), s(5,6), s(1,4), s(3,0),     0 ,  3 },
1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : R+ON       */ { s(3,0), s(4,3), s(5,5), s(5,6),     4 , s(3,0), s(3,0),  3 },
1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : R+EN       */ { s(3,0), s(4,3),     5 , s(5,6), s(1,4), s(3,0), s(3,0),  4 },
1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 6 : R+AN       */ { s(3,0), s(4,3), s(5,5),     6 , s(1,4), s(3,0), s(3,0),  4 }
1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS =
1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  The cases handled in this table are (visually):  R EN L
1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                     R L AN L
1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ { s(1,3),     0 ,     1 ,     1 ,     0 ,     0 ,     0 ,  0 },
1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : R+EN/AN    */ { s(2,3),     0 ,     1 ,     1 ,     2 , s(4,0),     0 ,  1 },
1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : R+EN/AN+ON */ { s(2,3),     0 ,     1 ,     1 ,     2 , s(4,0),     0 ,  0 },
1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : L          */ {     3 ,     0 ,     3 , s(3,6), s(1,4), s(4,0),     0 ,  1 },
1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : L+ON       */ { s(5,3), s(4,0),     5 , s(3,6),     4 , s(4,0), s(4,0),  0 },
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 5 : L+ON+EN    */ { s(5,3), s(4,0),     5 , s(3,6),     4 , s(4,0), s(4,0),  1 },
1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 6 : L+AN       */ { s(5,3), s(4,0),     6 ,     6 ,     4 , s(4,0), s(4,0),  3 }
1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpAct impAct2 = {0,1,7,8,9,10};
1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_INVERSE_LIKE_DIRECT_WITH_MARKS = {
1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_INVERSE_LIKE_DIRECT_WITH_MARKS,
1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS},
1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct2}};
1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_INVERSE_FOR_NUMBERS_SPECIAL = {
1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_NUMBERS_SPECIAL,
1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_INVERSE_LIKE_DIRECT},
1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct1}};
1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTab impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS =
1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*  The case handled in this table is (visually):  R EN L
1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/
1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*                         L ,     R ,    EN ,    AN ,    ON ,     S ,     B , Res */
1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 0 : init       */ {     0 , s(6,2),     1 ,     1 ,     0 ,     0 ,     0 ,  0 },
1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 1 : L+EN/AN    */ {     0 , s(6,2),     1 ,     1 ,     0 , s(3,0),     0 ,  4 },
1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2 : R          */ {     0 , s(6,2), s(5,4), s(5,4), s(1,3), s(3,0),     0 ,  3 },
1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 3 : R+ON       */ { s(3,0), s(4,2), s(5,4), s(5,4),     3 , s(3,0), s(3,0),  3 },
1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 4 : R+EN/AN    */ { s(3,0), s(4,2),     4 ,     4 , s(1,3), s(3,0), s(3,0),  4 }
1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const ImpTabPair impTab_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS = {
1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impTabL_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS,
1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         &impTabR_INVERSE_LIKE_DIRECT_WITH_MARKS},
1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        {&impAct0, &impAct2}};
1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#undef s
1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef struct {
1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const ImpTab * pImpTab;             /* level table pointer          */
1130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const ImpAct * pImpAct;             /* action map array             */
1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t startON;                    /* start of ON sequence         */
1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t startL2EN;                  /* start of level 2 sequence    */
1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t lastStrongRTL;              /* index of last found R or AL  */
1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t state;                      /* current state                */
1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel runLevel;                /* run level before implicit solving */
1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} LevState;
1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*------------------------------------------------------------------------*/
1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottaddPoint(UBiDi *pBiDi, int32_t pos, int32_t flag)
1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  /* param pos:     position where to insert
1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     param flag:    one of LRM_BEFORE, LRM_AFTER, RLM_BEFORE, RLM_AFTER
1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  */
1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
1146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define FIRSTALLOC  10
1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Point point;
1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    InsertPoints * pInsertPoints=&(pBiDi->insertPoints);
1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pInsertPoints->capacity == 0)
1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pInsertPoints->points=uprv_malloc(sizeof(Point)*FIRSTALLOC);
1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (pInsertPoints->points == NULL)
1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        {
1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->errorCode=U_MEMORY_ALLOCATION_ERROR;
1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pInsertPoints->capacity=FIRSTALLOC;
1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (pInsertPoints->size >= pInsertPoints->capacity) /* no room for new point */
1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        void * savePoints=pInsertPoints->points;
1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pInsertPoints->points=uprv_realloc(pInsertPoints->points,
1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           pInsertPoints->capacity*2*sizeof(Point));
1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (pInsertPoints->points == NULL)
1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        {
1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->points=savePoints;
1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->errorCode=U_MEMORY_ALLOCATION_ERROR;
1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        else  pInsertPoints->capacity*=2;
1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    point.pos=pos;
1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    point.flag=flag;
1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pInsertPoints->points[pInsertPoints->size]=point;
1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pInsertPoints->size++;
1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#undef FIRSTALLOC
1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */
1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This implementation of the (Wn) rules applies all rules in one pass.
1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * In order to do so, it needs a look-ahead of typically 1 character
1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * (except for W5: sequences of ET) and keeps track of changes
1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * in a rule Wp that affect a later Wq (p<q).
1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The (Nn) and (In) rules are also performed in that same single loop,
1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * but effectively one iteration behind for white space.
1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *
1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Since all implicit rules are performed in one step, it is not necessary
1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * to actually store the intermediate directional properties in dirProps[].
1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottprocessPropertySeq(UBiDi *pBiDi, LevState *pLevState, uint8_t _prop,
1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   int32_t start, int32_t limit) {
1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint8_t cell, oldStateSeq, actionSeq;
1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const ImpTab * pImpTab=pLevState->pImpTab;
1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const ImpAct * pImpAct=pLevState->pImpAct;
1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel * levels=pBiDi->levels;
1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel level, addLevel;
1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    InsertPoints * pInsertPoints;
1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t start0, k;
1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    start0=start;                           /* save original start position */
1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    oldStateSeq=(uint8_t)pLevState->state;
1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cell=(*pImpTab)[oldStateSeq][_prop];
1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pLevState->state=GET_STATE(cell);       /* isolate the new state */
1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    actionSeq=(*pImpAct)[GET_ACTION(cell)]; /* isolate the action */
1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addLevel=(*pImpTab)[pLevState->state][IMPTABLEVELS_RES];
1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(actionSeq) {
1214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        switch(actionSeq) {
1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 1:                         /* init ON seq */
1216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startON=start0;
1217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 2:                         /* prepend ON seq to current seq */
1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            start=pLevState->startON;
1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 3:                         /* L or S after possible relevant EN/AN */
1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* check if we had EN after R/AL */
1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (pLevState->startL2EN >= 0) {
1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addPoint(pBiDi, pLevState->startL2EN, LRM_BEFORE);
1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startL2EN=-1;  /* not within previous if since could also be -2 */
1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* check if we had any relevant EN/AN after R/AL */
1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints=&(pBiDi->insertPoints);
1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if ((pInsertPoints->capacity == 0) ||
1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                (pInsertPoints->size <= pInsertPoints->confirmed))
1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            {
1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* nothing, just clean up */
1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pLevState->lastStrongRTL=-1;
1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* check if we have a pending conditional segment */
1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                level=(*pImpTab)[oldStateSeq][IMPTABLEVELS_RES];
1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if ((level & 1) && (pLevState->startON > 0)) {  /* after ON */
1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    start=pLevState->startON;   /* reset to basic run level */
1240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if (_prop == DirProp_S)                /* add LRM before S */
1242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                {
1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    addPoint(pBiDi, start0, LRM_BEFORE);
1244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    pInsertPoints->confirmed=pInsertPoints->size;
1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* reset previous RTL cont to level for LTR text */
1249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for (k=pLevState->lastStrongRTL+1; k<start0; k++)
1250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            {
1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* reset odd level, leave runLevel+2 as is */
1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                levels[k]=(levels[k] - 2) & ~1;
1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* mark insert points as confirmed */
1255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->confirmed=pInsertPoints->size;
1256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->lastStrongRTL=-1;
1257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (_prop == DirProp_S)            /* add LRM before S */
1258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            {
1259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addPoint(pBiDi, start0, LRM_BEFORE);
1260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pInsertPoints->confirmed=pInsertPoints->size;
1261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 4:                         /* R/AL after possible relevant EN/AN */
1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* just clean up */
1266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints=&(pBiDi->insertPoints);
1267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (pInsertPoints->capacity > 0)
1268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* remove all non confirmed insert points */
1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pInsertPoints->size=pInsertPoints->confirmed;
1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startON=-1;
1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startL2EN=-1;
1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->lastStrongRTL=limit - 1;
1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 5:                         /* EN/AN after R/AL + possible cont */
1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* check for real AN */
1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if ((_prop == DirProp_AN) && (NO_CONTEXT_RTL(pBiDi->dirProps[start0]) == AN) &&
1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                (pBiDi->reorderingMode!=UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL))
1279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            {
1280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* real AN */
1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if (pLevState->startL2EN == -1) /* if no relevant EN already found */
1282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                {
1283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* just note the righmost digit as a strong RTL */
1284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    pLevState->lastStrongRTL=limit - 1;
1285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    break;
1286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if (pLevState->startL2EN >= 0)  /* after EN, no AN */
1288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                {
1289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    addPoint(pBiDi, pLevState->startL2EN, LRM_BEFORE);
1290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    pLevState->startL2EN=-2;
1291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* note AN */
1293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addPoint(pBiDi, start0, LRM_BEFORE);
1294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* if first EN/AN after R/AL */
1297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (pLevState->startL2EN == -1) {
1298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pLevState->startL2EN=start0;
1299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 6:                         /* note location of latest R/AL */
1303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->lastStrongRTL=limit - 1;
1304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startON=-1;
1305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 7:                         /* L after R+ON/EN/AN */
1308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* include possible adjacent number on the left */
1309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for (k=start0-1; k>=0 && !(levels[k]&1); k--);
1310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(k>=0) {
1311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addPoint(pBiDi, k, RLM_BEFORE);             /* add RLM before */
1312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pInsertPoints=&(pBiDi->insertPoints);
1313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pInsertPoints->confirmed=pInsertPoints->size;   /* confirm it */
1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startON=start0;
1316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 8:                         /* AN after L */
1319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* AN numbers between L text on both sides may be trouble. */
1320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* tentatively bracket with LRMs; will be confirmed if followed by L */
1321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            addPoint(pBiDi, start0, LRM_BEFORE);    /* add LRM before */
1322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            addPoint(pBiDi, start0, LRM_AFTER);     /* add LRM after  */
1323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 9:                         /* R after L+ON/EN/AN */
1326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* false alert, infirm LRMs around previous AN */
1327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints=&(pBiDi->insertPoints);
1328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->size=pInsertPoints->confirmed;
1329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (_prop == DirProp_S)            /* add RLM before S */
1330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            {
1331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addPoint(pBiDi, start0, RLM_BEFORE);
1332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pInsertPoints->confirmed=pInsertPoints->size;
1333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 10:                        /* L after L+ON/AN */
1337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            level=pLevState->runLevel + addLevel;
1338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for(k=pLevState->startON; k<start0; k++) {
1339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if (levels[k]<level)
1340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[k]=level;
1341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints=&(pBiDi->insertPoints);
1343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pInsertPoints->confirmed=pInsertPoints->size;   /* confirm inserts */
1344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pLevState->startON=start0;
1345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 11:                        /* L after L+ON+EN/AN/ON */
1348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            level=pLevState->runLevel;
1349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for(k=start0-1; k>=pLevState->startON; k--) {
1350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(levels[k]==level+3) {
1351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    while(levels[k]==level+3) {
1352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        levels[k--]-=2;
1353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
1354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    while(levels[k]==level) {
1355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        k--;
1356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
1357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(levels[k]==level+2) {
1359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[k]=level;
1360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    continue;
1361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                levels[k]=level+1;
1363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case 12:                        /* R after L+ON+EN/AN/ON */
1367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            level=pLevState->runLevel+1;
1368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for(k=start0-1; k>=pLevState->startON; k--) {
1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(levels[k]>level) {
1370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[k]-=2;
1371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        default:                        /* we should never get here */
1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            U_ASSERT(FALSE);
1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if((addLevel) || (start < start0)) {
1381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        level=pLevState->runLevel + addLevel;
1382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(k=start; k<limit; k++) {
1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            levels[k]=level;
1384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
1389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottresolveImplicitLevels(UBiDi *pBiDi,
1390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      int32_t start, int32_t limit,
1391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      DirProp sor, DirProp eor) {
1392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DirProp *dirProps=pBiDi->dirProps;
1393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LevState levState;
1395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t i, start1, start2;
1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint8_t oldStateImp, stateImp, actionImp;
1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint8_t gprop, resProp, cell;
1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool inverseRTL;
1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DirProp nextStrongProp=R;
1400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t nextStrongPos=-1;
1401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.startON = -1;  /* silence gcc flow analysis */
1403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check for RTL inverse BiDi mode */
1405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* FOOD FOR THOUGHT: in case of RTL inverse BiDi, it would make sense to
1406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * loop on the text characters from end to start.
1407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * This would need a different properties state table (at least different
1408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * actions) and different levels state tables (maybe very similar to the
1409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * LTR corresponding ones.
1410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    inverseRTL=(UBool)
1412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ((start<pBiDi->lastArabicPos) && (GET_PARALEVEL(pBiDi, start) & 1) &&
1413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         (pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT  ||
1414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL));
1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* initialize for levels state table */
1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.startL2EN=-1;              /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.lastStrongRTL=-1;          /* used for INVERSE_LIKE_DIRECT_WITH_MARKS */
1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.state=0;
1419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.runLevel=pBiDi->levels[start];
1420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.pImpTab=(const ImpTab*)((pBiDi->pImpTabPair)->pImpTab)[levState.runLevel&1];
1421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levState.pImpAct=(const ImpAct*)((pBiDi->pImpTabPair)->pImpAct)[levState.runLevel&1];
1422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    processPropertySeq(pBiDi, &levState, sor, start, start);
1423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* initialize for property state table */
1424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(dirProps[start]==NSM) {
1425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        stateImp = 1 + sor;
1426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        stateImp=0;
1428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    start1=start;
1430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    start2=start;
1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for(i=start; i<=limit; i++) {
1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(i>=limit) {
1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            gprop=eor;
1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            DirProp prop, prop1;
1437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            prop=NO_CONTEXT_RTL(dirProps[i]);
1438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(inverseRTL) {
1439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(prop==AL) {
1440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* AL before EN does not make it AN */
1441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    prop=R;
1442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if(prop==EN) {
1443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(nextStrongPos<=i) {
1444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        /* look for next strong char (L/R/AL) */
1445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        int32_t j;
1446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        nextStrongProp=R;   /* set default */
1447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        nextStrongPos=limit;
1448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        for(j=i+1; j<limit; j++) {
1449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            prop1=NO_CONTEXT_RTL(dirProps[j]);
1450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            if(prop1==L || prop1==R || prop1==AL) {
1451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                nextStrongProp=prop1;
1452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                nextStrongPos=j;
1453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                break;
1454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            }
1455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        }
1456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
1457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(nextStrongProp==AL) {
1458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        prop=AN;
1459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
1460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            gprop=groupProp[prop];
1463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        oldStateImp=stateImp;
1465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cell=impTabProps[oldStateImp][gprop];
1466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        stateImp=GET_STATEPROPS(cell);      /* isolate the new state */
1467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        actionImp=GET_ACTIONPROPS(cell);    /* isolate the action */
1468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if((i==limit) && (actionImp==0)) {
1469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* there is an unprocessed sequence if its property == eor   */
1470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            actionImp=1;                    /* process the last sequence */
1471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(actionImp) {
1473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            resProp=impTabProps[oldStateImp][IMPTABPROPS_RES];
1474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            switch(actionImp) {
1475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case 1:             /* process current seq1, init new seq1 */
1476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                processPropertySeq(pBiDi, &levState, resProp, start1, i);
1477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start1=i;
1478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case 2:             /* init new seq2 */
1480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start2=i;
1481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case 3:             /* process seq1, process seq2, init new seq1 */
1483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                processPropertySeq(pBiDi, &levState, resProp, start1, start2);
1484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                processPropertySeq(pBiDi, &levState, DirProp_ON, start2, i);
1485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start1=i;
1486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            case 4:             /* process seq1, set seq1=seq2, init new seq2 */
1488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                processPropertySeq(pBiDi, &levState, resProp, start1, start2);
1489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start1=start2;
1490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start2=i;
1491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            default:            /* we should never get here */
1493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                U_ASSERT(FALSE);
1494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                break;
1495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* flush possible pending sequence, e.g. ON */
1499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    processPropertySeq(pBiDi, &levState, eor, limit, limit);
1500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* perform (L1) and (X9) ---------------------------------------------------- */
1503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/*
1505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Reset the embedding levels for some non-graphic characters (L1).
1506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * This function also sets appropriate levels for BN, and
1507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * explicit embedding types that are supposed to have been removed
1508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * from the paragraph in (X9).
1509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */
1510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
1511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottadjustWSLevels(UBiDi *pBiDi) {
1512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DirProp *dirProps=pBiDi->dirProps;
1513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel *levels=pBiDi->levels;
1514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t i;
1515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->flags&MASK_WS) {
1517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        UBool orderParagraphsLTR=pBiDi->orderParagraphsLTR;
1518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Flags flag;
1519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        i=pBiDi->trailingWSStart;
1521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        while(i>0) {
1522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* reset a sequence of WS/BN before eop and B/S to the paragraph paraLevel */
1523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            while(i>0 && (flag=DIRPROP_FLAG_NC(dirProps[--i]))&MASK_WS) {
1524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(orderParagraphsLTR&&(flag&DIRPROP_FLAG(B))) {
1525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[i]=0;
1526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
1527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[i]=GET_PARALEVEL(pBiDi, i);
1528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* reset BN to the next character's paraLevel until B/S, which restarts above loop */
1532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* here, i+1 is guaranteed to be <length */
1533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            while(i>0) {
1534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                flag=DIRPROP_FLAG_NC(dirProps[--i]);
1535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(flag&MASK_BN_EXPLICIT) {
1536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[i]=levels[i+1];
1537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if(orderParagraphsLTR&&(flag&DIRPROP_FLAG(B))) {
1538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[i]=0;
1539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    break;
1540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else if(flag&MASK_B_S) {
1541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    levels[i]=GET_PARALEVEL(pBiDi, i);
1542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    break;
1543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BIDI_MIN(x, y)   ((x)<(y) ? (x) : (y))
1550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BIDI_ABS(x)      ((x)>=0  ? (x) : (-(x)))
1551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void
1552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottsetParaRunsOnly(UBiDi *pBiDi, const UChar *text, int32_t length,
1553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                UBiDiLevel paraLevel, UErrorCode *pErrorCode) {
1554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void *runsOnlyMemory;
1555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t *visualMap;
1556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UChar *visualText;
1557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t saveLength, saveTrailingWSStart;
1558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const UBiDiLevel *levels;
1559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiLevel *saveLevels;
1560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiDirection saveDirection;
1561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBool saveMayAllocateText;
1562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Run *runs;
1563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t visualLength, i, j, visualStart, logicalStart,
1564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            runCount, runLength, addedRuns, insertRemove,
1565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            start, limit, step, indexOddBit, logicalPos,
1566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            index0, index1;
1567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint32_t saveOptions;
1568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->reorderingMode=UBIDI_REORDER_DEFAULT;
1570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(length==0) {
1571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        ubidi_setPara(pBiDi, text, length, paraLevel, NULL, pErrorCode);
1572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        goto cleanup3;
1573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* obtain memory for mapping table and visual text */
1575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    runsOnlyMemory=uprv_malloc(length*(sizeof(int32_t)+sizeof(UChar)+sizeof(UBiDiLevel)));
1576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(runsOnlyMemory==NULL) {
1577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        goto cleanup3;
1579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    visualMap=runsOnlyMemory;
1581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    visualText=(UChar *)&visualMap[length];
1582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveLevels=(UBiDiLevel *)&visualText[length];
1583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveOptions=pBiDi->reorderingOptions;
1584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(saveOptions & UBIDI_OPTION_INSERT_MARKS) {
1585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->reorderingOptions&=~UBIDI_OPTION_INSERT_MARKS;
1586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->reorderingOptions|=UBIDI_OPTION_REMOVE_CONTROLS;
1587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    paraLevel&=1;                       /* accept only 0 or 1 */
1589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ubidi_setPara(pBiDi, text, length, paraLevel, NULL, pErrorCode);
1590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(U_FAILURE(*pErrorCode)) {
1591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        goto cleanup3;
1592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* we cannot access directly pBiDi->levels since it is not yet set if
1594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * direction is not MIXED
1595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    levels=ubidi_getLevels(pBiDi, pErrorCode);
1597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_memcpy(saveLevels, levels, pBiDi->length*sizeof(UBiDiLevel));
1598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveTrailingWSStart=pBiDi->trailingWSStart;
1599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveLength=pBiDi->length;
1600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveDirection=pBiDi->direction;
1601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* FOOD FOR THOUGHT: instead of writing the visual text, we could use
1603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * the visual map and the dirProps array to drive the second call
1604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * to ubidi_setPara (but must make provision for possible removal of
1605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * BiDi controls.  Alternatively, only use the dirProps array via
1606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * customized classifier callback.
1607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    visualLength=ubidi_writeReordered(pBiDi, visualText, length,
1609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      UBIDI_DO_MIRRORING, pErrorCode);
1610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ubidi_getVisualMap(pBiDi, visualMap, pErrorCode);
1611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(U_FAILURE(*pErrorCode)) {
1612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        goto cleanup2;
1613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->reorderingOptions=saveOptions;
1615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->reorderingMode=UBIDI_REORDER_INVERSE_LIKE_DIRECT;
1617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    paraLevel^=1;
1618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* Because what we did with reorderingOptions, visualText may be shorter
1619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * than the original text. But we don't want the levels memory to be
1620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * reallocated shorter than the original length, since we need to restore
1621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * the levels as after the first call to ubidi_setpara() before returning.
1622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * We will force mayAllocateText to FALSE before the second call to
1623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * ubidi_setpara(), and will restore it afterwards.
1624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    saveMayAllocateText=pBiDi->mayAllocateText;
1626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->mayAllocateText=FALSE;
1627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ubidi_setPara(pBiDi, visualText, visualLength, paraLevel, NULL, pErrorCode);
1628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->mayAllocateText=saveMayAllocateText;
1629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ubidi_getRuns(pBiDi, pErrorCode);
1630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(U_FAILURE(*pErrorCode)) {
1631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        goto cleanup1;
1632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check if some runs must be split, count how many splits */
1634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    addedRuns=0;
1635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    runCount=pBiDi->runCount;
1636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    runs=pBiDi->runs;
1637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    visualStart=0;
1638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for(i=0; i<runCount; i++, visualStart+=runLength) {
1639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        runLength=runs[i].visualLimit-visualStart;
1640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(runLength<2) {
1641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            continue;
1642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        logicalStart=GET_INDEX(runs[i].logicalStart);
1644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(j=logicalStart+1; j<logicalStart+runLength; j++) {
1645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            index0=visualMap[j];
1646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            index1=visualMap[j-1];
1647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if((BIDI_ABS(index0-index1)!=1) || (saveLevels[index0]!=saveLevels[index1])) {
1648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addedRuns++;
1649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(addedRuns) {
1653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(getRunsMemory(pBiDi, runCount+addedRuns)) {
1654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(runCount==1) {
1655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* because we switch from UBiDi.simpleRuns to UBiDi.runs */
1656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->runsMemory[0]=runs[0];
1657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            runs=pBiDi->runs=pBiDi->runsMemory;
1659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->runCount+=addedRuns;
1660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            goto cleanup1;
1662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* split runs which are not consecutive in source text */
1665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for(i=runCount-1; i>=0; i--) {
1666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        runLength= i==0 ? runs[0].visualLimit :
1667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          runs[i].visualLimit-runs[i-1].visualLimit;
1668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        logicalStart=runs[i].logicalStart;
1669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        indexOddBit=GET_ODD_BIT(logicalStart);
1670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        logicalStart=GET_INDEX(logicalStart);
1671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(runLength<2) {
1672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(addedRuns) {
1673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i+addedRuns]=runs[i];
1674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            logicalPos=visualMap[logicalStart];
1676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            runs[i+addedRuns].logicalStart=MAKE_INDEX_ODD_PAIR(logicalPos,
1677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            saveLevels[logicalPos]^indexOddBit);
1678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            continue;
1679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(indexOddBit) {
1681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            start=logicalStart;
1682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            limit=logicalStart+runLength-1;
1683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            step=1;
1684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            start=logicalStart+runLength-1;
1686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            limit=logicalStart;
1687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            step=-1;
1688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(j=start; j!=limit; j+=step) {
1690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            index0=visualMap[j];
1691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            index1=visualMap[j+step];
1692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if((BIDI_ABS(index0-index1)!=1) || (saveLevels[index0]!=saveLevels[index1])) {
1693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                logicalPos=BIDI_MIN(visualMap[start], index0);
1694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i+addedRuns].logicalStart=MAKE_INDEX_ODD_PAIR(logicalPos,
1695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            saveLevels[logicalPos]^indexOddBit);
1696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i+addedRuns].visualLimit=runs[i].visualLimit;
1697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i].visualLimit-=BIDI_ABS(j-start)+1;
1698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                insertRemove=runs[i].insertRemove&(LRM_AFTER|RLM_AFTER);
1699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i+addedRuns].insertRemove=insertRemove;
1700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                runs[i].insertRemove&=~insertRemove;
1701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start=j+step;
1702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                addedRuns--;
1703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(addedRuns) {
1706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            runs[i+addedRuns]=runs[i];
1707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        logicalPos=BIDI_MIN(visualMap[start], visualMap[limit]);
1709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        runs[i+addedRuns].logicalStart=MAKE_INDEX_ODD_PAIR(logicalPos,
1710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                            saveLevels[logicalPos]^indexOddBit);
1711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cleanup1:
1714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* restore initial paraLevel */
1715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->paraLevel^=1;
1716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cleanup2:
1717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* restore real text */
1718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->text=text;
1719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->length=saveLength;
1720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->originalLength=length;
1721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->direction=saveDirection;
1722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* the saved levels should never excess levelsSize, but we check anyway */
1723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(saveLength>pBiDi->levelsSize) {
1724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        saveLength=pBiDi->levelsSize;
1725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_memcpy(pBiDi->levels, saveLevels, saveLength*sizeof(UBiDiLevel));
1727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->trailingWSStart=saveTrailingWSStart;
1728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* free memory for mapping table and visual text */
1729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uprv_free(runsOnlyMemory);
1730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->runCount>1) {
1731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->direction=UBIDI_MIXED;
1732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cleanup3:
1734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->reorderingMode=UBIDI_REORDER_RUNS_ONLY;
1735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* ubidi_setPara ------------------------------------------------------------ */
1738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
1740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
1741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
1742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              UErrorCode *pErrorCode) {
1743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UBiDiDirection direction;
1744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check the argument values */
1746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
1747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi==NULL || text==NULL || length<-1 ||
1748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       (paraLevel>UBIDI_MAX_EXPLICIT_LEVEL && paraLevel<UBIDI_DEFAULT_LTR)) {
1749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
1750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
1751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(length==-1) {
1754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        length=u_strlen(text);
1755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* special treatment for RUNS_ONLY mode */
1758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->reorderingMode==UBIDI_REORDER_RUNS_ONLY) {
1759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        setParaRunsOnly(pBiDi, text, length, paraLevel, pErrorCode);
1760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
1761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* initialize the UBiDi structure */
1764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->pParaBiDi=NULL;          /* mark unfinished setPara */
1765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->text=text;
1766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->length=pBiDi->originalLength=pBiDi->resultLength=length;
1767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->paraLevel=paraLevel;
1768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->direction=UBIDI_LTR;
1769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->paraCount=1;
1770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->dirProps=NULL;
1772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->levels=NULL;
1773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->runs=NULL;
1774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->insertPoints.size=0;         /* clean up from last call */
1775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->insertPoints.confirmed=0;    /* clean up from last call */
1776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /*
1778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * Save the original paraLevel if contextual; otherwise, set to 0.
1779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_DEFAULT_LEVEL(paraLevel)) {
1781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->defaultParaLevel=paraLevel;
1782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->defaultParaLevel=0;
1784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(length==0) {
1787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /*
1788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * For an empty paragraph, create a UBiDi object with the paraLevel and
1789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * the flags and the direction set but without allocating zero-length arrays.
1790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * There is nothing more to do.
1791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         */
1792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(IS_DEFAULT_LEVEL(paraLevel)) {
1793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->paraLevel&=1;
1794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->defaultParaLevel=0;
1795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(paraLevel&1) {
1797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->flags=DIRPROP_FLAG(R);
1798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->direction=UBIDI_RTL;
1799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->flags=DIRPROP_FLAG(L);
1801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->direction=UBIDI_LTR;
1802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->runCount=0;
1805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->paraCount=0;
1806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->pParaBiDi=pBiDi;         /* mark successful setPara */
1807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
1808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->runCount=-1;
1811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /*
1813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * Get the directional properties,
1814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * the flags bit-set, and
1815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * determine the paragraph level if necessary.
1816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(getDirPropsMemory(pBiDi, length)) {
1818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->dirProps=pBiDi->dirPropsMemory;
1819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        getDirProps(pBiDi);
1820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
1823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* the processed length may have changed if UBIDI_OPTION_STREAMING */
1825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    length= pBiDi->length;
1826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->trailingWSStart=length;  /* the levels[] will reflect the WS run */
1827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* allocate paras memory */
1828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->paraCount>1) {
1829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(getInitialParasMemory(pBiDi, pBiDi->paraCount)) {
1830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->paras=pBiDi->parasMemory;
1831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->paras[pBiDi->paraCount-1]=length;
1832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* initialize paras for single paragraph */
1838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->paras=pBiDi->simpleParas;
1839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->simpleParas[0]=length;
1840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* are explicit levels specified? */
1843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(embeddingLevels==NULL) {
1844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* no: determine explicit levels according to the (Xn) rules */\
1845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(getLevelsMemory(pBiDi, length)) {
1846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->levels=pBiDi->levelsMemory;
1847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            direction=resolveExplicitLevels(pBiDi);
1848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
1850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
1853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* set BN for all explicit codes, check that all levels are 0 or paraLevel..UBIDI_MAX_EXPLICIT_LEVEL */
1854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->levels=embeddingLevels;
1855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        direction=checkExplicitLevels(pBiDi, pErrorCode);
1856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(U_FAILURE(*pErrorCode)) {
1857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /*
1862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * The steps after (X9) in the UBiDi algorithm are performed only if
1863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * the paragraph text has mixed directionality!
1864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
1865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->direction=direction;
1866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switch(direction) {
1867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case UBIDI_LTR:
1868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* make sure paraLevel is even */
1869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
1870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
1872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->trailingWSStart=0;
1873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
1874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case UBIDI_RTL:
1875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* make sure paraLevel is odd */
1876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->paraLevel|=1;
1877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
1879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->trailingWSStart=0;
1880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
1881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
1882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /*
1883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         *  Choose the right implicit state table
1884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         */
1885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        switch(pBiDi->reorderingMode) {
1886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_DEFAULT:
1887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->pImpTabPair=&impTab_DEFAULT;
1888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_NUMBERS_SPECIAL:
1890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->pImpTabPair=&impTab_NUMBERS_SPECIAL;
1891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_GROUP_NUMBERS_WITH_R:
1893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->pImpTabPair=&impTab_GROUP_NUMBERS_WITH_R;
1894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_INVERSE_NUMBERS_AS_L:
1896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            pBiDi->pImpTabPair=&impTab_INVERSE_NUMBERS_AS_L;
1897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_INVERSE_LIKE_DIRECT:
1899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
1900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->pImpTabPair=&impTab_INVERSE_LIKE_DIRECT_WITH_MARKS;
1901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } else {
1902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->pImpTabPair=&impTab_INVERSE_LIKE_DIRECT;
1903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        case UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL:
1906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if (pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) {
1907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->pImpTabPair=&impTab_INVERSE_FOR_NUMBERS_SPECIAL_WITH_MARKS;
1908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } else {
1909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                pBiDi->pImpTabPair=&impTab_INVERSE_FOR_NUMBERS_SPECIAL;
1910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        default:
1913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* we should never get here */
1914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            U_ASSERT(FALSE);
1915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            break;
1916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /*
1918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * If there are no external levels specified and there
1919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * are no significant explicit level codes in the text,
1920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * then we can treat the entire paragraph as one run.
1921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * Otherwise, we need to perform the following rules on runs of
1922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * the text with the same embedding levels. (X10)
1923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * "Significant" explicit level codes are ones that actually
1924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * affect non-BN characters.
1925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * Examples for "insignificant" ones are empty embeddings
1926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         * LRE-PDF, LRE-RLE-PDF-PDF, etc.
1927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         */
1928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if(embeddingLevels==NULL && pBiDi->paraCount<=1 &&
1929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
1930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            resolveImplicitLevels(pBiDi, 0, length,
1931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, 0)),
1932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, length-1)));
1933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        } else {
1934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* sor, eor: start and end types of same-level-run */
1935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            UBiDiLevel *levels=pBiDi->levels;
1936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            int32_t start, limit=0;
1937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            UBiDiLevel level, nextLevel;
1938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            DirProp sor, eor;
1939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            /* determine the first sor and set eor to it because of the loop body (sor=eor there) */
1941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            level=GET_PARALEVEL(pBiDi, 0);
1942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            nextLevel=levels[0];
1943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if(level<nextLevel) {
1944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                eor=GET_LR_FROM_LEVEL(nextLevel);
1945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } else {
1946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                eor=GET_LR_FROM_LEVEL(level);
1947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
1948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            do {
1950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* determine start and limit of the run (end points just behind the run) */
1951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* the values for this run's start are the same as for the previous run's end */
1953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                start=limit;
1954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                level=nextLevel;
1955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if((start>0) && (NO_CONTEXT_RTL(pBiDi->dirProps[start-1])==B)) {
1956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* except if this is a new paragraph, then set sor = para level */
1957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    sor=GET_LR_FROM_LEVEL(GET_PARALEVEL(pBiDi, start));
1958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
1959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    sor=eor;
1960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* search for the limit of this run */
1963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                while(++limit<length && levels[limit]==level) {}
1964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* get the correct level of the next run */
1966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(limit<length) {
1967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    nextLevel=levels[limit];
1968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
1969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    nextLevel=GET_PARALEVEL(pBiDi, length-1);
1970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* determine eor from max(level, nextLevel); sor is last run's eor */
1973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
1974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    eor=GET_LR_FROM_LEVEL(nextLevel);
1975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
1976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    eor=GET_LR_FROM_LEVEL(level);
1977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                /* if the run consists of overridden directional types, then there
1980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   are no implicit types to be resolved */
1981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(!(level&UBIDI_LEVEL_OVERRIDE)) {
1982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    resolveImplicitLevels(pBiDi, start, limit, sor, eor);
1983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                } else {
1984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    /* remove the UBIDI_LEVEL_OVERRIDE flags */
1985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    do {
1986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
1987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    } while(start<limit);
1988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
1989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            } while(limit<length);
1990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* check if we got any memory shortage while adding insert points */
1992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (U_FAILURE(pBiDi->insertPoints.errorCode))
1993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        {
1994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            *pErrorCode=pBiDi->insertPoints.errorCode;
1995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            return;
1996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
1997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        /* reset the embedding levels for some non-graphic characters (L1), (X9) */
1998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        adjustWSLevels(pBiDi);
1999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
2000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* add RLM for inverse Bidi with contextual orientation resolving
2002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     * to RTL which would not round-trip otherwise
2003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott     */
2004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if((pBiDi->defaultParaLevel>0) &&
2005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       (pBiDi->reorderingOptions & UBIDI_OPTION_INSERT_MARKS) &&
2006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ((pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_LIKE_DIRECT) ||
2007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (pBiDi->reorderingMode==UBIDI_REORDER_INVERSE_FOR_NUMBERS_SPECIAL))) {
2008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int32_t i, j, start, last;
2009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DirProp dirProp;
2010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        for(i=0; i<pBiDi->paraCount; i++) {
2011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            last=pBiDi->paras[i]-1;
2012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            if((pBiDi->dirProps[last] & CONTEXT_RTL)==0) {
2013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                continue;           /* LTR paragraph */
2014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
2015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            start= i==0 ? 0 : pBiDi->paras[i - 1];
2016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            for(j=last; j>=start; j--) {
2017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                dirProp=NO_CONTEXT_RTL(pBiDi->dirProps[j]);
2018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(dirProp==L) {
2019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    if(j<last) {
2020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        while(NO_CONTEXT_RTL(pBiDi->dirProps[last])==B) {
2021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            last--;
2022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                        }
2023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    }
2024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    addPoint(pBiDi, last, RLM_BEFORE);
2025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    break;
2026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
2027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                if(DIRPROP_FLAG(dirProp) & MASK_R_AL) {
2028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    break;
2029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                }
2030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            }
2031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        }
2032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi->reorderingOptions & UBIDI_OPTION_REMOVE_CONTROLS) {
2035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->resultLength -= pBiDi->controlCount;
2036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->resultLength += pBiDi->insertPoints.size;
2038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->pParaBiDi=pBiDi;             /* mark successful setPara */
2040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
2043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_orderParagraphsLTR(UBiDi *pBiDi, UBool orderParagraphsLTR) {
2044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi!=NULL) {
2045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pBiDi->orderParagraphsLTR=orderParagraphsLTR;
2046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBool U_EXPORT2
2050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_isOrderParagraphsLTR(UBiDi *pBiDi) {
2051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi!=NULL) {
2052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->orderParagraphsLTR;
2053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return FALSE;
2055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBiDiDirection U_EXPORT2
2059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getDirection(const UBiDi *pBiDi) {
2060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->direction;
2062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return UBIDI_LTR;
2064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI const UChar * U_EXPORT2
2068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getText(const UBiDi *pBiDi) {
2069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->text;
2071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return NULL;
2073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
2077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getLength(const UBiDi *pBiDi) {
2078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->originalLength;
2080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
2082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
2086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getProcessedLength(const UBiDi *pBiDi) {
2087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->length;
2089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
2091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
2095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getResultLength(const UBiDi *pBiDi) {
2096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->resultLength;
2098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
2100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* paragraphs API functions ------------------------------------------------- */
2104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UBiDiLevel U_EXPORT2
2106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getParaLevel(const UBiDi *pBiDi) {
2107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(IS_VALID_PARA_OR_LINE(pBiDi)) {
2108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->paraLevel;
2109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
2111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
2115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_countParagraphs(UBiDi *pBiDi) {
2116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(!IS_VALID_PARA_OR_LINE(pBiDi)) {
2117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return 0;
2118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return pBiDi->paraCount;
2120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
2124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getParagraphByIndex(const UBiDi *pBiDi, int32_t paraIndex,
2125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          int32_t *pParaStart, int32_t *pParaLimit,
2126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          UBiDiLevel *pParaLevel, UErrorCode *pErrorCode) {
2127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int32_t paraStart;
2128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check the argument values */
2130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
2131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode);
2132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_VOID_IF_BAD_RANGE(paraIndex, 0, pBiDi->paraCount, *pErrorCode);
2133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi=pBiDi->pParaBiDi;             /* get Para object if Line object */
2135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(paraIndex) {
2136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        paraStart=pBiDi->paras[paraIndex-1];
2137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        paraStart=0;
2139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pParaStart!=NULL) {
2141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pParaStart=paraStart;
2142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pParaLimit!=NULL) {
2144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pParaLimit=pBiDi->paras[paraIndex];
2145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pParaLevel!=NULL) {
2147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pParaLevel=GET_PARALEVEL(pBiDi, paraStart);
2148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI int32_t U_EXPORT2
2152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getParagraph(const UBiDi *pBiDi, int32_t charIndex,
2153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          int32_t *pParaStart, int32_t *pParaLimit,
2154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          UBiDiLevel *pParaLevel, UErrorCode *pErrorCode) {
2155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uint32_t paraIndex;
2156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* check the argument values */
2158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    /* pErrorCode will be checked by the call to ubidi_getParagraphByIndex */
2159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrorCode, -1);
2160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_IF_NOT_VALID_PARA_OR_LINE(pBiDi, *pErrorCode, -1);
2161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi=pBiDi->pParaBiDi;             /* get Para object if Line object */
2162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_IF_BAD_RANGE(charIndex, 0, pBiDi->length, *pErrorCode, -1);
2163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for(paraIndex=0; charIndex>=pBiDi->paras[paraIndex]; paraIndex++);
2165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ubidi_getParagraphByIndex(pBiDi, paraIndex, pParaStart, pParaLimit, pParaLevel, pErrorCode);
2166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return paraIndex;
2167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
2170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_setClassCallback(UBiDi *pBiDi, UBiDiClassCallback *newFn,
2171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       const void *newContext, UBiDiClassCallback **oldFn,
2172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       const void **oldContext, UErrorCode *pErrorCode)
2173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
2174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrorCode);
2175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi==NULL) {
2176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
2177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
2178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if( oldFn )
2180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
2181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *oldFn = pBiDi->fnClassCallback;
2182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if( oldContext )
2184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
2185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *oldContext = pBiDi->coClassCallback;
2186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->fnClassCallback = newFn;
2188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pBiDi->coClassCallback = newContext;
2189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI void U_EXPORT2
2192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getClassCallback(UBiDi *pBiDi, UBiDiClassCallback **fn, const void **context)
2193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
2194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if(pBiDi==NULL) {
2195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return;
2196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if( fn )
2198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
2199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *fn = pBiDi->fnClassCallback;
2200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if( context )
2202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
2203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        *context = pBiDi->coClassCallback;
2204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CAPI UCharDirection U_EXPORT2
2208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottubidi_getCustomizedClass(UBiDi *pBiDi, UChar32 c)
2209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{
2210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    UCharDirection dir;
2211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if( pBiDi->fnClassCallback == NULL ||
2213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        (dir = (*pBiDi->fnClassCallback)(pBiDi->coClassCallback, c)) == U_BIDI_CLASS_DEFAULT )
2214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
2215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ubidi_getClass(pBiDi->bdp, c);
2216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
2217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return dir;
2218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2221