1 /* Copyright libuv project contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22 #ifdef _WIN32 23 24 #include "task.h" 25 #include "uv.h" 26 27 #include <io.h> 28 #include <windows.h> 29 30 #include <errno.h> 31 #include <string.h> 32 33 #define ESC "\033" 34 #define CSI ESC "[" 35 #define ST ESC "\\" 36 #define BEL "\x07" 37 #define HELLO "Hello" 38 39 #define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) 40 #define FOREGROUND_BLACK 0 41 #define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN) 42 #define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE) 43 #define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE) 44 #define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) 45 #define BACKGROUND_BLACK 0 46 #define BACKGROUND_YELLOW (BACKGROUND_RED | BACKGROUND_GREEN) 47 #define BACKGROUND_CYAN (BACKGROUND_GREEN | BACKGROUND_BLUE) 48 #define BACKGROUND_MAGENTA (BACKGROUND_RED | BACKGROUND_BLUE) 49 50 #define F_INTENSITY 1 51 #define FB_INTENSITY 2 52 #define B_INTENSITY 5 53 #define INVERSE 7 54 #define F_INTENSITY_OFF1 21 55 #define F_INTENSITY_OFF2 22 56 #define B_INTENSITY_OFF 25 57 #define INVERSE_OFF 27 58 #define F_BLACK 30 59 #define F_RED 31 60 #define F_GREEN 32 61 #define F_YELLOW 33 62 #define F_BLUE 34 63 #define F_MAGENTA 35 64 #define F_CYAN 36 65 #define F_WHITE 37 66 #define F_DEFAULT 39 67 #define B_BLACK 40 68 #define B_RED 41 69 #define B_GREEN 42 70 #define B_YELLOW 43 71 #define B_BLUE 44 72 #define B_MAGENTA 45 73 #define B_CYAN 46 74 #define B_WHITE 47 75 #define B_DEFAULT 49 76 77 #define CURSOR_SIZE_SMALL 25 78 #define CURSOR_SIZE_MIDDLE 50 79 #define CURSOR_SIZE_LARGE 100 80 81 struct screen_info { 82 CONSOLE_SCREEN_BUFFER_INFO csbi; 83 int top; 84 int width; 85 int height; 86 int length; 87 WORD default_attr; 88 }; 89 90 struct captured_screen { 91 char* text; 92 WORD* attributes; 93 struct screen_info si; 94 }; 95 96 static void get_screen_info(uv_tty_t* tty_out, struct screen_info* si) { 97 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &(si->csbi))); 98 si->width = si->csbi.dwSize.X; 99 si->height = si->csbi.srWindow.Bottom - si->csbi.srWindow.Top + 1; 100 si->length = si->width * si->height; 101 si->default_attr = si->csbi.wAttributes; 102 si->top = si->csbi.srWindow.Top; 103 } 104 105 static void set_cursor_position(uv_tty_t* tty_out, COORD pos) { 106 HANDLE handle = tty_out->handle; 107 CONSOLE_SCREEN_BUFFER_INFO info; 108 ASSERT(GetConsoleScreenBufferInfo(handle, &info)); 109 pos.X -= 1; 110 pos.Y += info.srWindow.Top - 1; 111 ASSERT(SetConsoleCursorPosition(handle, pos)); 112 } 113 114 static void get_cursor_position(uv_tty_t* tty_out, COORD* cursor_position) { 115 HANDLE handle = tty_out->handle; 116 CONSOLE_SCREEN_BUFFER_INFO info; 117 ASSERT(GetConsoleScreenBufferInfo(handle, &info)); 118 cursor_position->X = info.dwCursorPosition.X + 1; 119 cursor_position->Y = info.dwCursorPosition.Y - info.srWindow.Top + 1; 120 } 121 122 static void set_cursor_to_home(uv_tty_t* tty_out) { 123 COORD origin = {1, 1}; 124 set_cursor_position(tty_out, origin); 125 } 126 127 static CONSOLE_CURSOR_INFO get_cursor_info(uv_tty_t* tty_out) { 128 HANDLE handle = tty_out->handle; 129 CONSOLE_CURSOR_INFO info; 130 ASSERT(GetConsoleCursorInfo(handle, &info)); 131 return info; 132 } 133 134 static void set_cursor_size(uv_tty_t* tty_out, DWORD size) { 135 CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out); 136 info.dwSize = size; 137 ASSERT(SetConsoleCursorInfo(tty_out->handle, &info)); 138 } 139 140 static DWORD get_cursor_size(uv_tty_t* tty_out) { 141 return get_cursor_info(tty_out).dwSize; 142 } 143 144 static void set_cursor_visibility(uv_tty_t* tty_out, BOOL visible) { 145 CONSOLE_CURSOR_INFO info = get_cursor_info(tty_out); 146 info.bVisible = visible; 147 ASSERT(SetConsoleCursorInfo(tty_out->handle, &info)); 148 } 149 150 static BOOL get_cursor_visibility(uv_tty_t* tty_out) { 151 return get_cursor_info(tty_out).bVisible; 152 } 153 154 static BOOL is_scrolling(uv_tty_t* tty_out, struct screen_info si) { 155 CONSOLE_SCREEN_BUFFER_INFO info; 156 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); 157 return info.srWindow.Top != si.top; 158 } 159 160 static void write_console(uv_tty_t* tty_out, char* src) { 161 int r; 162 uv_buf_t buf; 163 164 buf.base = src; 165 buf.len = strlen(buf.base); 166 167 r = uv_try_write((uv_stream_t*) tty_out, &buf, 1); 168 ASSERT(r >= 0); 169 ASSERT((unsigned int) r == buf.len); 170 } 171 172 static void setup_screen(uv_tty_t* tty_out) { 173 DWORD length, number_of_written; 174 COORD origin; 175 CONSOLE_SCREEN_BUFFER_INFO info; 176 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); 177 length = info.dwSize.X * (info.srWindow.Bottom - info.srWindow.Top + 1); 178 origin.X = 0; 179 origin.Y = info.srWindow.Top; 180 ASSERT(FillConsoleOutputCharacter( 181 tty_out->handle, '.', length, origin, &number_of_written)); 182 ASSERT(length == number_of_written); 183 } 184 185 static void clear_screen(uv_tty_t* tty_out, struct screen_info* si) { 186 DWORD length, number_of_written; 187 COORD origin; 188 CONSOLE_SCREEN_BUFFER_INFO info; 189 ASSERT(GetConsoleScreenBufferInfo(tty_out->handle, &info)); 190 length = (info.srWindow.Bottom - info.srWindow.Top + 1) * info.dwSize.X - 1; 191 origin.X = 0; 192 origin.Y = info.srWindow.Top; 193 FillConsoleOutputCharacterA( 194 tty_out->handle, ' ', length, origin, &number_of_written); 195 ASSERT(length == number_of_written); 196 FillConsoleOutputAttribute( 197 tty_out->handle, si->default_attr, length, origin, &number_of_written); 198 ASSERT(length == number_of_written); 199 } 200 201 static void free_screen(struct captured_screen* cs) { 202 free(cs->text); 203 cs->text = NULL; 204 free(cs->attributes); 205 cs->attributes = NULL; 206 } 207 208 static void capture_screen(uv_tty_t* tty_out, struct captured_screen* cs) { 209 DWORD length; 210 COORD origin; 211 get_screen_info(tty_out, &(cs->si)); 212 origin.X = 0; 213 origin.Y = cs->si.csbi.srWindow.Top; 214 cs->text = malloc(cs->si.length * sizeof(*cs->text)); 215 ASSERT(cs->text != NULL); 216 cs->attributes = (WORD*) malloc(cs->si.length * sizeof(*cs->attributes)); 217 ASSERT(cs->attributes != NULL); 218 ASSERT(ReadConsoleOutputCharacter( 219 tty_out->handle, cs->text, cs->si.length, origin, &length)); 220 ASSERT((unsigned int) cs->si.length == length); 221 ASSERT(ReadConsoleOutputAttribute( 222 tty_out->handle, cs->attributes, cs->si.length, origin, &length)); 223 ASSERT((unsigned int) cs->si.length == length); 224 } 225 226 static void make_expect_screen_erase(struct captured_screen* cs, 227 COORD cursor_position, 228 int dir, 229 BOOL entire_screen) { 230 /* beginning of line */ 231 char* start; 232 char* end; 233 start = cs->text + cs->si.width * (cursor_position.Y - 1); 234 if (dir == 0) { 235 if (entire_screen) { 236 /* erase to end of screen */ 237 end = cs->text + cs->si.length; 238 } else { 239 /* erase to end of line */ 240 end = start + cs->si.width; 241 } 242 /* erase from postition of cursor */ 243 start += cursor_position.X - 1; 244 } else if (dir == 1) { 245 /* erase to position of cursor */ 246 end = start + cursor_position.X; 247 if (entire_screen) { 248 /* erase form beginning of screen */ 249 start = cs->text; 250 } 251 } else if (dir == 2) { 252 if (entire_screen) { 253 /* erase form beginning of screen */ 254 start = cs->text; 255 /* erase to end of screen */ 256 end = cs->text + cs->si.length; 257 } else { 258 /* erase to end of line */ 259 end = start + cs->si.width; 260 } 261 } else { 262 ASSERT(FALSE); 263 } 264 ASSERT(start < end); 265 ASSERT(end - cs->text <= cs->si.length); 266 for (; start < end; start++) { 267 *start = ' '; 268 } 269 } 270 271 static void make_expect_screen_write(struct captured_screen* cs, 272 COORD cursor_position, 273 const char* text) { 274 /* postion of cursor */ 275 char* start; 276 start = cs->text + cs->si.width * (cursor_position.Y - 1) + 277 cursor_position.X - 1; 278 size_t length = strlen(text); 279 size_t remain_length = cs->si.length - (cs->text - start); 280 length = length > remain_length ? remain_length : length; 281 memcpy(start, text, length); 282 } 283 284 static void make_expect_screen_set_attr(struct captured_screen* cs, 285 COORD cursor_position, 286 size_t length, 287 WORD attr) { 288 WORD* start; 289 start = cs->attributes + cs->si.width * (cursor_position.Y - 1) + 290 cursor_position.X - 1; 291 size_t remain_length = cs->si.length - (cs->attributes - start); 292 length = length > remain_length ? remain_length : length; 293 while (length) { 294 *start = attr; 295 start++; 296 length--; 297 } 298 } 299 300 static BOOL compare_screen(uv_tty_t* tty_out, 301 struct captured_screen* actual, 302 struct captured_screen* expect) { 303 int line, col; 304 BOOL result = TRUE; 305 int current = 0; 306 ASSERT(actual->text); 307 ASSERT(actual->attributes); 308 ASSERT(expect->text); 309 ASSERT(expect->attributes); 310 if (actual->si.length != expect->si.length) { 311 return FALSE; 312 } 313 if (actual->si.width != expect->si.width) { 314 return FALSE; 315 } 316 if (actual->si.height != expect->si.height) { 317 return FALSE; 318 } 319 while (current < actual->si.length) { 320 if (*(actual->text + current) != *(expect->text + current)) { 321 line = current / actual->si.width + 1; 322 col = current - actual->si.width * (line - 1) + 1; 323 fprintf(stderr, 324 "line:%d col:%d expected character '%c' but found '%c'\n", 325 line, 326 col, 327 *(expect->text + current), 328 *(actual->text + current)); 329 result = FALSE; 330 } 331 if (*(actual->attributes + current) != *(expect->attributes + current)) { 332 line = current / actual->si.width + 1; 333 col = current - actual->si.width * (line - 1) + 1; 334 fprintf(stderr, 335 "line:%d col:%d expected attributes '%u' but found '%u'\n", 336 line, 337 col, 338 *(expect->attributes + current), 339 *(actual->attributes + current)); 340 result = FALSE; 341 } 342 current++; 343 } 344 clear_screen(tty_out, &expect->si); 345 free_screen(expect); 346 free_screen(actual); 347 return result; 348 } 349 350 static void initialize_tty(uv_tty_t* tty_out) { 351 int r; 352 int ttyout_fd; 353 /* Make sure we have an FD that refers to a tty */ 354 HANDLE handle; 355 356 uv_tty_set_vterm_state(UV_TTY_UNSUPPORTED); 357 358 handle = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 359 FILE_SHARE_READ | FILE_SHARE_WRITE, 360 NULL, 361 CONSOLE_TEXTMODE_BUFFER, 362 NULL); 363 ASSERT(handle != INVALID_HANDLE_VALUE); 364 365 ttyout_fd = _open_osfhandle((intptr_t) handle, 0); 366 ASSERT(ttyout_fd >= 0); 367 ASSERT(UV_TTY == uv_guess_handle(ttyout_fd)); 368 r = uv_tty_init(uv_default_loop(), tty_out, ttyout_fd, 0); /* Writable. */ 369 ASSERT(r == 0); 370 } 371 372 static void terminate_tty(uv_tty_t* tty_out) { 373 set_cursor_to_home(tty_out); 374 uv_close((uv_handle_t*) tty_out, NULL); 375 } 376 377 TEST_IMPL(tty_cursor_up) { 378 uv_tty_t tty_out; 379 uv_loop_t* loop; 380 COORD cursor_pos, cursor_pos_old; 381 char buffer[1024]; 382 struct screen_info si; 383 384 loop = uv_default_loop(); 385 386 initialize_tty(&tty_out); 387 get_screen_info(&tty_out, &si); 388 389 cursor_pos_old.X = si.width / 2; 390 cursor_pos_old.Y = si.height / 2; 391 set_cursor_position(&tty_out, cursor_pos_old); 392 393 /* cursor up one times if omitted arguments */ 394 snprintf(buffer, sizeof(buffer), "%sA", CSI); 395 write_console(&tty_out, buffer); 396 get_cursor_position(&tty_out, &cursor_pos); 397 ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y); 398 ASSERT(cursor_pos_old.X == cursor_pos.X); 399 400 /* cursor up nth times */ 401 cursor_pos_old = cursor_pos; 402 snprintf(buffer, sizeof(buffer), "%s%dA", CSI, si.height / 4); 403 write_console(&tty_out, buffer); 404 get_cursor_position(&tty_out, &cursor_pos); 405 ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y); 406 ASSERT(cursor_pos_old.X == cursor_pos.X); 407 408 /* cursor up from Window top does nothing */ 409 cursor_pos_old.X = 1; 410 cursor_pos_old.Y = 1; 411 set_cursor_position(&tty_out, cursor_pos_old); 412 snprintf(buffer, sizeof(buffer), "%sA", CSI); 413 write_console(&tty_out, buffer); 414 get_cursor_position(&tty_out, &cursor_pos); 415 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 416 ASSERT(cursor_pos_old.X == cursor_pos.X); 417 ASSERT(!is_scrolling(&tty_out, si)); 418 419 terminate_tty(&tty_out); 420 421 uv_run(loop, UV_RUN_DEFAULT); 422 423 MAKE_VALGRIND_HAPPY(); 424 return 0; 425 } 426 427 428 TEST_IMPL(tty_cursor_down) { 429 uv_tty_t tty_out; 430 uv_loop_t* loop; 431 COORD cursor_pos, cursor_pos_old; 432 char buffer[1024]; 433 struct screen_info si; 434 435 loop = uv_default_loop(); 436 437 initialize_tty(&tty_out); 438 get_screen_info(&tty_out, &si); 439 440 cursor_pos_old.X = si.width / 2; 441 cursor_pos_old.Y = si.height / 2; 442 set_cursor_position(&tty_out, cursor_pos_old); 443 444 /* cursor down one times if omitted arguments */ 445 snprintf(buffer, sizeof(buffer), "%sB", CSI); 446 write_console(&tty_out, buffer); 447 get_cursor_position(&tty_out, &cursor_pos); 448 ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y); 449 ASSERT(cursor_pos_old.X == cursor_pos.X); 450 451 /* cursor down nth times */ 452 cursor_pos_old = cursor_pos; 453 snprintf(buffer, sizeof(buffer), "%s%dB", CSI, si.height / 4); 454 write_console(&tty_out, buffer); 455 get_cursor_position(&tty_out, &cursor_pos); 456 ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y); 457 ASSERT(cursor_pos_old.X == cursor_pos.X); 458 459 /* cursor down from bottom line does nothing */ 460 cursor_pos_old.X = si.width / 2; 461 cursor_pos_old.Y = si.height; 462 set_cursor_position(&tty_out, cursor_pos_old); 463 snprintf(buffer, sizeof(buffer), "%sB", CSI); 464 write_console(&tty_out, buffer); 465 get_cursor_position(&tty_out, &cursor_pos); 466 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 467 ASSERT(cursor_pos_old.X == cursor_pos.X); 468 ASSERT(!is_scrolling(&tty_out, si)); 469 470 terminate_tty(&tty_out); 471 472 uv_run(loop, UV_RUN_DEFAULT); 473 474 MAKE_VALGRIND_HAPPY(); 475 return 0; 476 } 477 478 479 TEST_IMPL(tty_cursor_forward) { 480 uv_tty_t tty_out; 481 uv_loop_t* loop; 482 COORD cursor_pos, cursor_pos_old; 483 char buffer[1024]; 484 struct screen_info si; 485 486 loop = uv_default_loop(); 487 488 initialize_tty(&tty_out); 489 get_screen_info(&tty_out, &si); 490 491 cursor_pos_old.X = si.width / 2; 492 cursor_pos_old.Y = si.height / 2; 493 set_cursor_position(&tty_out, cursor_pos_old); 494 495 /* cursor forward one times if omitted arguments */ 496 snprintf(buffer, sizeof(buffer), "%sC", CSI); 497 write_console(&tty_out, buffer); 498 get_cursor_position(&tty_out, &cursor_pos); 499 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 500 ASSERT(cursor_pos_old.X + 1 == cursor_pos.X); 501 502 /* cursor forward nth times */ 503 cursor_pos_old = cursor_pos; 504 snprintf(buffer, sizeof(buffer), "%s%dC", CSI, si.width / 4); 505 write_console(&tty_out, buffer); 506 get_cursor_position(&tty_out, &cursor_pos); 507 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 508 ASSERT(cursor_pos_old.X + si.width / 4 == cursor_pos.X); 509 510 /* cursor forward from end of line does nothing*/ 511 cursor_pos_old.X = si.width; 512 cursor_pos_old.Y = si.height / 2; 513 set_cursor_position(&tty_out, cursor_pos_old); 514 snprintf(buffer, sizeof(buffer), "%sC", CSI); 515 write_console(&tty_out, buffer); 516 get_cursor_position(&tty_out, &cursor_pos); 517 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 518 ASSERT(cursor_pos_old.X == cursor_pos.X); 519 520 /* cursor forward from end of screen does nothing */ 521 cursor_pos_old.X = si.width; 522 cursor_pos_old.Y = si.height; 523 set_cursor_position(&tty_out, cursor_pos_old); 524 snprintf(buffer, sizeof(buffer), "%sC", CSI); 525 write_console(&tty_out, buffer); 526 get_cursor_position(&tty_out, &cursor_pos); 527 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 528 ASSERT(cursor_pos_old.X == cursor_pos.X); 529 ASSERT(!is_scrolling(&tty_out, si)); 530 531 terminate_tty(&tty_out); 532 533 uv_run(loop, UV_RUN_DEFAULT); 534 535 MAKE_VALGRIND_HAPPY(); 536 return 0; 537 } 538 539 540 TEST_IMPL(tty_cursor_back) { 541 uv_tty_t tty_out; 542 uv_loop_t* loop; 543 COORD cursor_pos, cursor_pos_old; 544 char buffer[1024]; 545 struct screen_info si; 546 547 loop = uv_default_loop(); 548 549 initialize_tty(&tty_out); 550 get_screen_info(&tty_out, &si); 551 552 cursor_pos_old.X = si.width / 2; 553 cursor_pos_old.Y = si.height / 2; 554 set_cursor_position(&tty_out, cursor_pos_old); 555 556 /* cursor back one times if omitted arguments */ 557 snprintf(buffer, sizeof(buffer), "%sD", CSI); 558 write_console(&tty_out, buffer); 559 get_cursor_position(&tty_out, &cursor_pos); 560 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 561 ASSERT(cursor_pos_old.X - 1 == cursor_pos.X); 562 563 /* cursor back nth times */ 564 cursor_pos_old = cursor_pos; 565 snprintf(buffer, sizeof(buffer), "%s%dD", CSI, si.width / 4); 566 write_console(&tty_out, buffer); 567 get_cursor_position(&tty_out, &cursor_pos); 568 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 569 ASSERT(cursor_pos_old.X - si.width / 4 == cursor_pos.X); 570 571 /* cursor back from beginning of line does nothing */ 572 cursor_pos_old.X = 1; 573 cursor_pos_old.Y = si.height / 2; 574 set_cursor_position(&tty_out, cursor_pos_old); 575 snprintf(buffer, sizeof(buffer), "%sD", CSI); 576 write_console(&tty_out, buffer); 577 get_cursor_position(&tty_out, &cursor_pos); 578 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 579 ASSERT(cursor_pos_old.X == cursor_pos.X); 580 581 /* cursor back from top of screen does nothing */ 582 cursor_pos_old.X = 1; 583 cursor_pos_old.Y = 1; 584 set_cursor_position(&tty_out, cursor_pos_old); 585 snprintf(buffer, sizeof(buffer), "%sD", CSI); 586 write_console(&tty_out, buffer); 587 get_cursor_position(&tty_out, &cursor_pos); 588 ASSERT(1 == cursor_pos.Y); 589 ASSERT(1 == cursor_pos.X); 590 ASSERT(!is_scrolling(&tty_out, si)); 591 592 terminate_tty(&tty_out); 593 594 uv_run(loop, UV_RUN_DEFAULT); 595 596 MAKE_VALGRIND_HAPPY(); 597 return 0; 598 } 599 600 601 TEST_IMPL(tty_cursor_next_line) { 602 uv_tty_t tty_out; 603 uv_loop_t* loop; 604 COORD cursor_pos, cursor_pos_old; 605 char buffer[1024]; 606 struct screen_info si; 607 608 loop = uv_default_loop(); 609 610 initialize_tty(&tty_out); 611 get_screen_info(&tty_out, &si); 612 613 cursor_pos_old.X = si.width / 2; 614 cursor_pos_old.Y = si.height / 2; 615 set_cursor_position(&tty_out, cursor_pos_old); 616 617 /* cursor next line one times if omitted arguments */ 618 snprintf(buffer, sizeof(buffer), "%sE", CSI); 619 write_console(&tty_out, buffer); 620 get_cursor_position(&tty_out, &cursor_pos); 621 ASSERT(cursor_pos_old.Y + 1 == cursor_pos.Y); 622 ASSERT(1 == cursor_pos.X); 623 624 /* cursor next line nth times */ 625 cursor_pos_old = cursor_pos; 626 snprintf(buffer, sizeof(buffer), "%s%dE", CSI, si.height / 4); 627 write_console(&tty_out, buffer); 628 get_cursor_position(&tty_out, &cursor_pos); 629 ASSERT(cursor_pos_old.Y + si.height / 4 == cursor_pos.Y); 630 ASSERT(1 == cursor_pos.X); 631 632 /* cursor next line from buttom row moves beginning of line */ 633 cursor_pos_old.X = si.width / 2; 634 cursor_pos_old.Y = si.height; 635 set_cursor_position(&tty_out, cursor_pos_old); 636 snprintf(buffer, sizeof(buffer), "%sE", CSI); 637 write_console(&tty_out, buffer); 638 get_cursor_position(&tty_out, &cursor_pos); 639 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 640 ASSERT(1 == cursor_pos.X); 641 ASSERT(!is_scrolling(&tty_out, si)); 642 643 terminate_tty(&tty_out); 644 645 uv_run(loop, UV_RUN_DEFAULT); 646 647 MAKE_VALGRIND_HAPPY(); 648 return 0; 649 } 650 651 652 TEST_IMPL(tty_cursor_previous_line) { 653 uv_tty_t tty_out; 654 uv_loop_t* loop; 655 COORD cursor_pos, cursor_pos_old; 656 char buffer[1024]; 657 struct screen_info si; 658 659 loop = uv_default_loop(); 660 661 initialize_tty(&tty_out); 662 get_screen_info(&tty_out, &si); 663 664 cursor_pos_old.X = si.width / 2; 665 cursor_pos_old.Y = si.height / 2; 666 set_cursor_position(&tty_out, cursor_pos_old); 667 668 /* cursor previous line one times if omitted arguments */ 669 snprintf(buffer, sizeof(buffer), "%sF", CSI); 670 write_console(&tty_out, buffer); 671 get_cursor_position(&tty_out, &cursor_pos); 672 ASSERT(cursor_pos_old.Y - 1 == cursor_pos.Y); 673 ASSERT(1 == cursor_pos.X); 674 675 /* cursor previous line nth times */ 676 cursor_pos_old = cursor_pos; 677 snprintf(buffer, sizeof(buffer), "%s%dF", CSI, si.height / 4); 678 write_console(&tty_out, buffer); 679 get_cursor_position(&tty_out, &cursor_pos); 680 ASSERT(cursor_pos_old.Y - si.height / 4 == cursor_pos.Y); 681 ASSERT(1 == cursor_pos.X); 682 683 /* cursor previous line from top of screen does nothing */ 684 cursor_pos_old.X = 1; 685 cursor_pos_old.Y = 1; 686 set_cursor_position(&tty_out, cursor_pos_old); 687 snprintf(buffer, sizeof(buffer), "%sD", CSI); 688 write_console(&tty_out, buffer); 689 get_cursor_position(&tty_out, &cursor_pos); 690 ASSERT(1 == cursor_pos.Y); 691 ASSERT(1 == cursor_pos.X); 692 ASSERT(!is_scrolling(&tty_out, si)); 693 694 terminate_tty(&tty_out); 695 696 uv_run(loop, UV_RUN_DEFAULT); 697 698 MAKE_VALGRIND_HAPPY(); 699 return 0; 700 } 701 702 703 TEST_IMPL(tty_cursor_horizontal_move_absolute) { 704 uv_tty_t tty_out; 705 uv_loop_t* loop; 706 COORD cursor_pos, cursor_pos_old; 707 char buffer[1024]; 708 struct screen_info si; 709 710 loop = uv_default_loop(); 711 712 initialize_tty(&tty_out); 713 get_screen_info(&tty_out, &si); 714 715 cursor_pos_old.X = si.width / 2; 716 cursor_pos_old.Y = si.height / 2; 717 set_cursor_position(&tty_out, cursor_pos_old); 718 719 /* Move to beginning of line if omitted argument */ 720 snprintf(buffer, sizeof(buffer), "%sG", CSI); 721 write_console(&tty_out, buffer); 722 get_cursor_position(&tty_out, &cursor_pos); 723 ASSERT(1 == cursor_pos.X); 724 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 725 726 /* Move cursor to nth character */ 727 snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width / 4); 728 write_console(&tty_out, buffer); 729 get_cursor_position(&tty_out, &cursor_pos); 730 ASSERT(si.width / 4 == cursor_pos.X); 731 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 732 733 /* Moving out of screen will fit within screen */ 734 snprintf(buffer, sizeof(buffer), "%s%dG", CSI, si.width + 1); 735 write_console(&tty_out, buffer); 736 get_cursor_position(&tty_out, &cursor_pos); 737 ASSERT(si.width == cursor_pos.X); 738 ASSERT(cursor_pos_old.Y == cursor_pos.Y); 739 740 terminate_tty(&tty_out); 741 742 uv_run(loop, UV_RUN_DEFAULT); 743 744 MAKE_VALGRIND_HAPPY(); 745 return 0; 746 } 747 748 749 TEST_IMPL(tty_cursor_move_absolute) { 750 uv_tty_t tty_out; 751 uv_loop_t* loop; 752 COORD cursor_pos; 753 char buffer[1024]; 754 struct screen_info si; 755 756 loop = uv_default_loop(); 757 758 initialize_tty(&tty_out); 759 get_screen_info(&tty_out, &si); 760 761 cursor_pos.X = si.width / 2; 762 cursor_pos.Y = si.height / 2; 763 set_cursor_position(&tty_out, cursor_pos); 764 765 /* Move the cursor to home if omitted arguments */ 766 snprintf(buffer, sizeof(buffer), "%sH", CSI); 767 write_console(&tty_out, buffer); 768 get_cursor_position(&tty_out, &cursor_pos); 769 ASSERT(1 == cursor_pos.X); 770 ASSERT(1 == cursor_pos.Y); 771 772 /* Move the cursor to the middle of the screen */ 773 snprintf( 774 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width / 2); 775 write_console(&tty_out, buffer); 776 get_cursor_position(&tty_out, &cursor_pos); 777 ASSERT(si.width / 2 == cursor_pos.X); 778 ASSERT(si.height / 2 == cursor_pos.Y); 779 780 /* Moving out of screen will fit within screen */ 781 snprintf( 782 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height / 2, si.width + 1); 783 write_console(&tty_out, buffer); 784 get_cursor_position(&tty_out, &cursor_pos); 785 ASSERT(si.width == cursor_pos.X); 786 ASSERT(si.height / 2 == cursor_pos.Y); 787 788 snprintf( 789 buffer, sizeof(buffer), "%s%d;%df", CSI, si.height + 1, si.width / 2); 790 write_console(&tty_out, buffer); 791 get_cursor_position(&tty_out, &cursor_pos); 792 ASSERT(si.width / 2 == cursor_pos.X); 793 ASSERT(si.height == cursor_pos.Y); 794 ASSERT(!is_scrolling(&tty_out, si)); 795 796 terminate_tty(&tty_out); 797 798 uv_run(loop, UV_RUN_DEFAULT); 799 800 MAKE_VALGRIND_HAPPY(); 801 return 0; 802 } 803 804 805 TEST_IMPL(tty_hide_show_cursor) { 806 uv_tty_t tty_out; 807 uv_loop_t* loop; 808 char buffer[1024]; 809 BOOL saved_cursor_visibility; 810 811 loop = uv_default_loop(); 812 813 initialize_tty(&tty_out); 814 815 saved_cursor_visibility = get_cursor_visibility(&tty_out); 816 817 /* Hide the cursor */ 818 set_cursor_visibility(&tty_out, TRUE); 819 snprintf(buffer, sizeof(buffer), "%s?25l", CSI); 820 write_console(&tty_out, buffer); 821 ASSERT(!get_cursor_visibility(&tty_out)); 822 823 /* Show the cursor */ 824 set_cursor_visibility(&tty_out, FALSE); 825 snprintf(buffer, sizeof(buffer), "%s?25h", CSI); 826 write_console(&tty_out, buffer); 827 ASSERT(get_cursor_visibility(&tty_out)); 828 829 set_cursor_visibility(&tty_out, saved_cursor_visibility); 830 terminate_tty(&tty_out); 831 832 uv_run(loop, UV_RUN_DEFAULT); 833 834 MAKE_VALGRIND_HAPPY(); 835 return 0; 836 } 837 838 839 TEST_IMPL(tty_erase) { 840 int dir; 841 uv_tty_t tty_out; 842 uv_loop_t* loop; 843 COORD cursor_pos; 844 char buffer[1024]; 845 struct captured_screen actual = {0}, expect = {0}; 846 847 loop = uv_default_loop(); 848 849 initialize_tty(&tty_out); 850 851 /* Erase to below if omitted argument */ 852 dir = 0; 853 setup_screen(&tty_out); 854 capture_screen(&tty_out, &expect); 855 cursor_pos.X = expect.si.width / 2; 856 cursor_pos.Y = expect.si.height / 2; 857 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); 858 859 set_cursor_position(&tty_out, cursor_pos); 860 snprintf(buffer, sizeof(buffer), "%sJ", CSI); 861 write_console(&tty_out, buffer); 862 capture_screen(&tty_out, &actual); 863 864 ASSERT(compare_screen(&tty_out, &actual, &expect)); 865 866 /* Erase to below(dir = 0) */ 867 setup_screen(&tty_out); 868 capture_screen(&tty_out, &expect); 869 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); 870 871 set_cursor_position(&tty_out, cursor_pos); 872 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); 873 write_console(&tty_out, buffer); 874 capture_screen(&tty_out, &actual); 875 876 ASSERT(compare_screen(&tty_out, &actual, &expect)); 877 878 /* Erase to above */ 879 dir = 1; 880 setup_screen(&tty_out); 881 capture_screen(&tty_out, &expect); 882 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); 883 884 set_cursor_position(&tty_out, cursor_pos); 885 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); 886 write_console(&tty_out, buffer); 887 capture_screen(&tty_out, &actual); 888 889 ASSERT(compare_screen(&tty_out, &actual, &expect)); 890 891 /* Erase All */ 892 dir = 2; 893 setup_screen(&tty_out); 894 capture_screen(&tty_out, &expect); 895 make_expect_screen_erase(&expect, cursor_pos, dir, TRUE); 896 897 set_cursor_position(&tty_out, cursor_pos); 898 snprintf(buffer, sizeof(buffer), "%s%dJ", CSI, dir); 899 write_console(&tty_out, buffer); 900 capture_screen(&tty_out, &actual); 901 902 ASSERT(compare_screen(&tty_out, &actual, &expect)); 903 904 terminate_tty(&tty_out); 905 906 uv_run(loop, UV_RUN_DEFAULT); 907 908 MAKE_VALGRIND_HAPPY(); 909 return 0; 910 } 911 912 913 TEST_IMPL(tty_erase_line) { 914 int dir; 915 uv_tty_t tty_out; 916 uv_loop_t* loop; 917 COORD cursor_pos; 918 char buffer[1024]; 919 struct captured_screen actual = {0}, expect = {0}; 920 921 loop = uv_default_loop(); 922 923 initialize_tty(&tty_out); 924 925 /* Erase to right if omitted arguments */ 926 dir = 0; 927 setup_screen(&tty_out); 928 capture_screen(&tty_out, &expect); 929 cursor_pos.X = expect.si.width / 2; 930 cursor_pos.Y = expect.si.height / 2; 931 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); 932 933 set_cursor_position(&tty_out, cursor_pos); 934 snprintf(buffer, sizeof(buffer), "%sK", CSI); 935 write_console(&tty_out, buffer); 936 capture_screen(&tty_out, &actual); 937 938 ASSERT(compare_screen(&tty_out, &actual, &expect)); 939 940 /* Erase to right(dir = 0) */ 941 setup_screen(&tty_out); 942 capture_screen(&tty_out, &expect); 943 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); 944 945 set_cursor_position(&tty_out, cursor_pos); 946 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); 947 write_console(&tty_out, buffer); 948 capture_screen(&tty_out, &actual); 949 950 ASSERT(compare_screen(&tty_out, &actual, &expect)); 951 952 /* Erase to Left */ 953 dir = 1; 954 setup_screen(&tty_out); 955 capture_screen(&tty_out, &expect); 956 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); 957 958 set_cursor_position(&tty_out, cursor_pos); 959 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); 960 write_console(&tty_out, buffer); 961 capture_screen(&tty_out, &actual); 962 963 ASSERT(compare_screen(&tty_out, &actual, &expect)); 964 965 /* Erase All */ 966 dir = 2; 967 setup_screen(&tty_out); 968 capture_screen(&tty_out, &expect); 969 make_expect_screen_erase(&expect, cursor_pos, dir, FALSE); 970 971 set_cursor_position(&tty_out, cursor_pos); 972 snprintf(buffer, sizeof(buffer), "%s%dK", CSI, dir); 973 write_console(&tty_out, buffer); 974 capture_screen(&tty_out, &actual); 975 976 ASSERT(compare_screen(&tty_out, &actual, &expect)); 977 978 terminate_tty(&tty_out); 979 980 uv_run(loop, UV_RUN_DEFAULT); 981 982 MAKE_VALGRIND_HAPPY(); 983 return 0; 984 } 985 986 987 TEST_IMPL(tty_set_cursor_shape) { 988 uv_tty_t tty_out; 989 uv_loop_t* loop; 990 DWORD saved_cursor_size; 991 char buffer[1024]; 992 993 loop = uv_default_loop(); 994 995 initialize_tty(&tty_out); 996 997 saved_cursor_size = get_cursor_size(&tty_out); 998 999 /* cursor size large if omitted arguments */ 1000 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1001 snprintf(buffer, sizeof(buffer), "%s q", CSI); 1002 write_console(&tty_out, buffer); 1003 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); 1004 1005 /* cursor size large */ 1006 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1007 snprintf(buffer, sizeof(buffer), "%s1 q", CSI); 1008 write_console(&tty_out, buffer); 1009 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); 1010 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1011 snprintf(buffer, sizeof(buffer), "%s2 q", CSI); 1012 write_console(&tty_out, buffer); 1013 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_LARGE); 1014 1015 /* cursor size small */ 1016 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1017 snprintf(buffer, sizeof(buffer), "%s3 q", CSI); 1018 write_console(&tty_out, buffer); 1019 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL); 1020 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1021 snprintf(buffer, sizeof(buffer), "%s6 q", CSI); 1022 write_console(&tty_out, buffer); 1023 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_SMALL); 1024 1025 /* Nothing occurs with arguments outside valid range */ 1026 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1027 snprintf(buffer, sizeof(buffer), "%s7 q", CSI); 1028 write_console(&tty_out, buffer); 1029 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); 1030 1031 /* restore cursor size if arguments is zero */ 1032 snprintf(buffer, sizeof(buffer), "%s0 q", CSI); 1033 write_console(&tty_out, buffer); 1034 ASSERT(get_cursor_size(&tty_out) == saved_cursor_size); 1035 1036 terminate_tty(&tty_out); 1037 1038 uv_run(loop, UV_RUN_DEFAULT); 1039 1040 MAKE_VALGRIND_HAPPY(); 1041 return 0; 1042 } 1043 1044 1045 TEST_IMPL(tty_set_style) { 1046 uv_tty_t tty_out; 1047 uv_loop_t* loop; 1048 COORD cursor_pos; 1049 char buffer[1024]; 1050 struct captured_screen actual = {0}, expect = {0}; 1051 WORD fg, bg; 1052 WORD fg_attrs[9][2] = {{F_BLACK, FOREGROUND_BLACK}, 1053 {F_RED, FOREGROUND_RED}, 1054 {F_GREEN, FOREGROUND_GREEN}, 1055 {F_YELLOW, FOREGROUND_YELLOW}, 1056 {F_BLUE, FOREGROUND_BLUE}, 1057 {F_MAGENTA, FOREGROUND_MAGENTA}, 1058 {F_CYAN, FOREGROUND_CYAN}, 1059 {F_WHITE, FOREGROUND_WHITE}, 1060 {F_DEFAULT, 0}}; 1061 WORD bg_attrs[9][2] = {{B_DEFAULT, 0}, 1062 {B_BLACK, BACKGROUND_BLACK}, 1063 {B_RED, BACKGROUND_RED}, 1064 {B_GREEN, BACKGROUND_GREEN}, 1065 {B_YELLOW, BACKGROUND_YELLOW}, 1066 {B_BLUE, BACKGROUND_BLUE}, 1067 {B_MAGENTA, BACKGROUND_MAGENTA}, 1068 {B_CYAN, BACKGROUND_CYAN}, 1069 {B_WHITE, BACKGROUND_WHITE}}; 1070 WORD attr; 1071 int i, length; 1072 1073 loop = uv_default_loop(); 1074 1075 initialize_tty(&tty_out); 1076 1077 capture_screen(&tty_out, &expect); 1078 fg_attrs[8][1] = expect.si.default_attr & FOREGROUND_WHITE; 1079 bg_attrs[0][1] = expect.si.default_attr & BACKGROUND_WHITE; 1080 1081 /* Set foreground color */ 1082 length = ARRAY_SIZE(fg_attrs); 1083 for (i = 0; i < length; i++) { 1084 capture_screen(&tty_out, &expect); 1085 cursor_pos.X = expect.si.width / 2; 1086 cursor_pos.Y = expect.si.height / 2; 1087 attr = (expect.si.default_attr & ~FOREGROUND_WHITE) | fg_attrs[i][1]; 1088 make_expect_screen_write(&expect, cursor_pos, HELLO); 1089 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1090 1091 set_cursor_position(&tty_out, cursor_pos); 1092 snprintf( 1093 buffer, sizeof(buffer), "%s%dm%s%sm", CSI, fg_attrs[i][0], HELLO, CSI); 1094 write_console(&tty_out, buffer); 1095 capture_screen(&tty_out, &actual); 1096 1097 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1098 } 1099 1100 /* Set background color */ 1101 length = ARRAY_SIZE(bg_attrs); 1102 for (i = 0; i < length; i++) { 1103 capture_screen(&tty_out, &expect); 1104 cursor_pos.X = expect.si.width / 2; 1105 cursor_pos.Y = expect.si.height / 2; 1106 attr = (expect.si.default_attr & ~BACKGROUND_WHITE) | bg_attrs[i][1]; 1107 make_expect_screen_write(&expect, cursor_pos, HELLO); 1108 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1109 1110 set_cursor_position(&tty_out, cursor_pos); 1111 snprintf( 1112 buffer, sizeof(buffer), "%s%dm%s%sm", CSI, bg_attrs[i][0], HELLO, CSI); 1113 write_console(&tty_out, buffer); 1114 capture_screen(&tty_out, &actual); 1115 1116 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1117 } 1118 1119 /* Set foregroud and background color */ 1120 ASSERT(ARRAY_SIZE(fg_attrs) == ARRAY_SIZE(bg_attrs)); 1121 length = ARRAY_SIZE(bg_attrs); 1122 for (i = 0; i < length; i++) { 1123 capture_screen(&tty_out, &expect); 1124 cursor_pos.X = expect.si.width / 2; 1125 cursor_pos.Y = expect.si.height / 2; 1126 attr = expect.si.default_attr & ~FOREGROUND_WHITE & ~BACKGROUND_WHITE; 1127 attr |= fg_attrs[i][1] | bg_attrs[i][1]; 1128 make_expect_screen_write(&expect, cursor_pos, HELLO); 1129 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1130 1131 set_cursor_position(&tty_out, cursor_pos); 1132 snprintf(buffer, 1133 sizeof(buffer), 1134 "%s%d;%dm%s%sm", 1135 CSI, 1136 bg_attrs[i][0], 1137 fg_attrs[i][0], 1138 HELLO, 1139 CSI); 1140 write_console(&tty_out, buffer); 1141 capture_screen(&tty_out, &actual); 1142 1143 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1144 } 1145 1146 /* Set foreground bright on */ 1147 capture_screen(&tty_out, &expect); 1148 cursor_pos.X = expect.si.width / 2; 1149 cursor_pos.Y = expect.si.height / 2; 1150 set_cursor_position(&tty_out, cursor_pos); 1151 attr = expect.si.default_attr; 1152 attr |= FOREGROUND_INTENSITY; 1153 make_expect_screen_write(&expect, cursor_pos, HELLO); 1154 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1155 cursor_pos.X += strlen(HELLO); 1156 make_expect_screen_write(&expect, cursor_pos, HELLO); 1157 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1158 1159 snprintf(buffer, 1160 sizeof(buffer), 1161 "%s%dm%s%s%dm%s%dm%s%s%dm", 1162 CSI, 1163 F_INTENSITY, 1164 HELLO, 1165 CSI, 1166 F_INTENSITY_OFF1, 1167 CSI, 1168 F_INTENSITY, 1169 HELLO, 1170 CSI, 1171 F_INTENSITY_OFF2); 1172 write_console(&tty_out, buffer); 1173 capture_screen(&tty_out, &actual); 1174 1175 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1176 1177 /* Set background bright on */ 1178 capture_screen(&tty_out, &expect); 1179 cursor_pos.X = expect.si.width / 2; 1180 cursor_pos.Y = expect.si.height / 2; 1181 set_cursor_position(&tty_out, cursor_pos); 1182 attr = expect.si.default_attr; 1183 attr |= BACKGROUND_INTENSITY; 1184 make_expect_screen_write(&expect, cursor_pos, HELLO); 1185 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1186 1187 snprintf(buffer, 1188 sizeof(buffer), 1189 "%s%dm%s%s%dm", 1190 CSI, 1191 B_INTENSITY, 1192 HELLO, 1193 CSI, 1194 B_INTENSITY_OFF); 1195 write_console(&tty_out, buffer); 1196 capture_screen(&tty_out, &actual); 1197 1198 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1199 1200 /* Inverse */ 1201 capture_screen(&tty_out, &expect); 1202 cursor_pos.X = expect.si.width / 2; 1203 cursor_pos.Y = expect.si.height / 2; 1204 set_cursor_position(&tty_out, cursor_pos); 1205 attr = expect.si.default_attr; 1206 fg = attr & FOREGROUND_WHITE; 1207 bg = attr & BACKGROUND_WHITE; 1208 attr &= (~FOREGROUND_WHITE & ~BACKGROUND_WHITE); 1209 attr |= COMMON_LVB_REVERSE_VIDEO; 1210 attr |= fg << 4; 1211 attr |= bg >> 4; 1212 make_expect_screen_write(&expect, cursor_pos, HELLO); 1213 make_expect_screen_set_attr(&expect, cursor_pos, strlen(HELLO), attr); 1214 cursor_pos.X += strlen(HELLO); 1215 make_expect_screen_write(&expect, cursor_pos, HELLO); 1216 1217 snprintf(buffer, 1218 sizeof(buffer), 1219 "%s%dm%s%s%dm%s", 1220 CSI, 1221 INVERSE, 1222 HELLO, 1223 CSI, 1224 INVERSE_OFF, 1225 HELLO); 1226 write_console(&tty_out, buffer); 1227 capture_screen(&tty_out, &actual); 1228 1229 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1230 1231 terminate_tty(&tty_out); 1232 1233 uv_run(loop, UV_RUN_DEFAULT); 1234 1235 MAKE_VALGRIND_HAPPY(); 1236 return 0; 1237 } 1238 1239 1240 TEST_IMPL(tty_save_restore_cursor_position) { 1241 uv_tty_t tty_out; 1242 uv_loop_t* loop; 1243 COORD cursor_pos, cursor_pos_old; 1244 char buffer[1024]; 1245 struct screen_info si; 1246 1247 loop = uv_default_loop(); 1248 1249 initialize_tty(&tty_out); 1250 get_screen_info(&tty_out, &si); 1251 1252 cursor_pos_old.X = si.width / 2; 1253 cursor_pos_old.Y = si.height / 2; 1254 set_cursor_position(&tty_out, cursor_pos_old); 1255 1256 /* save the cursor position */ 1257 snprintf(buffer, sizeof(buffer), "%ss", CSI); 1258 write_console(&tty_out, buffer); 1259 1260 cursor_pos.X = si.width / 4; 1261 cursor_pos.Y = si.height / 4; 1262 set_cursor_position(&tty_out, cursor_pos); 1263 1264 /* restore the cursor postion */ 1265 snprintf(buffer, sizeof(buffer), "%su", CSI); 1266 write_console(&tty_out, buffer); 1267 get_cursor_position(&tty_out, &cursor_pos); 1268 ASSERT(cursor_pos.X == cursor_pos_old.X); 1269 ASSERT(cursor_pos.Y == cursor_pos_old.Y); 1270 1271 cursor_pos_old.X = si.width / 2; 1272 cursor_pos_old.Y = si.height / 2; 1273 set_cursor_position(&tty_out, cursor_pos_old); 1274 1275 /* save the cursor position */ 1276 snprintf(buffer, sizeof(buffer), "%s7", ESC); 1277 write_console(&tty_out, buffer); 1278 1279 cursor_pos.X = si.width / 4; 1280 cursor_pos.Y = si.height / 4; 1281 set_cursor_position(&tty_out, cursor_pos); 1282 1283 /* restore the cursor postion */ 1284 snprintf(buffer, sizeof(buffer), "%s8", ESC); 1285 write_console(&tty_out, buffer); 1286 get_cursor_position(&tty_out, &cursor_pos); 1287 ASSERT(cursor_pos.X == cursor_pos_old.X); 1288 ASSERT(cursor_pos.Y == cursor_pos_old.Y); 1289 1290 terminate_tty(&tty_out); 1291 1292 uv_run(loop, UV_RUN_DEFAULT); 1293 1294 MAKE_VALGRIND_HAPPY(); 1295 return 0; 1296 } 1297 1298 1299 TEST_IMPL(tty_full_reset) { 1300 uv_tty_t tty_out; 1301 uv_loop_t* loop; 1302 char buffer[1024]; 1303 struct captured_screen actual = {0}, expect = {0}; 1304 COORD cursor_pos; 1305 DWORD saved_cursor_size; 1306 BOOL saved_cursor_visibility; 1307 1308 loop = uv_default_loop(); 1309 1310 initialize_tty(&tty_out); 1311 1312 capture_screen(&tty_out, &expect); 1313 setup_screen(&tty_out); 1314 cursor_pos.X = expect.si.width; 1315 cursor_pos.Y = expect.si.height; 1316 set_cursor_position(&tty_out, cursor_pos); 1317 snprintf(buffer, sizeof(buffer), "%s%d;%dm%s", CSI, F_CYAN, B_YELLOW, HELLO); 1318 saved_cursor_size = get_cursor_size(&tty_out); 1319 set_cursor_size(&tty_out, 1320 saved_cursor_size == CURSOR_SIZE_LARGE ? CURSOR_SIZE_SMALL 1321 : CURSOR_SIZE_LARGE); 1322 saved_cursor_visibility = get_cursor_visibility(&tty_out); 1323 set_cursor_visibility(&tty_out, saved_cursor_visibility ? FALSE : TRUE); 1324 write_console(&tty_out, buffer); 1325 snprintf(buffer, sizeof(buffer), "%sc", ESC); 1326 write_console(&tty_out, buffer); 1327 capture_screen(&tty_out, &actual); 1328 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1329 ASSERT(get_cursor_size(&tty_out) == saved_cursor_size); 1330 ASSERT(get_cursor_visibility(&tty_out) == saved_cursor_visibility); 1331 ASSERT(actual.si.csbi.srWindow.Top == 0); 1332 1333 terminate_tty(&tty_out); 1334 1335 uv_run(loop, UV_RUN_DEFAULT); 1336 1337 MAKE_VALGRIND_HAPPY(); 1338 return 0; 1339 } 1340 1341 1342 TEST_IMPL(tty_escape_sequence_processing) { 1343 uv_tty_t tty_out; 1344 uv_loop_t* loop; 1345 COORD cursor_pos, cursor_pos_old; 1346 DWORD saved_cursor_size; 1347 char buffer[1024]; 1348 struct captured_screen actual = {0}, expect = {0}; 1349 int dir; 1350 1351 loop = uv_default_loop(); 1352 1353 initialize_tty(&tty_out); 1354 1355 /* CSI + finaly byte does not output anything */ 1356 cursor_pos.X = 1; 1357 cursor_pos.Y = 1; 1358 set_cursor_position(&tty_out, cursor_pos); 1359 capture_screen(&tty_out, &expect); 1360 make_expect_screen_write(&expect, cursor_pos, HELLO); 1361 cursor_pos.X += strlen(HELLO); 1362 make_expect_screen_write(&expect, cursor_pos, HELLO); 1363 snprintf(buffer, sizeof(buffer), "%s@%s%s~%s", CSI, HELLO, CSI, HELLO); 1364 write_console(&tty_out, buffer); 1365 capture_screen(&tty_out, &actual); 1366 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1367 1368 /* CSI(C1) + finaly byte does not output anything */ 1369 cursor_pos.X = 1; 1370 cursor_pos.Y = 1; 1371 set_cursor_position(&tty_out, cursor_pos); 1372 capture_screen(&tty_out, &expect); 1373 make_expect_screen_write(&expect, cursor_pos, HELLO); 1374 cursor_pos.X += strlen(HELLO); 1375 make_expect_screen_write(&expect, cursor_pos, HELLO); 1376 snprintf(buffer, sizeof(buffer), "\xC2\x9B@%s\xC2\x9B~%s", HELLO, HELLO); 1377 write_console(&tty_out, buffer); 1378 capture_screen(&tty_out, &actual); 1379 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1380 1381 /* CSI + intermediate byte + finaly byte does not output anything */ 1382 cursor_pos.X = 1; 1383 cursor_pos.Y = 1; 1384 set_cursor_position(&tty_out, cursor_pos); 1385 capture_screen(&tty_out, &expect); 1386 make_expect_screen_write(&expect, cursor_pos, HELLO); 1387 cursor_pos.X += strlen(HELLO); 1388 make_expect_screen_write(&expect, cursor_pos, HELLO); 1389 snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO); 1390 write_console(&tty_out, buffer); 1391 capture_screen(&tty_out, &actual); 1392 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1393 1394 /* CSI + parameter byte + finaly byte does not output anything */ 1395 cursor_pos.X = 1; 1396 cursor_pos.Y = 1; 1397 set_cursor_position(&tty_out, cursor_pos); 1398 capture_screen(&tty_out, &expect); 1399 snprintf(buffer, 1400 sizeof(buffer), 1401 "%s0@%s%s>~%s%s?~%s", 1402 CSI, 1403 HELLO, 1404 CSI, 1405 HELLO, 1406 CSI, 1407 HELLO); 1408 make_expect_screen_write(&expect, cursor_pos, HELLO); 1409 cursor_pos.X += strlen(HELLO); 1410 make_expect_screen_write(&expect, cursor_pos, HELLO); 1411 cursor_pos.X += strlen(HELLO); 1412 make_expect_screen_write(&expect, cursor_pos, HELLO); 1413 write_console(&tty_out, buffer); 1414 capture_screen(&tty_out, &actual); 1415 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1416 1417 /* ESC Single-char control does not output anyghing */ 1418 cursor_pos.X = 1; 1419 cursor_pos.Y = 1; 1420 set_cursor_position(&tty_out, cursor_pos); 1421 capture_screen(&tty_out, &expect); 1422 make_expect_screen_write(&expect, cursor_pos, HELLO); 1423 cursor_pos.X += strlen(HELLO); 1424 make_expect_screen_write(&expect, cursor_pos, HELLO); 1425 snprintf(buffer, sizeof(buffer), "%s @%s%s/~%s", CSI, HELLO, CSI, HELLO); 1426 write_console(&tty_out, buffer); 1427 capture_screen(&tty_out, &actual); 1428 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1429 1430 /* Nothing is output from ESC + ^, _, P, ] to BEL or ESC \ */ 1431 /* Operaging System Command */ 1432 cursor_pos.X = 1; 1433 cursor_pos.Y = 1; 1434 set_cursor_position(&tty_out, cursor_pos); 1435 capture_screen(&tty_out, &expect); 1436 make_expect_screen_write(&expect, cursor_pos, HELLO); 1437 snprintf(buffer, sizeof(buffer), "%s]0;%s%s%s", ESC, HELLO, BEL, HELLO); 1438 write_console(&tty_out, buffer); 1439 capture_screen(&tty_out, &actual); 1440 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1441 /* Device Control Sequence */ 1442 cursor_pos.X = 1; 1443 cursor_pos.Y = 1; 1444 set_cursor_position(&tty_out, cursor_pos); 1445 capture_screen(&tty_out, &expect); 1446 make_expect_screen_write(&expect, cursor_pos, HELLO); 1447 snprintf(buffer, sizeof(buffer), "%sP$m%s%s", ESC, ST, HELLO); 1448 write_console(&tty_out, buffer); 1449 capture_screen(&tty_out, &actual); 1450 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1451 /* Privacy Message */ 1452 cursor_pos.X = 1; 1453 cursor_pos.Y = 1; 1454 set_cursor_position(&tty_out, cursor_pos); 1455 capture_screen(&tty_out, &expect); 1456 make_expect_screen_write(&expect, cursor_pos, HELLO); 1457 snprintf(buffer, 1458 sizeof(buffer), 1459 "%s^\"%s\\\"%s\"%s%s", 1460 ESC, 1461 HELLO, 1462 HELLO, 1463 ST, 1464 HELLO); 1465 write_console(&tty_out, buffer); 1466 capture_screen(&tty_out, &actual); 1467 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1468 /* Application Program Command */ 1469 cursor_pos.X = 1; 1470 cursor_pos.Y = 1; 1471 set_cursor_position(&tty_out, cursor_pos); 1472 capture_screen(&tty_out, &expect); 1473 make_expect_screen_write(&expect, cursor_pos, HELLO); 1474 snprintf(buffer, 1475 sizeof(buffer), 1476 "%s_\"%s%s%s\"%s%s", 1477 ESC, 1478 HELLO, 1479 ST, 1480 HELLO, 1481 BEL, 1482 HELLO); 1483 write_console(&tty_out, buffer); 1484 capture_screen(&tty_out, &actual); 1485 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1486 1487 /* Ignore double escape */ 1488 cursor_pos.X = 1; 1489 cursor_pos.Y = 1; 1490 set_cursor_position(&tty_out, cursor_pos); 1491 capture_screen(&tty_out, &expect); 1492 make_expect_screen_write(&expect, cursor_pos, HELLO); 1493 cursor_pos.X += strlen(HELLO); 1494 make_expect_screen_write(&expect, cursor_pos, HELLO); 1495 snprintf(buffer, 1496 sizeof(buffer), 1497 "%s%s@%s%s%s~%s", 1498 ESC, 1499 CSI, 1500 HELLO, 1501 ESC, 1502 CSI, 1503 HELLO); 1504 write_console(&tty_out, buffer); 1505 capture_screen(&tty_out, &actual); 1506 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1507 1508 /* Ignored if argument overflow */ 1509 set_cursor_to_home(&tty_out); 1510 snprintf(buffer, sizeof(buffer), "%s1;%dH", CSI, UINT16_MAX + 1); 1511 write_console(&tty_out, buffer); 1512 get_cursor_position(&tty_out, &cursor_pos); 1513 ASSERT(cursor_pos.X == 1); 1514 ASSERT(cursor_pos.Y == 1); 1515 1516 /* Too many argument are ignored */ 1517 cursor_pos.X = 1; 1518 cursor_pos.Y = 1; 1519 set_cursor_position(&tty_out, cursor_pos); 1520 capture_screen(&tty_out, &expect); 1521 make_expect_screen_write(&expect, cursor_pos, HELLO); 1522 snprintf(buffer, 1523 sizeof(buffer), 1524 "%s%d;%d;%d;%d;%dm%s%sm", 1525 CSI, 1526 F_RED, 1527 F_INTENSITY, 1528 INVERSE, 1529 B_CYAN, 1530 B_INTENSITY_OFF, 1531 HELLO, 1532 CSI); 1533 write_console(&tty_out, buffer); 1534 capture_screen(&tty_out, &actual); 1535 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1536 1537 /* In the case of DECSCUSR, the others are ignored */ 1538 set_cursor_to_home(&tty_out); 1539 snprintf(buffer, 1540 sizeof(buffer), 1541 "%s%d;%d H", 1542 CSI, 1543 expect.si.height / 2, 1544 expect.si.width / 2); 1545 write_console(&tty_out, buffer); 1546 get_cursor_position(&tty_out, &cursor_pos); 1547 ASSERT(cursor_pos.X == 1); 1548 ASSERT(cursor_pos.Y == 1); 1549 1550 /* Invalid sequence are ignored */ 1551 saved_cursor_size = get_cursor_size(&tty_out); 1552 set_cursor_size(&tty_out, CURSOR_SIZE_MIDDLE); 1553 snprintf(buffer, sizeof(buffer), "%s 1q", CSI); 1554 write_console(&tty_out, buffer); 1555 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); 1556 snprintf(buffer, sizeof(buffer), "%s 1 q", CSI); 1557 write_console(&tty_out, buffer); 1558 ASSERT(get_cursor_size(&tty_out) == CURSOR_SIZE_MIDDLE); 1559 set_cursor_size(&tty_out, saved_cursor_size); 1560 1561 /* #1874 2. */ 1562 snprintf(buffer, sizeof(buffer), "%s??25l", CSI); 1563 write_console(&tty_out, buffer); 1564 ASSERT(get_cursor_visibility(&tty_out)); 1565 snprintf(buffer, sizeof(buffer), "%s25?l", CSI); 1566 write_console(&tty_out, buffer); 1567 ASSERT(get_cursor_visibility(&tty_out)); 1568 cursor_pos_old.X = expect.si.width / 2; 1569 cursor_pos_old.Y = expect.si.height / 2; 1570 set_cursor_position(&tty_out, cursor_pos_old); 1571 snprintf(buffer, 1572 sizeof(buffer), 1573 "%s??%d;%df", 1574 CSI, 1575 expect.si.height / 4, 1576 expect.si.width / 4); 1577 write_console(&tty_out, buffer); 1578 get_cursor_position(&tty_out, &cursor_pos); 1579 ASSERT(cursor_pos.X = cursor_pos_old.X); 1580 ASSERT(cursor_pos.Y = cursor_pos_old.Y); 1581 set_cursor_to_home(&tty_out); 1582 1583 /* CSI 25 l does nothing (#1874 4.) */ 1584 snprintf(buffer, sizeof(buffer), "%s25l", CSI); 1585 write_console(&tty_out, buffer); 1586 ASSERT(get_cursor_visibility(&tty_out)); 1587 1588 /* Unsupported sequences are ignored(#1874 5.) */ 1589 dir = 2; 1590 setup_screen(&tty_out); 1591 capture_screen(&tty_out, &expect); 1592 set_cursor_position(&tty_out, cursor_pos); 1593 snprintf(buffer, sizeof(buffer), "%s?%dJ", CSI, dir); 1594 write_console(&tty_out, buffer); 1595 capture_screen(&tty_out, &actual); 1596 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1597 1598 /* Finaly byte immedately after CSI [ are also output(#1874 1.) */ 1599 cursor_pos.X = expect.si.width / 2; 1600 cursor_pos.Y = expect.si.height / 2; 1601 set_cursor_position(&tty_out, cursor_pos); 1602 capture_screen(&tty_out, &expect); 1603 make_expect_screen_write(&expect, cursor_pos, HELLO); 1604 snprintf(buffer, sizeof(buffer), "%s[%s", CSI, HELLO); 1605 write_console(&tty_out, buffer); 1606 capture_screen(&tty_out, &actual); 1607 ASSERT(compare_screen(&tty_out, &actual, &expect)); 1608 1609 terminate_tty(&tty_out); 1610 1611 uv_run(loop, UV_RUN_DEFAULT); 1612 1613 MAKE_VALGRIND_HAPPY(); 1614 return 0; 1615 } 1616 1617 #else 1618 1619 typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */ 1620 1621 #endif /* ifdef _WIN32 */ 1622