tildefriends/deps/libuv/test/test-tty-escape-sequence-processing.c

1633 lines
49 KiB
C
Raw Normal View History

/* Copyright libuv project contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifdef _WIN32
#include "task.h"
#include "uv.h"
#include <io.h>
#include <windows.h>
#include <errno.h>
#include <string.h>
#define ESC "\033"
#define CSI ESC "["
#define ST ESC "\\"
#define BEL "\x07"
#define HELLO "Hello"
#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_BLACK 0
#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
#define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
#define BACKGROUND_BLACK 0
#define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN)
#define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE)
#define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE)
#define F_INTENSITY 1
#define FB_INTENSITY 2
#define B_INTENSITY 5
#define INVERSE 7
#define F_INTENSITY_OFF1 21
#define F_INTENSITY_OFF2 22
#define B_INTENSITY_OFF 25
#define INVERSE_OFF 27
#define F_BLACK 30
#define F_RED 31
#define F_GREEN 32
#define F_YELLOW 33
#define F_BLUE 34
#define F_MAGENTA 35
#define F_CYAN 36
#define F_WHITE 37
#define F_DEFAULT 39
#define B_BLACK 40
#define B_RED 41
#define B_GREEN 42
#define B_YELLOW 43
#define B_BLUE 44
#define B_MAGENTA 45
#define B_CYAN 46
#define B_WHITE 47
#define B_DEFAULT 49
#define CURSOR_SIZE_SMALL 25
#define CURSOR_SIZE_MIDDLE 50
#define CURSOR_SIZE_LARGE 100
struct screen_info {
CONSOLE_SCREEN_BUFFER_INFO csbi;
int top;
int width;
int height;
int length;
WORD default_attr;
};
struct captured_screen {
char* text;
WORD* attributes;
struct screen_info si;
};
static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) {
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi)));
si->width = si->csbi.dwSize.X;
si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1;
si->length = si->width * si->height;
si->default_attr = si->csbi.wAttributes;
si->top = si->csbi.srWindow.Top;
}
static void set_cursor_position(uv_tty_t* tty_out, COORD pos) {
HANDLE handle = tty_out->handle;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(handle, &info));
pos.X -= 1;
pos.Y += info.srWindow.Top - 1;
ASSERT(SetConsoleCursorPosition(handle, pos));
}
static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) {
HANDLE handle = tty_out->handle;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(handle, &info));
cursor_position->X = info.dwCursorPosition.X + 1;
cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1;
}
static void set_cursor_to_home(uv_tty_t* tty_out) {
COORD origin = {1, 1};
set_cursor_position(tty_out, origin);
}
static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) {
HANDLE handle = tty_out->handle;
CONSOLE_CURSOR_INFO info;
ASSERT(GetConsoleCursorInfo(handle, &info));
return info;
}
static void set_cursor_size(uv_tty_t* tty_out, DWORD size) {
CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
info.dwSize = size;
ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
}
static DWORD get_cursor_size(uv_tty_t* tty_out) {
return get_cursor_info(tty_out).dwSize;
}
static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) {
CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out);
info.bVisible = visible;
ASSERT(SetConsoleCursorInfo(tty_out->handle, &info));
}
static BOOL get_cursor_visibility(uv_tty_t* tty_out) {
return get_cursor_info(tty_out).bVisible;
}
static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) {
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
return info.srWindow.Top != si.top;
}
static void write_console(uv_tty_t* tty_out, char* src) {
int r;
uv_buf_t buf;
buf.base = src;
buf.len = strlen(buf.base);
r = uv_try_write((uv_stream_t*) tty_out, &buf, 1);
ASSERT(r >= 0);
ASSERT((unsigned int) r == buf.len);
}
static void setup_screen(uv_tty_t* tty_out) {
DWORD length, number_of_written;
COORD origin;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1);
origin.X = 0;
origin.Y = info.srWindow.Top;
ASSERT(FillConsoleOutputCharacter(
tty_out->handle, '.', length, origin, &number_of_written));
ASSERT(length == number_of_written);
}
static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) {
DWORD length, number_of_written;
COORD origin;
CONSOLE_SCREEN_BUFFER_INFO info;
ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info));
length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1;
origin.X = 0;
origin.Y = info.srWindow.Top;
FillConsoleOutputCharacterA(
tty_out->handle, ' ', length, origin, &number_of_written);
ASSERT(length == number_of_written);
FillConsoleOutputAttribute(
tty_out->handle, si->default_attr, length, origin, &number_of_written);
ASSERT(length == number_of_written);
}
static void free_screen(struct captured_screen* cs) {
free(cs->text);
cs->text = NULL;
free(cs->attributes);
cs->attributes = NULL;
}
static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) {
DWORD length;
COORD origin;
get_screen_info(tty_out, &(cs->si));
origin.X = 0;
origin.Y = cs->si.csbi.srWindow.Top;
cs->text = malloc(cs->si.length * sizeof(*cs->text));
ASSERT_NOT_NULL(cs->text);
cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes));
ASSERT_NOT_NULL(cs->attributes);
ASSERT(ReadConsoleOutputCharacter(
tty_out->handle, cs->text, cs->si.length, origin, &length));
ASSERT((unsigned int) cs->si.length == length);
ASSERT(ReadConsoleOutputAttribute(
tty_out->handle, cs->attributes, cs->si.length, origin, &length));
ASSERT((unsigned int) cs->si.length == length);
}
static void make_expect_screen_erase(struct captured_screen* cs,
COORD cursor_position,
int dir,
BOOL entire_screen) {
/* beginning of line */
char* start;
char* end;
start = cs->text + cs->si.width * (cursor_position.Y - 1);
if (dir == 0) {
if (entire_screen) {
/* erase to end of screen */
end = cs->text + cs->si.length;
} else {
/* erase to end of line */
end = start + cs->si.width;
}
/* erase from postition of cursor */
start += cursor_position.X - 1;
} else if (dir == 1) {
/* erase to position of cursor */
end = start + cursor_position.X;
if (entire_screen) {
/* erase form beginning of screen */
start = cs->text;
}
} else if (dir == 2) {
if (entire_screen) {
/* erase form beginning of screen */
start = cs->text;
/* erase to end of screen */
end = cs->text + cs->si.length;
} else {
/* erase to end of line */
end = start + cs->si.width;
}
} else {
ASSERT(FALSE);
}
ASSERT(start < end);
ASSERT(end - cs->text <= cs->si.length);
for (; start < end; start++) {
*start = ' ';
}
}
static void make_expect_screen_write(struct captured_screen* cs,
COORD cursor_position,
const char* text) {
/* position of cursor */
char* start;
start = cs->text + cs->si.width * (cursor_position.Y - 1) +
cursor_position.X - 1;
size_t length = strlen(text);
size_t remain_length = cs->si.length - (cs->text - start);
length = length > remain_length ? remain_length : length;
memcpy(start, text, length);
}
static void make_expect_screen_set_attr(struct captured_screen* cs,
COORD cursor_position,
size_t length,
WORD attr) {
WORD* start;
start = cs->attributes + cs->si.width * (cursor_position.Y - 1) +
cursor_position.X - 1;
size_t remain_length = cs->si.length - (cs->attributes - start);
length = length > remain_length ? remain_length : length;
while (length) {
*start = attr;
start++;
length--;
}
}
static BOOL compare_screen(uv_tty_t* tty_out,
struct captured_screen* actual,
struct captured_screen* expect) {
int line, col;
BOOL result = TRUE;
int current = 0;
ASSERT(actual->text);
ASSERT(actual->attributes);
ASSERT(expect->text);
ASSERT(expect->attributes);
if (actual->si.length != expect->si.length) {
return FALSE;
}
if (actual->si.width != expect->si.width) {
return FALSE;
}
if (actual->si.height != expect->si.height) {
return FALSE;
}
while (current < actual->si.length) {
if (*(actual->text + current) != *(expect->text + current)) {
line = current / actual->si.width + 1;
col = current - actual->si.width * (line - 1) + 1;
fprintf(stderr,
"line:%d col:%d expected character '%c' but found '%c'\n",
line,
col,
*(expect->text + current),
*(actual->text + current));
result = FALSE;
}
if (*(actual->attributes + current) != *(expect->attributes + current)) {
line = current / actual->si.width + 1;
col = current - actual->si.width * (line - 1) + 1;
fprintf(stderr,
"line:%d col:%d expected attributes '%u' but found '%u'\n",
line,
col,
*(expect->attributes + current),
*(actual->attributes + current));
result = FALSE;
}
current++;
}
clear_screen(tty_out, &expect->si);
free_screen(expect);
free_screen(actual);
return result;
}
static void initialize_tty(uv_tty_t* tty_out) {
int r;
int ttyout_fd;
/* Make sure we have an FD that refers to a tty */
HANDLE handle;
uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED);
handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL);
ASSERT(handle != INVALID_HANDLE_VALUE);
ttyout_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT(ttyout_fd >= 0);
ASSERT(UV_TTY == uv_guess_handle(ttyout_fd));
r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */
ASSERT(r == 0);
}
static void terminate_tty(uv_tty_t* tty_out) {
set_cursor_to_home(tty_out);
uv_close((uv_handle_t*) tty_out, NULL);
}
TEST_IMPL(tty_cursor_up) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor up one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sA", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor up nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor up from Window top does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sA", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_down) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor down one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sB", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor down nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor down from bottom line does nothing */
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sB", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_forward) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor forward one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X + 1 == cursor_pos.X);
/* cursor forward nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X);
/* cursor forward from end of line does nothing*/
cursor_pos_old.X = si.width;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor forward from end of screen does nothing */
cursor_pos_old.X = si.width;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sC", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_back) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor back one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X - 1 == cursor_pos.X);
/* cursor back nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X);
/* cursor back from beginning of line does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(cursor_pos_old.X == cursor_pos.X);
/* cursor back from top of screen does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_next_line) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor next line one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sE", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor next line nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor next line from buttom row moves beginning of line */
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sE", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_previous_line) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* cursor previous line one times if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sF", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor previous line nth times */
cursor_pos_old = cursor_pos;
snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
/* cursor previous line from top of screen does nothing */
cursor_pos_old.X = 1;
cursor_pos_old.Y = 1;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer, sizeof(buffer), "%sD", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.Y);
ASSERT(1 == cursor_pos.X);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_horizontal_move_absolute) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* Move to beginning of line if omitted argument */
snprintf(buffer, sizeof(buffer), "%sG", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
/* Move cursor to nth character */
snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 4 == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
/* Moving out of screen will fit within screen */
snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width == cursor_pos.X);
ASSERT(cursor_pos_old.Y == cursor_pos.Y);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_cursor_move_absolute) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos.X = si.width / 2;
cursor_pos.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
/* Move the cursor to home if omitted arguments */
snprintf(buffer, sizeof(buffer), "%sH", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(1 == cursor_pos.X);
ASSERT(1 == cursor_pos.Y);
/* Move the cursor to the middle of the screen */
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 2 == cursor_pos.X);
ASSERT(si.height / 2 == cursor_pos.Y);
/* Moving out of screen will fit within screen */
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width == cursor_pos.X);
ASSERT(si.height / 2 == cursor_pos.Y);
snprintf(
buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(si.width / 2 == cursor_pos.X);
ASSERT(si.height == cursor_pos.Y);
ASSERT(!is_scrolling(&tty_out, si));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_hide_show_cursor) {
uv_tty_t tty_out;
uv_loop_t* loop;
char buffer[1024];
BOOL saved_cursor_visibility;
loop = uv_default_loop();
initialize_tty(&tty_out);
saved_cursor_visibility = get_cursor_visibility(&tty_out);
/* Hide the cursor */
set_cursor_visibility(&tty_out, TRUE);
snprintf(buffer, sizeof(buffer), "%s?25l", CSI);
write_console(&tty_out, buffer);
ASSERT(!get_cursor_visibility(&tty_out));
/* Show the cursor */
set_cursor_visibility(&tty_out, FALSE);
snprintf(buffer, sizeof(buffer), "%s?25h", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
set_cursor_visibility(&tty_out, saved_cursor_visibility);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_erase) {
int dir;
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
loop = uv_default_loop();
initialize_tty(&tty_out);
/* Erase to below if omitted argument */
dir = 0;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%sJ", CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to below(dir = 0) */
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to above */
dir = 1;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase All */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, TRUE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_erase_line) {
int dir;
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
loop = uv_default_loop();
initialize_tty(&tty_out);
/* Erase to right if omitted arguments */
dir = 0;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%sK", CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to right(dir = 0) */
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase to Left */
dir = 1;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Erase All */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
make_expect_screen_erase(&expect, cursor_pos, dir, FALSE);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_set_cursor_shape) {
uv_tty_t tty_out;
uv_loop_t* loop;
DWORD saved_cursor_size;
char buffer[1024];
loop = uv_default_loop();
initialize_tty(&tty_out);
saved_cursor_size = get_cursor_size(&tty_out);
/* cursor size large if omitted arguments */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
/* cursor size large */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s1 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s2 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE);
/* cursor size small */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s3 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s6 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL);
/* Nothing occurs with arguments outside valid range */
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s7 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
/* restore cursor size if arguments is zero */
snprintf(buffer, sizeof(buffer), "%s0 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_set_style) {
#if _MSC_VER >= 1920 && _MSC_VER <= 1929
RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
"See: https://github.com/libuv/libuv/issues/3304");
#else
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
WORD fg, bg;
WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK},
{F_RED, FOREGROUND_RED},
{F_GREEN, FOREGROUND_GREEN},
{F_YELLOW, FOREGROUND_YELLOW},
{F_BLUE, FOREGROUND_BLUE},
{F_MAGENTA, FOREGROUND_MAGENTA},
{F_CYAN, FOREGROUND_CYAN},
{F_WHITE, FOREGROUND_WHITE},
{F_DEFAULT, 0}};
WORD bg_attrs[9][2] = {{B_DEFAULT, 0},
{B_BLACK, BACKGROUND_BLACK},
{B_RED, BACKGROUND_RED},
{B_GREEN, BACKGROUND_GREEN},
{B_YELLOW, BACKGROUND_YELLOW},
{B_BLUE, BACKGROUND_BLUE},
{B_MAGENTA, BACKGROUND_MAGENTA},
{B_CYAN, BACKGROUND_CYAN},
{B_WHITE, BACKGROUND_WHITE}};
WORD attr;
int i, length;
loop = uv_default_loop();
initialize_tty(&tty_out);
capture_screen(&tty_out, &expect);
fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE;
bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE;
/* Set foreground color */
length = ARRAY_SIZE(fg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(
buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set background color */
length = ARRAY_SIZE(bg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(
buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set foreground and background color */
ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs));
length = ARRAY_SIZE(bg_attrs);
for (i = 0; i < length; i++) {
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE;
attr |= fg_attrs[i][1] | bg_attrs[i][1];
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer,
sizeof(buffer),
"%s%d;%dm%s%sm",
CSI,
bg_attrs[i][0],
fg_attrs[i][0],
HELLO,
CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
}
/* Set foreground bright on */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
attr |= FOREGROUND_INTENSITY;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm%s%dm%s%s%dm",
CSI,
F_INTENSITY,
HELLO,
CSI,
F_INTENSITY_OFF1,
CSI,
F_INTENSITY,
HELLO,
CSI,
F_INTENSITY_OFF2);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Set background bright on */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
attr |= BACKGROUND_INTENSITY;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm",
CSI,
B_INTENSITY,
HELLO,
CSI,
B_INTENSITY_OFF);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Inverse */
capture_screen(&tty_out, &expect);
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
attr = expect.si.default_attr;
fg = attr & FOREGROUND_WHITE;
bg = attr & BACKGROUND_WHITE;
attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE);
attr |= COMMON_LVB_REVERSE_VIDEO;
attr |= fg << 4;
attr |= bg >> 4;
make_expect_screen_write(&expect, cursor_pos, HELLO);
make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%dm%s%s%dm%s",
CSI,
INVERSE,
HELLO,
CSI,
INVERSE_OFF,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
#endif
}
TEST_IMPL(tty_save_restore_cursor_position) {
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
char buffer[1024];
struct screen_info si;
loop = uv_default_loop();
initialize_tty(&tty_out);
get_screen_info(&tty_out, &si);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* save the cursor position */
snprintf(buffer, sizeof(buffer), "%ss", CSI);
write_console(&tty_out, buffer);
cursor_pos.X = si.width / 4;
cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor position */
snprintf(buffer, sizeof(buffer), "%su", CSI);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == cursor_pos_old.X);
ASSERT(cursor_pos.Y == cursor_pos_old.Y);
cursor_pos_old.X = si.width / 2;
cursor_pos_old.Y = si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
/* save the cursor position */
snprintf(buffer, sizeof(buffer), "%s7", ESC);
write_console(&tty_out, buffer);
cursor_pos.X = si.width / 4;
cursor_pos.Y = si.height / 4;
set_cursor_position(&tty_out, cursor_pos);
/* restore the cursor position */
snprintf(buffer, sizeof(buffer), "%s8", ESC);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == cursor_pos_old.X);
ASSERT(cursor_pos.Y == cursor_pos_old.Y);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_full_reset) {
uv_tty_t tty_out;
uv_loop_t* loop;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
COORD cursor_pos;
DWORD saved_cursor_size;
BOOL saved_cursor_visibility;
loop = uv_default_loop();
initialize_tty(&tty_out);
capture_screen(&tty_out, &expect);
setup_screen(&tty_out);
cursor_pos.X = expect.si.width;
cursor_pos.Y = expect.si.height;
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO);
saved_cursor_size = get_cursor_size(&tty_out);
set_cursor_size(&tty_out,
saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL
: CURSOR_SIZE_LARGE);
saved_cursor_visibility = get_cursor_visibility(&tty_out);
set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE);
write_console(&tty_out, buffer);
snprintf(buffer, sizeof(buffer), "%sc", ESC);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
ASSERT(get_cursor_size(&tty_out) == saved_cursor_size);
ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility);
ASSERT(actual.si.csbi.srWindow.Top == 0);
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_escape_sequence_processing) {
#if _MSC_VER >= 1920 && _MSC_VER <= 1929
RETURN_SKIP("Broken on Microsoft Visual Studio 2019, to be investigated. "
"See: https://github.com/libuv/libuv/issues/3304");
#else
uv_tty_t tty_out;
uv_loop_t* loop;
COORD cursor_pos, cursor_pos_old;
DWORD saved_cursor_size;
char buffer[1024];
struct captured_screen actual = {0}, expect = {0};
int dir;
loop = uv_default_loop();
initialize_tty(&tty_out);
/* CSI + finally byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI(C1) + finally byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI + intermediate byte + finally byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* CSI + parameter byte + finally byte does not output anything */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
snprintf(buffer,
sizeof(buffer),
"%s0@%s%s>~%s%s?~%s",
CSI,
HELLO,
CSI,
HELLO,
CSI,
HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* ESC Single-char control does not output anyghing */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */
/* Operaging System Command */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Device Control Sequence */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Privacy Message */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s^\"%s\\\"%s\"%s%s",
ESC,
HELLO,
HELLO,
ST,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Application Program Command */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s_\"%s%s%s\"%s%s",
ESC,
HELLO,
ST,
HELLO,
BEL,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Ignore double escape */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
cursor_pos.X += strlen(HELLO);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%s@%s%s%s~%s",
ESC,
CSI,
HELLO,
ESC,
CSI,
HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Ignored if argument overflow */
set_cursor_to_home(&tty_out);
snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == 1);
ASSERT(cursor_pos.Y == 1);
/* Too many argument are ignored */
cursor_pos.X = 1;
cursor_pos.Y = 1;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer,
sizeof(buffer),
"%s%d;%d;%d;%d;%dm%s%sm",
CSI,
F_RED,
F_INTENSITY,
INVERSE,
B_CYAN,
B_INTENSITY_OFF,
HELLO,
CSI);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* In the case of DECSCUSR, the others are ignored */
set_cursor_to_home(&tty_out);
snprintf(buffer,
sizeof(buffer),
"%s%d;%d H",
CSI,
expect.si.height / 2,
expect.si.width / 2);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X == 1);
ASSERT(cursor_pos.Y == 1);
/* Invalid sequence are ignored */
saved_cursor_size = get_cursor_size(&tty_out);
set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s 1q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
snprintf(buffer, sizeof(buffer), "%s 1 q", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE);
set_cursor_size(&tty_out, saved_cursor_size);
/* #1874 2. */
snprintf(buffer, sizeof(buffer), "%s??25l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
snprintf(buffer, sizeof(buffer), "%s25?l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
cursor_pos_old.X = expect.si.width / 2;
cursor_pos_old.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos_old);
snprintf(buffer,
sizeof(buffer),
"%s??%d;%df",
CSI,
expect.si.height / 4,
expect.si.width / 4);
write_console(&tty_out, buffer);
get_cursor_position(&tty_out, &cursor_pos);
ASSERT(cursor_pos.X = cursor_pos_old.X);
ASSERT(cursor_pos.Y = cursor_pos_old.Y);
set_cursor_to_home(&tty_out);
/* CSI 25 l does nothing (#1874 4.) */
snprintf(buffer, sizeof(buffer), "%s25l", CSI);
write_console(&tty_out, buffer);
ASSERT(get_cursor_visibility(&tty_out));
/* Unsupported sequences are ignored(#1874 5.) */
dir = 2;
setup_screen(&tty_out);
capture_screen(&tty_out, &expect);
set_cursor_position(&tty_out, cursor_pos);
snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
/* Finally byte immedately after CSI [ are also output(#1874 1.) */
cursor_pos.X = expect.si.width / 2;
cursor_pos.Y = expect.si.height / 2;
set_cursor_position(&tty_out, cursor_pos);
capture_screen(&tty_out, &expect);
make_expect_screen_write(&expect, cursor_pos, HELLO);
snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO);
write_console(&tty_out, buffer);
capture_screen(&tty_out, &actual);
ASSERT(compare_screen(&tty_out, &actual, &expect));
terminate_tty(&tty_out);
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
#endif
}
#else
typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
#endif /* ifdef _WIN32 */