diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 39544fb8a9d..07d90a3a1ae 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -1948,7 +1948,16 @@ static NTSTATUS write_console( struct screen_buffer *screen_buffer, const WCHAR if (screen_buffer->cursor_x == screen_buffer->width) { - if (screen_buffer->mode & ENABLE_WRAP_AT_EOL_OUTPUT) screen_buffer->cursor_x--; + if (screen_buffer->mode & ENABLE_WRAP_AT_EOL_OUTPUT) + { + if (!(screen_buffer->mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + { + screen_buffer->cursor_x = 0; + if (++screen_buffer->cursor_y == screen_buffer->height) + new_line( screen_buffer, &update_rect ); + } + else screen_buffer->cursor_x--; + } else screen_buffer->cursor_x = update_rect.left; } diff --git a/programs/conhost/tests/tty.c b/programs/conhost/tests/tty.c index 7cc37fa7fe1..c60dd253dfe 100644 --- a/programs/conhost/tests/tty.c +++ b/programs/conhost/tests/tty.c @@ -149,6 +149,7 @@ enum req_type REQ_CREATE_SCREEN_BUFFER, REQ_FILL_CHAR, REQ_GET_INPUT, + REQ_GET_SB_INFO, REQ_READ_CONSOLE, REQ_READ_CONSOLE_A, REQ_READ_CONSOLE_FILE, @@ -551,8 +552,30 @@ static void expect_char_key_(unsigned int line, WCHAR ch) expect_key_pressed_(line, ch, ch, vk, ctrl); } +#define test_cursor_pos(a,b) _test_cursor_pos(__LINE__,a,b) +static void _test_cursor_pos(unsigned line, int expect_x, int expect_y) +{ + struct pseudoconsole_req req = { REQ_GET_SB_INFO }; + CONSOLE_SCREEN_BUFFER_INFO info; + DWORD read; + BOOL ret; + + ret = WriteFile(child_pipe, &req, sizeof(req), &read, NULL); + ok(ret, "WriteFile failed: %u\n", GetLastError()); + + ret = ReadFile(child_pipe, &info, sizeof(info), &read, NULL); + ok(ret, "ReadFile failed: %u\n", GetLastError()); + + ok_(__FILE__,line)(info.dwCursorPosition.X == expect_x, "dwCursorPosition.X = %u, expected %u\n", + info.dwCursorPosition.X, expect_x); + ok_(__FILE__,line)(info.dwCursorPosition.Y == expect_y, "dwCursorPosition.Y = %u, expected %u\n", + info.dwCursorPosition.Y, expect_y); +} + static void test_write_console(void) { + child_set_output_mode(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + child_string_request(REQ_WRITE_CONSOLE, L"abc"); skip_hide_cursor(); expect_output_sequence("abc"); @@ -761,6 +784,55 @@ static void test_write_console(void) expect_empty_output(); child_set_output_mode(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + + child_set_cursor(28, 20); + skip_hide_cursor(); + expect_output_sequence("\x1b[21;29H"); /* set cursor */ + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + + child_string_request(REQ_WRITE_CONSOLE, L"ab"); + skip_hide_cursor(); + expect_output_sequence("ab"); + expect_output_sequence("\r\n"); + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + test_cursor_pos(0, 21); + + child_string_request(REQ_WRITE_CONSOLE, L"c"); + skip_hide_cursor(); + expect_output_sequence("c"); + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + test_cursor_pos(1, 21); + + child_set_cursor(28, 22); + skip_hide_cursor(); + expect_output_sequence("\x1b[23;29H"); /* set cursor */ + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + + child_string_request(REQ_WRITE_CONSOLE, L"x"); + skip_hide_cursor(); + expect_output_sequence("x"); + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + test_cursor_pos(29, 22); + + child_string_request(REQ_WRITE_CONSOLE, L"y"); + skip_hide_cursor(); + expect_output_sequence("y"); + expect_output_sequence("\r\n"); + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + test_cursor_pos(0, 23); + + child_string_request(REQ_WRITE_CONSOLE, L"z"); + skip_hide_cursor(); + expect_output_sequence("z"); + skip_sequence("\x1b[?25h"); /* show cursor */ + expect_empty_output(); + test_cursor_pos(1, 23); } static void test_tty_output(void) @@ -1300,6 +1372,16 @@ static void child_process(HANDLE pipe) break; } + case REQ_GET_SB_INFO: + { + CONSOLE_SCREEN_BUFFER_INFO info; + ret = GetConsoleScreenBufferInfo(output, &info); + ok(ret, "GetConsoleScreenBufferInfo failed: %u\n", GetLastError()); + ret = WriteFile(pipe, &info, sizeof(info), &count, NULL); + ok(ret, "WriteFile failed: %u\n", GetLastError()); + break; + } + case REQ_READ_CONSOLE: ret = ReadConsoleW(input, buf, req->u.size, &count, NULL ); ok(ret, "ReadConsoleW failed: %u\n", GetLastError());