nortrans.cpp revision b13da9df870a61b11249bf741347908dbea0edd8
1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Copyright (C) 2001-2007, International Business Machines
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/03/01    aliu        Creation.
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru**********************************************************************
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_TRANSLITERATION
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uniset.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uiter.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "nortrans.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unormimp.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(NormalizationTransliterator)
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * System registration hook.
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid NormalizationTransliterator::registerIDs() {
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode = U_ZERO_ERROR;
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!unorm_haveData(&errorCode)) {
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFC"),
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     _create, integerToken(UNORM_NFC));
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFKC"),
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     _create, integerToken(UNORM_NFKC));
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFD"),
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     _create, integerToken(UNORM_NFD));
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFKD"),
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     _create, integerToken(UNORM_NFKD));
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerSpecialInverse(UNICODE_STRING_SIMPLE("NFC"),
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                            UNICODE_STRING_SIMPLE("NFD"), TRUE);
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::_registerSpecialInverse(UNICODE_STRING_SIMPLE("NFKC"),
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                            UNICODE_STRING_SIMPLE("NFKD"), TRUE);
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Factory methods
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTransliterator* NormalizationTransliterator::_create(const UnicodeString& ID,
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                     Token context) {
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new NormalizationTransliterator(ID, (UNormalizationMode) context.integer, 0);
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Constructs a transliterator.
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNormalizationTransliterator::NormalizationTransliterator(
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 const UnicodeString& id,
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 UNormalizationMode mode, int32_t opt) :
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator(id, 0) {
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fMode = mode;
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    options = opt;
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Destructor.
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNormalizationTransliterator::~NormalizationTransliterator() {
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Copy constructor.
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruNormalizationTransliterator::NormalizationTransliterator(const NormalizationTransliterator& o) :
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTransliterator(o) {
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fMode = o.fMode;
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    options = o.options;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Assignment operator.
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*NormalizationTransliterator& NormalizationTransliterator::operator=(const NormalizationTransliterator& o) {
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Transliterator::operator=(o);
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fMode = o.fMode;
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    options = o.options;
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}*/
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Transliterator API.
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTransliterator* NormalizationTransliterator::clone(void) const {
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return new NormalizationTransliterator(*this);
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Implements {@link Transliterator#handleTransliterate}.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid NormalizationTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                                      UBool isIncremental) const {
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // start and limit of the input range
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = offsets.start;
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t limit = offsets.limit;
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t length, delta;
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(start >= limit) {
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // a C code unit iterator, implemented around the Replaceable
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UCharIterator iter;
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uiter_setReplaceable(&iter, &text);
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the output string and buffer pointer
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString output;
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar *buffer;
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool neededToNormalize;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode errorCode;
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /*
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * Normalize as short chunks at a time as possible even in
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * bulk mode, so that styled text is minimally disrupted.
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * In incremental mode, a chunk that ends with offsets.limit
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * must not be normalized.
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * If it was known that the input text is not styled, then
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * a bulk mode normalization could look like this:
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UChar staticChars[256];
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString input;
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    length = limit - start;
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    input.setTo(staticChars, 0, sizeof(staticChars)/U_SIZEOF_UCHAR); // writable alias
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _Replaceable_extractBetween(text, start, limit, input.getBuffer(length));
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    input.releaseBuffer(length);
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Normalizer::normalize(input, fMode, options, output, status);
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    text.handleReplaceBetween(start, limit, output);
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t delta = output.length() - length;
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offsets.contextLimit += delta;
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offsets.limit += delta;
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offsets.start = limit + delta;
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     *
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    while(start < limit) {
156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // set the iterator limits for the remaining input range
157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // this is a moving target because of the replacements in the text object
158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        iter.start = iter.index = start;
159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        iter.limit = limit;
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // incrementally normalize a small chunk of the input
162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        buffer = output.getBuffer(-1);
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errorCode = U_ZERO_ERROR;
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        length = unorm_next(&iter, buffer, output.getCapacity(),
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            fMode, 0,
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            TRUE, &neededToNormalize,
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            &errorCode);
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        output.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // use a larger output string buffer and do it again from the start
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            iter.index = start;
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            buffer = output.getBuffer(length);
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errorCode = U_ZERO_ERROR;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            length = unorm_next(&iter, buffer, output.getCapacity(),
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                fMode, 0,
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                TRUE, &neededToNormalize,
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                &errorCode);
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            output.releaseBuffer(U_SUCCESS(errorCode) ? length : 0);
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(errorCode)) {
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        limit = iter.index;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(isIncremental && limit == iter.limit) {
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // stop in incremental mode when we reach the input limit
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // in case there are additional characters that could change the
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // normalization result
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // UNLESS all characters in the result of the normalization of
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // the last run are in the skippable set
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UChar *s=output.getBuffer();
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i=0, outLength=output.length();
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            UChar32 c;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while(i<outLength) {
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                U16_NEXT(s, i, outLength, c);
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(!unorm_isNFSkippable(c, fMode)) {
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    outLength=-1; // I wish C++ had labeled loops and break outer; ...
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (outLength<0) {
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(neededToNormalize) {
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // replace the input chunk with its normalized form
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            text.handleReplaceBetween(start, limit, output);
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // update all necessary indexes accordingly
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delta = length - (limit - start);   // length change in the text object
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start = limit += delta;             // the next chunk starts where this one ends, with adjustment
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit = offsets.limit += delta;     // set the iteration limit to the adjusted end of the input range
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            offsets.contextLimit += delta;
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // delta == 0
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start = limit;
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit = offsets.limit;
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offsets.start = start;
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_TRANSLITERATION */
232