void HideIndeterminateProgress(Thread indeterminateProgressThread) { try { indeterminateProgressThread.Interrupt( ); indeterminateProgressThread.Join(333); indeterminateProgressThread.Abort( ); } catch (Exception exc) { _ = exc; if (Debugger.IsAttached) { Debugger.Break( ); } // ignore } UITaskHelper.BeginInvoke(this, CancellationToken.None, () => { ucMatches.ShowIndeterminateProgress(false); }); }
void ShowTextInfoThreadProc(ICancellable cnc) { UITaskHelper.BeginInvoke(this, () => { var td = ucText.GetTextData(GetEolOption( )); if (cnc.IsCancellationRequested) { return; } lblTextInfo.Visibility = lblTextInfo.Visibility == Visibility.Visible || td.Text.Length != 0 ? Visibility.Visible : Visibility.Collapsed; if (lblTextInfo.Visibility == Visibility.Visible) { int text_elements = td.LengthInTextElements; string s = $"(Length: {td.Text.Length:#,##0}"; if (text_elements != td.Text.Length) { s += $", Text Elements: {text_elements:#,##0}"; } if (ucTextHadFocus) { s += $", Index: {td.SelectionStart:#,##0}"; } s += ")"; lblTextInfo.Text = s; } }); }
void IndeterminateProgressThreadProc( ) { try { Thread.Sleep(2222); UITaskHelper.Invoke(this, CancellationToken.None, () => { ucMatches.ShowIndeterminateProgress(true); ucMatches.ShowInfo("The engine is busy, please wait…", true); ucText.SetMatches(RegexMatches.Empty, cbShowCaptures.IsChecked == true, GetEolOption( )); }); } catch (ThreadInterruptedException) { // ignore } catch (ThreadAbortException) { // ignore } catch (Exception exc) { _ = exc; if (Debugger.IsAttached) { Debugger.Break( ); } // ignore } }
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; }); }
bool CollectEof(ICancellable cnc, TextData td, Rect clip_rect, int top_index) { if (cnc.IsCancellationRequested) { return(false); } var rtb = Rtb; double max_x = double.NaN; Rect end_rect = Rect.Empty; UITaskHelper.Invoke(rtb, () => { var end = rtb.Document.ContentEnd; end_rect = end.GetCharacterRect(LogicalDirection.Forward); // (no width) if (end_rect.Bottom < clip_rect.Top || end_rect.Top > clip_rect.Bottom) { return; } max_x = end_rect.Left; // if no RTL, then return a quick answer var begin_line = end.GetLineStartPosition(0); if (begin_line != null) { var r = new TextRange(begin_line, end); var text = r.Text; bool has_RTL = false; for (int k = 0; k < text.Length; ++k) { if (cnc.IsCancellationRequested) { return; } if (UnicodeUtilities.IsRTL(text[k])) { has_RTL = true; break; } } if (!has_RTL) { return; } } // we have RTL segments that need additional navigation to find the rightmost X for (var tp = end; ;) { if (cnc.IsCancellationRequested) { return; } tp = tp.GetNextInsertionPosition(LogicalDirection.Backward); if (tp == null) { break; } // WORKAROUND for lines like "0ראל", when "0" is matched and highlighted tp = tp.GetInsertionPosition(LogicalDirection.Forward); var rect = tp.GetCharacterRect(LogicalDirection.Forward); if (rect.Bottom < end_rect.Bottom) { break; } if (max_x < rect.Left) { max_x = rect.Left; } } }); if (cnc.IsCancellationRequested) { return(false); } lock (this) { if (double.IsNaN(max_x)) { PositionEof = Rect.Empty; } else { PositionEof = new Rect(new Point(max_x, end_rect.Top), end_rect.Size); PositionEof.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); } } DelayedInvalidateVisual( ); return(true); }
bool CollectEols(ICancellable cnc, TextData td, Rect clip_rect, int top_index) { if (cnc.IsCancellationRequested) { return(false); } var rtb = Rtb; List <Rect> positions_eols = new List <Rect>( ); // lines with no right-to-left segments var matches = EolRegex.Matches(td.Text); for (int i = 0; i < matches.Count; ++i) { if (cnc.IsCancellationRequested) { return(false); } int index = matches[i].Index; if (index < top_index) { continue; } int previous_index = i == 0 ? 0 : matches[i - 1].Index; bool has_RTL = false; for (int k = previous_index; k < index; ++k) { if (cnc.IsCancellationRequested) { return(false); } if (UnicodeUtilities.IsRTL(td.Text[k])) { has_RTL = true; break; } } if (has_RTL) { // RTL needs more navigation to find the rightmost X Rect left_rect = Rect.Empty; double max_x = double.NaN; bool should_continue = false; bool should_break = false; UITaskHelper.Invoke(rtb, () => { TextPointer left = td.TextPointers.GetTextPointer(index); left_rect = left.GetCharacterRect(LogicalDirection.Forward); if (left_rect.Bottom < clip_rect.Top) { should_continue = true; return; } if (left_rect.Top > clip_rect.Bottom) { should_break = true; return; } max_x = left_rect.Left; for (var tp = left.GetInsertionPosition(LogicalDirection.Backward); ;) { if (cnc.IsCancellationRequested) { return; } tp = tp.GetNextInsertionPosition(LogicalDirection.Backward); if (tp == null) { break; } // WORKAROUND for lines like "0ראל", when "0" is matched and highlighted tp = tp.GetInsertionPosition(LogicalDirection.Forward); var rect_b = tp.GetCharacterRect(LogicalDirection.Backward); var rect_f = tp.GetCharacterRect(LogicalDirection.Forward); if (cnc.IsCancellationRequested) { return; } if (rect_b.Bottom < left_rect.Top && rect_f.Bottom < left_rect.Top) { break; } if (rect_b.Bottom > left_rect.Top) { if (max_x < rect_b.Left) { max_x = rect_b.Left; } } if (rect_f.Bottom > left_rect.Top) { if (max_x < rect_f.Left) { max_x = rect_f.Left; } } } }); if (cnc.IsCancellationRequested) { return(false); } if (should_continue) { continue; } if (should_break) { break; } Rect eol_rect = new Rect(new Point(max_x, left_rect.Top), left_rect.Size); eol_rect.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); positions_eols.Add(eol_rect); } else { // no RTL; quick answer Rect eol_rect = Rect.Empty; UITaskHelper.Invoke(rtb, () => { TextPointer left = td.TextPointers.GetTextPointer(index); eol_rect = left.GetCharacterRect(LogicalDirection.Forward); }); if (eol_rect.Bottom < clip_rect.Top) { continue; } if (eol_rect.Top > clip_rect.Bottom) { break; } eol_rect.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); positions_eols.Add(eol_rect); } } if (cnc.IsCancellationRequested) { return(false); } lock (this) { PositionsEols = positions_eols; } DelayedInvalidateVisual( ); return(true); }
bool CollectSpaces(ICancellable cnc, TextData td, Rect clipRect, int topIndex) { if (cnc.IsCancellationRequested) { return(false); } var rtb = Rtb; List <Rect> positions_spaces = new List <Rect>( ); List <Rect> positions_tabs = new List <Rect>( ); List <int> indices = new List <int>( ); for (var i = td.Text.IndexOfAny(SpacesAndTabs, topIndex); i >= 0; i = td.Text.IndexOfAny(SpacesAndTabs, i + 1)) { if (cnc.IsCancellationRequested) { return(false); } indices.Add(i); } var intermediate_results1 = new List <(int index, Rect left, Rect right)>( ); var intermediate_results2 = new List <(int index, Rect left, Rect right)>( ); int current_i = 0; void do_things( ) { Debug.Assert(!intermediate_results1.Any( )); var end_time = Environment.TickCount + 22; do { if (current_i >= indices.Count) { break; } if (cnc.IsCancellationRequested) { return; } var index = indices[current_i]; var tps = td.TextPointers.GetTextPointers(index, index + 1); var left = tps.Item1; var right = tps.Item2; var left_rect = left.GetCharacterRect(LogicalDirection.Forward); var right_rect = right.GetCharacterRect(LogicalDirection.Backward); intermediate_results1.Add((index, left_rect, right_rect)); if (left_rect.Top > clipRect.Bottom) { break; } ++current_i; } while(Environment.TickCount < end_time); } if (cnc.IsCancellationRequested) { return(false); } var d = UITaskHelper.BeginInvoke(rtb, do_things); for (; ;) { d.Wait( ); if (cnc.IsCancellationRequested) { return(false); } (intermediate_results1, intermediate_results2) = (intermediate_results2, intermediate_results1); if (!intermediate_results2.Any( )) { break; } d = UITaskHelper.BeginInvoke(rtb, do_things); bool should_break = false; Debug.Assert(!Rtb.Dispatcher.CheckAccess( )); foreach (var(index, left_rect, right_rect) in intermediate_results2) { if (cnc.IsCancellationRequested) { return(false); } if (right_rect.Bottom < clipRect.Top) { continue; } if (left_rect.Top > clipRect.Bottom) { should_break = true; break; } switch (td.Text[index]) { case '\t': positions_tabs.Add(Rect.Offset(left_rect, rtb.HorizontalOffset, rtb.VerticalOffset)); break; default: // (space) var r = new Rect(left_rect.TopLeft, right_rect.BottomRight); r.Offset(rtb.HorizontalOffset, rtb.VerticalOffset); positions_spaces.Add(r); break; } } if (should_break) { break; } intermediate_results2.Clear( ); } if (cnc.IsCancellationRequested) { return(false); } lock (this) { PositionsSpaces = positions_spaces; PositionsTabs = positions_tabs; } DelayedInvalidateVisual( ); return(true); }
void ThreadProc(ICancellable cnc) { if (!mShowWhitespaces) { return; } var rtb = Rtb; TextData td = null; Rect clip_rect = Rect.Empty; int top_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(null); if (cnc.IsCancellationRequested) { return; } td = td0; clip_rect = new Rect(new Size(rtb.ViewportWidth, rtb.ViewportHeight)); TextPointer start_pointer = rtb.GetPositionFromPoint(new Point(0, 0), snapToText: true).GetLineStartPosition(-1, out int unused); top_index = td.TextPointers.GetIndex(start_pointer, LogicalDirection.Backward); if (top_index < 0) { top_index = 0; } }); if (cnc.IsCancellationRequested) { return; } if (td != null) { CollectEols(cnc, td, clip_rect, top_index); if (cnc.IsCancellationRequested) { return; } CollectEof(cnc, td, clip_rect, top_index); if (cnc.IsCancellationRequested) { return; } CollectSpaces(cnc, td, clip_rect, top_index); } }
void UpdateWhitespaceWarningThreadProc(ICancellable cnc) { bool has_whitespaces = false; bool show_whitespaces_option = false; string eol = null; BaseTextData td = null; UITaskHelper.Invoke(this, () => { show_whitespaces_option = cbShowWhitespaces.IsChecked == true; eol = GetEolOption( ); td = ucPattern.GetBaseTextData(eol); if (cnc.IsCancellationRequested) { return; } }); if (cnc.IsCancellationRequested) { return; } has_whitespaces = RegexHasWhitespace.IsMatch(td.Text); if (!has_whitespaces) { UITaskHelper.Invoke(this, () => { td = ucText.GetBaseTextData(eol); }); has_whitespaces = RegexHasWhitespace.IsMatch(td.Text); } bool show1 = false; bool show2 = false; if (show_whitespaces_option) { if (has_whitespaces) { show2 = true; } } else { if (has_whitespaces) { show1 = true; } } UITaskHelper.Invoke(this, () => { if (show1 && lblWhitespaceWarning1.Parent == null) { lblWarnings.Inlines.Add(lblWhitespaceWarning1); } if (!show1 && lblWhitespaceWarning1.Parent != null) { lblWarnings.Inlines.Remove(lblWhitespaceWarning1); } if (show2 && lblWhitespaceWarning2.Parent == null) { lblWarnings.Inlines.Add(lblWhitespaceWarning2); } if (!show2 && lblWhitespaceWarning2.Parent != null) { lblWarnings.Inlines.Remove(lblWhitespaceWarning2); } }); }
void FindMatchesThreadProc(ICancellable cnc) { string eol = null; string pattern = null; string text = null; bool first_only = false; IRegexEngine engine = null; UITaskHelper.Invoke(this, () => { eol = GetEolOption( ); pattern = ucPattern.GetBaseTextData(eol).Text; if (cnc.IsCancellationRequested) { return; } text = ucText.GetBaseTextData(eol).Text; if (cnc.IsCancellationRequested) { return; } first_only = cbShowFirstOnly.IsChecked == true; engine = CurrentRegexEngine; }); if (cnc.IsCancellationRequested) { return; } if (string.IsNullOrEmpty(pattern)) { UITaskHelper.BeginInvoke(this, () => { ucText.SetMatches(RegexMatches.Empty, cbShowCaptures.IsChecked == true, GetEolOption( )); ucMatches.ShowNoPattern( ); lblMatches.Text = "Matches"; pnlShowAll.Visibility = Visibility.Collapsed; pnlShowFirst.Visibility = Visibility.Collapsed; }); } else { IMatcher parsed_pattern = null; RegexMatches matches = null; bool is_good = false; try { UITaskHelper.BeginInvoke(this, CancellationToken.None, () => ucMatches.ShowMatchingInProgress(true)); parsed_pattern = engine.ParsePattern(pattern); var indeterminate_progress_thread = new Thread(IndeterminateProgressThreadProc) { IsBackground = true }; try { indeterminate_progress_thread.Start( ); matches = parsed_pattern.Matches(text, cnc); } finally { HideIndeterminateProgress(indeterminate_progress_thread); } is_good = true; } catch (Exception exc) { if (cnc.IsCancellationRequested) { return; } UITaskHelper.BeginInvoke(this, CancellationToken.None, () => { ucText.SetMatches(RegexMatches.Empty, cbShowCaptures.IsChecked == true, GetEolOption( )); ucMatches.ShowError(exc, engine.Capabilities.HasFlag(RegexEngineCapabilityEnum.ScrollErrorsToEnd)); lblMatches.Text = "Error"; pnlShowAll.Visibility = Visibility.Collapsed; pnlShowFirst.Visibility = Visibility.Collapsed; }); Debug.Assert(!is_good); } finally { UITaskHelper.BeginInvoke(this, CancellationToken.None, () => ucMatches.ShowMatchingInProgress(false)); } if (cnc.IsCancellationRequested) { return; } if (is_good) { int count = matches.Count; var matches_to_show = first_only ? new RegexMatches(Math.Min(1, count), matches.Matches.Take(1)) : matches; if (cnc.IsCancellationRequested) { return; } UITaskHelper.BeginInvoke(this, () => { ucText.SetMatches(matches_to_show, cbShowCaptures.IsChecked == true, GetEolOption( )); ucMatches.SetMatches(text, matches_to_show, first_only, cbShowSucceededGroupsOnly.IsChecked == true, cbShowCaptures.IsChecked == true); lblMatches.Text = count == 0 ? "Matches" : count == 1 ? "1 match" : $"{count:#,##0} matches"; pnlShowAll.Visibility = first_only && count > 1 ? Visibility.Visible : Visibility.Collapsed; pnlShowFirst.Visibility = !first_only && count > 1 ? Visibility.Visible : Visibility.Collapsed; }); } } }
public ViewModelBase() { _uiTaskHelper = new UITaskHelper(); _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); }
void HighlightingThreadProc(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; bool is_focused = false; 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 (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') } is_focused = rtb.IsFocused; }); 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); Highlights highlights = null; if (is_focused) { var visible_segment = new Segment(top_index, bottom_index - top_index + 1); highlights = new Highlights( ); regex_engine.HighlightPattern(cnc, highlights, td.Text, td.SelectionStart, td.SelectionEnd, visible_segment); } if (cnc.IsCancellationRequested) { return; } lock ( Locker ) { ChangeEventHelper.Invoke(CancellationToken.None, () => { TryHighlight(ref LeftHighlightedParenthesis, highlights?.LeftPar ?? Segment.Empty, td, PatternParaHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } TryHighlight(ref RightHighlightedParenthesis, highlights?.RightPar ?? Segment.Empty, td, PatternParaHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } TryHighlight(ref LeftHighlightedBracket, highlights?.LeftBracket ?? Segment.Empty, td, PatternCharGroupBracketHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } TryHighlight(ref RightHighlightedBracket, highlights?.RightBracket ?? Segment.Empty, td, PatternCharGroupBracketHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } TryHighlight(ref LeftHighlightedCurlyBrace, highlights?.LeftCurlyBrace ?? Segment.Empty, td, PatternRangeCurlyBraceHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } TryHighlight(ref RightHighlightedCurlyBrace, highlights?.RightCurlyBrace ?? Segment.Empty, td, PatternRangeCurlyBraceHighlightStyleInfo); if (cnc.IsCancellationRequested) { return; } }); } }
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); }