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