| 90 | } |
| 91 | |
| 92 | static void VConsolePrint(wchar_t const* format, va_list val, bool newLine) |
| 93 | { |
| 94 | wchar_t buffer[256]; |
| 95 | uint32_t numChars = VPrint(buffer, _countof(buffer), format, val); |
| 96 | |
| 97 | HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); |
| 98 | |
| 99 | CONSOLE_SCREEN_BUFFER_INFO info = {}; |
| 100 | GetConsoleScreenBufferInfo(console, &info); |
| 101 | if (info.dwSize.X == 0) { |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | COORD endPosition; |
| 106 | endPosition.Y = gWritePosition.Y + (SHORT) ((numChars + gWritePosition.X) / info.dwSize.X); |
| 107 | endPosition.X = (numChars + gWritePosition.X) % info.dwSize.X; |
| 108 | |
| 109 | SHORT finalY = endPosition.Y + (newLine ? 1 : 0); |
| 110 | if (finalY >= info.dwSize.Y) { |
| 111 | SHORT deltaY = finalY - info.dwSize.Y + 1; |
| 112 | |
| 113 | SMALL_RECT rect; |
| 114 | rect.Left = 0; |
| 115 | rect.Top = deltaY; |
| 116 | rect.Right = info.dwSize.X - 1; |
| 117 | rect.Bottom = info.dwSize.Y - deltaY - 1; |
| 118 | |
| 119 | COORD dstPos; |
| 120 | dstPos.X = 0; |
| 121 | dstPos.Y = 0; |
| 122 | |
| 123 | CHAR_INFO fill; |
| 124 | fill.Char.UnicodeChar = L' '; |
| 125 | fill.Attributes = info.wAttributes; |
| 126 | |
| 127 | ScrollConsoleScreenBufferW(console, &rect, nullptr, dstPos, &fill); |
| 128 | |
| 129 | info.dwCursorPosition.Y -= deltaY; |
| 130 | gWritePosition.Y -= deltaY; |
| 131 | endPosition.Y -= deltaY; |
| 132 | |
| 133 | SetConsoleCursorPosition(console, info.dwCursorPosition); |
| 134 | } |
| 135 | |
| 136 | if (info.dwCursorPosition.Y >= info.srWindow.Top && |
| 137 | info.dwCursorPosition.Y <= info.srWindow.Bottom && |
| 138 | finalY > info.srWindow.Bottom) { |
| 139 | SHORT deltaY = finalY - info.srWindow.Bottom; |
| 140 | |
| 141 | SMALL_RECT rect; |
| 142 | rect.Left = 0; |
| 143 | rect.Top = deltaY; |
| 144 | rect.Right = 0; |
| 145 | rect.Bottom = deltaY; |
| 146 | |
| 147 | SetConsoleWindowInfo(console, FALSE, &rect); |
| 148 | } |
| 149 |
no test coverage detected