void RecolouringThreadProc(ICancellable cnc) { RegexMatches matches; string eol; bool show_captures; lock (this) { matches = LastMatches; eol = LastEol; show_captures = LastShowCaptures; } TextData td = null; Rect clip_rect = Rect.Empty; int top_index = 0; int bottom_index = 0; UITaskHelper.Invoke(rtb, () => { td = null; var start_doc = rtb.Document.ContentStart; var end_doc = rtb.Document.ContentStart; if (!start_doc.HasValidLayout || !end_doc.HasValidLayout) { return; } var td0 = rtb.GetTextData(eol); if (cnc.IsCancellationRequested) { return; } td = td0; clip_rect = new Rect(new Size(rtb.ViewportWidth, rtb.ViewportHeight)); TextPointer top_pointer = rtb.GetPositionFromPoint(new Point(0, 0), snapToText: true).GetLineStartPosition(-1, out int _); if (cnc.IsCancellationRequested) { return; } top_index = td.TextPointers.GetIndex(top_pointer, LogicalDirection.Backward); if (cnc.IsCancellationRequested) { return; } if (top_index < 0) { top_index = 0; } TextPointer bottom_pointer = rtb.GetPositionFromPoint(new Point(0, rtb.ViewportHeight), snapToText: true).GetLineStartPosition(+1, out int lines_skipped); if (cnc.IsCancellationRequested) { return; } if (bottom_pointer == null || lines_skipped == 0) { bottom_index = td.Text.Length; } else { bottom_index = td.TextPointers.GetIndex(bottom_pointer, LogicalDirection.Forward); if (cnc.IsCancellationRequested) { return; } } if (bottom_index > td.Text.Length) { bottom_index = td.Text.Length; } if (bottom_index < top_index) { bottom_index = top_index; // (including 'if bottom_index == 0') } }); if (cnc.IsCancellationRequested) { return; } if (td == null) { return; } if (td.Text.Length == 0) { return; } Debug.Assert(top_index >= 0); Debug.Assert(bottom_index >= top_index); Debug.Assert(bottom_index <= td.Text.Length); // (NOTE. Overlaps are possible in this example: (?=(..)) var segments_and_styles = new List <(Segment segment, StyleInfo styleInfo)>( ); var segments_to_uncolour = new List <Segment>( ); segments_to_uncolour.Add(new Segment(top_index, bottom_index - top_index + 1)); if (matches != null && matches.Count > 0) { int i = -1; foreach (var match in matches.Matches) { ++i; if (cnc.IsCancellationRequested) { break; } Debug.Assert(match.Success); // TODO: consider these conditions for bi-directional text if (match.TextIndex + match.TextLength < top_index) { continue; } if (match.TextIndex > bottom_index) { continue; // (do not break; the order of indices is unspecified) } var highlight_index = unchecked (i % HighlightStyleInfos.Length); Segment.Except(segments_to_uncolour, match.TextIndex, match.TextLength); segments_and_styles.Add((new Segment(match.TextIndex, match.TextLength), HighlightStyleInfos[highlight_index])); } } if (cnc.IsCancellationRequested) { return; } List <(Segment segment, StyleInfo styleInfo)> segments_to_uncolour_with_style = segments_to_uncolour .Select(s => (s, NormalStyleInfo)) .ToList( ); if (cnc.IsCancellationRequested) { return; } int center_index = (top_index + bottom_index) / 2; var all_segments_and_styles = segments_and_styles.Concat(segments_to_uncolour_with_style) .OrderBy(s => Math.Abs(center_index - (s.segment.Index + s.segment.Length / 2))) .ToList( ); if (cnc.IsCancellationRequested) { return; } RtbUtilities.ApplyStyle(cnc, ChangeEventHelper, pbProgress, td, all_segments_and_styles); if (cnc.IsCancellationRequested) { return; } UITaskHelper.BeginInvoke(pbProgress, () => { pbProgress.Visibility = Visibility.Hidden; }); }
void RecolouringThreadProc(ICancellable cnc) { IRegexEngine regex_engine; string eol; lock (this) { regex_engine = mRegexEngine; eol = mEol; } if (regex_engine == null) { return; } TextData td = null; Rect clip_rect = Rect.Empty; int top_index = 0; int bottom_index = 0; UITaskHelper.Invoke(rtb, () => { td = null; var start_doc = rtb.Document.ContentStart; var end_doc = rtb.Document.ContentStart; if (!start_doc.HasValidLayout || !end_doc.HasValidLayout) { return; } var td0 = rtb.GetTextData(eol); if (cnc.IsCancellationRequested) { return; } td = td0; clip_rect = new Rect(new Size(rtb.ViewportWidth, rtb.ViewportHeight)); TextPointer top_pointer = rtb.GetPositionFromPoint(new Point(0, 0), snapToText: true).GetLineStartPosition(-1, out int _); if (cnc.IsCancellationRequested) { return; } top_index = td.TextPointers.GetIndex(top_pointer, LogicalDirection.Backward); if (cnc.IsCancellationRequested) { return; } if (top_index < 0) { top_index = 0; } TextPointer bottom_pointer = rtb.GetPositionFromPoint(new Point(0, rtb.ViewportHeight), snapToText: true).GetLineStartPosition(+1, out int lines_skipped); if (cnc.IsCancellationRequested) { return; } if (bottom_pointer == null || lines_skipped == 0) { bottom_index = td.Text.Length; } else { bottom_index = td.TextPointers.GetIndex(bottom_pointer, LogicalDirection.Forward); if (cnc.IsCancellationRequested) { return; } } if (bottom_index > td.Text.Length) { bottom_index = td.Text.Length; } if (bottom_index < top_index) { bottom_index = top_index; // (including 'if bottom_index == 0') } }); if (cnc.IsCancellationRequested) { return; } if (td == null) { return; } if (td.Text.Length == 0) { return; } Debug.Assert(top_index >= 0); Debug.Assert(bottom_index >= top_index); //Debug.Assert( bottom_index < td.OldPointers.Count ); Debug.Assert(bottom_index <= td.Text.Length); var visible_segment = new Segment(top_index, bottom_index - top_index + 1); var segments_to_colourise = new ColouredSegments( ); regex_engine.ColourisePattern(cnc, segments_to_colourise, td.Text, visible_segment); if (cnc.IsCancellationRequested) { return; } int center_index = (top_index + bottom_index) / 2; var arranged_escapes = segments_to_colourise.Escapes .OrderBy(s => Math.Abs(center_index - (s.Index + s.Length / 2))) .ToList( ); RtbUtilities.ApplyStyle(cnc, ChangeEventHelper, null, td, segments_to_colourise.Comments, PatternCommentStyleInfo); RtbUtilities.ApplyStyle(cnc, ChangeEventHelper, null, td, arranged_escapes, PatternEscapeStyleInfo); RtbUtilities.ApplyStyle(cnc, ChangeEventHelper, null, td, segments_to_colourise.GroupNames, PatternGroupNameStyleInfo); var uncovered_segments = new List <Segment> { new Segment(0, td.Text.Length) }; foreach (var s in segments_to_colourise.All.SelectMany(s => s)) { if (cnc.IsCancellationRequested) { return; } Segment.Except(uncovered_segments, s); } Segment.Except(uncovered_segments, LeftHighlightedParenthesis); Segment.Except(uncovered_segments, RightHighlightedParenthesis); Segment.Except(uncovered_segments, LeftHighlightedBracket); Segment.Except(uncovered_segments, RightHighlightedBracket); Segment.Except(uncovered_segments, LeftHighlightedCurlyBrace); Segment.Except(uncovered_segments, RightHighlightedCurlyBrace); var segments_to_uncolour = uncovered_segments .Select(s => Segment.Intersection(s, visible_segment)) .Where(s => !s.IsEmpty) .OrderBy(s => Math.Abs(center_index - (s.Index + s.Length / 2))) .ToList( ); if (cnc.IsCancellationRequested) { return; } RtbUtilities.ApplyStyle(cnc, ChangeEventHelper, null, td, segments_to_uncolour, PatternNormalStyleInfo); }