Пример #1
0
        public void InsertCharacters(int index, string chars, TerminalFont font)
        {
            lock (this)
            {
                if (chars.Length == 0)
                {
                    return;
                }
                if (length < index)
                {
                    extend(index);
                }

                int runIndex = 0;
                for (int i = 0; i < runs.Count; ++i)
                {
                    var run = runs[i];

                    if (runIndex + run.Text.Length >= index)
                    {
                        if (run.Font == font)
                        {
                            run.Text = run.Text.Insert(index - runIndex, chars);
                        }
                        else
                        {
                            var newRun = new TerminalRun()
                            {
                                Text = chars,
                                Font = font
                            };

                            var splitRun = new TerminalRun()
                            {
                                Text = run.Text.Substring(index - runIndex),
                                Font = run.Font
                            };
                            run.Text = run.Text.Substring(0, index - runIndex);
                            if (run.Text.Length == 0)
                            {
                                run.Text = newRun.Text;
                                run.Font = newRun.Font;

                                if (splitRun.Text.Length > 0)
                                {
                                    runs.Insert(i + 1, splitRun);
                                }
                            }
                            else if (splitRun.Text.Length > 0)
                            {
                                runs.InsertRange(i + 1, new[] { newRun, splitRun });
                            }
                            else
                            {
                                runs.Insert(i + 1, newRun);
                            }
                        }
                        break;
                    }

                    runIndex += run.Text.Length;
                }
                savedRuns = null;
            }

            if (RunsChanged != null)
            {
                RunsChanged(this, EventArgs.Empty);
            }
        }
Пример #2
0
        /// <summary>
        /// Replaces the characters on this line in the range [<paramref name="index"/>,
        /// <paramref name="index"/> + <paramref name="chars"/>.Length) with those in
        /// <paramref name="chars"/>.
        ///
        /// If the run at (<paramref name="index"/> - 1) or (<paramref name="index"/> +
        /// <paramref name="chars"/>.Length) has the same font as <paramref name="font"/>,
        /// it will be extended to include the new characters.  Otherwise, a new run will
        /// be created.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="chars"></param>
        /// <param name="font"></param>
        public void SetCharacters(int index, string chars, TerminalFont font)
        {
            lock (this)
            {
                if (chars.Length == 0)
                {
                    return;
                }
                if (length < index + chars.Length)
                {
                    extend(index + chars.Length);
                }

                int totalIndex = 0;
                for (int i = 0; i < runs.Count; ++i)
                {
                    var run = runs[i];

                    // Completely replacing an existing run
                    if (index == totalIndex && chars.Length == run.Text.Length)
                    {
                        run.Text = chars;
                        run.Font = font;

                        break;
                    }
                    // Inside an existing run
                    else if (index >= totalIndex && index < totalIndex + run.Text.Length)
                    {
                        int newLength = Math.Min(chars.Length, totalIndex + run.Text.Length - index);
                        var newRun    = new TerminalRun()
                        {
                            Text = chars.Substring(0, newLength),
                            Font = font
                        };

                        var splitRun = new TerminalRun()
                        {
                            Text = run.Text.Substring(index - totalIndex + newLength),
                            Font = run.Font
                        };
                        run.Text = run.Text.Substring(0, index - totalIndex);
                        if (run.Text.Length == 0)
                        {
                            run.Text = newRun.Text;
                            run.Font = newRun.Font;

                            if (splitRun.Text.Length > 0)
                            {
                                runs.Insert(i + 1, splitRun);
                            }
                        }
                        else if (splitRun.Text.Length > 0)
                        {
                            runs.InsertRange(i + 1, new[] { newRun, splitRun });
                        }
                        else
                        {
                            runs.Insert(i + 1, newRun);
                        }

                        if (newLength != chars.Length)
                        {
                            SetCharacters(index + newLength, chars.Substring(newLength), font);
                        }

                        break;
                    }
                    totalIndex += run.Text.Length;
                }

                Color black = Color.FromRgb(0, 0, 0);

                for (int i = 0; i < runs.Count - 1; ++i)
                {
                    var run1 = runs[i];
                    var run2 = runs[i + 1];

                    bool specialMerge =
                        run1.Font.Background == run2.Font.Background &&
                        run1.Font.Inverse == run2.Font.Inverse &&
                        (run2.Font.Hidden || run2.Text == " ");

                    if (run1.Font == run2.Font || specialMerge)
                    {
                        if (specialMerge)
                        {
                            run1.Text += new string(' ', run2.Text.Length);
                        }
                        else
                        {
                            run1.Text += run2.Text;
                        }
                        runs.RemoveAt(i + 1);
                        i--;
                    }
                }
                savedRuns = null;
            }

            if (RunsChanged != null)
            {
                RunsChanged(this, EventArgs.Empty);
            }
        }
Пример #3
0
        private void redraw(TerminalRun[] runs)
        {
            Dispatcher.VerifyAccess();

            //drawnRuns = new List<VisualRun>(runs.Length);
            //for (int i = 0; i < runs.Length; ++i)
            //{
            //	drawnRuns.Add(new VisualRun() { Run = runs[i], Text = null });
            //}
            bool changed = false;
            for (int i = 0; i < Math.Min(drawnRuns.Count, runs.Length); ++i)
            {
                if (drawnRuns[i].Run.Text != runs[i].Text || drawnRuns[i].Run.Font != runs[i].Font)
                {
                    drawnRuns[i] = new VisualRun() { Run = runs[i], Text = null };
                    changed = true;
                }
            }

            if (drawnRuns.Count > runs.Length)
                drawnRuns.RemoveRange(runs.Length, drawnRuns.Count - runs.Length);
            else if (drawnRuns.Count < runs.Length)
                drawnRuns.AddRange(runs.Skip(drawnRuns.Count).Select(x => new VisualRun() { Run = x }));
            else if (!changed && !selectionChanged)
                return;
            selectionChanged = false;

            for (int i = 0; i < drawnRuns.Count; ++i)
            {
                var run = drawnRuns[i].Run;
                if (drawnRuns[i].Text != null)
                    continue;

                SolidColorBrush foreground = Terminal.GetFontForegroundBrush(run.Font);

                // Format the text for this run.  However, this is drawn NEXT run.  The
                // background is drawn one run ahead of the text so the text doesn't get
                // clipped.
                var ft = new FormattedText(
                    run.Text,
                    System.Globalization.CultureInfo.CurrentUICulture,
                    Terminal.FlowDirection,
                    Terminal.GetFontTypeface(run.Font),
                    Terminal.FontSize,
                    foreground,
                    new NumberSubstitution(),
                    TextFormattingMode.Ideal
                    );

                if (run.Font.Underline || run.Font.Strike)
                {
                    var textDecorations = new TextDecorationCollection(2);

                    if (run.Font.Underline)
                        textDecorations.Add(TextDecorations.Underline);
                    if (run.Font.Strike)
                        textDecorations.Add(TextDecorations.Strikethrough);

                    ft.SetTextDecorations(textDecorations);
                }

                drawnRuns[i] = new VisualRun() { Run = drawnRuns[i].Run, Text = ft };
            }

            var context = RenderOpen();
            try
            {
                var drawPoint = new System.Windows.Point(0, 0);
                int index = 0;
                foreach (var run in drawnRuns)
                {
                    if (run.Run.Font.Hidden && index == drawnRuns.Count - 1)
                        break;

                    SolidColorBrush background = Terminal.GetFontBackgroundBrush(run.Run.Font);

                    // Draw the background and border for the current run
                    Pen border = null;
                    if (Terminal.DrawRunBoxes)
                        border = new Pen(DebugColors.GetBrush(index), 1);

                    var backgroundTopLeft = new System.Windows.Point(Math.Floor(drawPoint.X), Math.Floor(drawPoint.Y));
                    var backgroundSize = new Vector(Math.Floor(run.Text.WidthIncludingTrailingWhitespace), Math.Ceiling(run.Text.Height));
                    context.DrawRectangle(background, border, new Rect(backgroundTopLeft, backgroundSize));

                    drawPoint.X += run.Text.WidthIncludingTrailingWhitespace;

                    index++;
                }

                drawPoint = new System.Windows.Point(0, 0);
                index = 0;
                foreach (var run in drawnRuns)
                {
                    if (run.Run.Font.Hidden && index == drawnRuns.Count - 1)
                        break;

                    context.DrawText(run.Text, drawPoint);
                    drawPoint.X += run.Text.WidthIncludingTrailingWhitespace;

                    index++;
                }

                // TODO: This selection drawing logic doesn't account for multi-width characters.
                if (SelectionStart != SelectionEnd)
                {
                    var selectRect = new Rect(
                        new System.Windows.Point(Math.Floor(Math.Min(drawPoint.X, Terminal.CharWidth * SelectionStart)), 0.0),
                        new System.Windows.Point(Math.Ceiling(Math.Min(drawPoint.X, Terminal.CharWidth * SelectionEnd)), Math.Ceiling(Terminal.CharHeight)));

                    var brush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(128, 90, 180, 230));
                    context.DrawRectangle(brush, null, selectRect);
                }
            }
            finally
            {
                context.Close();
            }
        }
Пример #4
0
 TerminalRun[] CopyLine(TerminalLine line)
 {
     var runs = line.Runs;
     var result = new TerminalRun[runs.Count];
     for (int i = 0; i < runs.Count; ++i)
     {
         var run = runs[i];
         result[i] = new TerminalRun(run.Text, run.Font);
     }
     return result;
 }
Пример #5
0
		void AssertAreEqual(TerminalRun run1, TerminalRun run2)
		{
			Assert.AreEqual(run1.Text, run2.Text);
			Assert.AreEqual(run1.Font, run2.Font);
		}
Пример #6
0
        /// <summary>
        /// Replaces the characters on this line in the range [<paramref name="index"/>, 
        /// <paramref name="index"/> + <paramref name="chars"/>.Length) with those in 
        /// <paramref name="chars"/>.
        /// 
        /// If the run at (<paramref name="index"/> - 1) or (<paramref name="index"/> + 
        /// <paramref name="chars"/>.Length) has the same font as <paramref name="font"/>,
        /// it will be extended to include the new characters.  Otherwise, a new run will
        /// be created.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="chars"></param>
        /// <param name="font"></param>
        public void SetCharacters(int index, string chars, TerminalFont font)
        {
            lock (this)
            {
                if (chars.Length == 0)
                    return;
                if (length < index + chars.Length)
                    extend(index + chars.Length);

                int totalIndex = 0;
                for (int i = 0; i < runs.Count; ++i)
                {
                    var run = runs[i];

                    // Completely replacing an existing run
                    if (index == totalIndex && chars.Length == run.Text.Length)
                    {
                        run.Text = chars;
                        run.Font = font;

                        break;
                    }
                    // Inside an existing run
                    else if (index >= totalIndex && index < totalIndex + run.Text.Length)
                    {
                        int newLength = Math.Min(chars.Length, totalIndex + run.Text.Length - index);
                        var newRun = new TerminalRun()
                        {
                            Text = chars.Substring(0, newLength),
                            Font = font
                        };

                        var splitRun = new TerminalRun()
                        {
                            Text = run.Text.Substring(index - totalIndex + newLength),
                            Font = run.Font
                        };
                        run.Text = run.Text.Substring(0, index - totalIndex);
                        if (run.Text.Length == 0)
                        {
                            run.Text = newRun.Text;
                            run.Font = newRun.Font;

                            if (splitRun.Text.Length > 0)
                                runs.Insert(i + 1, splitRun);
                        }
                        else if (splitRun.Text.Length > 0)
                            runs.InsertRange(i + 1, new[] { newRun, splitRun });
                        else
                            runs.Insert(i + 1, newRun);

                        if (newLength != chars.Length)
                        {
                            SetCharacters(index + newLength, chars.Substring(newLength), font);
                        }

                        break;
                    }
                    totalIndex += run.Text.Length;
                }

                Color black = Color.FromRgb(0, 0, 0);

                for (int i = 0; i < runs.Count - 1; ++i)
                {
                    var run1 = runs[i];
                    var run2 = runs[i + 1];

                    bool specialMerge =
                        run1.Font.Background == run2.Font.Background &&
                        run1.Font.Inverse == run2.Font.Inverse &&
                        (run2.Font.Hidden || run2.Text == " ");

                    if (run1.Font == run2.Font || specialMerge)
                    {
                        if (specialMerge)
                            run1.Text += new string(' ', run2.Text.Length);
                        else
                            run1.Text += run2.Text;
                        runs.RemoveAt(i + 1);
                        i--;
                    }
                }
                savedRuns = null;
            }

            if (RunsChanged != null)
                RunsChanged(this, EventArgs.Empty);
        }
Пример #7
0
        public void InsertCharacters(int index, string chars, TerminalFont font)
        {
            lock (this)
            {
                if (chars.Length == 0)
                    return;
                if (length < index)
                    extend(index);

                int runIndex = 0;
                for (int i = 0; i < runs.Count; ++i)
                {
                    var run = runs[i];

                    if (runIndex + run.Text.Length >= index)
                    {
                        if (run.Font == font)
                        {
                            run.Text = run.Text.Insert(index - runIndex, chars);
                        }
                        else
                        {
                            var newRun = new TerminalRun()
                            {
                                Text = chars,
                                Font = font
                            };

                            var splitRun = new TerminalRun()
                            {
                                Text = run.Text.Substring(index - runIndex),
                                Font = run.Font
                            };
                            run.Text = run.Text.Substring(0, index - runIndex);
                            if (run.Text.Length == 0)
                            {
                                run.Text = newRun.Text;
                                run.Font = newRun.Font;

                                if (splitRun.Text.Length > 0)
                                    runs.Insert(i + 1, splitRun);
                            }
                            else if (splitRun.Text.Length > 0)
                                runs.InsertRange(i + 1, new[] { newRun, splitRun });
                            else
                                runs.Insert(i + 1, newRun);
                        }
                        break;
                    }

                    runIndex += run.Text.Length;
                }
                savedRuns = null;
            }

            if (RunsChanged != null)
                RunsChanged(this, EventArgs.Empty);
        }