Beispiel #1
0
        private static string Benchmark(int frameCount, IBufferedAbsConsole <CHAR_INFO> screen)
        {
            var r    = new Random();
            var stop = new Stopwatch();

            stop.Start();
            for (int i = 0; i < frameCount; i++)
            {
                var x   = r.Next(screen.Width);
                var y   = r.Next(screen.Height);
                var a   = r.Next(26);
                var clr = r.Next(0, 255);

                screen[x, y] = new CHAR_INFO(TestHelper.GetCharOffset('A', a), (ushort)clr);
                screen.Update();

                if (i % 50 == 0)
                {
                    System.Console.Title = i.ToString();
                }
            }

            stop.Stop();
            return($"{frameCount} frames in {stop.Elapsed} at {frameCount / stop.Elapsed.TotalSeconds} FPS");
        }
Beispiel #2
0
        protected override void Setup()
        {
            var letterA = new CHAR_INFO {
                AsciiChar = 'A',
            };

            letterA.Attributes = (UInt16)
                                 (FOREGROUND_RED | FOREGROUND_INTENSITY |
                                  BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY);

            var charBufSize = new COORD {
                X = 1,
                Y = 1,
            };
            var characterPos = new COORD {
                X = 0,
                Y = 0,
            };

            var writeArea = new SMALL_RECT {
                Left   = 0,
                Top    = 0,
                Right  = 0,
                Bottom = 0,
            };

            WriteConsoleOutput(
                WriteHandle, new CHAR_INFO[] { letterA }, charBufSize, characterPos, ref writeArea);
            Console.Write("\n");
        }
 public static extern bool ScrollConsoleScreenBuffer(
     IntPtr hConsoleOutput,
     [In] ref SMALL_RECT lpScrollRectangle,
     IntPtr lpClipRectangle,
     COORD dwDestinationOrigin,
     [In] ref CHAR_INFO lpFill
     );
Beispiel #4
0
        protected override void Setup()
        {
            var consoleBuffer = new CHAR_INFO[Width * Height];

            for (int h = 0; h < Height; ++h)
            {
                for (int w = 0; w < Width; ++w)
                {
                    consoleBuffer[w + Width * h].AsciiChar  = 'A' /*(char)Random.Next(256)*/;
                    consoleBuffer[w + Width * h].Attributes = (UInt16)Random.Next(256);
                }
            }

            var charBufSize = new COORD {
                X = Width,
                Y = Height,
            };
            var characterPos = new COORD {
                X = 0,
                Y = 0,
            };

            WriteConsoleOutput(
                WriteHandle, consoleBuffer, charBufSize, characterPos, ref WindowSize);
        }
Beispiel #5
0
        private CHAR_INFO[] CreateCharInfoBuffer(int lines, params object[] items)
        {
            var result = new List <CHAR_INFO>();
            var fg     = _console.ForegroundColor;
            var bg     = _console.BackgroundColor;

            foreach (var i in items)
            {
                var item = i;
                if (item is char)
                {
                    result.Add(new CHAR_INFO((char)item, fg, bg));
                    continue;
                }
                if (item is InvertedToken)
                {
                    fg = (ConsoleColor)((int)fg ^ 7);
                    bg = (ConsoleColor)((int)bg ^ 7);
                    continue;
                }
                if (item is NextLineToken)
                {
                    item = new string(' ', _console.BufferWidth - (result.Count % _console.BufferWidth));
                    fg   = _console.ForegroundColor;
                    bg   = _console.BackgroundColor;
                    // Fallthrough to string case.
                }
                if (item is string str)
                {
                    result.AddRange(str.Select(c => new CHAR_INFO(c, fg, bg)));
                    continue;
                }
                if (item is TokenClassification)
                {
                    fg = ForegroundColors[(int)(TokenClassification)item];
                    bg = BackgroundColors[(int)(TokenClassification)item];
                    continue;
                }
                if (item is Tuple <ConsoleColor, ConsoleColor> tuple)
                {
                    fg = tuple.Item1;
                    bg = tuple.Item2;
                    continue;
                }
                throw new ArgumentException("Unexpected type");
            }

            var extraSpacesNeeded = (lines * _console.BufferWidth) - result.Count;

            if (extraSpacesNeeded > 0)
            {
                var space = new CHAR_INFO(' ', _console.ForegroundColor, _console.BackgroundColor);
                result.AddRange(Enumerable.Repeat(space, extraSpacesNeeded));
            }

            return(result.ToArray());
        }
        public void SetChar()
        {
            const ConCharAttributes attribute = (ConCharAttributes)0xCCCC;
            CHAR_INFO source = new CHAR_INFO(' ', attribute);
            var       result = source.SetChar('x');

            result.Char.Should().Be('x');
            result.Attributes.Should().Be(attribute);
        }
        public void Setforeground()
        {
            const ConCharAttributes attribute = (ConCharAttributes)0xCCCC;
            const ConCharAttributes expected  = (ConCharAttributes)0xCCC0 | ConCharAttributes.ForeGroundGreen | ConCharAttributes.ForeGroundIntensity;
            CHAR_INFO source = new CHAR_INFO('x', attribute);
            var       result = source.SetForeground(ConsoleColor.Green);

            result.Char.Should().Be('x');
            result.Attributes.Should().Be(expected);
        }
Beispiel #8
0
 /// <summary>
 /// Renderer should call this method before any control render.
 /// </summary>
 public void Clear()
 {
     for (int x = 0; x < width; x++)
     {
         for (int y = 0; y < height; y++)
         {
             buffer[x, y]        = new CHAR_INFO();
             opacityMatrix[x, y] = 0;
         }
     }
 }
Beispiel #9
0
        public CHAR_INFO[] ReadConsoleOutput(ConsoleOutputHandle consoleOutputHandle, Rectangle region)
        {
            SMALL_RECT rect = new SMALL_RECT(region);

            CHAR_INFO[] buffer = new CHAR_INFO[region.Width * region.Height];
            if (!NativeMethods.ReadConsoleOutput(consoleOutputHandle, buffer, new COORD(region), default, ref rect))
            {
                throw Exceptions.Win32();
            }
            return(buffer);
        }
Beispiel #10
0
            static CHAR_INFO ToCharInfo(char c)
            {
                var info = new CHAR_INFO();

                // Give it our character to write
                info.Char.UnicodeChar = c;
                // Use our attributes
                info.Attributes = Attributes;
                // Return info for this character
                return(info);
            }
        //private char[,] buffer = new char[80, 25];

        private void initBuffer()
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    buffer[y, x] = new CHAR_INFO(  )
                    {
                        UnicodeChar = ' '
                    };
                }
            }
        }
Beispiel #12
0
        public void FillArea_CorrectArea_FilledCorrectly()
        {
            const char character  = 'X';
            Size       size       = new Size(4, 4);
            var        mainBuffer = Enumerable.Repeat(cc, 16).ToArray();
            CHAR_INFO  c0         = new CHAR_INFO
            {
                Attributes = attributes,
                Char       = character
            };
            var expectedBuffer = new[]
            {
                cc, cc, cc, cc,
                cc, c0, c0, cc,
                cc, c0, c0, cc,
                cc, cc, cc, cc
            };

            bool written = false, successful = false;

            using var stubbedApi = new StubbedNativeCalls();
            stubbedApi.ReadConsoleOutputConsoleOutputHandleRectangle = (handle, rectangle) =>
            {
                rectangle.Size.Should().Be(size);
                handle.Should().Be(stubbedApi.ScreenHandle);
                return(mainBuffer);
            };
            stubbedApi.WriteConsoleOutputConsoleOutputHandleCHAR_INFOArrayRectangle = (handle, buffer, area) =>
            {
                written = true;
                handle.Should().Be(stubbedApi.ScreenHandle);
                area.Size.Should().Be(size);
                buffer.Should().Equal(expectedBuffer);
                successful = true;
            };
            var sut = new ConControls.Controls.Drawing.ConsoleGraphics(stubbedApi.ScreenHandle, stubbedApi, size,
                                                                       new ConControls.Controls.Drawing.FrameCharSets());

            sut.FillArea(
                background: background,
                foreColor: foreground,
                c: character,
                area: new Rectangle(1, 1, 2, 2));

            written.Should().BeFalse();
            mainBuffer.Should().Equal(expectedBuffer);
            sut.Flush();
            written.Should().BeTrue();
            successful.Should().BeTrue();
        }
Beispiel #13
0
        internal void WriteOutputBuffer(char[] bufferChars, ConsoleColor[] bufferFg, ConsoleColor[] bufferBg, int width, int height, List <RowSpan> invalidSpans)
        {
            // This copying of the backbuffer data into a local CHAR_INFO array is a lot of
            // copying that might be a perf issue.  If so consider storing a CHAR_INFO array
            // directly in the BackBuffer class.
            var charinfos = new CHAR_INFO[bufferChars.Length];

            for (int i = 0; i < bufferChars.Length; i += 1)
            {
                charinfos[i].UnicodeChar = bufferChars[i];
                charinfos[i].Attributes  = CharInfoAttributeFromConsoleColors(bufferFg[i], bufferBg[i]);
            }

            COORD bufferSize;

            bufferSize.x = (short)width;
            bufferSize.y = (short)height;

            COORD      bufferCoord;
            SMALL_RECT writeRegion;

            if (invalidSpans == null)
            {
                writeRegion.Top    = 0;
                writeRegion.Left   = 0;
                writeRegion.Bottom = (short)(height - 1);
                writeRegion.Right  = (short)(width - 1);

                bufferCoord.x = 0;
                bufferCoord.y = 0;

                WriteConsoleOutput(_handleOut, charinfos, bufferSize, bufferCoord, ref writeRegion);
            }
            else
            {
                foreach (var span in invalidSpans)
                {
                    writeRegion.Top    = (short)span.Row;
                    writeRegion.Bottom = (short)span.Row;
                    writeRegion.Left   = (short)span.Start;
                    writeRegion.Right  = (short)(span.End - 1);

                    bufferCoord.y = writeRegion.Top;
                    bufferCoord.x = writeRegion.Left;

                    WriteConsoleOutput(_handleOut, charinfos, bufferSize, bufferCoord, ref writeRegion);
                }
            }
        }
Beispiel #14
0
        public static IEnumerable <string> ReadFromBuffer(short x, short y, short width, short height)
        {
            IntPtr buffer = Marshal.AllocHGlobal(width * height * Marshal.SizeOf(typeof(CHAR_INFO)));

            if (buffer == null)
            {
                throw new OutOfMemoryException();
            }

            try
            {
                COORD      coord = new COORD();
                SMALL_RECT rc    = new SMALL_RECT();
                rc.Left   = x;
                rc.Top    = y;
                rc.Right  = (short)(x + width - 1);
                rc.Bottom = (short)(y + height - 1);

                COORD size = new COORD();
                size.X = width;
                size.Y = height;

                const int STD_OUTPUT_HANDLE = -11;
                if (!ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buffer, size, coord, ref rc))
                {
                    // 'Not enough storage is available to process this command' may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                IntPtr ptr = buffer;
                for (int h = 0; h < height; h++)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int w = 0; w < width; w++)
                    {
                        CHAR_INFO ci    = (CHAR_INFO)Marshal.PtrToStructure(ptr, typeof(CHAR_INFO));
                        char[]    chars = Console.OutputEncoding.GetChars(ci.charData);
                        sb.Append(chars[0]);
                        ptr += Marshal.SizeOf(typeof(CHAR_INFO));
                    }
                    yield return(sb.ToString());
                }
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
Beispiel #15
0
        public override void ScrollBuffer(int lines)
        {
            var handle          = GetStdHandle((uint)StandardHandleId.Output);
            var scrollRectangle = new SMALL_RECT
            {
                Top    = (short)lines,
                Left   = 0,
                Bottom = (short)(Console.BufferHeight - 1),
                Right  = (short)Console.BufferWidth
            };
            var destinationOrigin = new COORD {
                X = 0, Y = 0
            };
            var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);

            ScrollConsoleScreenBuffer(handle, ref scrollRectangle, IntPtr.Zero, destinationOrigin, ref fillChar);
        }
Beispiel #16
0
        public static void DrawRectangle(int left, int top, int right, int bottom)
        {
            if (!AreScreenBufferArraysEqual(left, top, right, bottom))
            {
                int rows = bottom - top + 1;
                int cols = right - left + 1;

                CHAR_INFO[] rectBuf = new CHAR_INFO[rows * cols];

                int i = 0;
                for (int row = top; row <= bottom; row++)
                {
                    for (int col = left; col <= right; col++)
                    {
                        rectBuf[i++] = ScreenBuffer.screenBuf[(row * ScreenBuffer.cols) + col];
                    }
                }

                COORD rectBufSize = new COORD()
                {
                    X = (short)cols, Y = (short)rows
                };
                COORD rectBufCoord = new COORD()
                {
                    X = 0, Y = 0
                };

                SMALL_RECT rectangle = new SMALL_RECT()
                {
                    Left = (short)left, Top = (short)top, Right = (short)right, Bottom = (short)bottom
                };

                // note that the screen is NOT cleared at any point as this will simply
                // overwrite the existing values on screen. Clearing will cause flickering again.
                bool b = WriteConsoleOutput(
                    ScreenBuffer.handle,
                    rectBuf,
                    rectBufSize,
                    rectBufCoord,
                    ref rectangle);

                Array.Copy(ScreenBuffer.screenBuf, ScreenBuffer.screenBufCopy, ScreenBuffer.screenBuf.Length);
            }
        }
        public void DrawBackground_AreaTooLarge_ClippedCorrectly()
        {
            const char expectedCharacter = default;
            Size       size       = new Size(4, 4);
            var        mainBuffer = Enumerable.Repeat(cc, 16).ToArray();
            CHAR_INFO  c0         = new CHAR_INFO
            {
                Attributes = background.ToBackgroundColor() | background.ToForegroundColor(),
                Char       = expectedCharacter
            };
            var expectedBuffer = Enumerable.Repeat(c0, 16).ToArray();

            bool written = false, successful = false;

            using var stubbedApi = new StubbedNativeCalls();
            stubbedApi.ReadConsoleOutputConsoleOutputHandleRectangle = (handle, rectangle) =>
            {
                rectangle.Size.Should().Be(size);
                handle.Should().Be(stubbedApi.ScreenHandle);
                return(mainBuffer);
            };
            stubbedApi.WriteConsoleOutputConsoleOutputHandleCHAR_INFOArrayRectangle = (handle, buffer, area) =>
            {
                written = true;
                handle.Should().Be(stubbedApi.ScreenHandle);
                area.Size.Should().Be(size);
                buffer.Should().Equal(expectedBuffer);
                successful = true;
            };
            var sut = new ConControls.Controls.Drawing.ConsoleGraphics(stubbedApi.ScreenHandle, stubbedApi, size,
                                                                       new ConControls.Controls.Drawing.FrameCharSets());

            sut.DrawBackground(
                color: background,
                area: new Rectangle(-1, -1, 7, 7));

            written.Should().BeFalse();
            mainBuffer.Should().Equal(expectedBuffer);
            sut.Flush();
            written.Should().BeTrue();
            successful.Should().BeTrue();
        }
Beispiel #18
0
        private static void Main(string[] args)
        {
            uint   outChars;
            IntPtr consoleHandle = Process.GetCurrentProcess().MainWindowHandle;

            CConsole.WriteConsole(consoleHandle, "HELLO C WORLD FROM C#", 21, out outChars, new IntPtr(0));
            Console.WriteLine("OutputWrite testing:");
            CHAR_INFO[,] BufferData = new CHAR_INFO[8, 2];
            CHAR_INFO a = new CHAR_INFO {
                UnicodeChar = 'C'
            };
            SMALL_RECT writeBounds = new SMALL_RECT {
                Top = 3, Left = 2, Bottom = 5, Right = 10
            };

            CConsole.WriteConsoleOutput(consoleHandle, BufferData, new COORD {
                X = 8, Y = 2
            }, new COORD {
                X = 2, Y = 4
            }, ref writeBounds);
        }
Beispiel #19
0
        /// <summary>
        /// Копирует affectedRect из буфера на экран консоли с учетом того, что буфер
        /// находится на экране консоли по смещению offset.
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="affectedRect">Измененная область относительно this.</param>
        /// <param name="offset">В какой точке экрана размещен контрол (см <see cref="Renderer.RootElementRect"/>).</param>
        public void CopyToPhysicalCanvas(PhysicalCanvas canvas, Rect affectedRect, Point offset)
        {
            Rect rectToCopy = affectedRect;
            Rect bufferRect = new Rect(new Point(0, 0), new Size(this.width, this.height));
            Rect canvasRect = new Rect(new Point(-offset.X, -offset.Y), canvas.Size);

            rectToCopy.Intersect(canvasRect);
            rectToCopy.Intersect(bufferRect);
            //
            for (int x = 0; x < rectToCopy.width; x++)
            {
                int bufferX = x + rectToCopy.x;
                int canvasX = x + rectToCopy.x + offset.x;
                for (int y = 0; y < rectToCopy.height; y++)
                {
                    int       bufferY  = y + rectToCopy.y;
                    int       canvasY  = y + rectToCopy.y + offset.y;
                    CHAR_INFO charInfo = buffer[bufferX, bufferY];
                    canvas[canvasX][canvasY].Assign(charInfo);
                }
            }
        }
Beispiel #20
0
        /// <summary>
        /// Write a line of text with specific foreground/background colors to the console.
        /// </summary>
        /// <param name="x">The 0-based destination x coordinate.</param>
        /// <param name="y">The 0-based destination y coordinate.</param>
        /// <param name="foreground">Foreground color</param>
        /// <param name="background">Background color</param>
        /// <param name="s">The string to write.</param>
        /// <returns>True if the write was successful, false if there was a failure.</returns>
        public static bool WriteColor(int x, int y, ConsoleColor foreground, ConsoleColor background, string s)
        {
            // the attribute is the combination of the foreground color [0x00, 0x0F] and background color [0x00, 0xF0]
            ushort attribute = (ushort)((int)foreground | (((int)background) << 4));

            // Build a CHAR_INFO array containing the characters we want to write and the attributes
            CHAR_INFO[] info  = new CHAR_INFO[s.Length];
            char[]      array = s.ToCharArray();
            for (int i = 0; i < s.Length; i++)
            {
                info[i].UnicodeChar = (ushort)array[i];
                info[i].Attributes  = attribute;
            }

            // Writing the length of the string, one character tall.
            COORD myBufferSize;

            myBufferSize.X = (short)s.Length;
            myBufferSize.Y = (short)1;

            // Starting at 0,0 in the source CHAR_INFO array
            COORD myBufferPosition;

            myBufferPosition.X = 0;
            myBufferPosition.Y = 0;

            // from x..(x+s.Length), one line for y direction.
            SMALL_RECT mySmallRect;

            mySmallRect.Left   = (short)x;
            mySmallRect.Right  = (short)(x + s.Length);
            mySmallRect.Top    = (short)y;
            mySmallRect.Bottom = (short)y;

            // Write.
            return(WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), info, myBufferSize, myBufferPosition, ref mySmallRect));
        }
Beispiel #21
0
        public string readvalue(ref System.IntPtr ptr, short a)
        {
            SMALL_RECT srctReadRect = new SMALL_RECT
            {
                Top = 0,
                Left = 0,
                Bottom = 1,
                Right = 80
            };
            CHAR_INFO[,] chiBuffer = new CHAR_INFO[2, 80]; // [2][80];10 lines,  with 50 characters

            COORD coordBufSize = new COORD
            {
                X = 80,
                Y = 2
            };
            COORD coordBufCoord = new COORD
            {
                X = 0,
                Y = 0
            };

            bool fSuccess;
            int i = 0;
            int j = 0;
            string chartostring = "start";
            string previousstring = "";

            short g = a;
            short h = (short)(g + 1);

            srctReadRect.Top = g;
            srctReadRect.Bottom = h;
            int count = 0;

            //System.Console.WriteLine(g + "." + h);
            while (count < 1)//Hunting:if it find 1 empty rows with text then it will stop reading
            {
                previousstring = chartostring;
                srctReadRect.Top = g;
                srctReadRect.Bottom = h;

                fSuccess = ReadConsoleOutput(ptr, chiBuffer, coordBufSize, coordBufCoord, ref srctReadRect);

                i = 0;
                j = 0;
                chartostring = "";
                while (j < coordBufSize.Y)
                {
                    while (i < coordBufSize.X)
                    {
                        if (chiBuffer[j, i].UnicodeChar != 0 && chiBuffer[j, i].UnicodeChar != 32)
                            chartostring += chiBuffer[j, i].UnicodeChar;
                        i++;
                    }
                    i = 0;
                    j++;
                }

                if (chartostring.Length == 0)//The character length is zero, reverse the top of the source rect
                {
                    count++;
                }
                else
                {
                    count = 0;
                }
                g += 1;
                h += 1;
            }
            return previousstring;
        }
Beispiel #22
0
        private void ReallyRender()
        {
            var text = ParseInput();

            int statusLineCount = GetStatusLineCount();
            int j = _initialX + (_bufferWidth * Options.ExtraPromptLineCount);
            var backgroundColor = _initialBackgroundColor;
            var foregroundColor = _initialForegroundColor;
            bool afterLastToken = false;
            int totalBytes = j;
            int bufferWidth = _console.BufferWidth;

            var tokenStack = new Stack<SavedTokenState>();
            tokenStack.Push(new SavedTokenState
            {
                Tokens = _tokens,
                Index = 0,
                BackgroundColor = _initialBackgroundColor,
                ForegroundColor = _initialForegroundColor
            });

            int bufferLineCount;

            try
            {
                _console.StartRender();

                bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + statusLineCount;
                if (_consoleBuffer.Length != bufferLineCount * bufferWidth)
                {
                    var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth];
                    Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
                    if (_consoleBuffer.Length > bufferLineCount * bufferWidth)
                    {
                        int consoleBufferOffset = ConvertOffsetToConsoleBufferOffset(text.Length, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
                        // Need to erase the extra lines that we won't draw again
                        for (int i = consoleBufferOffset; i < _consoleBuffer.Length; i++)
                        {
                            _consoleBuffer[i] = _space;
                        }
                        _console.WriteBufferLines(_consoleBuffer, ref _initialY);
                    }
                    _consoleBuffer = newBuffer;
                }

                for (int i = 0; i < text.Length; i++)
                {
                    totalBytes = totalBytes % bufferWidth;
                    if (!afterLastToken)
                    {
                        // Figure out the color of the character - if it's in a token,
                        // use the tokens color otherwise use the initial color.
                        var state = tokenStack.Peek();
                        var token = state.Tokens[state.Index];
                        if (i == token.Extent.EndOffset)
                        {
                            if (token == state.Tokens[state.Tokens.Length - 1])
                            {
                                tokenStack.Pop();
                                if (tokenStack.Count == 0)
                                {
                                    afterLastToken = true;
                                    token = null;
                                    foregroundColor = _initialForegroundColor;
                                    backgroundColor = _initialBackgroundColor;
                                }
                                else
                                {
                                    state = tokenStack.Peek();
                                }
                            }

                            if (!afterLastToken)
                            {
                                foregroundColor = state.ForegroundColor;
                                backgroundColor = state.BackgroundColor;

                                token = state.Tokens[++state.Index];
                            }
                        }

                        if (!afterLastToken && i == token.Extent.StartOffset)
                        {
                            GetTokenColors(token, out foregroundColor, out backgroundColor);

                            var stringToken = token as StringExpandableToken;
                            if (stringToken != null)
                            {
                                // We might have nested tokens.
                                if (stringToken.NestedTokens != null && stringToken.NestedTokens.Any())
                                {
                                    var tokens = new Token[stringToken.NestedTokens.Count + 1];
                                    stringToken.NestedTokens.CopyTo(tokens, 0);
                                    // NestedTokens doesn't have an "EOS" token, so we use
                                    // the string literal token for that purpose.
                                    tokens[tokens.Length - 1] = stringToken;

                                    tokenStack.Push(new SavedTokenState
                                    {
                                        Tokens = tokens,
                                        Index = 0,
                                        BackgroundColor = backgroundColor,
                                        ForegroundColor = foregroundColor
                                    });

                                    if (i == tokens[0].Extent.StartOffset)
                                    {
                                        GetTokenColors(tokens[0], out foregroundColor, out backgroundColor);
                                    }
                                }
                            }
                        }
                    }

                    var charToRender = text[i];
                    if (charToRender == '\n')
                    {
                        while ((j % bufferWidth) != 0)
                        {
                            _consoleBuffer[j++] = _space;
                        }

                        for (int k = 0; k < Options.ContinuationPrompt.Length; k++, j++)
                        {
                            _consoleBuffer[j].UnicodeChar = Options.ContinuationPrompt[k];
                            _consoleBuffer[j].ForegroundColor = Options.ContinuationPromptForegroundColor;
                            _consoleBuffer[j].BackgroundColor = Options.ContinuationPromptBackgroundColor;
                        }
                    }
                    else
                    {
                        int size = LengthInBufferCells(charToRender);
                        totalBytes += size;

                        //if there is no enough space for the character at the edge, fill in spaces at the end and
                        //put the character to next line.
                        int filling = totalBytes > bufferWidth ? (totalBytes - bufferWidth) % size : 0;
                        for (int f = 0; f < filling; f++)
                        {
                            _consoleBuffer[j++] = _space;
                            totalBytes++;
                        }

                        if (char.IsControl(charToRender))
                        {
                            _consoleBuffer[j].UnicodeChar = '^';
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                            _consoleBuffer[j].UnicodeChar = (char)('@' + charToRender);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);

                        }
                        else if (size > 1)
                        {
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            _consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
                                                           (uint)CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            _consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
                                                           (uint)CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                        }
                        else
                        {
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                        }
                    }
                }
            }
            finally
            {
                _console.EndRender();
            }

            for (; j < (_consoleBuffer.Length - (statusLineCount * _bufferWidth)); j++)
            {
                _consoleBuffer[j] = _space;
            }

            if (_statusLinePrompt != null)
            {
                foregroundColor = _statusIsErrorMessage ? Options.ErrorForegroundColor : _console.ForegroundColor;
                backgroundColor = _statusIsErrorMessage ? Options.ErrorBackgroundColor : _console.BackgroundColor;

                for (int i = 0; i < _statusLinePrompt.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusLinePrompt[i];
                    _consoleBuffer[j].ForegroundColor = foregroundColor;
                    _consoleBuffer[j].BackgroundColor = backgroundColor;
                }
                for (int i = 0; i < _statusBuffer.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusBuffer[i];
                    _consoleBuffer[j].ForegroundColor = foregroundColor;
                    _consoleBuffer[j].BackgroundColor = backgroundColor;
                }

                for (; j < _consoleBuffer.Length; j++)
                {
                    _consoleBuffer[j] = _space;
                }
            }

            bool rendered = false;
            if (_parseErrors.Length > 0)
            {
                int promptChar = _initialX - 1 + (_bufferWidth * Options.ExtraPromptLineCount);

                while (promptChar >= 0)
                {
                    var c = (char)_consoleBuffer[promptChar].UnicodeChar;
                    if (char.IsWhiteSpace(c))
                    {
                        promptChar -= 1;
                        continue;
                    }

                    ConsoleColor prevColor = _consoleBuffer[promptChar].ForegroundColor;
                    _consoleBuffer[promptChar].ForegroundColor = ConsoleColor.Red;
                    _console.WriteBufferLines(_consoleBuffer, ref _initialY);
                    rendered = true;
                    _consoleBuffer[promptChar].ForegroundColor = prevColor;
                    break;
                }
            }

            if (!rendered)
            {
                _console.WriteBufferLines(_consoleBuffer, ref _initialY);
            }

            PlaceCursor();

            if ((_initialY + bufferLineCount) > (_console.WindowTop + _console.WindowHeight))
            {
                _console.WindowTop = _initialY + bufferLineCount - _console.WindowHeight;
            }

            _lastRenderTime.Restart();
        }
Beispiel #23
0
        private void MaybeEmphasize(ref CHAR_INFO charInfo, int i, ConsoleColor foregroundColor, ConsoleColor backgroundColor)
        {
            if (i >= _emphasisStart && i < (_emphasisStart + _emphasisLength))
            {
                backgroundColor = _options.EmphasisBackgroundColor;
                foregroundColor = _options.EmphasisForegroundColor;
            }
            else if (_visualSelectionCommandCount > 0 && InRegion(i))
            {
                // We can't quite emulate real console selection because it inverts
                // based on actual screen colors, our pallete is limited.  The choice
                // to invert only the lower 3 bits to change the color is somewhat
                // but looks best with the 2 default color schemes - starting PowerShell
                // from it's shortcut or from a cmd shortcut.
                foregroundColor = (ConsoleColor)((int)foregroundColor ^ 7);
                backgroundColor = (ConsoleColor)((int)backgroundColor ^ 7);
            }

            charInfo.ForegroundColor = foregroundColor;
            charInfo.BackgroundColor = backgroundColor;
        }
Beispiel #24
0
 private static void WriteBlankLines(int count, int top)
 {
     var console = _singleton._console;
     var blanks = new CHAR_INFO[count * console.BufferWidth];
     for (int i = 0; i < blanks.Length; i++)
     {
         blanks[i].BackgroundColor = console.BackgroundColor;
         blanks[i].ForegroundColor = console.ForegroundColor;
         blanks[i].UnicodeChar = ' ';
     }
     console.WriteBufferLines(blanks, ref top);
 }
 public CHAR_INFO[] ReadBufferLines(int top, int count)
 {
     var toCopy = BufferWidth * count;
     var result = new CHAR_INFO[toCopy];
     Array.Copy(buffer, top * BufferWidth, result, 0, toCopy);
     return result;
 }
Beispiel #26
0
 public static extern bool WriteConsoleOutput(
     IntPtr hConsoleOutput,
     CHAR_INFO[] lpBuffer,
     COORD dwBufferSize,
     COORD dwBufferCoord,
     ref SMALL_RECT lpWriteRegion
     );
        private CHAR_INFO[] CreateCharInfoBuffer(int lines, params object[] items)
        {
            var result = new List<CHAR_INFO>();
            var fg = _console.ForegroundColor;
            var bg = _console.BackgroundColor;

            foreach (var i in items)
            {
                var item = i;
                if (item is char)
                {
                    result.Add(new CHAR_INFO((char)item, fg, bg));
                    continue;
                }
                if (item is InvertedToken)
                {
                    fg = (ConsoleColor)((int)fg ^ 7);
                    bg = (ConsoleColor)((int)bg ^ 7);
                    continue;
                }
                if (item is NextLineToken)
                {
                    item = new string(' ', _console.BufferWidth - (result.Count % _console.BufferWidth));
                    fg = _console.ForegroundColor;
                    bg = _console.BackgroundColor;
                    // Fallthrough to string case.
                }
                var str = item as string;
                if (str != null)
                {
                    result.AddRange(str.Select(c => new CHAR_INFO(c, fg, bg)));
                    continue;
                }
                if (item is TokenClassification)
                {
                    fg = ForegroundColors[(int)(TokenClassification)item];
                    bg = BackgroundColors[(int)(TokenClassification)item];
                    continue;
                }
                var tuple = item as Tuple<ConsoleColor, ConsoleColor>;
                if (tuple != null)
                {
                    fg = tuple.Item1;
                    bg = tuple.Item2;
                    continue;
                }
                throw new ArgumentException("Unexpected type");
            }

            var extraSpacesNeeded = (lines * _console.BufferWidth) - result.Count;
            if (extraSpacesNeeded > 0)
            {
                var space = new CHAR_INFO(' ', _console.ForegroundColor, _console.BackgroundColor);
                result.AddRange(Enumerable.Repeat(space, extraSpacesNeeded));
            }

            return result.ToArray();
        }
Beispiel #28
0
        static void Box(List <string> list)
        {
            int internalBoxWidth  = Math.Min(Console.BufferWidth - 2, list.Max(e => e.Length));
            int boxWidth          = internalBoxWidth + 2;
            int internalBoxHeight = list.Count;
            int boxHeight         = internalBoxHeight + 2;

            var buffer = new CHAR_INFO[boxWidth * boxHeight];

            buffer[0].UnicodeChar            = '+';
            buffer[boxWidth - 1].UnicodeChar = '+';
            for (int i = 1; i < boxWidth - 1; i++)
            {
                buffer[i].UnicodeChar = '-';
            }
            for (int i = 0; i < list.Count; i++)
            {
                int rowStart = (i + 1) * boxWidth;
                buffer[rowStart++].UnicodeChar = '|';
                buffer[rowStart + internalBoxWidth].UnicodeChar = '|';

                string s = list[i];
                int    j;
                for (j = 0; j < s.Length; j++)
                {
                    buffer[rowStart + j].UnicodeChar = s[j];
                }
                for (; j < internalBoxWidth; j++)
                {
                    buffer[rowStart + j].UnicodeChar = ' ';
                }
            }
            int lastRowStart = (boxHeight - 1) * boxWidth;

            buffer[lastRowStart].UnicodeChar = '+';
            for (int i = 1; i < boxWidth - 1; i++)
            {
                buffer[i + lastRowStart].UnicodeChar = '-';
            }
            buffer[lastRowStart + boxWidth - 1].UnicodeChar = '+';

            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i].Attributes = (ushort)ConsoleColor.Blue |
                                       ((ushort)(ConsoleColor.DarkGreen) << 4);
                if (i % 2 != 0)
                {
                    buffer[i].Attributes |= 0xfff0;
                }
            }

            var handle     = NativeMethods.GetStdHandle((uint)StandardHandleId.Output);
            var bufferSize = new COORD {
                X = (short)boxWidth, Y = (short)boxHeight
            };
            var bufferCoord = new COORD {
                X = 0, Y = 0
            };
            var writeRegion = new SMALL_RECT {
                Top    = 1,
                Left   = 1,
                Bottom = (short)(1 + boxHeight),
                Right  = (short)(1 + boxWidth)
            };

            Console.WriteLine("some random stuff");
            Console.WriteLine("and more some random stuff");
            Console.WriteLine("lorem ipsum blah blah");
            Console.ReadKey();
            var saveBuffer = new CHAR_INFO[buffer.Length];

            NativeMethods.ReadConsoleOutput(handle, saveBuffer,
                                            bufferSize, bufferCoord, ref writeRegion);
            unsafe
            {
                fixed(CHAR_INFO *p = &buffer[0])
                fixed(CHAR_INFO * sp = &saveBuffer[0])
                {
                    NativeMethods.WriteConsoleOutput(handle, buffer,
                                                     bufferSize, bufferCoord, ref writeRegion);
                    Console.ReadKey();
                    NativeMethods.WriteConsoleOutput(handle, saveBuffer,
                                                     bufferSize, bufferCoord, ref writeRegion);
                }
            }
            Console.ReadKey();
        }
 public void WriteBufferLines(CHAR_INFO[] bufferToWrite, ref int top, bool ensureBottomLineVisible)
 {
     var startPos = top * BufferWidth;
     for (int i = 0; i < bufferToWrite.Length; i++)
     {
         buffer[startPos + i] = bufferToWrite[i];
     }
 }
 private static void InvertSelectedCompletion(CHAR_INFO[] buffer, int selectedItem, int menuColumnWidth, int menuRows)
 {
     var selectedX = selectedItem / menuRows;
     var selectedY = selectedItem - (selectedX * menuRows);
     var start = selectedY * Console.BufferWidth + selectedX * menuColumnWidth;
     for (int i = 0; i < menuColumnWidth; i++)
     {
         int j = i + start;
         buffer[j].ForegroundColor = (ConsoleColor)((int)buffer[j].ForegroundColor ^ 7);
         buffer[j].BackgroundColor = (ConsoleColor)((int)buffer[j].BackgroundColor ^ 7);
     }
 }
 void ClearBuffer()
 {
     for (int i = 0; i < buffer.Length; i++)
     {
         buffer[i] = new CHAR_INFO(' ', ForegroundColor, BackgroundColor);
     }
 }
 public void Assign(CHAR_INFO charInfo)
 {
     canvas.buffer[y, x] = charInfo;
 }
Beispiel #33
0
 internal static unsafe extern bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
 public void WriteBufferLines(CHAR_INFO[] bufferToWrite, ref int top)
 {
     WriteBufferLines(bufferToWrite, ref top, true);
 }
Beispiel #35
0
 internal static unsafe extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
Beispiel #36
0
    /// <summary>
    /// Write a line of text with specific foreground/background colors to the console.
    /// </summary>
    /// <param name="x">The 0-based destination x coordinate.</param>
    /// <param name="y">The 0-based destination y coordinate.</param>
    /// <param name="foreground">Foreground color</param>
    /// <param name="background">Background color</param>
    /// <param name="s">The string to write.</param>
    /// <returns>True if the write was successful, false if there was a failure.</returns>
    public static bool WriteColor(int x, int y, ConsoleColor foreground, ConsoleColor background, string s)
    {
      // the attribute is the combination of the foreground color [0x00, 0x0F] and background color [0x00, 0xF0]
      ushort attribute = (ushort)((int)foreground | (((int)background)<<4));
      
      // Build a CHAR_INFO array containing the characters we want to write and the attributes
      CHAR_INFO[] info = new CHAR_INFO[s.Length];
      char[] array = s.ToCharArray();
      for(int i = 0; i < s.Length; i++)
      {
        info[i].UnicodeChar = (ushort)array[i];
        info[i].Attributes = attribute;
      }
      
      // Writing the length of the string, one character tall.
      COORD myBufferSize;
      myBufferSize.X = (short)s.Length;
      myBufferSize.Y = (short)1;

      // Starting at 0,0 in the source CHAR_INFO array 
      COORD myBufferPosition;
      myBufferPosition.X = 0;
      myBufferPosition.Y = 0;

      // from x..(x+s.Length), one line for y direction.
      SMALL_RECT mySmallRect;
      mySmallRect.Left = (short)x;
      mySmallRect.Right = (short)(x + s.Length);
      mySmallRect.Top = (short)y;
      mySmallRect.Bottom = (short)y;

      // Write.
      return WriteConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), info, myBufferSize, myBufferPosition, ref mySmallRect);
    }
 /// <summary>
 ///  Moves a block of data in a screen buffer. The effects of the move can be limited by specifying a clipping rectangle, so the contents of the console screen buffer outside the clipping rectangle are unchanged.
 /// </summary>
 /// <param name="hConsoleOutput">A handle to the console input buffer. The handle must have the <see cref="BUFFER_ACCESS_MODE.GENERIC_READ"/> access right.</param>
 /// <param name="lpScrollRectangle">A pointer to a <see cref="SMALL_RECT"/> structure whose members specify the upper-left and lower-right coordinates of the console screen buffer rectangle to be moved.</param>
 /// <param name="lpClipRectangle">A pointer to a <see cref="SMALL_RECT"/> structure whose members specify the upper-left and lower-right coordinates of the console screen buffer rectangle that is affected by the scrolling. This pointer can be <see langword="null"/>.</param>
 /// <param name="dwDestinationOrigin">A <see cref="COORD"/> structure that specifies the upper-left corner of the new location of the <paramref name="lpScrollRectangle"/> contents, in characters.</param>
 /// <param name="lpFill">A pointer to a <see cref="CHAR_INFO"/> structure that specifies the character and color attributes to be used in filling the cells within the intersection of <paramref name="lpScrollRectangle"/> and <paramref name="lpClipRectangle"/> that were left empty as a result of the move.</param>
 /// <returns>If the function succeeds, returns TRUE, otherwise, retun FALSE.</returns>
 [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ScrollConsoleScreenBuffer([In] IntPtr hConsoleOutput, [In] ref SMALL_RECT lpScrollRectangle, [In, Optional] IntPtr lpClipRectangle, [In] COORD dwDestinationOrigin, [In] ref CHAR_INFO lpFill);
Beispiel #38
0
        /// <summary>
        /// Оверлоад для оптимизированного наложения в случае, когда известно, что в дочернем
        /// контроле поменялась лишь часть, идентифицируемая параметром affectedRect.
        /// Будет обработана только эта часть дочернего контрола, и количество операций уменьшится.
        /// </summary>
        /// <param name="childBuffer"></param>
        /// <param name="actualOffset"></param>
        /// <param name="childRenderSize"></param>
        /// <param name="renderSlotRect"></param>
        /// <param name="layoutClip"></param>
        /// <param name="affectedRect">Прямоугольник в дочернем контроле, который был изменен.</param>
        public void ApplyChild(RenderingBuffer childBuffer, Vector actualOffset,
                               Size childRenderSize, Rect renderSlotRect,
                               Rect layoutClip, Rect?affectedRect)
        {
            // Считаем finalRect - прямоугольник относительно parent, который нужно закрасить
            Rect finalRect = layoutClip;

            if (affectedRect != null)
            {
                finalRect.Intersect(affectedRect.Value);
            }

            // Если child.RenderSlotRect больше child.RenderSize, а rendering buffer
            // дочернего контрола больше его RenderSize (такое бывает после уменьшения
            // размеров контрола - т.к. буфер может только увеличиваться, но не уменьшаться) -
            // то нам нужно либо передать в метод ApplyChild и child.RenderSize, либо
            // выполнить пересечение заранее
            finalRect.Intersect(new Rect(new Point(0, 0), childRenderSize));

            // Because cannot call Offset() method of empty rect
            if (finalRect.IsEmpty)
            {
                return;
            }

            finalRect.Offset(actualOffset);
            finalRect.Intersect(renderSlotRect);

            // Нужно также учесть размеры буфера текущего контрола
            finalRect.Intersect(new Rect(new Point(0, 0), new Size(this.width, this.height)));

            for (int x = finalRect.Left; x < finalRect.Right; x++)
            {
                int parentX = x;
                int childX  = parentX - actualOffset.x;
                for (int y = finalRect.Top; y < finalRect.Bottom; y++)
                {
                    int parentY = y;
                    int childY  = parentY - actualOffset.y;

                    CHAR_INFO charInfo = childBuffer.buffer[childX, childY];
                    int       opacity  = childBuffer.opacityMatrix[childX, childY];

                    // Для полностью прозрачных пикселей родительского буфера - присваиваем и значение
                    // пикселя, и значение opacity, дальше дело за следующим родителем
                    if (this.opacityMatrix[parentX, parentY] == 2 || this.opacityMatrix[parentX, parentY] == 6)
                    {
                        this.buffer[parentX, parentY]        = charInfo;
                        this.opacityMatrix[parentX, parentY] = opacity;
                    }
                    else
                    {
                        // В остальных случаях opacity родительского буфера остаётся, а
                        // сам пиксель зависит от opacity дочернего элемента
                        if (opacity == 0 || opacity == 4)
                        {
                            this.buffer[parentX, parentY] = charInfo;
                        }
                        else if (opacity == 1 || opacity == 5)
                        {
                            charInfo.Attributes      = Colors.Blend(Color.DarkGray, Color.Black);
                            charInfo.UnicodeChar     = buffer[parentX, parentY].UnicodeChar;
                            buffer[parentX, parentY] = charInfo;
                        }
                        else if (opacity == 3 || opacity == 7)
                        {
                            // берем фоновые атрибуты символа из родительского буфера
                            Attr parentAttr = buffer[parentX, parentY].Attributes;
                            if ((parentAttr & Attr.BACKGROUND_BLUE) == Attr.BACKGROUND_BLUE)
                            {
                                charInfo.Attributes |= Attr.BACKGROUND_BLUE;
                            }
                            else
                            {
                                charInfo.Attributes &= ~Attr.BACKGROUND_BLUE;
                            }
                            if ((parentAttr & Attr.BACKGROUND_GREEN) == Attr.BACKGROUND_GREEN)
                            {
                                charInfo.Attributes |= Attr.BACKGROUND_GREEN;
                            }
                            else
                            {
                                charInfo.Attributes &= ~Attr.BACKGROUND_GREEN;
                            }
                            if ((parentAttr & Attr.BACKGROUND_RED) == Attr.BACKGROUND_RED)
                            {
                                charInfo.Attributes |= Attr.BACKGROUND_RED;
                            }
                            else
                            {
                                charInfo.Attributes &= ~Attr.BACKGROUND_RED;
                            }
                            if ((parentAttr & Attr.BACKGROUND_INTENSITY) == Attr.BACKGROUND_INTENSITY)
                            {
                                charInfo.Attributes |= Attr.BACKGROUND_INTENSITY;
                            }
                            else
                            {
                                charInfo.Attributes &= ~Attr.BACKGROUND_INTENSITY;
                            }
                            buffer[parentX, parentY] = charInfo;
                        }
                    }
                }
            }
        }