public TestScreenBuffer(int width, int height, char defaultChar, Colors colors, params string[] lines) { int size = height * width; var buffer = new CharAndColor[size]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = y * width + x; buffer[offset] = ColorExtensions.Set(colors, defaultChar); } } for (int i = 0; i < lines.Length; i++) { for (int x = 0; x < lines[i].Length; x++) { int offset = i * width + x; buffer[offset] = ColorExtensions.Set(colors, lines[i][x]); } } Buffer = buffer; }
// write up specs (tests) to follow these notes // https://docs.microsoft.com/en-us/dotnet/api/system.console.movebufferarea?view=netframework-4.8 // by implementing this using a source and destination // I'll be able to create a scrollable text area that can display a subsection (visible region) of a larger area. // for now, all I need is one scroll direction, that is panDown aka scrollUp. (scroll the contents UP but move the viewport DOWN. ) // if we're literally scrolling an expanding window, when we print to the bottom we extend the height by 1 row, and move the viewport down 1 row. // if we limit the maximum bytes allowed to be used then we clip from the top and show @clipped@ or "clipmessage" when we scroll back the other way. // if Highspeed logging , you can quickly hot 100 000 rows , which would be 20MB to 30MB, of buffer. So clipping is essential // to prevent memory exhaustion for a server monitoring applicaion, or a high speed logging utility. // do I want to use a linkedList of Rows for the buffer, so that I can easily expand (and clip) the buffer without performance problems? public Scroller(CharAndColor[] buffer, int bufferWidth, int bufferHeight, char emptySpaceChar, Colors colors) { _buffer = buffer; _bufferWidth = bufferWidth; _bufferHeight = bufferHeight; _colors = colors; _fillChar = _colors.Set(emptySpaceChar); }
public void ClearScreen() { CharAndColor @char = Colors.Set(ClearScreenChar); for (int x = 0; x < _width; x++) { for (int y = 0; y < _height; y++) { int xy = y * _width + x; _buffer[xy] = @char; } } }
/// <summary> /// 文字列内に存在する独自のタグを解析する /// </summary> private void ColorTagCheck(string str) { messageAndColor = new List <CharAndColor>(); CharAndColor charAndColor = new CharAndColor(); int state = 0; ColorState currentColor = ColorState.NONE; // 文字色 ColorState candidateColor = ColorState.NONE; // タグから解析している途中で候補に挙がった色 bool isTagClosed = false; for (int i = 0; i < str.Length; i++) { switch (state) { case 0: if (str[i] == '<') { state = 1; isTagClosed = false; continue; } break; case 1: if (str[i] == 'r') { state = 2; candidateColor = ColorState.RED; } else if (str[i] == 'g') { state = 2; candidateColor = ColorState.GREEN; } else if (str[i] == 'b') { state = 2; candidateColor = ColorState.BLUE; } else if (str[i] == 'c') { state = 2; candidateColor = ColorState.CYAN; } else if (str[i] == 'm') { state = 2; candidateColor = ColorState.MAGENTA; } else if (str[i] == 'y') { state = 2; candidateColor = ColorState.YELLOW; } else if (str[i] == 'w') { state = 2; candidateColor = ColorState.WHITE; } else if (str[i] == '/') { state = 2; isTagClosed = true; } else { state = 0; break; } continue; case 2: if (str[i] == '>') { state = 0; currentColor = candidateColor; continue; } state = 1; isTagClosed = false; break; } // </>が使われた次の文字からはデフォルトに戻す if (isTagClosed) { currentColor = ColorState.NONE; isTagClosed = false; } charAndColor.character = str[i]; charAndColor.objColor = currentColor; messageAndColor.Add(charAndColor); } }
/// <summary> /// 文字列内に存在する独自のタグを解析する /// </summary> private void ColorTagCheck(string str) { messageAndColor = new List<CharAndColor>(); CharAndColor charAndColor = new CharAndColor(); int state = 0; ColorState currentColor = ColorState.NONE; // 文字色 ColorState candidateColor = ColorState.NONE; // タグから解析している途中で候補に挙がった色 bool isTagClosed = false; for (int i = 0; i < str.Length; i++) { switch (state) { case 0: if (str[i] == '<') { state = 1; isTagClosed = false; continue; } break; case 1: if (str[i] == 'r') { state = 2; candidateColor = ColorState.RED; } else if (str[i] == 'g') { state = 2; candidateColor = ColorState.GREEN; } else if (str[i] == 'b') { state = 2; candidateColor = ColorState.BLUE; } else if (str[i] == 'c') { state = 2; candidateColor = ColorState.CYAN; } else if (str[i] == 'm') { state = 2; candidateColor = ColorState.MAGENTA; } else if (str[i] == 'y') { state = 2; candidateColor = ColorState.YELLOW; } else if (str[i] == 'w') { state = 2; candidateColor = ColorState.WHITE; } else if (str[i] == '/') { state = 2; isTagClosed = true; } else { state = 0; break; } continue; case 2: if (str[i] == '>') { state = 0; currentColor = candidateColor; continue; } state = 1; isTagClosed = false; break; } // </>が使われた次の文字からはデフォルトに戻す if (isTagClosed) { currentColor = ColorState.NONE; isTagClosed = false; } charAndColor.character = str[i]; charAndColor.objColor = currentColor; messageAndColor.Add(charAndColor); } }