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