public virtual void Render(TargetBase target)
        {
            if (!Show)
            {
                return;
            }

            IRenderableScreenCopy screenCopy = this.screen.GetScreenCopy();

            var context2D = target.DeviceManager.ContextDirect2D;

            context2D.BeginDraw();
            context2D.Transform = Matrix.Identity;
            context2D.Clear(TerminalBackgroundColor);

            RectangleF rect  = new RectangleF();
            var        lines = screenCopy.Cells;

            for (int y = 0; y < lines.Count(); y++)
            {
                var cols = lines[y];
                rect.Top    = y * CellHeight;
                rect.Bottom = rect.Top + CellHeight;
                for (int x = 0; x < cols.Count(); x++)
                {
                    var cell = cols[x];
                    rect.Left  = x * CellWidth;
                    rect.Right = rect.Left + CellWidth;

                    bool isCursor = !screenCopy.CursorHidden && y == screenCopy.CursorRow && x == screenCopy.CursorColumn;
                    this.DrawCell(target, rect, cell, isCursor, screenCopy.HasFocus);
                }
            }

            context2D.EndDraw();
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates the RTF for the currently displayed terminal screen content.
        /// </summary>
        /// <param name="screenCopy">The currently displayed terminal screen content.</param>
        /// <returns>The generate RTF async operation.</returns>
        private async Task<Tuple<InMemoryRandomAccessStream, float>> GenerateRtf(IRenderableScreenCopy screenCopy)
        {
            int rightmostNonSpace = -1;
            int columnCount = -1;
            Encoding codepage1252 = Encoding.GetEncoding("Windows-1252");
            var rtfStream = new InMemoryRandomAccessStream();
            using (DataWriter rtf = new DataWriter(rtfStream))
            {
                rtf.WriteString(@"{");
                rtf.WriteString(@"\rtf1");
                rtf.WriteString(@"\ansi");
                rtf.WriteString(@"\ansicpg1252");
                rtf.WriteString(@"{\fonttbl{\f0\fmodern " + this.screenDisplay.ColorTheme.FontFamily + ";}}");
                rtf.WriteString(Environment.NewLine);

                rtf.WriteString(@"{\colortbl ;");
                var colorTable = this.screenDisplay.ColorTheme.ColorTable;
                for (ScreenColor screenColor = ScreenColor.DefaultBackground; screenColor <= ScreenColor.WhiteBright; screenColor++)
                {
                    var color = colorTable[screenColor];
                    rtf.WriteString(@"\red" + color.R + @"\green" + color.G + @"\blue" + color.B + ";");
                }
                rtf.WriteString(@"}");
                rtf.WriteString(Environment.NewLine);

                int fontSize = (int)(ScreenDisplay.BaseLogicalFontMetrics[this.screenDisplay.ColorTheme.FontFamily].FontSize * (1 + (ScreenDisplay.FontSizeScalingFactor * (float)this.screenDisplay.ColorTheme.FontSize)));
                rtf.WriteString(@"\pard\ltrpar\f0\fs" + fontSize);
                rtf.WriteString(Environment.NewLine);

                StringBuilder formatCodes = new StringBuilder();
                for (int y = 0; y < screenCopy.Cells.Length; y++)
                {
                    var line = screenCopy.Cells[y];
                    string lineString = new string(line.Select(c => c.Character).ToArray());
                    var hyperlinkMatches = hyperlinkRegex.Value.Matches(lineString).Cast<Match>();

                    for (int x = 0; x < line.Length; x++)
                    {
                        Match startingMatch = hyperlinkMatches.Where(m => m.Index == x).SingleOrDefault();
                        if (startingMatch != null)
                        {
                            rtf.WriteString(@"{\field{\*\fldinst HYPERLINK """ + RtfEscape(startingMatch.Value) + @"""}{\fldrslt ");
                        }

                        if (x == 0 || line[x - 1].BackgroundColor != line[x].BackgroundColor)
                        {
                            formatCodes.Append(@"\chshdng0\chcbpat" + (line[x].BackgroundColor - ScreenColor.DefaultBackground + 1));
                        }

                        if (x == 0 || line[x - 1].ForegroundColor != line[x].ForegroundColor)
                        {
                            formatCodes.Append(@"\cf" + (line[x].ForegroundColor - ScreenColor.DefaultBackground + 1));
                        }

                        if (x == 0 || line[x - 1].Modifications.HasFlag(ScreenCellModifications.Bold) != line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                        {
                            formatCodes.Append(@"\b");
                            if (!line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                            {
                                formatCodes.Append("0");
                            }
                        }

                        if (x == 0 || line[x - 1].Modifications.HasFlag(ScreenCellModifications.Underline) != line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                        {
                            formatCodes.Append(@"\ul");
                            if (!line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                            {
                                formatCodes.Append("0");
                            }
                        }

                        if (formatCodes.Length > 0)
                        {
                            rtf.WriteString(formatCodes.ToString());
                            formatCodes.Clear();
                            rtf.WriteString(" ");
                        }

                        if (line[x].Character == CjkWidth.UCSWIDE)
                        {
                            // don't write this
                        }
                        else if (line[x].Character == codepage1252.GetChars(codepage1252.GetBytes(new[] { line[x].Character }))[0])
                        {
                            rtf.WriteBytes(codepage1252.GetBytes(RtfEscape(line[x].Character.ToString())));
                        }
                        else
                        {
                            rtf.WriteString(@"\u" + ((int)line[x].Character).ToString() + "?");
                        }

                        Match endingMatch = hyperlinkMatches.Where(m => m.Index + m.Length == x + 1).SingleOrDefault();
                        if (endingMatch != null)
                        {
                            rtf.WriteString("}}");
                        }

                        if (x + 1 >= line.Length)
                        {
                            if (line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                            {
                                formatCodes.Append(@"\b0");
                            }
                            if (line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                            {
                                formatCodes.Append(@"\ul0");
                            }
                        }

                        if (line[x].Character != 0x0020)
                        {
                            rightmostNonSpace = Math.Max(rightmostNonSpace, x);
                        }
                    }

                    if (formatCodes.Length > 0)
                    {
                        rtf.WriteString(formatCodes.ToString());
                        formatCodes.Clear();
                    }

                    if (y + 1 < screenCopy.Cells.Length)
                    {
                        rtf.WriteString(@"\par" + Environment.NewLine);
                    }

                    columnCount = Math.Max(columnCount, line.Length);
                }

                rtf.WriteString(@"}");

                await rtf.StoreAsync();
                await rtf.FlushAsync();
                rtf.DetachStream();
            }

            rtfStream.Seek(0);

            float widthRatio = rightmostNonSpace >= 0 ? (rightmostNonSpace + 1f) / columnCount : -1f;

            return new Tuple<InMemoryRandomAccessStream, float>(rtfStream, widthRatio);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Renders the screen.
        /// </summary>
        /// <param name="target">The Direct2D drawing target.</param>
        public virtual void Render(TargetBase target)
        {
            Point drawingPosition = new Point(0, 0);
            SurfaceImageSourceTarget surfaceImageSourceTarget = target as SurfaceImageSourceTarget;

            if (surfaceImageSourceTarget != null)
            {
                drawingPosition = surfaceImageSourceTarget.DrawingPosition;
            }

            IRenderableScreenCopy screenCopy = this.screen.GetScreenCopy();

            var context2D = target.DeviceManager.ContextDirect2D;

            context2D.BeginDraw();
            context2D.Transform = Matrix.Identity;
            context2D.Clear(this.GetColor(ScreenColor.DefaultBackground));

            // 1. Paint backgrounds
            {
                RectangleF rect  = new RectangleF();
                var        lines = screenCopy.Cells;
                for (int y = 0; y < lines.Length; y++)
                {
                    var cols = lines[y];

                    rect.Top    = drawingPosition.Y + (y * this.physicalFontMetrics.CellHeight);
                    rect.Bottom = rect.Top + this.physicalFontMetrics.CellHeight;

                    ScreenColor currentBackgroundColor = cols.Length > 0 ? cols[0].BackgroundColor : ScreenColor.DefaultBackground;
                    ScreenColor cellBackgroundColor;
                    int         blockStart = 0;
                    for (int x = 0; x <= cols.Length; x++) // loop once above the upper bound
                    {
                        var cell = cols[x < cols.Length ? x : x - 1];

                        bool isCursor = !screenCopy.CursorHidden && y == screenCopy.CursorRow && x == screenCopy.CursorColumn;
                        cellBackgroundColor = isCursor ? ScreenColor.CursorBackground : cell.BackgroundColor;
                        if (cellBackgroundColor != currentBackgroundColor || x == cols.Length)
                        {
                            rect.Left  = drawingPosition.X + (blockStart * this.physicalFontMetrics.CellWidth);
                            rect.Right = drawingPosition.X + (x * this.physicalFontMetrics.CellWidth);

                            Brush backgroundBrush = this.GetBrush(context2D, this.GetColor(currentBackgroundColor));
                            if (currentBackgroundColor == ScreenColor.CursorBackground && !screenCopy.HasFocus)
                            {
                                rect.Right = rect.Right - 1.0f;
                                context2D.DrawRectangle(rect, backgroundBrush);
                            }
                            else
                            {
                                context2D.FillRectangle(rect, backgroundBrush);
                            }

                            blockStart = x;

                            currentBackgroundColor = cellBackgroundColor;
                        }
                    }
                }
            }

            // 2. Paint foregrounds
            {
                RectangleF rect  = new RectangleF();
                var        lines = screenCopy.Cells;
                for (int y = 0; y < lines.Length; y++)
                {
                    var cols = lines[y];

                    rect.Top    = drawingPosition.Y + (y * this.physicalFontMetrics.CellHeight);
                    rect.Bottom = rect.Top + this.physicalFontMetrics.CellHeight;

                    ScreenColor             currentForegroundColor   = cols.Length > 0 ? cols[0].ForegroundColor : ScreenColor.DefaultForeground;
                    ScreenCellModifications currentCellModifications = cols.Length > 0 ? cols[0].Modifications : ScreenCellModifications.None;
                    bool        currentCellUCSWIDE = cols.Length > 0 ? cols[0].Character == CjkWidth.UCSWIDE : false;
                    ScreenColor cellForegroundColor;
                    int         blockStart = 0;
                    for (int x = 0; x <= cols.Length; x++) // loop once above the upper bound
                    {
                        var cell = cols[x < cols.Length ? x : x - 1];

                        bool isCursor = !screenCopy.CursorHidden && y == screenCopy.CursorRow && x == screenCopy.CursorColumn;
                        cellForegroundColor = isCursor && screenCopy.HasFocus ? ScreenColor.CursorForeground : cell.ForegroundColor;
                        if (currentCellUCSWIDE || cellForegroundColor != currentForegroundColor || cell.Modifications != currentCellModifications || x == cols.Length)
                        {
                            rect.Left  = drawingPosition.X + (blockStart * this.physicalFontMetrics.CellWidth);
                            rect.Right = drawingPosition.X + (x * this.physicalFontMetrics.CellWidth);

                            Brush      foregroundBrush = this.GetBrush(context2D, this.GetColor(currentForegroundColor));
                            TextFormat textFormat      = this.textFormatNormal;
                            if (currentCellModifications.HasFlag(ScreenCellModifications.Bold))
                            {
                                textFormat = this.textFormatBold;
                            }

                            string text = new string(cols.Skip(blockStart).Take(x - blockStart).Select(c => char.IsWhiteSpace(c.Character) ? ' ' : c.Character).Where(ch => ch != CjkWidth.UCSWIDE).ToArray()).TrimEnd();

                            if (text.Length > 0)
                            {
                                context2D.DrawText(text, textFormat, rect, foregroundBrush, DrawTextOptions.Clip);
                            }

                            if (currentCellModifications.HasFlag(ScreenCellModifications.Underline))
                            {
                                var point1 = new Vector2(rect.Left, rect.Bottom - 1.0f) + drawingPosition;
                                var point2 = new Vector2(rect.Right, rect.Bottom - 1.0f) + drawingPosition;
                                context2D.DrawLine(point1, point2, foregroundBrush);
                            }

                            blockStart = x;

                            currentForegroundColor = cellForegroundColor;
                        }
                        currentCellUCSWIDE = cell.Character == CjkWidth.UCSWIDE;
                    }
                }
            }

            context2D.EndDraw();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generates the RTF for the currently displayed terminal screen content.
        /// </summary>
        /// <param name="screenCopy">The currently displayed terminal screen content.</param>
        /// <returns>The generate RTF async operation.</returns>
        private async Task <Tuple <InMemoryRandomAccessStream, float> > GenerateRtf(IRenderableScreenCopy screenCopy)
        {
            int      rightmostNonSpace = -1;
            int      columnCount       = -1;
            Encoding codepage1252      = Encoding.GetEncoding("Windows-1252");
            var      rtfStream         = new InMemoryRandomAccessStream();

            using (DataWriter rtf = new DataWriter(rtfStream))
            {
                rtf.WriteString(@"{");
                rtf.WriteString(@"\rtf1");
                rtf.WriteString(@"\ansi");
                rtf.WriteString(@"\ansicpg1252");
                rtf.WriteString(@"{\fonttbl{\f0\fmodern " + this.screenDisplay.ColorTheme.FontFamily + ";}}");
                rtf.WriteString(Environment.NewLine);

                rtf.WriteString(@"{\colortbl ;");
                var colorTable = this.screenDisplay.ColorTheme.ColorTable;
                for (ScreenColor screenColor = ScreenColor.DefaultBackground; screenColor <= ScreenColor.WhiteBright; screenColor++)
                {
                    var color = colorTable[screenColor];
                    rtf.WriteString(@"\red" + color.R + @"\green" + color.G + @"\blue" + color.B + ";");
                }
                rtf.WriteString(@"}");
                rtf.WriteString(Environment.NewLine);

                int fontSize = (int)(ScreenDisplay.BaseLogicalFontMetrics[this.screenDisplay.ColorTheme.FontFamily].FontSize * (1 + (ScreenDisplay.FontSizeScalingFactor * (float)this.screenDisplay.ColorTheme.FontSize)));
                rtf.WriteString(@"\pard\ltrpar\f0\fs" + fontSize);
                rtf.WriteString(Environment.NewLine);

                StringBuilder formatCodes = new StringBuilder();
                for (int y = 0; y < screenCopy.Cells.Length; y++)
                {
                    var    line             = screenCopy.Cells[y];
                    string lineString       = new string(line.Select(c => c.Character).ToArray());
                    var    hyperlinkMatches = hyperlinkRegex.Value.Matches(lineString).Cast <Match>();

                    for (int x = 0; x < line.Length; x++)
                    {
                        Match startingMatch = hyperlinkMatches.Where(m => m.Index == x).SingleOrDefault();
                        if (startingMatch != null)
                        {
                            rtf.WriteString(@"{\field{\*\fldinst HYPERLINK """ + RtfEscape(startingMatch.Value) + @"""}{\fldrslt ");
                        }

                        if (x == 0 || line[x - 1].BackgroundColor != line[x].BackgroundColor)
                        {
                            formatCodes.Append(@"\chshdng0\chcbpat" + (line[x].BackgroundColor - ScreenColor.DefaultBackground + 1));
                        }

                        if (x == 0 || line[x - 1].ForegroundColor != line[x].ForegroundColor)
                        {
                            formatCodes.Append(@"\cf" + (line[x].ForegroundColor - ScreenColor.DefaultBackground + 1));
                        }

                        if (x == 0 || line[x - 1].Modifications.HasFlag(ScreenCellModifications.Bold) != line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                        {
                            formatCodes.Append(@"\b");
                            if (!line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                            {
                                formatCodes.Append("0");
                            }
                        }

                        if (x == 0 || line[x - 1].Modifications.HasFlag(ScreenCellModifications.Underline) != line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                        {
                            formatCodes.Append(@"\ul");
                            if (!line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                            {
                                formatCodes.Append("0");
                            }
                        }

                        if (formatCodes.Length > 0)
                        {
                            rtf.WriteString(formatCodes.ToString());
                            formatCodes.Clear();
                            rtf.WriteString(" ");
                        }

                        if (line[x].Character == CjkWidth.UCSWIDE)
                        {
                            // don't write this
                        }
                        else if (line[x].Character == codepage1252.GetChars(codepage1252.GetBytes(new[] { line[x].Character }))[0])
                        {
                            rtf.WriteBytes(codepage1252.GetBytes(RtfEscape(line[x].Character.ToString())));
                        }
                        else
                        {
                            rtf.WriteString(@"\u" + ((int)line[x].Character).ToString() + "?");
                        }

                        Match endingMatch = hyperlinkMatches.Where(m => m.Index + m.Length == x + 1).SingleOrDefault();
                        if (endingMatch != null)
                        {
                            rtf.WriteString("}}");
                        }

                        if (x + 1 >= line.Length)
                        {
                            if (line[x].Modifications.HasFlag(ScreenCellModifications.Bold))
                            {
                                formatCodes.Append(@"\b0");
                            }
                            if (line[x].Modifications.HasFlag(ScreenCellModifications.Underline))
                            {
                                formatCodes.Append(@"\ul0");
                            }
                        }

                        if (line[x].Character != 0x0020)
                        {
                            rightmostNonSpace = Math.Max(rightmostNonSpace, x);
                        }
                    }

                    if (formatCodes.Length > 0)
                    {
                        rtf.WriteString(formatCodes.ToString());
                        formatCodes.Clear();
                    }

                    if (y + 1 < screenCopy.Cells.Length)
                    {
                        rtf.WriteString(@"\par" + Environment.NewLine);
                    }

                    columnCount = Math.Max(columnCount, line.Length);
                }

                rtf.WriteString(@"}");

                await rtf.StoreAsync();

                await rtf.FlushAsync();

                rtf.DetachStream();
            }

            rtfStream.Seek(0);

            float widthRatio = rightmostNonSpace >= 0 ? (rightmostNonSpace + 1f) / columnCount : -1f;

            return(new Tuple <InMemoryRandomAccessStream, float>(rtfStream, widthRatio));
        }