void ClearScreen() { auto console = WinApiHelpers::CreateFile(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, OPEN_EXISTING, FILE_SHARE_WRITE); // Obtain some info CONSOLE_SCREEN_BUFFER_INFOEX info = WinApiHelpers::GetConsoleScreenBufferInfoEx(console); // Do the actual clearing DWORD cells = info.dwSize.X * info.dwSize.Y; COORD origin = { 0, 0 }; DWORD written = 0; if (!FillConsoleOutputCharacterW(console, L' ', cells, origin, &written)) { WinApiHelpers::ThrowLastError("FillConsoleOutputCharacterW"); } if (!FillConsoleOutputAttribute(console, info.wAttributes, cells, origin, &written)) { WinApiHelpers::ThrowLastError("FillConsoleOutputAttribute"); } // Finally, move the cursor the the origin if (!SetConsoleCursorPosition(console, origin)) { WinApiHelpers::ThrowLastError("SetConsoleCursorPosition"); } }
static int clear_line() { HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO info; COORD coord; DWORD written; handle = (HANDLE)_get_osfhandle(fileno(stderr)); if (handle == INVALID_HANDLE_VALUE) return -1; if (!GetConsoleScreenBufferInfo(handle, &info)) return -1; coord = info.dwCursorPosition; if (coord.Y <= 0) return -1; coord.X = 0; if (!SetConsoleCursorPosition(handle, coord)) return -1; if (!FillConsoleOutputCharacterW(handle, 0x20, info.dwSize.X, coord, &written)) return -1; return 0; }
static void putwchxyattrwh(int x, int y, wchar_t ch, int attr, int w, int h) { HANDLE con; COORD c; int i; if (x<ti.winleft) w -= ti.winleft - x; if (y<ti.wintop) h -= ti.wintop - y; if (x + w - 1>ti.winright) w = ti.winright - x + 1; if (y + h - 1>ti.winbottom) h = ti.winbottom - y + 1; if (w <= 0 || h <= 0) return; con = GetStdHandle(STD_OUTPUT_HANDLE); for (i = 0; i<h; ++i) { DWORD written; c.X = x - 1; c.Y = y - 1 + i; FillConsoleOutputAttribute(con, attr, w, c, &written); FillConsoleOutputCharacterW(con, ch, w, c, &written); } }
static void erase_line(int mode) { COORD start; start.Y = console->y + console->top; int count; if (mode == 0) { /* Erase to end */ start.X = console->x; count = console->width - console->x; } else if (mode == 1) { /* Erase to begin */ start.X = 0; count = console->x + 1; } else if (mode == 2) { /* Erase whole line */ start.X = 0; count = console->width; } else { log_error("erase_line(): Invalid mode %d\n", mode); return; } DWORD num_written; FillConsoleOutputAttribute(console->out, get_text_attribute(console), count, start, &num_written); FillConsoleOutputCharacterW(console->out, L' ', count, start, &num_written); }
static void erase_screen(int mode) { COORD start; int count; if (mode == 0) { /* Erase current line to bottom */ start.X = console->x; start.Y = console->y + console->top; count = (console->width - console->x + 1) + (console->height - console->y - 1) * console->width; } else if (mode == 1) { /* Erase top to current line */ start.X = 0; start.Y = console->top; count = console->y * console->width + console->x + 1; } else if (mode == 2) { /* Erase entire screen */ start.X = 0; start.Y = console->top; count = console->width * console->height; } else { log_error("erase_screen(): Invalid mode %d\n", mode); return; } DWORD num_written; FillConsoleOutputAttribute(console->out, get_text_attribute(console), count, start, &num_written); FillConsoleOutputCharacterW(console->out, L' ', count, start, &num_written); }
//------------------------------------------------------------------------------ void win_screen_buffer::delete_chars(int count) { if (count <= 0) return; CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(m_handle, &csbi); SMALL_RECT rect; rect.Left = csbi.dwCursorPosition.X + count; rect.Right = csbi.dwSize.X - 1; rect.Top = rect.Bottom = csbi.dwCursorPosition.Y; CHAR_INFO fill; fill.Char.AsciiChar = ' '; fill.Attributes = csbi.wAttributes; ScrollConsoleScreenBuffer(m_handle, &rect, NULL, csbi.dwCursorPosition, &fill); int chars_moved = rect.Right - rect.Left + 1; if (chars_moved < count) { COORD xy = csbi.dwCursorPosition; xy.X += chars_moved; count -= chars_moved; DWORD written; FillConsoleOutputCharacterW(m_handle, ' ', count, xy, &written); FillConsoleOutputAttribute(m_handle, csbi.wAttributes, count, xy, &written); } }
//------------------------------------------------------------------------------ void win_screen_buffer::clear_line(clear_type type) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(m_handle, &csbi); int width; COORD xy; switch (type) { case clear_type_all: width = csbi.dwSize.X; xy = { 0, csbi.dwCursorPosition.Y }; break; case clear_type_before: width = csbi.dwCursorPosition.X + 1; xy = { 0, csbi.dwCursorPosition.Y }; break; case clear_type_after: width = csbi.dwSize.X - csbi.dwCursorPosition.X; xy = { csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y }; break; } DWORD written; FillConsoleOutputCharacterW(m_handle, ' ', width, xy, &written); FillConsoleOutputAttribute(m_handle, csbi.wAttributes, width, xy, &written); }
JNIEXPORT void JNICALL Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEndOfLine(JNIEnv *env, jclass target, jobject result) { CONSOLE_SCREEN_BUFFER_INFO console_info; if (!GetConsoleScreenBufferInfo(current_console, &console_info)) { mark_failed_with_errno(env, "could not get console buffer", result); return; } DWORD count; if (!FillConsoleOutputCharacterW(current_console, L' ', console_info.dwSize.X - console_info.dwCursorPosition.X, console_info.dwCursorPosition, &count)) { mark_failed_with_errno(env, "could not clear console", result); } }
static void control_escape_sharp(char ch) { switch (ch) { case '8': { /* DECALN: DEC screen alignment test */ /* Fill screen with 'E' */ COORD start; start.X = 0; start.Y = 0; DWORD bytes_written; FillConsoleOutputAttribute(console->out, get_text_attribute(), console->width * console->height, start, &bytes_written); FillConsoleOutputCharacterW(console->out, L'E', console->width * console->height, start, &bytes_written); console->processor = NULL; } default: log_error("control_escape_sharp(): Unhandled character %c\n", ch); console->processor = NULL; } }
//------------------------------------------------------------------------------ static void simulate_sigwinch() { // In the land of POSIX a terminal would raise a SIGWINCH signal when it is // resized. See rl_sigwinch_handler() in readline/signal.c. extern int _rl_vis_botlin; extern int _rl_last_c_pos; extern int _rl_last_v_pos; CONSOLE_SCREEN_BUFFER_INFO csbi; COORD cursor_pos; HANDLE handle; int cell_count; DWORD written; handle = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(handle, &csbi); // If the cursor was outside of the new buffer size, conhost will move it // down one line. This needs to be accounted for to prevent artefacts. if (_rl_last_c_pos >= csbi.dwSize.X) ++_rl_last_v_pos; // Move the cursor to the prompt line cursor_pos = csbi.dwCursorPosition; cursor_pos.Y -= _rl_last_v_pos; cursor_pos.X = 0; SetConsoleCursorPosition(handle, cursor_pos); // Clear the buffer used by the line previously. cell_count = csbi.dwSize.X * (_rl_vis_botlin + 1); FillConsoleOutputCharacterW(handle, ' ', cell_count, cursor_pos, &written); FillConsoleOutputAttribute(handle, csbi.wAttributes, cell_count, cursor_pos, &written); // Tell Readline the buffer's resized. rl_resize_terminal(); }
//------------------------------------------------------------------------------ void win_screen_buffer::clear(clear_type type) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(m_handle, &csbi); int width, height, count = 0; COORD xy; switch (type) { case clear_type_all: width = csbi.dwSize.X; height = (csbi.srWindow.Bottom - csbi.srWindow.Top) + 1; xy = { 0, csbi.srWindow.Top }; break; case clear_type_before: width = csbi.dwSize.X; height = csbi.dwCursorPosition.Y - csbi.srWindow.Top; xy = { 0, csbi.srWindow.Top }; count = csbi.dwCursorPosition.X + 1; break; case clear_type_after: width = csbi.dwSize.X; height = csbi.srWindow.Bottom - csbi.dwCursorPosition.Y; xy = { csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y }; count = width - csbi.dwCursorPosition.X; break; } count += width * height; DWORD written; FillConsoleOutputCharacterW(m_handle, ' ', count, xy, &written); FillConsoleOutputAttribute(m_handle, csbi.wAttributes, count, xy, &written); }
static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, DWORD* error) { unsigned short argc = handle->ansi_csi_argc; unsigned short* argv = handle->ansi_csi_argv; CONSOLE_SCREEN_BUFFER_INFO info; COORD start, end; DWORD count, written; int x1, x2, y1, y2; int x1r, x2r, y1r, y2r; if (*error != ERROR_SUCCESS) { return -1; } if (dir == 0) { /* Clear from current position */ x1 = 0; x1r = 1; } else { /* Clear from column 0 */ x1 = 0; x1r = 0; } if (dir == 1) { /* Clear to current position */ x2 = 0; x2r = 1; } else { /* Clear to end of row. We pretend the console is 65536 characters wide, */ /* uv_tty_make_real_coord will clip it to the actual console width. */ x2 = 0xffff; x2r = 0; } if (!entire_screen) { /* Stay on our own row */ y1 = y2 = 0; y1r = y2r = 1; } else { /* Apply columns direction to row */ y1 = x1; y1r = x1r; y2 = x2; y2r = x2r; } retry: if (!GetConsoleScreenBufferInfo(handle->handle, &info)) { *error = GetLastError(); return -1; } start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r); end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r); count = (end.Y * info.dwSize.X + end.X) - (start.Y * info.dwSize.X + start.X) + 1; if (!(FillConsoleOutputCharacterW(handle->handle, L'\x20', count, start, &written) && FillConsoleOutputAttribute(handle->handle, info.wAttributes, written, start, &written))) { if (GetLastError() == ERROR_INVALID_PARAMETER) { /* The console may be resized - retry */ goto retry; } else { *error = GetLastError(); return -1; } } return 0; }
// Mutates the input argument (buf), because we're evil. void mp_write_console_ansi(HANDLE wstream, char *buf) { while (*buf) { char *next = strchr(buf, '\033'); if (!next) { write_console_text(wstream, buf); break; } next[0] = '\0'; // mutate input for fun and profit write_console_text(wstream, buf); if (next[1] != '[') { write_console_text(wstream, "\033"); buf = next; continue; } next += 2; // ANSI codes generally follow this syntax: // "\033[" [ <i> (';' <i> )* ] <c> // where <i> are integers, and <c> a single char command code. // Also see: http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes int params[2] = {-1, -1}; // 'm' might be unlimited; ignore that int num_params = 0; while (num_params < 2) { char *end = next; long p = strtol(next, &end, 10); if (end == next) break; next = end; params[num_params++] = p; if (next[0] != ';' || !next[0]) break; next += 1; } char code = next[0]; if (code) next += 1; CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(wstream, &info); switch (code) { case 'K': { // erase to end of line COORD at = info.dwCursorPosition; int len = info.dwSize.X - at.X; FillConsoleOutputCharacterW(wstream, ' ', len, at, &(DWORD){0}); SetConsoleCursorPosition(wstream, at); break; } case 'A': { // cursor up info.dwCursorPosition.Y -= 1; SetConsoleCursorPosition(wstream, info.dwCursorPosition); break; } case 'm': { // "SGR" for (int n = 0; n < num_params; n++) { int p = params[n]; if (p == 0) { info.wAttributes = stdoutAttrs; SetConsoleTextAttribute(wstream, info.wAttributes); } else if (p == 1) { info.wAttributes |= FOREGROUND_INTENSITY; SetConsoleTextAttribute(wstream, info.wAttributes); } else if (p >= 30 && p < 38) { info.wAttributes &= ~FOREGROUND_ALL; info.wAttributes |= ansi2win32[p - 30]; SetConsoleTextAttribute(wstream, info.wAttributes); } } break; } } buf = next; } }