2 * PROJECT: ReactOS api tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Test for i18n console test
5 * PROGRAMMERS: Katayama Hirofumi MZ
12 #define okCURSOR(hCon, c) do { \
13 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
14 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
15 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
16 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
17 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
21 (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
23 static const WCHAR u0414
[] = { 0x0414, 0 }; /* Д */
24 static const WCHAR u9580
[] = { 0x9580, 0 }; /* 門 */
25 static const WCHAR ideograph_space
= (WCHAR
)0x3000; /* fullwidth space */
26 LCID lcidJapanese
= MAKELCID(MAKELANGID(LANG_JAPANESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
27 LCID lcidRussian
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
29 /* Russian Code Page 855 */
30 // NOTE that CP 866 can also be used
31 static void test_cp855(HANDLE hConOut
)
38 CONSOLE_SCREEN_BUFFER_INFO csbi
;
43 if (!IsValidCodePage(855))
45 skip("Codepage 855 not available\n");
50 oldcp
= GetConsoleOutputCP();
51 SetLastError(0xdeadbeef);
52 ret
= SetConsoleOutputCP(855);
55 skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
60 ret
= GetConsoleScreenBufferInfo(hConOut
, &csbi
);
61 ok(ret
, "GetConsoleScreenBufferInfo failed\n");
62 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi
.dwSize
.X
, csbi
.dwSize
.Y
);
63 count
= csbi
.dwSize
.X
* 3 / 2;
64 trace("count: %d\n", count
);
68 /* Output u0414 "count" times at (0,0) */
70 SetConsoleCursorPosition(hConOut
, c
);
72 for (n
= 0; n
< count
; ++n
)
74 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
75 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
79 len
= count
; /* u0414 is normal width in Russian */
80 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
81 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
84 /* Read characters at (0,0) */
86 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
87 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
88 ok(len
== 6, "len was: %ld\n", len
);
89 ok(str
[0] == 0x414, "str[0] was: 0x%04X\n", str
[0]);
90 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
91 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
96 ret
= SetConsoleCursorPosition(hConOut
, c
);
97 ok(ret
, "SetConsoleCursorPosition failed\n");
102 FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
104 /* Output u0414 "count" times at (1,0) */
107 SetConsoleCursorPosition(hConOut
, c
);
108 okCURSOR(hConOut
, c
);
109 for (n
= 0; n
< count
; ++n
)
111 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
112 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
117 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
118 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
119 okCURSOR(hConOut
, c
);
121 /* Read characters at (0,0) */
123 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
124 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
125 ok(len
== 6, "len was: %ld\n", len
);
126 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
127 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
128 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
133 /* Output u9580 "count" times at (0,0) */
135 SetConsoleCursorPosition(hConOut
, c
);
136 okCURSOR(hConOut
, c
);
137 for (n
= 0; n
< count
; ++n
)
139 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
140 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
144 len
= count
; /* u9580 is normal width in Russian */
145 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
146 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
147 okCURSOR(hConOut
, c
);
152 ret
= SetConsoleCursorPosition(hConOut
, c
);
153 ok(ret
, "SetConsoleCursorPosition failed\n");
154 okCURSOR(hConOut
, c
);
158 ret
= FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
159 ok(ret
, "FillConsoleOutputCharacterW failed\n");
160 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
162 /* Output u9580 "count" times at (1,0) */
165 SetConsoleCursorPosition(hConOut
, c
);
166 okCURSOR(hConOut
, c
);
167 for (n
= 0; n
< count
; ++n
)
169 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
170 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
175 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
176 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
177 okCURSOR(hConOut
, c
);
179 /* Fill by ideograph space */
181 ret
= FillConsoleOutputCharacterW(hConOut
, ideograph_space
, csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
182 ok(ret
, "FillConsoleOutputCharacterW failed\n");
183 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
185 /* Read characters at (0,0) */
187 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
188 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
189 ok(len
== 6, "len was: %ld\n", len
);
190 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
191 ok(str
[1] == ideograph_space
|| str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
192 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
194 /* Read attr at (0,0) */
196 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
197 ok(ret
, "ReadConsoleOutputAttribute failed\n");
198 ok(attr
== ATTR
, "attr was: %d\n", attr
);
199 ok(len
== 1, "len was %ld\n", len
);
201 /* Read characters at (1,0) */
204 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
205 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
206 ok(len
== 6, "len was: %ld\n", len
);
207 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
208 ok(str
[1] == ideograph_space
|| str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
209 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
211 /* Output u9580 "count" once at (1,0) */
214 SetConsoleCursorPosition(hConOut
, c
);
215 okCURSOR(hConOut
, c
);
216 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
217 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
219 /* Read attr (1,0) */
222 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
223 ok(ret
, "ReadConsoleOutputAttribute failed\n");
224 ok(attr
== ATTR
, "attr was: %d\n", attr
);
225 ok(len
== 1, "len was %ld\n", len
);
230 okCURSOR(hConOut
, c
);
232 /* Read characters at (0,0) */
234 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
235 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
236 ok(len
== 6, "len was: %ld\n", len
);
237 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
238 ok(str
[1] == 0x9580 || str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
239 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
242 /* Restore code page */
243 SetConsoleOutputCP(oldcp
);
246 /* Japanese Code Page 932 */
247 static void test_cp932(HANDLE hConOut
)
254 CONSOLE_SCREEN_BUFFER_INFO csbi
;
259 if (!IsValidCodePage(932))
261 skip("Codepage 932 not available\n");
266 oldcp
= GetConsoleOutputCP();
267 SetLastError(0xdeadbeef);
268 ret
= SetConsoleOutputCP(932);
271 skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
276 ret
= GetConsoleScreenBufferInfo(hConOut
, &csbi
);
277 ok(ret
, "GetConsoleScreenBufferInfo failed\n");
278 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi
.dwSize
.X
, csbi
.dwSize
.Y
);
279 count
= csbi
.dwSize
.X
* 3 / 2;
280 trace("count: %d\n", count
);
284 /* Output u0414 "count" times at (0,0) */
286 SetConsoleCursorPosition(hConOut
, c
);
287 okCURSOR(hConOut
, c
);
288 for (n
= 0; n
< count
; ++n
)
290 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
291 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
295 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
296 len
= count
* 2; /* u0414 is fullwidth in Japanese */
297 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
298 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
299 okCURSOR(hConOut
, c
);
301 /* Read characters at (0,0) */
303 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
304 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
305 ok(len
== 3, "len was: %ld\n", len
);
306 ok(str
[0] == 0x414, "str[0] was: 0x%04X\n", str
[0]);
307 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
308 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
313 ret
= SetConsoleCursorPosition(hConOut
, c
);
314 ok(ret
, "SetConsoleCursorPosition failed\n");
315 okCURSOR(hConOut
, c
);
319 FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
321 /* Output u0414 "count" times at (1,0) */
324 SetConsoleCursorPosition(hConOut
, c
);
325 okCURSOR(hConOut
, c
);
326 for (n
= 0; n
< count
; ++n
)
328 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
329 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
333 len
= csbi
.dwSize
.X
+ (count
- (csbi
.dwSize
.X
- 1) / 2) * 2;
334 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
335 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
336 okCURSOR(hConOut
, c
);
338 /* Read characters at (0,0) */
341 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
342 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
343 ok(len
== 4, "len was: %ld\n", len
);
344 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
345 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
346 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
351 /* Output u9580 "count" times at (0,0) */
353 SetConsoleCursorPosition(hConOut
, c
);
354 okCURSOR(hConOut
, c
);
355 for (n
= 0; n
< count
; ++n
)
357 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
358 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
362 len
= count
* 2; /* u9580 is fullwidth in Japanese */
363 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
364 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
365 okCURSOR(hConOut
, c
);
370 ret
= SetConsoleCursorPosition(hConOut
, c
);
371 ok(ret
, "SetConsoleCursorPosition failed\n");
372 okCURSOR(hConOut
, c
);
376 ret
= FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
377 ok(ret
, "FillConsoleOutputCharacterW failed\n");
378 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
380 /* Output u9580 "count" times at (1,0) */
383 SetConsoleCursorPosition(hConOut
, c
);
384 okCURSOR(hConOut
, c
);
385 for (n
= 0; n
< count
; ++n
)
387 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
388 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
392 len
= csbi
.dwSize
.X
+ (count
- (csbi
.dwSize
.X
- 1) / 2) * 2;
393 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
394 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
395 okCURSOR(hConOut
, c
);
397 /* Fill by ideograph space */
399 ret
= FillConsoleOutputCharacterW(hConOut
, ideograph_space
, csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
400 ok(ret
, "FillConsoleOutputCharacterW failed\n");
401 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
403 /* Read characters at (0,0) */
405 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
406 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
407 ok(len
== 3, "len was: %ld\n", len
);
408 ok(str
[0] == ideograph_space
, "str[0] was: 0x%04X\n", str
[0]);
409 ok(str
[1] == ideograph_space
, "str[1] was: 0x%04X\n", str
[1]);
410 ok(str
[2] == ideograph_space
, "str[2] was: 0x%04X\n", str
[2]);
413 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
414 ok(ret
, "ReadConsoleOutputAttribute failed\n");
415 ok(attr
== ATTR
, "attr was: %d\n", attr
);
416 ok(len
== 1, "len was %ld\n", len
);
418 /* Output u9580 "count" once at (1,0) */
421 SetConsoleCursorPosition(hConOut
, c
);
422 okCURSOR(hConOut
, c
);
423 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
424 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
427 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
428 ok(ret
, "ReadConsoleOutputAttribute failed\n");
429 ok(attr
== ATTR
, "attr was: %d\n", attr
);
430 ok(len
== 1, "len was %ld\n", len
);
435 okCURSOR(hConOut
, c
);
437 /* Read characters */
439 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
440 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
441 ok(len
== 4, "len was: %ld\n", len
);
442 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
443 ok(str
[1] == 0x9580, "str[1] was: 0x%04X\n", str
[1]);
444 ok(str
[2] == L
' ', "str[2] was: 0x%04X\n", str
[2]);
447 /* Restore code page */
448 SetConsoleOutputCP(oldcp
);
453 HANDLE hConIn
, hConOut
;
455 ok(AllocConsole(), "Couldn't alloc console\n");
457 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
458 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
459 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
460 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
462 if (IsValidLocale(lcidRussian
, LCID_INSTALLED
))
465 skip("Russian locale is not installed\n");
467 if (IsValidLocale(lcidJapanese
, LCID_INSTALLED
))
470 skip("Japanese locale is not installed\n");
473 CloseHandle(hConOut
);
475 ok(AllocConsole(), "Couldn't alloc console\n");