protected override ITsString NewValue(int hvo)
{
ITsString tss = OldValue(hvo);
if (tss == null)
{
ITsStrFactory tsf = TsStrFactoryClass.Create();
tss = tsf.MakeString("", m_accessor.WritingSystem);
}
m_textSourceInit.SetString(tss);
int ichMin, ichLim;
int ichStartSearch = 0;
ITsStrBldr tsb = null;
int delta = 0; // Amount added to length of string (negative if shorter).
int cch = tss.Length;
// Some tricky stuff going on here. We allow a match ONCE where ichStartSearch = cch,
// because some patterns match an empty string, and (once) we want to allow that.
// But we must not allow it repeatedly, because we can get an infinite sequence
// of replacements if ichLim comes out of FindIn equal to ichStartSearch.
// Also, normally we want a pattern which matched, say, chars 1 and 2 to also
// be able to match chars 3 and 4. But we don't want one which matched 1 and 2
// to also match the empty position between 2 and 3. Or, for example, ".*" to
// match the whole input, and then again the empty string at the end.
// To achieve this, we allow each match to start where the last one ended,
// but a match of zero length that ends exactly where a previous match
// ended is discarded.
int ichLimLastMatch = -1;
for ( ; ichStartSearch <= cch; )
{
m_pattern.FindIn(m_ts, ichStartSearch, cch, true, out ichMin, out ichLim, null);
if (ichMin < 0)
break;
if (ichLim == ichLimLastMatch)
{
ichStartSearch = ichLim + 1;
continue;
}
ichLimLastMatch = ichLim;
if (tsb == null)
tsb = tss.GetBldr();
ITsString tssRep = m_pattern.ReplacementText;
tsb.ReplaceTsString(ichMin + delta, ichLim + delta, tssRep);
delta += tssRep.Length - (ichLim - ichMin);
ichStartSearch = ichLim;
}
if (tsb == null)
return null;
return tsb.GetString().get_NormalizedForm(FwNormalizationMode.knmNFD);
}