private BufferChar[] ToBufferCharBuffer(CHAR_INFO[] buffer) { var result = new BufferChar[buffer.Length]; for (int i = 0; i < buffer.Length; i++) { result[i] = BufferChar.FromCharInfo(buffer[i]); } return(result); }
public static BufferChar FromCharInfo(CHAR_INFO charInfo) { BufferChar result = new BufferChar { UnicodeChar = (char)charInfo.UnicodeChar, ForegroundColor = (ConsoleColor)(charInfo.Attributes & 0xf), BackgroundColor = (ConsoleColor)((charInfo.Attributes & 0x00f0) >> 4), }; return(result); }
public BufferChar[] ReadBufferLines(int top, int count) { var result = new BufferChar[BufferWidth * count]; for (int i = 0; i < BufferWidth * count; ++i) { result[i].UnicodeChar = ' '; result[i].ForegroundColor = Console.ForegroundColor; result[i].BackgroundColor = Console.BackgroundColor; } return(result); }
private void MaybeEmphasize(ref BufferChar 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 palette 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. #if UNIX // TODO: set Inverse attribute and let render choose what to do. ConsoleColor tempColor = (foregroundColor == UnknownColor) ? ConsoleColor.White : foregroundColor; foregroundColor = (backgroundColor == UnknownColor) ? ConsoleColor.Black : backgroundColor; backgroundColor = tempColor; #else foregroundColor = (ConsoleColor)((int)foregroundColor ^ 7); backgroundColor = (ConsoleColor)((int)backgroundColor ^ 7); #endif } charInfo.ForegroundColor = foregroundColor; charInfo.BackgroundColor = backgroundColor; }
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 BufferChar[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); } #if !UNIX else if (size > 1) { _consoleBuffer[j].UnicodeChar = charToRender; _consoleBuffer[j].IsLeadByte = true; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); _consoleBuffer[j].UnicodeChar = charToRender; _consoleBuffer[j].IsTrailByte = true; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); } #endif 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 = _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)) { #if !UNIX // TODO: verify this isn't necessary for LINUX _console.WindowTop = _initialY + bufferLineCount - _console.WindowHeight; #endif } _lastRenderTime.Restart(); }
private BufferChar[] ToBufferCharBuffer(CHAR_INFO[] buffer) { var result = new BufferChar[buffer.Length]; for (int i = 0; i < buffer.Length; i++) { result[i] = BufferChar.FromCharInfo(buffer[i]); } return result; }
private static void WriteBlankLines(int count, int top) { var console = _singleton._console; var blanks = new BufferChar[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 void WriteBufferLines(BufferChar[] buffer, ref int top, bool ensureBottomLineVisible) { int bufferWidth = Console.BufferWidth; int bufferLineCount = buffer.Length / bufferWidth; if ((top + bufferLineCount) > Console.BufferHeight) { var scrollCount = (top + bufferLineCount) - Console.BufferHeight; ScrollBuffer(scrollCount); top -= scrollCount; } var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var bufferSize = new COORD { X = (short) bufferWidth, Y = (short) bufferLineCount }; var bufferCoord = new COORD {X = 0, Y = 0}; var bottom = top + bufferLineCount - 1; var writeRegion = new SMALL_RECT { Top = (short) top, Left = 0, Bottom = (short) bottom, Right = (short) (bufferWidth - 1) }; NativeMethods.WriteConsoleOutput(handle, ToCharInfoBuffer(buffer), bufferSize, bufferCoord, ref writeRegion); // Now make sure the bottom line is visible if (ensureBottomLineVisible && (bottom >= (Console.WindowTop + Console.WindowHeight))) { Console.CursorTop = bottom; } }
private CHAR_INFO[] ToCharInfoBuffer(BufferChar[] buffer) { if (cachedBuffer == null || cachedBuffer.Length != buffer.Length) { cachedBuffer = new CHAR_INFO[buffer.Length]; } for (int i = 0; i < buffer.Length; i++) { cachedBuffer[i] = buffer[i].ToCharInfo(); } return cachedBuffer; }
public void WriteBufferLines(BufferChar[] buffer, ref int top) { WriteBufferLines(buffer, ref top, true); }
public static BufferChar FromCharInfo(CHAR_INFO charInfo) { BufferChar result = new BufferChar { UnicodeChar = (char) charInfo.UnicodeChar, ForegroundColor = (ConsoleColor)(charInfo.Attributes & 0xf), BackgroundColor = (ConsoleColor)((charInfo.Attributes & 0x00f0) >> 4), }; return result; }
public BufferChar[] ReadBufferLines(int top, int count) { var result = new BufferChar[BufferWidth * count]; for (int i=0; i<BufferWidth*count; ++i) { result[i].UnicodeChar = ' '; result[i].ForegroundColor = Console.ForegroundColor; result[i].BackgroundColor = Console.BackgroundColor; } return result; }
public void WriteBufferLines(BufferChar[] buffer, ref int top, bool ensureBottomLineVisible) { int bufferWidth = Console.BufferWidth; int bufferLineCount = buffer.Length / bufferWidth; if ((top + bufferLineCount) > Console.BufferHeight) { var scrollCount = (top + bufferLineCount) - Console.BufferHeight; ScrollBuffer(scrollCount); top -= scrollCount; } ConsoleColor foregroundColor = Console.ForegroundColor; ConsoleColor backgroundColor = Console.BackgroundColor; Console.SetCursorPosition(0, (top>=0) ? top : 0); for (int i = 0; i < buffer.Length; ++i) { // TODO: use escape sequences for better perf Console.ForegroundColor = buffer[i].ForegroundColor; Console.BackgroundColor = buffer[i].BackgroundColor; Console.Write(buffer[i].UnicodeChar); } Console.BackgroundColor = backgroundColor; Console.ForegroundColor = foregroundColor; }
private static void InvertSelectedCompletion(BufferChar[] buffer, int selectedItem, int menuColumnWidth, int menuRows) { var selectedX = selectedItem / menuRows; var selectedY = selectedItem - (selectedX * menuRows); var start = selectedY * _singleton._console.BufferWidth + selectedX * menuColumnWidth; for (int i = 0; i < menuColumnWidth; i++) { buffer[i + start].Inverse = true; } }