/// <summary> /// Gets the cursos position. /// </summary> /// <returns></returns> public Coordinates GetCursorPosition() { var buffer = GetOutputBuffer(); ConsoleHostNativeMethods.CONSOLE_SCREEN_BUFFER_INFO info = DotConsoleNative.GetConsoleScreenBufferInfo(buffer); return(new Coordinates(info.cursorPosition.X, info.cursorPosition.Y)); }
/// <summary> /// Sets the cursor position. /// </summary> /// <param name="orgin"></param> public void SetCursorPosition(Coordinates orgin) { var handle = GetOutputBuffer(); DotConsoleNative.SetConsoleCursorPosition(handle, new ConsoleHostNativeMethods.COORD() { X = (short)(orgin.X), Y = (short)(orgin.Y) }); }
/// <summary> /// Gets the output buffer windows as a rectangle. /// </summary> /// <returns></returns> public Region GetOutputBufferWindow() { var buffer = GetOutputBuffer(); ConsoleHostNativeMethods.CONSOLE_SCREEN_BUFFER_INFO info = DotConsoleNative.GetConsoleScreenBufferInfo(buffer); return(new Region() { Left = info.window.Left, Top = info.window.Top, Height = info.window.Bottom, Width = info.window.Right }); }
/// <summary> /// Gets the output buffer window size. /// </summary> /// <returns></returns> public Coordinates GetOutputBufferWindowSize() { var buffer = GetOutputBuffer(); ConsoleHostNativeMethods.CONSOLE_SCREEN_BUFFER_INFO info = DotConsoleNative.GetConsoleScreenBufferInfo(buffer); return(new Coordinates() { X = info.size.X, Y = info.size.Y }); }
private void FillBuffer(string text, int row, int col, int colLen) { //TODO Move this code out of here to ColorMap. ConsoleColor foregroundCopy = ConsoleColor.White; ConsoleColor backgroundCopy = ConsoleColor.Black; bool fcInMap = Renderer.ColorMap.TryGetMappedColor(ForegroundColor, out foregroundCopy); bool bcInMap = Renderer.ColorMap.TryGetMappedColor(BackgroundColor, out backgroundCopy); if (fcInMap == false) //add this color to map. { Renderer.ColorMap.AddColor(ForegroundColor); Renderer.ColorMap.TryGetMappedColor(ForegroundColor, out foregroundCopy); } if (bcInMap == false) { Renderer.ColorMap.AddColor(BackgroundColor); Renderer.ColorMap.TryGetMappedColor(BackgroundColor, out backgroundCopy); } int textIndex = 0; for (int idx = col; idx < col + colLen; idx++) { if (idx >= Options.BufferSize.X) { break; } //Clear this char if (text == null || text.Length == 0) { this.contentBuffer.Cells[row, idx].Char = 0; this.contentBuffer.Cells[row, idx].Attributes = 0; } else { if (textIndex < text.Length) { this.contentBuffer.Cells[row, idx].Char = (ushort)text[textIndex]; } this.contentBuffer.Cells[row, idx].Attributes = (ushort)DotConsoleNative.ToNativeConsoleColor(foregroundCopy, backgroundCopy); } textIndex++; } }
/// <summary> /// Writes lines of text into the output buffer at a specified coordinates. /// </summary> /// <param name="orgin"></param> /// <param name="content"></param> public void WriteOutput(Coordinates orgin, string[] content) { int lineId = 0; int charId = 0; //Find the widest line and set the OutputCell matrix to such width var max = content.Max(x => x.Length); CellBuffer buffer = new CellBuffer(content.Length, max); foreach (var line in content) { charId = 0; foreach (var c in line) { buffer.Cells[lineId, charId].Char = (ushort)c; buffer.Cells[lineId, charId].Attributes = (ushort)DotConsoleNative.ToNativeConsoleColor(ForegroundColor, BackgroundColor); charId++; } } WriteOutput(orgin, buffer); }
/// <summary> /// Reads cell matrix form the output buffer using the provided rectangle. /// </summary> /// <param name="region"></param> /// <returns></returns> public CellBuffer ReadOutput(Region region) { var handle = GetOutputBuffer(); //Get len of X coordinate, the plan here is to partition by Y var sizeOfX = (region.Width - region.Left + 1) * 4; //partition by Y coordinate. var partitionY = (int)Math.Ceiling((decimal)(maxBufferSize / sizeOfX)); int sizeOfY = (region.Height - region.Top); //if Y is smaller then the partition by Y then we need //to set the partiton size to Y size. if (sizeOfY < partitionY) { partitionY = sizeOfY; } ConsoleHostNativeMethods.COORD bufferCoord = new ConsoleHostNativeMethods.COORD(); bufferCoord.X = 0; bufferCoord.Y = 0; ConsoleHostNativeMethods.COORD bufferSize = new ConsoleHostNativeMethods.COORD(); bufferSize.X = (short)(region.Width - region.Left); CellBuffer cells = new CellBuffer(sizeOfY, bufferSize.X); int cursor = 0; int i = 0; do { i += partitionY; //the size of the Y coordinate is always the size of the buffer. bufferSize.X = (short)(region.Width - region.Left); bufferSize.Y = (short)partitionY; //If we exceeded the maximum size of the buffer we need to substract to the size of the remaining buffer. if (i > sizeOfY) { int diff = i - sizeOfY; bufferSize.Y = (short)(partitionY - diff); } //Fill the buffer part. ConsoleHostNativeMethods.SMALL_RECT readRegion = new ConsoleHostNativeMethods.SMALL_RECT(); readRegion.Left = (short)region.Left; readRegion.Top = (short)region.Top; readRegion.Right = (short)(region.Left + bufferSize.X); readRegion.Bottom = (short)(region.Top + bufferSize.Y); ConsoleHostNativeMethods.CHAR_INFO[] buffer = new ConsoleHostNativeMethods.CHAR_INFO[bufferSize.X * bufferSize.Y]; buffer = DotConsoleNative.ReadConsoleOutput(handle, buffer, bufferSize, bufferCoord, ref readRegion); //Fill the output buffer cells. int idx = 0; for (int k = cursor; k < bufferSize.Y; k++) { for (int n = 0; n < bufferSize.X; n++) { cells.Cells[k, n].Attributes = buffer[idx].Attributes; cells.Cells[k, n].Char = buffer[idx].UnicodeChar; idx++; } cursor = k; } }while (i < sizeOfY); return(cells); }
public void WriteOutput(Coordinates orgin, CellBuffer cellBuffer) { var handle = GetOutputBuffer(); //Get len of X coordinate, the plan here is to partition by Y var sizeOfX = cellBuffer.GetLengthOfX() * 4; //partition by Y coordinate. int partitionY = (int)Math.Ceiling((decimal)(maxBufferSize / sizeOfX)); var sizeOfY = cellBuffer.GetLengthOfY(); //if Y is smaller then the partition by Y then we need //to set the partiton size to Y size. if (sizeOfY < partitionY) { partitionY = sizeOfY; } //Get partitoned buffer size. int charBufferSize = (int)(partitionY * cellBuffer.GetLengthOfX()); int cursor = 0; int i = 0; do { i += partitionY; //If we exceeded the maximum size of the buffer we need to substract to the size of the remaining buffer. if (i > sizeOfY) { int diff = i - sizeOfY; i = i - diff; } //Fill the buffer part. ConsoleHostNativeMethods.CHAR_INFO[] buffer = new ConsoleHostNativeMethods.CHAR_INFO[charBufferSize]; int idx = 0; for (int y = cursor; y < i; y++) { for (int x = 0; x < cellBuffer.GetLengthOfX(); x++) { var cellToWrite = cellBuffer[y, x]; if (cellToWrite.Attributes == 0) { //Don't set the foreground color for empty cells this will force the ConsoleHost //to do a very expensive calculation for each cell and slow things down. cellToWrite.Attributes = (ushort)DotConsoleNative.ToNativeConsoleColor(0, BackgroundColor); } buffer[idx].Attributes = cellToWrite.Attributes; buffer[idx].UnicodeChar = cellToWrite.Char; idx++; } } ConsoleHostNativeMethods.COORD bufferSize = new ConsoleHostNativeMethods.COORD(); bufferSize.X = (short)cellBuffer.GetLengthOfX(); bufferSize.Y = (short)partitionY; ConsoleHostNativeMethods.COORD bufferCoord = new ConsoleHostNativeMethods.COORD(); bufferCoord.X = 0; bufferCoord.Y = 0; ConsoleHostNativeMethods.SMALL_RECT writeRegion = new ConsoleHostNativeMethods.SMALL_RECT(); writeRegion.Left = (short)orgin.X; writeRegion.Top = (short)(orgin.Y + cursor); writeRegion.Right = (short)(orgin.X + bufferSize.X); writeRegion.Bottom = (short)(orgin.Y + cursor + bufferSize.Y); DotConsoleNative.WriteConsoleOutput(handle, buffer, bufferSize, bufferCoord, ref writeRegion); cursor = i; }while (i < sizeOfY); }
/// <summary> /// Reads the input from the input buffer. /// </summary> public ReadRef ReadInput(ReadOptions options) { var handle = GetInputBuffer(); uint read = 0; var readRef = new ReadRef(); StringBuilder inputBuffer = new StringBuilder(options.InitialContent); int currentLength = 0; //Save current mode. uint currentMode = 0; ConsoleHostNativeMethods.GetConsoleMode(handle.DangerousGetHandle(), out currentMode); ConsoleModes newMode = (ConsoleModes)currentMode & ~ConsoleModes.WindowInput & ~ConsoleModes.MouseInput & ~ConsoleModes.ProcessedInput; ConsoleHostNativeMethods.SetConsoleMode(handle.DangerousGetHandle(), (uint)newMode); while (true) { var inputs = DotConsoleNative.ReadConsoleKeys(handle, 1, out read); if (inputs != null && inputs.Length > 0) { if (read == 1) { var input = inputs[0]; if (input.KeyEvent.repeatCount == 0) { //for some bizzare reson this can return a key or record //but repeat count is zero so we should not process it in any way. //This can happen if we're after mouse inputs such as mouse move. continue; } if (input.KeyEvent.keyDown == true) { if (input.EventType == (ushort)KeyEventType.KEY_EVENT) { if (input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Return) { break; } if (input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Left) { //set cursor position. //Should we use the cursor position from renderrer ? or perhaps use //the one from the output buffer of the console that we're using ? var currentCursorPosition = parent.GetCursorPosition(); currentCursorPosition.X -= 1; parent.SetCursorPosition(currentCursorPosition); parent.SetBufferPosition(currentCursorPosition); } else if (input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Right) { //set cursor position. //Should we use the cursor position from renderrer ? or perhaps use //the one from the output buffer of the console that we're using ? var currentCursorPosition = parent.GetCursorPosition(); currentCursorPosition.X += 1; parent.SetCursorPosition(currentCursorPosition); parent.SetBufferPosition(currentCursorPosition); } else if (input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Back) { var currentCursorPosition = parent.GetCursorPosition(); currentCursorPosition.X -= 1; inputBuffer.Remove(inputBuffer.Length - 1, 1); if (options.NoEcho == false) { parent.AlterLine(string.Empty, currentCursorPosition.Y, currentCursorPosition.X, 1, options.BackgroundColor, options.ForegroundColor); } parent.SetCursorPosition(currentCursorPosition); parent.SetBufferPosition(currentCursorPosition); } else { if (options.StopOnUpArrow && input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Up) { readRef.IsUpArrow = true; break; } else if (options.StopOnDownArrow && input.KeyEvent.virtualKeyCode == (ushort)VirtualInputCode.Down) { readRef.IsDownArrow = true; break; } if (options.StopChars != null) { if (options.StopChars.Contains(input.KeyEvent.unicodeChar)) { readRef.StopChar = (input.KeyEvent.unicodeChar); break; } } currentLength++; inputBuffer.Append(input.KeyEvent.unicodeChar); if (options.NoEcho == false) { parent.Write(input.KeyEvent.unicodeChar.ToString(), options.BackgroundColor, options.ForegroundColor, false); } //Maximum allowed chars read, break the input loop. if (options.ReadLength.HasValue && currentLength >= options.ReadLength) { break; } } } } } } } //Restore saved mode. ConsoleHostNativeMethods.SetConsoleMode(handle.DangerousGetHandle(), currentMode); readRef.ReadInput = inputBuffer.ToString(); return(readRef); }
/// <summary> /// Consctructs the Console Color map. /// </summary> private void ConstructMap() { ConsoleHostNativeMethods.CONSOLE_SCREEN_BUFFER_INFO_EX screenBufferInfo = DotConsoleNative.GetConsoleScreenBufferInfoExtended(consoleHandle); colorMap.Add(ConsoleColor.Black, Convert(screenBufferInfo.black.Color)); colorMap.Add(ConsoleColor.White, Convert(screenBufferInfo.white.Color)); colorMap.Add(ConsoleColor.Red, Convert(screenBufferInfo.red.Color)); colorMap.Add(ConsoleColor.Green, Convert(screenBufferInfo.green.Color)); colorMap.Add(ConsoleColor.Blue, Convert(screenBufferInfo.blue.Color)); colorMap.Add(ConsoleColor.Gray, Convert(screenBufferInfo.gray.Color)); colorMap.Add(ConsoleColor.Cyan, Convert(screenBufferInfo.cyan.Color)); colorMap.Add(ConsoleColor.Magenta, Convert(screenBufferInfo.magenta.Color)); colorMap.Add(ConsoleColor.DarkRed, Convert(screenBufferInfo.darkRed.Color)); colorMap.Add(ConsoleColor.DarkGreen, Convert(screenBufferInfo.darkGreen.Color)); colorMap.Add(ConsoleColor.DarkBlue, Convert(screenBufferInfo.darkBlue.Color)); colorMap.Add(ConsoleColor.DarkGray, Convert(screenBufferInfo.darkGray.Color)); colorMap.Add(ConsoleColor.DarkYellow, Convert(screenBufferInfo.darkYellow.Color)); colorMap.Add(ConsoleColor.DarkCyan, Convert(screenBufferInfo.darkCyan.Color)); colorMap.Add(ConsoleColor.DarkMagenta, Convert(screenBufferInfo.darkMagenta.Color)); }
/// <summary> /// Send the updated Color to the console host under the specified ConsoleColor key. /// </summary> /// <param name="keyColor"></param> /// <param name="targetColor"></param> private void MapToConsoleHost(ConsoleColor keyColor, Color targetColor) { ConsoleHostNativeMethods.CONSOLE_SCREEN_BUFFER_INFO_EX screenBufferInfo = DotConsoleNative.GetConsoleScreenBufferInfoExtended(consoleHandle); switch (keyColor) { case ConsoleColor.Black: screenBufferInfo.black.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.White: screenBufferInfo.white.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Blue: screenBufferInfo.blue.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Cyan: screenBufferInfo.cyan.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Red: screenBufferInfo.red.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Green: screenBufferInfo.green.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Magenta: screenBufferInfo.magenta.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Gray: screenBufferInfo.gray.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.Yellow: screenBufferInfo.yellow.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkYellow: screenBufferInfo.darkYellow.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkRed: screenBufferInfo.darkRed.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkGreen: screenBufferInfo.darkGreen.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkBlue: screenBufferInfo.darkBlue.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkMagenta: screenBufferInfo.darkMagenta.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkGray: screenBufferInfo.darkGray.Color = Convert(colorMap[keyColor]); break; case ConsoleColor.DarkCyan: screenBufferInfo.darkCyan.Color = Convert(colorMap[keyColor]); break; } // SUPER WHACKY CODE HERE. // WHY???!!! // This looks to me like a bug but it's needed since buffer info seems to shrink one line at a time in every direction :| screenBufferInfo.window.Bottom++; screenBufferInfo.window.Right++; DotConsoleNative.SetConsoleScreenBufferInfoExtended(consoleHandle, screenBufferInfo); }