Пример #1
0
        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);
            });
        }
Пример #2
0
        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;
                }
            });
        }
Пример #3
0
        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;
            });
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
                    });
                }
            }
        }