1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 2008-2010, International Business Machines 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Date Name Description 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* 05/11/2008 Andy Heninger Port from Java 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/ 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h" 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_TRANSLITERATION && !UCONFIG_NO_BREAK_ITERATION 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/unifilt.h" 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uchar.h" 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uniset.h" 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/brkiter.h" 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "brktrans.h" 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uchar.h" 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uprops.h" 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uinvchar.h" 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "util.h" 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uvectr32.h" 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_BEGIN 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BreakTransliterator) 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar SPACE = 32; // ' ' 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Constructs a transliterator with the default delimiters '{' and 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * '}'. 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)BreakTransliterator::BreakTransliterator(UnicodeFilter* adoptedFilter) : 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator(UNICODE_STRING("Any-BreakInternal", 17), adoptedFilter), 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fInsertion(SPACE) { 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi = NULL; 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundaries = new UVector32(status); 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Destructor. 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)BreakTransliterator::~BreakTransliterator() { 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete bi; 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi = NULL; 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delete boundaries; 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundaries = NULL; 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Copy constructor. 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)BreakTransliterator::BreakTransliterator(const BreakTransliterator& o) : 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Transliterator(o) { 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi = NULL; 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (o.bi != NULL) { 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi = o.bi->clone(); 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fInsertion = o.fInsertion; 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundaries = new UVector32(status); 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Transliterator API. 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)Transliterator* BreakTransliterator::clone(void) const { 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return new BreakTransliterator(*this); 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Implements {@link Transliterator#handleTransliterate}. 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void BreakTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets, 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UBool isIncremental ) const { 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundaries->removeAllElements(); 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) BreakTransliterator *nonConstThis = (BreakTransliterator *)this; 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) nonConstThis->getBreakIterator(); // Lazy-create it if necessary 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString sText = replaceableAsString(text); 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi->setText(sText); 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi->preceding(offsets.start); 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // To make things much easier, we will stack the boundaries, and then insert at the end. 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // generally, we won't need too many, since we will be filtered. 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t boundary; 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) for(boundary = bi->next(); boundary != UBRK_DONE && boundary < offsets.limit; boundary = bi->next()) { 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (boundary == 0) continue; 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // HACK: Check to see that preceeding item was a letter 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UChar32 cp = sText.char32At(boundary-1); 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int type = u_charType(cp); 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //System.out.println(Integer.toString(cp,16) + " (before): " + type); 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if ((U_MASK(type) & (U_GC_L_MASK | U_GC_M_MASK)) == 0) continue; 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) cp = sText.char32At(boundary); 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) type = u_charType(cp); 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) //System.out.println(Integer.toString(cp,16) + " (after): " + type); 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if ((U_MASK(type) & (U_GC_L_MASK | U_GC_M_MASK)) == 0) continue; 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundaries->addElement(boundary, status); 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // printf("Boundary at %d\n", boundary); 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int delta = 0; 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int lastBoundary = 0; 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (boundaries->size() != 0) { // if we found something, adjust 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) delta = boundaries->size() * fInsertion.length(); 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) lastBoundary = boundaries->lastElementi(); 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // we do this from the end backwards, so that we don't have to keep updating. 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (boundaries->size() > 0) { 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) boundary = boundaries->popi(); 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) text.handleReplaceBetween(boundary, boundary, fInsertion); 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Now fix up the return values 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offsets.contextLimit += delta; 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offsets.limit += delta; 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offsets.start = isIncremental ? lastBoundary + delta : offsets.limit; 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // TODO: do something with U_FAILURE(status); 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // (need to look at transliterators overall, not just here.) 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// getInsertion() 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UnicodeString &BreakTransliterator::getInsertion() const { 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return fInsertion; 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// setInsertion() 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void BreakTransliterator::setInsertion(const UnicodeString &insertion) { 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) this->fInsertion = insertion; 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// getBreakIterator Lazily create the break iterator if it does 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// not already exist. Copied from Java, probably 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// better to just create it in the constructor. 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)BreakIterator *BreakTransliterator::getBreakIterator() { 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode status = U_ZERO_ERROR; 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (bi == NULL) { 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // Note: Thai breaking behavior is universal, it is not 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) // tied to the Thai locale. 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) bi = BreakIterator::createWordInstance(Locale::getEnglish(), status); 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return bi; 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// replaceableAsString Hack to let break iterators work 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// on the replaceable text from transliterators. 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// In practice, the only real Replaceable type that we 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// will be seeing is UnicodeString, so this function 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// will normally be efficient. 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString BreakTransliterator::replaceableAsString(Replaceable &r) { 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString s; 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UnicodeString *rs = dynamic_cast<UnicodeString *>(&r); 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if (rs != NULL) { 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) s = *rs; 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) r.extractBetween(0, r.length(), s); 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return s; 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_END 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_TRANSLITERATION */ 189