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
10 #define okCURSOR(hCon, c) do { \
11 CONSOLE_SCREEN_BUFFER_INFO __sbi; \
12 BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
13 __sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
14 ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
15 (c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
19 (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
21 static const WCHAR u0414
[] = { 0x0414, 0 }; /* Д */
22 static const WCHAR u9580
[] = { 0x9580, 0 }; /* 門 */
23 static const WCHAR ideograph_space
= (WCHAR
)0x3000; /* fullwidth space */
24 LCID lcidJapanese
= MAKELCID(MAKELANGID(LANG_JAPANESE
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
25 LCID lcidRussian
= MAKELCID(MAKELANGID(LANG_RUSSIAN
, SUBLANG_DEFAULT
), SORT_DEFAULT
);
27 /* Russian Code Page 855 */
28 // NOTE that CP 866 can also be used
29 static void test_cp855(HANDLE hConOut
)
36 CONSOLE_SCREEN_BUFFER_INFO csbi
;
41 if (!IsValidCodePage(855))
43 skip("Codepage 855 not available\n");
48 oldcp
= GetConsoleOutputCP();
49 SetLastError(0xdeadbeef);
50 ret
= SetConsoleOutputCP(855);
53 skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
58 ret
= GetConsoleScreenBufferInfo(hConOut
, &csbi
);
59 ok(ret
, "GetConsoleScreenBufferInfo failed\n");
60 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi
.dwSize
.X
, csbi
.dwSize
.Y
);
61 count
= csbi
.dwSize
.X
* 3 / 2;
62 trace("count: %d\n", count
);
66 /* Output u0414 "count" times at (0,0) */
68 SetConsoleCursorPosition(hConOut
, c
);
70 for (n
= 0; n
< count
; ++n
)
72 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
73 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
77 len
= count
; /* u0414 is normal width in Russian */
78 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
79 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
82 /* Read characters at (0,0) */
84 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
85 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
86 ok(len
== 6, "len was: %ld\n", len
);
87 ok(str
[0] == 0x414, "str[0] was: 0x%04X\n", str
[0]);
88 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
89 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
94 ret
= SetConsoleCursorPosition(hConOut
, c
);
95 ok(ret
, "SetConsoleCursorPosition failed\n");
100 FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
102 /* Output u0414 "count" times at (1,0) */
105 SetConsoleCursorPosition(hConOut
, c
);
106 okCURSOR(hConOut
, c
);
107 for (n
= 0; n
< count
; ++n
)
109 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
110 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
115 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
116 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
117 okCURSOR(hConOut
, c
);
119 /* Read characters at (0,0) */
121 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
122 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
123 ok(len
== 6, "len was: %ld\n", len
);
124 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
125 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
126 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
131 /* Output u9580 "count" times at (0,0) */
133 SetConsoleCursorPosition(hConOut
, c
);
134 okCURSOR(hConOut
, c
);
135 for (n
= 0; n
< count
; ++n
)
137 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
138 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
142 len
= count
; /* u9580 is normal width in Russian */
143 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
144 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
145 okCURSOR(hConOut
, c
);
150 ret
= SetConsoleCursorPosition(hConOut
, c
);
151 ok(ret
, "SetConsoleCursorPosition failed\n");
152 okCURSOR(hConOut
, c
);
156 ret
= FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
157 ok(ret
, "FillConsoleOutputCharacterW failed\n");
158 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
160 /* Output u9580 "count" times at (1,0) */
163 SetConsoleCursorPosition(hConOut
, c
);
164 okCURSOR(hConOut
, c
);
165 for (n
= 0; n
< count
; ++n
)
167 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
168 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
173 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
174 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
175 okCURSOR(hConOut
, c
);
177 /* Fill by ideograph space */
179 ret
= FillConsoleOutputCharacterW(hConOut
, ideograph_space
, csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
180 ok(ret
, "FillConsoleOutputCharacterW failed\n");
181 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
183 /* Read characters at (0,0) */
185 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
186 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
187 ok(len
== 6, "len was: %ld\n", len
);
188 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
189 ok(str
[1] == ideograph_space
|| str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
190 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
192 /* Read attr at (0,0) */
194 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
195 ok(ret
, "ReadConsoleOutputAttribute failed\n");
196 ok(attr
== ATTR
, "attr was: %d\n", attr
);
197 ok(len
== 1, "len was %ld\n", len
);
199 /* Read characters at (1,0) */
202 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
203 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
204 ok(len
== 6, "len was: %ld\n", len
);
205 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
206 ok(str
[1] == ideograph_space
|| str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
207 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
209 /* Output u9580 "count" once at (1,0) */
212 SetConsoleCursorPosition(hConOut
, c
);
213 okCURSOR(hConOut
, c
);
214 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
215 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
217 /* Read attr (1,0) */
220 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
221 ok(ret
, "ReadConsoleOutputAttribute failed\n");
222 ok(attr
== ATTR
, "attr was: %d\n", attr
);
223 ok(len
== 1, "len was %ld\n", len
);
228 okCURSOR(hConOut
, c
);
230 /* Read characters at (0,0) */
232 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
233 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
234 ok(len
== 6, "len was: %ld\n", len
);
235 ok(str
[0] == ideograph_space
|| str
[0] == L
'?', "str[0] was: 0x%04X\n", str
[0]);
236 ok(str
[1] == 0x9580 || str
[1] == L
'?', "str[1] was: 0x%04X\n", str
[1]);
237 ok(str
[2] == ideograph_space
|| str
[2] == L
'?', "str[2] was: 0x%04X\n", str
[2]);
240 /* Restore code page */
241 SetConsoleOutputCP(oldcp
);
244 /* Japanese Code Page 932 */
245 static void test_cp932(HANDLE hConOut
)
252 CONSOLE_SCREEN_BUFFER_INFO csbi
;
257 if (!IsValidCodePage(932))
259 skip("Codepage 932 not available\n");
264 oldcp
= GetConsoleOutputCP();
265 SetLastError(0xdeadbeef);
266 ret
= SetConsoleOutputCP(932);
269 skip("SetConsoleOutputCP failed with last error %lu\n", GetLastError());
274 ret
= GetConsoleScreenBufferInfo(hConOut
, &csbi
);
275 ok(ret
, "GetConsoleScreenBufferInfo failed\n");
276 trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi
.dwSize
.X
, csbi
.dwSize
.Y
);
277 count
= csbi
.dwSize
.X
* 3 / 2;
278 trace("count: %d\n", count
);
282 /* Output u0414 "count" times at (0,0) */
284 SetConsoleCursorPosition(hConOut
, c
);
285 okCURSOR(hConOut
, c
);
286 for (n
= 0; n
< count
; ++n
)
288 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
289 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
293 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
294 len
= count
* 2; /* u0414 is fullwidth in Japanese */
295 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
296 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
297 okCURSOR(hConOut
, c
);
299 /* Read characters at (0,0) */
301 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
302 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
303 ok(len
== 3, "len was: %ld\n", len
);
304 ok(str
[0] == 0x414, "str[0] was: 0x%04X\n", str
[0]);
305 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
306 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
311 ret
= SetConsoleCursorPosition(hConOut
, c
);
312 ok(ret
, "SetConsoleCursorPosition failed\n");
313 okCURSOR(hConOut
, c
);
317 FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
319 /* Output u0414 "count" times at (1,0) */
322 SetConsoleCursorPosition(hConOut
, c
);
323 okCURSOR(hConOut
, c
);
324 for (n
= 0; n
< count
; ++n
)
326 ret
= WriteConsoleW(hConOut
, u0414
, lstrlenW(u0414
), &len
, NULL
);
327 ok(ret
&& len
== lstrlenW(u0414
), "WriteConsoleW failed\n");
331 len
= csbi
.dwSize
.X
+ (count
- (csbi
.dwSize
.X
- 1) / 2) * 2;
332 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
333 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
334 okCURSOR(hConOut
, c
);
336 /* Read characters at (0,0) */
339 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
340 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
341 ok(len
== 4, "len was: %ld\n", len
);
342 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
343 ok(str
[1] == 0x414, "str[1] was: 0x%04X\n", str
[1]);
344 ok(str
[2] == 0x414, "str[2] was: 0x%04X\n", str
[2]);
349 /* Output u9580 "count" times at (0,0) */
351 SetConsoleCursorPosition(hConOut
, c
);
352 okCURSOR(hConOut
, c
);
353 for (n
= 0; n
< count
; ++n
)
355 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
356 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
360 len
= count
* 2; /* u9580 is fullwidth in Japanese */
361 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
362 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
363 okCURSOR(hConOut
, c
);
368 ret
= SetConsoleCursorPosition(hConOut
, c
);
369 ok(ret
, "SetConsoleCursorPosition failed\n");
370 okCURSOR(hConOut
, c
);
374 ret
= FillConsoleOutputCharacterW(hConOut
, L
' ', csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
375 ok(ret
, "FillConsoleOutputCharacterW failed\n");
376 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
378 /* Output u9580 "count" times at (1,0) */
381 SetConsoleCursorPosition(hConOut
, c
);
382 okCURSOR(hConOut
, c
);
383 for (n
= 0; n
< count
; ++n
)
385 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
386 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
390 len
= csbi
.dwSize
.X
+ (count
- (csbi
.dwSize
.X
- 1) / 2) * 2;
391 c
.X
= (SHORT
)(len
% csbi
.dwSize
.X
);
392 c
.Y
= (SHORT
)(len
/ csbi
.dwSize
.X
);
393 okCURSOR(hConOut
, c
);
395 /* Fill by ideograph space */
397 ret
= FillConsoleOutputCharacterW(hConOut
, ideograph_space
, csbi
.dwSize
.X
* csbi
.dwSize
.Y
, c
, &len
);
398 ok(ret
, "FillConsoleOutputCharacterW failed\n");
399 ok(len
== csbi
.dwSize
.X
* csbi
.dwSize
.Y
, "len was: %ld\n", len
);
401 /* Read characters at (0,0) */
403 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
404 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
405 ok(len
== 3, "len was: %ld\n", len
);
406 ok(str
[0] == ideograph_space
, "str[0] was: 0x%04X\n", str
[0]);
407 ok(str
[1] == ideograph_space
, "str[1] was: 0x%04X\n", str
[1]);
408 ok(str
[2] == ideograph_space
, "str[2] was: 0x%04X\n", str
[2]);
411 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
412 ok(ret
, "ReadConsoleOutputAttribute failed\n");
413 ok(attr
== ATTR
, "attr was: %d\n", attr
);
414 ok(len
== 1, "len was %ld\n", len
);
416 /* Output u9580 "count" once at (1,0) */
419 SetConsoleCursorPosition(hConOut
, c
);
420 okCURSOR(hConOut
, c
);
421 ret
= WriteConsoleW(hConOut
, u9580
, lstrlenW(u9580
), &len
, NULL
);
422 ok(ret
&& len
== lstrlenW(u9580
), "WriteConsoleW failed\n");
425 ret
= ReadConsoleOutputAttribute(hConOut
, &attr
, 1, c
, &len
);
426 ok(ret
, "ReadConsoleOutputAttribute failed\n");
427 ok(attr
== ATTR
, "attr was: %d\n", attr
);
428 ok(len
== 1, "len was %ld\n", len
);
433 okCURSOR(hConOut
, c
);
435 /* Read characters */
437 ret
= ReadConsoleOutputCharacterW(hConOut
, str
, 3 * sizeof(WCHAR
), c
, &len
);
438 ok(ret
, "ReadConsoleOutputCharacterW failed\n");
439 ok(len
== 4, "len was: %ld\n", len
);
440 ok(str
[0] == L
' ', "str[0] was: 0x%04X\n", str
[0]);
441 ok(str
[1] == 0x9580, "str[1] was: 0x%04X\n", str
[1]);
442 ok(str
[2] == L
' ', "str[2] was: 0x%04X\n", str
[2]);
445 /* Restore code page */
446 SetConsoleOutputCP(oldcp
);
449 START_TEST(ConsoleCP
)
451 HANDLE hConIn
, hConOut
;
453 ok(AllocConsole(), "Couldn't alloc console\n");
455 hConIn
= CreateFileA("CONIN$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
456 hConOut
= CreateFileA("CONOUT$", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, 0);
457 ok(hConIn
!= INVALID_HANDLE_VALUE
, "Opening ConIn\n");
458 ok(hConOut
!= INVALID_HANDLE_VALUE
, "Opening ConOut\n");
460 if (IsValidLocale(lcidRussian
, LCID_INSTALLED
))
463 skip("Russian locale is not installed\n");
465 if (IsValidLocale(lcidJapanese
, LCID_INSTALLED
))
468 skip("Japanese locale is not installed\n");
471 CloseHandle(hConOut
);
473 ok(AllocConsole(), "Couldn't alloc console\n");