2015-10-10 07:14:31 +00:00
|
|
|
|
// Demonstrates how U+30FC is sometimes handled as a single-width character
|
|
|
|
|
// when it should be handled as a double-width character.
|
|
|
|
|
//
|
|
|
|
|
// It only runs on computers where 932 is a valid code page. Set the system
|
|
|
|
|
// local to "Japanese (Japan)" to ensure this.
|
|
|
|
|
//
|
|
|
|
|
// The problem seems to happen when U+30FC is printed in a console using the
|
|
|
|
|
// Lucida Console font, and only when that font is at certain sizes.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <locale.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "TestUtil.cc"
|
|
|
|
|
#include "../shared/DebugClient.cc"
|
|
|
|
|
|
|
|
|
|
#define COUNT_OF(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
|
|
|
|
|
|
static void setFont(const wchar_t *faceName, int pxSize) {
|
|
|
|
|
CONSOLE_FONT_INFOEX infoex = {0};
|
|
|
|
|
infoex.cbSize = sizeof(infoex);
|
|
|
|
|
infoex.dwFontSize.Y = pxSize;
|
|
|
|
|
wcsncpy(infoex.FaceName, faceName, COUNT_OF(infoex.FaceName));
|
|
|
|
|
BOOL ret = SetCurrentConsoleFontEx(
|
|
|
|
|
GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &infoex);
|
|
|
|
|
assert(ret);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-10 07:29:47 +00:00
|
|
|
|
static bool performTest(const wchar_t testChar) {
|
2015-10-10 07:14:31 +00:00
|
|
|
|
const HANDLE conout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
|
|
|
|
|
SetConsoleTextAttribute(conout, 7);
|
|
|
|
|
|
|
|
|
|
system("cls");
|
|
|
|
|
DWORD actual = 0;
|
2015-10-10 07:29:47 +00:00
|
|
|
|
BOOL ret = WriteConsoleW(conout, &testChar, 1, &actual, NULL);
|
2015-10-10 07:14:31 +00:00
|
|
|
|
assert(ret && actual == 1);
|
|
|
|
|
|
|
|
|
|
CHAR_INFO verify[2];
|
|
|
|
|
COORD bufSize = {2, 1};
|
|
|
|
|
COORD bufCoord = {0, 0};
|
|
|
|
|
const SMALL_RECT readRegion = {0, 0, 1, 0};
|
|
|
|
|
SMALL_RECT actualRegion = readRegion;
|
|
|
|
|
ret = ReadConsoleOutputW(conout, verify, bufSize, bufCoord, &actualRegion);
|
|
|
|
|
assert(ret && !memcmp(&readRegion, &actualRegion, sizeof(readRegion)));
|
2015-10-10 07:29:47 +00:00
|
|
|
|
assert(verify[0].Char.UnicodeChar == testChar);
|
2015-10-10 07:14:31 +00:00
|
|
|
|
|
2015-10-10 07:29:47 +00:00
|
|
|
|
if (verify[1].Char.UnicodeChar == testChar) {
|
2015-10-10 07:14:31 +00:00
|
|
|
|
// Typical double-width behavior with a TrueType font. Pass.
|
|
|
|
|
assert(verify[0].Attributes == 0x107);
|
|
|
|
|
assert(verify[1].Attributes == 0x207);
|
|
|
|
|
return true;
|
|
|
|
|
} else if (verify[1].Char.UnicodeChar == 0) {
|
|
|
|
|
// Typical double-width behavior with a Raster Font. Pass.
|
|
|
|
|
assert(verify[0].Attributes == 7);
|
|
|
|
|
assert(verify[1].Attributes == 0);
|
|
|
|
|
return true;
|
|
|
|
|
} else if (verify[1].Char.UnicodeChar == L' ') {
|
|
|
|
|
// Single-width behavior. Fail.
|
|
|
|
|
assert(verify[0].Attributes == 7);
|
|
|
|
|
assert(verify[1].Attributes == 7);
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
// Unexpected output.
|
|
|
|
|
assert(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
|
if (argc == 1) {
|
|
|
|
|
startChildProcess(L"CHILD");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(SetConsoleCP(932));
|
|
|
|
|
assert(SetConsoleOutputCP(932));
|
|
|
|
|
|
2015-10-10 07:29:47 +00:00
|
|
|
|
const wchar_t testChar = 0x30FC;
|
|
|
|
|
const wchar_t *const faceNames[] = {
|
|
|
|
|
L"Lucida Console",
|
|
|
|
|
L"Consolas",
|
|
|
|
|
L"MS ゴシック",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
trace("Test started");
|
|
|
|
|
|
|
|
|
|
for (auto faceName : faceNames) {
|
|
|
|
|
for (int px = 1; px <= 50; ++px) {
|
|
|
|
|
setFont(faceName, px);
|
|
|
|
|
if (!performTest(testChar)) {
|
|
|
|
|
trace("FAILURE: %s %dpx", narrowString(faceName).c_str(), px);
|
|
|
|
|
}
|
2015-10-10 07:14:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-10 07:29:47 +00:00
|
|
|
|
|
2015-10-10 07:14:31 +00:00
|
|
|
|
trace("Test complete");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|