jdk/src/share/native/sun/font/bidi/ubidi.c
author peytoia
Mon, 08 Sep 2008 10:44:57 +0900
changeset 1310 edc39463f896
parent 2 90ce3da70b43
child 1639 a97859015238
permissions -rw-r--r--
6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct Reviewed-by: okutsu
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Portions Copyright 2000-2004 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * (C) Copyright IBM Corp. 1999-2003 - All Rights Reserved
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * The original version of this source code and documentation is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 * copyrighted and owned by IBM. These materials are provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * under terms of a License Agreement between IBM and Sun.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * This technology is protected by multiple US and International
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * patents. This notice and attribution to IBM may not be removed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
******************************************************************************
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
*   file name:  ubidi.c
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
*   encoding:   US-ASCII
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
*   tab size:   8 (not used)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
*   indentation:4
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
*   created on: 1999jul27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
*   created by: Markus W. Scherer
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
/* set import/export definitions */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
#ifndef U_COMMON_IMPLEMENTATION
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
#   define U_COMMON_IMPLEMENTATION
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
#include "cmemory.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
#include "utypes.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
#include "uchardir.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
#include "ubidi.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
#include "ubidiimp.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * General implementation notes:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * Throughout the implementation, there are comments like (W2) that refer to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * rules of the BiDi algorithm in its version 5, in this example to the second
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * rule of the resolution of weak types.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * For handling surrogate pairs, where two UChar's form one "abstract" (or UTF-32)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * character according to UTF-16, the second UChar gets the directional property of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * the entire character assigned, while the first one gets a BN, a boundary
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * neutral, type, which is ignored by most of the algorithm according to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * rule (X9) and the implementation suggestions of the BiDi algorithm.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * Later, adjustWSLevels() will set the level for each BN to that of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * following character (UChar), which results in surrogate pairs getting the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * same level on each of their surrogates.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * In a UTF-8 implementation, the same thing could be done: the last byte of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * a multi-byte sequence would get the "real" property, while all previous
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * bytes of that sequence would get BN.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * It is not possible to assign all those parts of a character the same real
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * property because this would fail in the resolution of weak types with rules
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * that look at immediately surrounding types.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * As a related topic, this implementation does not remove Boundary Neutral
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * types from the input, but ignores them whereever this is relevant.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * For example, the loop for the resolution of the weak types reads
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * types until it finds a non-BN.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * Also, explicit embedding codes are neither changed into BN nor removed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * They are only treated the same way real BNs are.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * As stated before, adjustWSLevels() takes care of them at the end.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * For the purpose of conformance, the levels of all these codes
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * do not matter.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * Note that this implementation never modifies the dirProps
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * after the initial setup.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * In this implementation, the resolution of weak types (Wn),
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * neutrals (Nn), and the assignment of the resolved level (In)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * are all done in one single loop, in resolveImplicitLevels().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * Changes of dirProp values are done on the fly, without writing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * them back to the dirProps array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * This implementation contains code that allows to bypass steps of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * algorithm that are not needed on the specific paragraph
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * in order to speed up the most common cases considerably,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 * like text that is entirely LTR, or RTL text without numbers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
 * Most of this is done by setting a bit for each directional property
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 * in a flags variable and later checking for whether there are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * any LTR characters or any RTL characters, or both, whether
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * there are any explicit embedding codes, etc.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * If the (Xn) steps are performed, then the flags are re-evaluated,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 * because they will then not contain the embedding codes any more
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 * and will be adjusted for override codes, so that subsequently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 * more bypassing may be possible than what the initial flags suggested.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 * If the text is not mixed-directional, then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 * algorithm steps for the weak type resolution are not performed,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 * and all levels are set to the paragraph level.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
 * If there are no explicit embedding codes, then the (Xn) steps
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
 * are not performed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
 * If embedding levels are supplied as a parameter, then all
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
 * explicit embedding codes are ignored, and the (Xn) steps
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
 * are not performed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
 * White Space types could get the level of the run they belong to,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
 * and are checked with a test of (flags&MASK_EMBEDDING) to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
 * consider if the paragraph direction should be considered in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
 * the flags variable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
 * If there are no White Space types in the paragraph, then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
 * (L1) is not necessary in adjustWSLevels().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
/* prototypes --------------------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
getDirProps(UBiDi *pBiDi, const UChar *text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
resolveExplicitLevels(UBiDi *pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
directionFromFlags(Flags flags);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
resolveImplicitLevels(UBiDi *pBiDi,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                      int32_t start, int32_t limit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                      DirProp sor, DirProp eor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
adjustWSLevels(UBiDi *pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
/* to avoid some conditional statements, use tiny constant arrays */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
static const Flags flagLR[2]={ DIRPROP_FLAG(L), DIRPROP_FLAG(R) };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
static const Flags flagE[2]={ DIRPROP_FLAG(LRE), DIRPROP_FLAG(RLE) };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
static const Flags flagO[2]={ DIRPROP_FLAG(LRO), DIRPROP_FLAG(RLO) };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
#define DIRPROP_FLAG_LR(level) flagLR[(level)&1]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
#define DIRPROP_FLAG_E(level) flagE[(level)&1]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
#define DIRPROP_FLAG_O(level) flagO[(level)&1]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
/* UBiDi object management -------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
U_CAPI UBiDi * U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
ubidi_open(void)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
    UErrorCode errorCode=U_ZERO_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    return ubidi_openSized(0, 0, &errorCode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
U_CAPI UBiDi * U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
ubidi_openSized(int32_t maxLength, int32_t maxRunCount, UErrorCode *pErrorCode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    UBiDi *pBiDi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    /* check the argument values */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    } else if(maxLength<0 || maxRunCount<0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        return NULL;    /* invalid arguments */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
    /* allocate memory for the object */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    pBiDi=(UBiDi *)icu_malloc(sizeof(UBiDi));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    if(pBiDi==NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    /* reset the object, all pointers NULL, all flags FALSE, all sizes 0 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
    icu_memset(pBiDi, 0, sizeof(UBiDi));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    /* allocate memory for arrays as requested */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    if(maxLength>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        if( !getInitialDirPropsMemory(pBiDi, maxLength) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
            !getInitialLevelsMemory(pBiDi, maxLength)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        pBiDi->mayAllocateText=TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
    if(maxRunCount>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        if(maxRunCount==1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            /* use simpleRuns[] */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            pBiDi->runsSize=sizeof(Run);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        } else if(!getInitialRunsMemory(pBiDi, maxRunCount)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        pBiDi->mayAllocateRuns=TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    if(U_SUCCESS(*pErrorCode)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        return pBiDi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        ubidi_close(pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
 * We are allowed to allocate memory if memory==NULL or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
 * mayAllocate==TRUE for each array that we need.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
 * We also try to grow and shrink memory as needed if we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
 * allocate it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
 * Assume sizeNeeded>0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
 * If *pMemory!=NULL, then assume *pSize>0.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
 * ### this realloc() may unnecessarily copy the old data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
 * which we know we don't need any more;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
 * is this the best way to do this??
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
extern bool_t
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
ubidi_getMemory(void **pMemory, int32_t *pSize, bool_t mayAllocate, int32_t sizeNeeded) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    /* check for existing memory */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    if(*pMemory==NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        /* we need to allocate memory */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        if(mayAllocate && (*pMemory=icu_malloc(sizeNeeded))!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            *pSize=sizeNeeded;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        /* there is some memory, is it enough or too much? */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        if(sizeNeeded>*pSize && !mayAllocate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            /* not enough memory, and we must not allocate */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        } else if(sizeNeeded!=*pSize && mayAllocate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            /* we may try to grow or shrink */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            void *memory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            if((memory=icu_realloc(*pMemory, sizeNeeded))!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                *pMemory=memory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                *pSize=sizeNeeded;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                /* we failed to grow */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            /* we have at least enough memory and must not allocate */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
            return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
U_CAPI void U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
ubidi_close(UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        if(pBiDi->dirPropsMemory!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
            icu_free(pBiDi->dirPropsMemory);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        if(pBiDi->levelsMemory!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            icu_free(pBiDi->levelsMemory);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        if(pBiDi->runsMemory!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            icu_free(pBiDi->runsMemory);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        icu_free(pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
/* set to approximate "inverse BiDi" ---------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
U_CAPI void U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
ubidi_setInverse(UBiDi *pBiDi, bool_t isInverse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        pBiDi->isInverse=isInverse;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
U_CAPI bool_t U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
ubidi_isInverse(UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        return pBiDi->isInverse;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
/* ubidi_setPara ------------------------------------------------------------ */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
U_CAPI void U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
              UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
              UErrorCode *pErrorCode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    UBiDiDirection direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
    /* check the argument values */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    } else if(pBiDi==NULL || text==NULL ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
              ((UBIDI_MAX_EXPLICIT_LEVEL<paraLevel) && !IS_DEFAULT_LEVEL(paraLevel)) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
              length<-1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    if(length==-1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        // length=u_strlen(text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                const UChar *p = text - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                while(*++p);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                length = p - text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    /* initialize the UBiDi structure */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
    pBiDi->text=text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    pBiDi->length=length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    pBiDi->paraLevel=paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
    pBiDi->direction=UBIDI_LTR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    pBiDi->trailingWSStart=length;  /* the levels[] will reflect the WS run */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
    pBiDi->dirProps=NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    pBiDi->levels=NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    pBiDi->runs=NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    if(length==0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
         * For an empty paragraph, create a UBiDi object with the paraLevel and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
         * the flags and the direction set but without allocating zero-length arrays.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
         * There is nothing more to do.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        if(IS_DEFAULT_LEVEL(paraLevel)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
            pBiDi->paraLevel&=1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        if(paraLevel&1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            pBiDi->flags=DIRPROP_FLAG(R);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            pBiDi->direction=UBIDI_RTL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            pBiDi->flags=DIRPROP_FLAG(L);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
            pBiDi->direction=UBIDI_LTR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        pBiDi->runCount=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    pBiDi->runCount=-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     * Get the directional properties,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     * the flags bit-set, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
     * determine the partagraph level if necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
    if(getDirPropsMemory(pBiDi, length)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        pBiDi->dirProps=pBiDi->dirPropsMemory;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        getDirProps(pBiDi, text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
1310
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   387
    if (getLevelsMemory(pBiDi, length)) {
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   388
        pBiDi->levels=pBiDi->levelsMemory;
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   389
        /* are explicit levels specified? */
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   390
        if(embeddingLevels==NULL) {
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   391
            /* no: determine explicit levels according to the (Xn) rules */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            direction=resolveExplicitLevels(pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        } else {
1310
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   394
            /* set BN for all explicit codes, check that all levels are paraLevel..UBIDI_MAX_EXPLICIT_LEVEL */
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   395
            icu_memcpy(pBiDi->levels, embeddingLevels, length);
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   396
            direction=checkExplicitLevels(pBiDi, pErrorCode);
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   397
            if(U_FAILURE(*pErrorCode)) {
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   398
                 return;
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   399
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    } else {
1310
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   402
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
edc39463f896 6665028: native code of method j*.text.Bidi.nativeBidiChars is using the contents of a primitive array direct
peytoia
parents: 2
diff changeset
   403
        return;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
     * The steps after (X9) in the UBiDi algorithm are performed only if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
     * the paragraph text has mixed directionality!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    pBiDi->direction=direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    switch(direction) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    case UBIDI_LTR:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        /* make sure paraLevel is even */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        pBiDi->paraLevel=(UBiDiLevel)((pBiDi->paraLevel+1)&~1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        pBiDi->trailingWSStart=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
    case UBIDI_RTL:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        /* make sure paraLevel is odd */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        pBiDi->paraLevel|=1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        /* all levels are implicitly at paraLevel (important for ubidi_getLevels()) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        pBiDi->trailingWSStart=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
    default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
         * If there are no external levels specified and there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
         * are no significant explicit level codes in the text,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
         * then we can treat the entire paragraph as one run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
         * Otherwise, we need to perform the following rules on runs of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
         * the text with the same embedding levels. (X10)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
         * "Significant" explicit level codes are ones that actually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
         * affect non-BN characters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
         * Examples for "insignificant" ones are empty embeddings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
         * LRE-PDF, LRE-RLE-PDF-PDF, etc.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        if(embeddingLevels==NULL && !(pBiDi->flags&DIRPROP_FLAG_MULTI_RUNS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            resolveImplicitLevels(pBiDi, 0, length,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                                    GET_LR_FROM_LEVEL(pBiDi->paraLevel),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                                    GET_LR_FROM_LEVEL(pBiDi->paraLevel));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
            /* sor, eor: start and end types of same-level-run */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            UBiDiLevel *levels=pBiDi->levels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
            int32_t start, limit=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            UBiDiLevel level, nextLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
            DirProp sor, eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
            /* determine the first sor and set eor to it because of the loop body (sor=eor there) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            level=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            nextLevel=levels[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
            if(level<nextLevel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                eor=GET_LR_FROM_LEVEL(nextLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                eor=GET_LR_FROM_LEVEL(level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
            do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                /* determine start and limit of the run (end points just behind the run) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                /* the values for this run's start are the same as for the previous run's end */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                sor=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                start=limit;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                level=nextLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                /* search for the limit of this run */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                while(++limit<length && levels[limit]==level) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                /* get the correct level of the next run */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                if(limit<length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                    nextLevel=levels[limit];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                    nextLevel=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                /* determine eor from max(level, nextLevel); sor is last run's eor */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                if((level&~UBIDI_LEVEL_OVERRIDE)<(nextLevel&~UBIDI_LEVEL_OVERRIDE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                    eor=GET_LR_FROM_LEVEL(nextLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                    eor=GET_LR_FROM_LEVEL(level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                /* if the run consists of overridden directional types, then there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                   are no implicit types to be resolved */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                if(!(level&UBIDI_LEVEL_OVERRIDE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                    resolveImplicitLevels(pBiDi, start, limit, sor, eor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                    /* remove the UBIDI_LEVEL_OVERRIDE flags */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                        levels[start++]&=~UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                    } while(start<limit);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            } while(limit<length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        /* reset the embedding levels for some non-graphic characters (L1), (X9) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        adjustWSLevels(pBiDi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        /* for "inverse BiDi", ubidi_getRuns() modifies the levels of numeric runs following RTL runs */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        if(pBiDi->isInverse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            if(!ubidi_getRuns(pBiDi)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
/* perform (P2)..(P3) ------------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
 * Get the directional properties for the text,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
 * calculate the flags bit-set, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
 * determine the partagraph level if necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
getDirProps(UBiDi *pBiDi, const UChar *text) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
    DirProp *dirProps=pBiDi->dirPropsMemory;    /* pBiDi->dirProps is const */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
    int32_t i=0, i0, i1, length=pBiDi->length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    Flags flags=0;      /* collect all directionalities in the text */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    UChar uchar;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    DirProp dirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
    if(IS_DEFAULT_LEVEL(pBiDi->paraLevel)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        /* determine the paragraph level (P2..P3) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        for(;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
            uchar=text[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
            if(!IS_FIRST_SURROGATE(uchar) || i+1==length || !IS_SECOND_SURROGATE(text[i+1])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                /* not a surrogate pair */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_charDirection(uchar));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                /* a surrogate pair */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                dirProps[i++]=BN;   /* first surrogate in the pair gets the BN type */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_surrogatePairDirection(uchar, text[i]))|DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
            ++i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            if(dirProp==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                pBiDi->paraLevel=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            } else if(dirProp==R || dirProp==AL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                pBiDi->paraLevel=1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            } else if(i>=length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
                 * see comment in ubidi.h:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                 * the DEFAULT_XXX values are designed so that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
                 * their bit 0 alone yields the intended default
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
                pBiDi->paraLevel&=1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
    /* get the rest of the directional properties and the flags bits */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    while(i<length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        uchar=text[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        if(!IS_FIRST_SURROGATE(uchar) || i+1==length || !IS_SECOND_SURROGATE(text[i+1])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
            /* not a surrogate pair */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
            flags|=DIRPROP_FLAG(dirProps[i]=u_charDirection(uchar));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            /* a surrogate pair */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            dirProps[i++]=BN;   /* first surrogate in the pair gets the BN type */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            flags|=DIRPROP_FLAG(dirProps[i]=dirProp=u_surrogatePairDirection(uchar, text[i]))|DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        ++i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    if(flags&MASK_EMBEDDING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
    pBiDi->flags=flags;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
/* perform (X1)..(X9) ------------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
 * Resolve the explicit levels as specified by explicit embedding codes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
 * Recalculate the flags to have them reflect the real properties
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
 * after taking the explicit embeddings into account.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
 * The BiDi algorithm is designed to result in the same behavior whether embedding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
 * levels are externally specified (from "styled text", supposedly the preferred
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
 * method) or set by explicit embedding codes (LRx, RLx, PDF) in the plain text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
 * That is why (X9) instructs to remove all explicit codes (and BN).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
 * However, in a real implementation, this removal of these codes and their index
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
 * positions in the plain text is undesirable since it would result in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
 * reallocated, reindexed text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
 * Instead, this implementation leaves the codes in there and just ignores them
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
 * in the subsequent processing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
 * In order to get the same reordering behavior, positions with a BN or an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
 * explicit embedding code just get the same level assigned as the last "real"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
 * character.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
 * Some implementations, not this one, then overwrite some of these
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
 * directionality properties at "real" same-level-run boundaries by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
 * L or R codes so that the resolution of weak types can be performed on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
 * entire paragraph at once instead of having to parse it once more and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
 * perform that resolution on same-level-runs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
 * This limits the scope of the implicit rules in effectively
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
 * the same way as the run limits.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
 * Instead, this implementation does not modify these codes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
 * On one hand, the paragraph has to be scanned for same-level-runs, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
 * on the other hand, this saves another loop to reset these codes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
 * or saves making and modifying a copy of dirProps[].
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
 * Note that (Pn) and (Xn) changed significantly from version 4 of the BiDi algorithm.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
 * Handling the stack of explicit levels (Xn):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
 * With the BiDi stack of explicit levels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
 * as pushed with each LRE, RLE, LRO, and RLO and popped with each PDF,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
 * the explicit level must never exceed UBIDI_MAX_EXPLICIT_LEVEL==61.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
 * In order to have a correct push-pop semantics even in the case of overflows,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
 * there are two overflow counters:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
 * - countOver60 is incremented with each LRx at level 60
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
 * - from level 60, one RLx increases the level to 61
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
 * - countOver61 is incremented with each LRx and RLx at level 61
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
 * Popping levels with PDF must work in the opposite order so that level 61
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
 * is correct at the correct point. Underflows (too many PDFs) must be checked.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
 * This implementation assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
resolveExplicitLevels(UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    const DirProp *dirProps=pBiDi->dirProps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
    UBiDiLevel *levels=pBiDi->levels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
    int32_t i=0, length=pBiDi->length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
    Flags flags=pBiDi->flags;       /* collect all directionalities in the text */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
    DirProp dirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
    UBiDiLevel level=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
    UBiDiDirection direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
    /* determine if the text is mixed-directional or single-directional */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
    direction=directionFromFlags(flags);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
    /* we may not need to resolve any explicit levels */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
    if(direction!=UBIDI_MIXED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        /* not mixed directionality: levels don't matter - trailingWSStart will be 0 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
    } else if(!(flags&MASK_EXPLICIT) || pBiDi->isInverse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        /* mixed, but all characters are at the same embedding level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        /* or we are in "inverse BiDi" */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
        /* set all levels to the paragraph level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        for(i=0; i<length; ++i) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            levels[i]=level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
        /* continue to perform (Xn) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        /* (X1) level is set for all codes, embeddingLevel keeps track of the push/pop operations */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        /* both variables may carry the UBIDI_LEVEL_OVERRIDE flag to indicate the override status */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        UBiDiLevel embeddingLevel=level, newLevel, stackTop=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
        UBiDiLevel stack[UBIDI_MAX_EXPLICIT_LEVEL];        /* we never push anything >=UBIDI_MAX_EXPLICIT_LEVEL */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        uint32_t countOver60=0, countOver61=0;  /* count overflows of explicit levels */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
        /* recalculate the flags */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
        flags=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        /* since we assume that this is a single paragraph, we ignore (X8) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        for(i=0; i<length; ++i) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
            dirProp=dirProps[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            switch(dirProp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
            case LRE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
            case LRO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                /* (X3, X5) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                newLevel=(UBiDiLevel)((embeddingLevel+2)&~(UBIDI_LEVEL_OVERRIDE|1)); /* least greater even level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                    stack[stackTop]=embeddingLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                    ++stackTop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                    embeddingLevel=newLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
                    if(dirProp==LRO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
                        embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                        embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                } else if((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                    ++countOver61;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
                } else /* (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)==UBIDI_MAX_EXPLICIT_LEVEL-1 */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
                    ++countOver60;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
                flags|=DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
            case RLE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            case RLO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
                /* (X2, X4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                newLevel=(UBiDiLevel)(((embeddingLevel&~UBIDI_LEVEL_OVERRIDE)+1)|1); /* least greater odd level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                if(newLevel<=UBIDI_MAX_EXPLICIT_LEVEL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                    stack[stackTop]=embeddingLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                    ++stackTop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                    embeddingLevel=newLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                    if(dirProp==RLO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                        embeddingLevel|=UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                        embeddingLevel&=~UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                    ++countOver61;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                flags|=DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
            case PDF:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                /* (X7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                /* handle all the overflow cases first */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                if(countOver61>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                    --countOver61;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                } else if(countOver60>0 && (embeddingLevel&~UBIDI_LEVEL_OVERRIDE)!=UBIDI_MAX_EXPLICIT_LEVEL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                    /* handle LRx overflows from level 60 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                    --countOver60;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                } else if(stackTop>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                    /* this is the pop operation; it also pops level 61 while countOver60>0 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                    --stackTop;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                    embeddingLevel=stack[stackTop];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
                /* } else { (underflow) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                flags|=DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
            case B:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                 * We do not really expect to see a paragraph separator (B),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                 * but we should do something reasonable with it,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                 * especially at the end of the text.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                stackTop=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                countOver60=countOver61=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                embeddingLevel=level=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                flags|=DIRPROP_FLAG(B);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            case BN:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                /* BN, LRE, RLE, and PDF are supposed to be removed (X9) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                /* they will get their levels set correctly in adjustWSLevels() */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                flags|=DIRPROP_FLAG(BN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                /* all other types get the "real" level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                if(level!=embeddingLevel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
                    level=embeddingLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                    if(level&UBIDI_LEVEL_OVERRIDE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
                        flags|=DIRPROP_FLAG_O(level)|DIRPROP_FLAG_MULTI_RUNS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
                        flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG_MULTI_RUNS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                if(!(level&UBIDI_LEVEL_OVERRIDE)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
                    flags|=DIRPROP_FLAG(dirProp);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
             * We need to set reasonable levels even on BN codes and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
             * explicit codes because we will later look at same-level runs (X10).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            levels[i]=level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
        if(flags&MASK_EMBEDDING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
            flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
        /* subsequently, ignore the explicit codes and BN (X9) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        /* again, determine if the text is mixed-directional or single-directional */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
        pBiDi->flags=flags;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        direction=directionFromFlags(flags);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
    return direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
 * Use a pre-specified embedding levels array:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
 * Adjust the directional properties for overrides (->LEVEL_OVERRIDE),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
 * ignore all explicit codes (X9),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
 * and check all the preset levels.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
 * Recalculate the flags to have them reflect the real properties
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
 * after taking the explicit embeddings into account.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
checkExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
    const DirProp *dirProps=pBiDi->dirProps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
    UBiDiLevel *levels=pBiDi->levels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
    int32_t i, length=pBiDi->length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
    Flags flags=0;  /* collect all directionalities in the text */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
    UBiDiLevel level, paraLevel=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
    for(i=0; i<length; ++i) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
      // dlf: we special case levels array for java, 0 means base level, not actually 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
      if (levels[i] == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        levels[i] = paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        level=levels[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
        if(level&UBIDI_LEVEL_OVERRIDE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
            /* keep the override flag in levels[i] but adjust the flags */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
            level&=~UBIDI_LEVEL_OVERRIDE;     /* make the range check below simpler */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
            flags|=DIRPROP_FLAG_O(level);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
            /* set the flags */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
            flags|=DIRPROP_FLAG_E(level)|DIRPROP_FLAG(dirProps[i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        if(level<paraLevel || UBIDI_MAX_EXPLICIT_LEVEL<level) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
            /* level out of bounds */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
            *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
            return UBIDI_LTR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
    if(flags&MASK_EMBEDDING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
        flags|=DIRPROP_FLAG_LR(pBiDi->paraLevel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
    /* determine if the text is mixed-directional or single-directional */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
    pBiDi->flags=flags;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
    return directionFromFlags(flags);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
/* determine if the text is mixed-directional or single-directional */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
static UBiDiDirection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
directionFromFlags(Flags flags) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
    /* if the text contains AN and neutrals, then some neutrals may become RTL */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
    if(!(flags&MASK_RTL || ((flags&DIRPROP_FLAG(AN)) && (flags&MASK_POSSIBLE_N)))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
        return UBIDI_LTR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
    } else if(!(flags&MASK_LTR)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        return UBIDI_RTL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
        return UBIDI_MIXED;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
/* perform rules (Wn), (Nn), and (In) on a run of the text ------------------ */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
 * This implementation of the (Wn) rules applies all rules in one pass.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
 * In order to do so, it needs a look-ahead of typically 1 character
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
 * (except for W5: sequences of ET) and keeps track of changes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
 * in a rule Wp that affect a later Wq (p<q).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
 * historyOfEN is a variable-saver: it contains 4 boolean states;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
 * a bit in it set to 1 means:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
 *  bit 0: the current code is an EN after W2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
 *  bit 1: the current code is an EN after W4
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
 *  bit 2: the previous code was an EN after W2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
 *  bit 3: the previous code was an EN after W4
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
 * In other words, b0..1 have transitions of EN in the current iteration,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
 * while b2..3 have the transitions of EN in the previous iteration.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
 * A simple historyOfEN<<=2 suffices for the propagation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
 * The (Nn) and (In) rules are also performed in that same single loop,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
 * but effectively one iteration behind for white space.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
 * Since all implicit rules are performed in one step, it is not necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
 * to actually store the intermediate directional properties in dirProps[].
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
#define EN_SHIFT 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
#define EN_AFTER_W2 1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
#define EN_AFTER_W4 2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
#define EN_ALL 3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
#define PREV_EN_AFTER_W2 4
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
#define PREV_EN_AFTER_W4 8
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
resolveImplicitLevels(UBiDi *pBiDi,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                      int32_t start, int32_t limit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                      DirProp sor, DirProp eor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
    const DirProp *dirProps=pBiDi->dirProps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
    UBiDiLevel *levels=pBiDi->levels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
    int32_t i, next, neutralStart=-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
    DirProp prevDirProp, dirProp, nextDirProp, lastStrong, beforeNeutral=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
    UBiDiLevel numberLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
    uint8_t historyOfEN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
    /* initialize: current at sor, next at start (it is start<limit) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
    next=start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
    dirProp=lastStrong=sor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
    nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
    historyOfEN=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
    if(pBiDi->isInverse) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
         * For "inverse BiDi", we set the levels of numbers just like for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
         * regular L characters, plus a flag that ubidi_getRuns() will use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
         * to set a similar flag on the corresponding output run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        numberLevel=levels[start];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        if(numberLevel&1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
            ++numberLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
        /* normal BiDi: least greater even level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        numberLevel=(UBiDiLevel)((levels[start]+2)&~1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
     * In all steps of this implementation, BN and explicit embedding codes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
     * must be treated as if they didn't exist (X9).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
     * They will get levels set before a non-neutral character, and remain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
     * undefined before a neutral one, but adjustWSLevels() will take care
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
     * of all of them.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
    while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        if(++next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            nextDirProp=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
     * Note: at the end of this file, there is a prototype
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
     * of a version of this function that uses a statetable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
     * at the core of this state machine.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
     * If you make changes to this state machine,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
     * please update that prototype as well.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
    /* loop for entire run */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
    while(next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
        /* advance */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
        prevDirProp=dirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
        dirProp=nextDirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
        i=next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
            if(++next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
                nextDirProp=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        } while(DIRPROP_FLAG(nextDirProp)&MASK_BN_EXPLICIT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
        historyOfEN<<=EN_SHIFT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        /* (W1..W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
        switch(dirProp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
        case L:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            lastStrong=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
        case R:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            lastStrong=R;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        case AL:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            /* (W3) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
            lastStrong=AL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
            dirProp=R;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
        case EN:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
            /* we have to set historyOfEN correctly */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
            if(lastStrong==AL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                /* (W2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
                dirProp=AN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
                if(lastStrong==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                    /* (W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
                    dirProp=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
                /* this EN stays after (W2) and (W4) - at least before (W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
                historyOfEN|=EN_ALL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
        case ES:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
            if( historyOfEN&PREV_EN_AFTER_W2 &&     /* previous was EN before (W4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
                nextDirProp==EN && lastStrong!=AL   /* next is EN and (W2) won't make it AN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
            ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                /* (W4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                if(lastStrong!=L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                    dirProp=EN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
                    /* (W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
                    dirProp=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
                historyOfEN|=EN_AFTER_W4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
                /* (W6) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
                dirProp=ON;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
        case CS:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
            if( historyOfEN&PREV_EN_AFTER_W2 &&     /* previous was EN before (W4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
                nextDirProp==EN && lastStrong!=AL   /* next is EN and (W2) won't make it AN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
            ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
                /* (W4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
                if(lastStrong!=L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
                    dirProp=EN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
                    /* (W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
                    dirProp=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
                historyOfEN|=EN_AFTER_W4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
            } else if(prevDirProp==AN &&                    /* previous was AN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                      (nextDirProp==AN ||                   /* next is AN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
                      (nextDirProp==EN && lastStrong==AL))  /* or (W2) will make it one */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
            ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
                /* (W4) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
                dirProp=AN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
                /* (W6) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
                dirProp=ON;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
        case ET:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
            /* get sequence of ET; advance only next, not current, previous or historyOfEN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
            if(next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                while(DIRPROP_FLAG(nextDirProp)&MASK_ET_NSM_BN /* (W1), (X9) */) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
                    if(++next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                        nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
                        nextDirProp=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
            /* now process the sequence of ET like a single ET */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
            if((historyOfEN&PREV_EN_AFTER_W4) ||     /* previous was EN before (W5) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
                (nextDirProp==EN && lastStrong!=AL)   /* next is EN and (W2) won't make it AN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
            ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
                /* (W5) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
                if(lastStrong!=L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                    dirProp=EN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                    /* (W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                    dirProp=L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
                /* (W6) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
                dirProp=ON;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
            /* apply the result of (W1), (W5)..(W7) to the entire sequence of ET */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
        case NSM:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
            /* (W1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
            dirProp=prevDirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
            /* set historyOfEN back to prevDirProp's historyOfEN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
            historyOfEN>>=EN_SHIFT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
             * Technically, this should be done before the switch() in the form
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
             *      if(nextDirProp==NSM) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
             *          dirProps[next]=nextDirProp=dirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
             *      }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
             * - effectively one iteration ahead.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
             * However, whether the next dirProp is NSM or is equal to the current dirProp
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
             * does not change the outcome of any condition in (W2)..(W7).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
        /* here, it is always [prev,this,next]dirProp!=BN; it may be next>i+1 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
        /* perform (Nn) - here, only L, R, EN, AN, and neutrals are left */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
        /* for "inverse BiDi", treat neutrals like L */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
        /* this is one iteration late for the neutrals */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
        if(DIRPROP_FLAG(dirProp)&MASK_N) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
            if(neutralStart<0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
                /* start of a sequence of neutrals */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
                neutralStart=i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
                beforeNeutral=prevDirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
        } else /* not a neutral, can be only one of { L, R, EN, AN } */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
             * Note that all levels[] values are still the same at this
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
             * point because this function is called for an entire
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
             * same-level run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
             * Therefore, we need to read only one actual level.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
            UBiDiLevel level=levels[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
            if(neutralStart>=0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
                UBiDiLevel final;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
                /* end of a sequence of neutrals (dirProp is "afterNeutral") */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                if(!(pBiDi->isInverse)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
                    if(beforeNeutral==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
                        if(dirProp==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
                            final=0;                /* make all neutrals L (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
                            final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                    } else /* beforeNeutral is one of { R, EN, AN } */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
                        if(dirProp==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
                            final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
                            final=1;                /* make all neutrals R (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
                    /* "inverse BiDi": collapse [before]dirProps L, EN, AN into L */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
                    if(beforeNeutral!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                        if(dirProp!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
                            final=0;                /* make all neutrals L (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
                            final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
                    } else /* beforeNeutral is one of { R, EN, AN } */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
                        if(dirProp!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                            final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
                        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
                            final=1;                /* make all neutrals R (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
                /* perform (In) on the sequence of neutrals */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
                if((level^final)&1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
                    /* do something only if we need to _change_ the level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
                    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
                        ++levels[neutralStart];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
                    } while(++neutralStart<i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
                neutralStart=-1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
            /* perform (In) on the non-neutral character */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
             * in the cases of (W5), processing a sequence of ET,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
             * and of (X9), skipping BN,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
             * there may be multiple characters from i to <next
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
             * that all get (virtually) the same dirProp and (really) the same level
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
            if(dirProp==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
                if(level&1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
                    ++level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
                    i=next;     /* we keep the levels */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
            } else if(dirProp==R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
                if(!(level&1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
                    ++level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
                    i=next;     /* we keep the levels */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
            } else /* EN or AN */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
                /* this level depends on whether we do "inverse BiDi" */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
                level=numberLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
            /* apply the new level to the sequence, if necessary */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
            while(i<next) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
                levels[i++]=level;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
    /* perform (Nn) - here,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
       the character after the the neutrals is eor, which is either L or R */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
    /* this is one iteration late for the neutrals */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
    if(neutralStart>=0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
         * Note that all levels[] values are still the same at this
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
         * point because this function is called for an entire
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
         * same-level run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
         * Therefore, we need to read only one actual level.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
        UBiDiLevel level=levels[neutralStart], final;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
        /* end of a sequence of neutrals (eor is "afterNeutral") */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
        if(!(pBiDi->isInverse)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
            if(beforeNeutral==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
                if(eor==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
                    final=0;                /* make all neutrals L (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
                    final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
            } else /* beforeNeutral is one of { R, EN, AN } */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
                if(eor==L) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
                    final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
                    final=1;                /* make all neutrals R (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
            /* "inverse BiDi": collapse [before]dirProps L, EN, AN into L */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
            if(beforeNeutral!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
                if(eor!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
                    final=0;                /* make all neutrals L (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
                    final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
            } else /* beforeNeutral is one of { R, EN, AN } */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
                if(eor!=R) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
                    final=level;            /* make all neutrals "e" (N2) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
                    final=1;                /* make all neutrals R (N1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
        /* perform (In) on the sequence of neutrals */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
        if((level^final)&1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
            /* do something only if we need to _change_ the level */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
            do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
                ++levels[neutralStart];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
            } while(++neutralStart<limit);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
/* perform (L1) and (X9) ---------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
 * Reset the embedding levels for some non-graphic characters (L1).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
 * This function also sets appropriate levels for BN, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
 * explicit embedding types that are supposed to have been removed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
 * from the paragraph in (X9).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
adjustWSLevels(UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
    const DirProp *dirProps=pBiDi->dirProps;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
    UBiDiLevel *levels=pBiDi->levels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
    int32_t i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
    if(pBiDi->flags&MASK_WS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
        UBiDiLevel paraLevel=pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
        Flags flag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
        i=pBiDi->trailingWSStart;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
        while(i>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
            /* reset a sequence of WS/BN before eop and B/S to the paragraph paraLevel */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
            while(i>0 && DIRPROP_FLAG(dirProps[--i])&MASK_WS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
                levels[i]=paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
            /* reset BN to the next character's paraLevel until B/S, which restarts above loop */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
            /* here, i+1 is guaranteed to be <length */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
            while(i>0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
                flag=DIRPROP_FLAG(dirProps[--i]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
                if(flag&MASK_BN_EXPLICIT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
                    levels[i]=levels[i+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
                } else if(flag&MASK_B_S) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
                    levels[i]=paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
    /* now remove the UBIDI_LEVEL_OVERRIDE flags, if any */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
    /* (a separate loop can be optimized more easily by a compiler) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
    if(pBiDi->flags&MASK_OVERRIDE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
        for(i=pBiDi->trailingWSStart; i>0;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
            levels[--i]&=~UBIDI_LEVEL_OVERRIDE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
/* -------------------------------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
U_CAPI UBiDiDirection U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
ubidi_getDirection(const UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
        return pBiDi->direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
        return UBIDI_LTR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
U_CAPI const UChar * U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
ubidi_getText(const UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
        return pBiDi->text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
U_CAPI int32_t U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
ubidi_getLength(const UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
        return pBiDi->length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
U_CAPI UBiDiLevel U_EXPORT2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
ubidi_getParaLevel(const UBiDi *pBiDi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
    if(pBiDi!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
        return pBiDi->paraLevel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
/* statetable prototype ----------------------------------------------------- */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
 * This is here for possible future
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
 * performance work and is not compiled right now.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
#if 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
 * This is a piece of code that could be part of ubidi.c/resolveImplicitLevels().
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
 * It replaces in the (Wn) state machine the switch()-if()-cascade with
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
 * just a few if()s and a state table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
/* use the state table only for the following dirProp's */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
#define MASK_W_TABLE (FLAG(L)|FLAG(R)|FLAG(AL)|FLAG(EN)|FLAG(ES)|FLAG(CS)|FLAG(ET)|FLAG(AN))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
 * inputs:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
 * 0..1 historyOfEN - 2b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
 * 2    prevDirProp==AN - 1b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
 * 3..4 lastStrong, one of { L, R, AL, none } - 2b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
 * 5..7 dirProp, one of { L, R, AL, EN, ES, CS, ET, AN } - 3b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
 * 8..9 nextDirProp, one of { EN, AN, other }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
 * total: 10b=1024 states
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
enum { _L, _R, _AL, _EN, _ES, _CS, _ET, _AN, _OTHER };  /* lastStrong, dirProp */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
enum { __EN, __AN, __OTHER };                           /* nextDirProp */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
#define LAST_STRONG_SHIFT 3
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
#define DIR_PROP_SHIFT 5
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
#define NEXT_DIR_PROP_SHIFT 8
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
/* masks after shifting */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
#define LAST_STRONG_MASK 3
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
#define DIR_PROP_MASK 7
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
#define STATE_MASK 0x1f
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
/* convert dirProp into _dirProp (above enum) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
static DirProp inputDirProp[dirPropCount]={ _X<<DIR_PROP_SHIFT, ... };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
/* convert dirProp into __dirProp (above enum) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
static DirProp inputNextDirProp[dirPropCount]={ __X<<NEXT_DIR_PROP_SHIFT, ... };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
 * outputs:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
 * dirProp, one of { L, R, EN, AN, ON } - 3b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
 * 0..1 historyOfEN - 2b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
 * 2    prevDirProp==AN - 1b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
 * 3..4 lastStrong, one of { L, R, AL, none } - 2b
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
 * 5..7 new dirProp, one of { L, R, EN, AN, ON }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
 * total: 8 bits=1 byte per state
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
enum { ___L, ___R, ___EN, ___AN, ___ON, ___count };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
/* convert ___dirProp into dirProp (above enum) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
static DirProp outputDirProp[___count]={ X, ... };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
/* state table */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
static uint8_t wnTable[1024]={ /* calculate with switch()-if()-cascade */ };
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
static void
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
resolveImplicitLevels(BiDi *pBiDi,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
                      Index start, Index end,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
                      DirProp sor, DirProp eor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
    /* new variable */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
    uint8_t state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
    /* remove variable lastStrong */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
    /* set initial state (set lastStrong, the rest is 0) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
    state= sor==L ? 0 : _R<<LAST_STRONG_SHIFT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
    while(next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
        /* advance */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
        prevDirProp=dirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
        dirProp=nextDirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
        i=next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
            if(++next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
                nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
                nextDirProp=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
        } while(FLAG(nextDirProp)&MASK_BN_EXPLICIT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
        /* (W1..W7) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
        /* ### This may be more efficient with a switch(dirProp). */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
        if(FLAG(dirProp)&MASK_W_TABLE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
            state=wnTable[
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
                    ((int)state)|
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
                    inputDirProp[dirProp]|
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
                    inputNextDirProp[nextDirProp]
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
            ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
            dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
            state&=STATE_MASK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
        } else if(dirProp==ET) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
            /* get sequence of ET; advance only next, not current, previous or historyOfEN */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
            while(next<limit && FLAG(nextDirProp)&MASK_ET_NSM_BN /* (W1), (X9) */) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
                if(++next<limit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
                    nextDirProp=dirProps[next];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
                    nextDirProp=eor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
            state=wnTable[
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
                    ((int)state)|
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
                    _ET<<DIR_PROP_SHIFT|
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
                    inputNextDirProp[nextDirProp]
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
            ];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
            dirProp=outputDirProp[state>>DIR_PROP_SHIFT];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
            state&=STATE_MASK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
            /* apply the result of (W1), (W5)..(W7) to the entire sequence of ET */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
        } else if(dirProp==NSM) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
            /* (W1) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
            dirProp=prevDirProp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
            /* keep prevDirProp's EN and AN states! */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1424
        } else /* other */ {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1425
            /* set EN and AN states to 0 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1426
            state&=LAST_STRONG_MASK<<LAST_STRONG_SHIFT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1427
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
        /* perform (Nn) and (In) as usual */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
    /* perform (Nn) and (In) as usual */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
#endif