public override void TextAppendLine(string text, int textColumnIndex) { // Special consideration is taken if it is the first line being appended. Then it begins on index 0 (obviously). var newLine = new TextLine(this.TextLength > 0 ? this.TextLength + 1 : 0, text); this.Lines.Add(newLine); this.DispatchTextSegmentAlter(new AlterTextSegmentArgs(newLine, this.Lines.Count - 1, newLine.GetLength(textColumnIndex) + 1, textColumnIndex)); foreach (var textView in this.GetTextViews()) { this.TextSegmentStyledManager.SearchAndApplyTo(textView, newLine, 0, newLine.GetLength(textColumnIndex), textColumnIndex); } }
/// <summary> /// /// </summary> /// <param name="textView"></param> /// <param name="textLine"></param> /// <param name="relativeIndex">Relative index is the index before the new character, so text[relativeIndex] is the <see cref="c"/>.</param> /// <param name="c"></param> /// <param name="alterTextStyleIndexes"></param> /// <param name="length"></param> /// <param name="textColumnIndex"></param> private void ModifyStyledTextSegments(ITextView textView, TextLine textLine, int relativeIndex, char c, bool alterTextStyleIndexes, int length, int textColumnIndex) { var isErase = c == '\0' && length <= 0; if (isErase) { length *= -1; } IEnumerable <ITextSegmentStyled> befores = null; IEnumerable <ITextSegmentStyled> afters = null; var startSearch = Math.Max(0, relativeIndex - 1); const bool foundMatch = false; if (alterTextStyleIndexes) { var offsetCount = 0; for (var n = 0; n < textLine.StyledTextSegments.Count - offsetCount; n++) { if (textLine.StyledTextSegments[n].Index > textLine.GetLength(textColumnIndex)) { // The style starts after the end of the line, which is silly and should be filtered out. textLine.StyledTextSegments[n].TextLine = null; n--; } else if (isErase && textLine.StyledTextSegments[n].Style.Type == TextStyleType.Automatic && textLine.StyledTextSegments[n].Index >= relativeIndex && textLine.StyledTextSegments[n].Index + textLine.StyledTextSegments[n].GetLength(textColumnIndex) <= relativeIndex + length) { // The whole styled text segment was inside the removed range of text. // It does not exist anymore and is automatically eligible for removing. textLine.StyledTextSegments[n].TextLine = null; n--; } else if (textLine.StyledTextSegments[n].Style.Type == TextStyleType.Automatic && textLine.StyledTextSegments[n].Contains(relativeIndex, length, isErase, true)) { if (befores == null) { // This will search from the character before the change, the character before a new addition, // or the character before the character that was removed. befores = this.FindStyles(textView, textLine, startSearch, textColumnIndex); // If a new addition, we search from the character after the change (so "pol<new space>ice" will search on "i" and not <new space>). // When removing we only need to search from where the removal took place. var afterSearchIdx = isErase == false?Math.Min(textLine.GetLength(textColumnIndex), startSearch + 2) : startSearch + 1; afters = this.FindStyles(textView, textLine, afterSearchIdx, textColumnIndex); } var current = textLine.StyledTextSegments[n]; if (befores != null || afters != null) { ITextSegmentStyled before = null; ITextSegmentStyled after = null; if (befores != null) { foreach (var b in befores) { if (b.Style.NameKey == current.Style.NameKey) { before = b; break; } } } if (afters != null) { foreach (var a in afters) { if (a.Style.NameKey == current.Style.NameKey) { after = a; break; } } } if (before == null) { if (after == null) { // The styled text segment is no more since it is no longer found. current.TextLine = null; n--; continue; } before = after; after = null; } else if (after != null && before.Object != null && before.Object.Equals(after.Object)) { after = null; } if (before.Index == current.Index && before.GetLength(textColumnIndex) == current.GetLength(textColumnIndex) && ((before.Object != null && before.Object.Equals(current.Object)) || before.Object == null && current.Object == null)) { continue; // No change was done. Just don't do any changes. } //foundMatch = true; if (before.Contains(current.Index, current.GetLength(textColumnIndex), true, true)) { current.TextLine = null; n--; } ((TextAnchor)before).TextLine = textLine; offsetCount++; if (after != null) { ((TextAnchor)after).TextLine = textLine; offsetCount++; } } else { // The styled text segment is no more since it is no longer found. current.TextLine = null; n--; } } else if (textLine.StyledTextSegments[n].Index > relativeIndex) { if (isErase) { textLine.StyledTextSegments[n].Index -= length; } else { textLine.StyledTextSegments[n].Index += length; } } } } if (foundMatch == false) { #if DEBUG var foundOne = #endif this.TextSegmentStyledManager.SearchAndApplyTo(textView, textLine, startSearch, 1, CharacterIsFinalizer(c), textColumnIndex); } }