installed pty
[VSoRC/.git] / node_modules / node-pty / deps / winpty / misc / FontSurvey.cc
1 #include <windows.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include <vector>
8
9 #include "TestUtil.cc"
10
11 #define COUNT_OF(array) (sizeof(array) / sizeof((array)[0]))
12
13 // See https://en.wikipedia.org/wiki/List_of_CJK_fonts
14 const wchar_t kMSGothic[] = { 0xff2d, 0xff33, 0x0020, 0x30b4, 0x30b7, 0x30c3, 0x30af, 0 }; // Japanese
15 const wchar_t kNSimSun[] = { 0x65b0, 0x5b8b, 0x4f53, 0 }; // Simplified Chinese
16 const wchar_t kMingLight[] = { 0x7d30, 0x660e, 0x9ad4, 0 }; // Traditional Chinese
17 const wchar_t kGulimChe[] = { 0xad74, 0xb9bc, 0xccb4, 0 }; // Korean
18
19 std::vector<bool> condense(const std::vector<CHAR_INFO> &buf) {
20     std::vector<bool> ret;
21     size_t i = 0;
22     while (i < buf.size()) {
23         if (buf[i].Char.UnicodeChar == L' ' &&
24                 ((buf[i].Attributes & 0x300) == 0)) {
25             // end of line
26             break;
27         } else if (i + 1 < buf.size() &&
28                 ((buf[i].Attributes & 0x300) == 0x100) &&
29                 ((buf[i + 1].Attributes & 0x300) == 0x200) &&
30                 buf[i].Char.UnicodeChar != L' ' &&
31                 buf[i].Char.UnicodeChar == buf[i + 1].Char.UnicodeChar) {
32             // double-width
33             ret.push_back(true);
34             i += 2;
35         } else if ((buf[i].Attributes & 0x300) == 0) {
36             // single-width
37             ret.push_back(false);
38             i++;
39         } else {
40             ASSERT(false && "unexpected output");
41         }
42     }
43     return ret;
44 }
45
46 int main(int argc, char *argv[]) {
47     if (argc != 2) {
48         printf("Usage: %s \"arguments for SetFont.exe\"\n", argv[0]);
49         return 1;
50     }
51
52     const char *setFontArgs = argv[1];
53
54     const wchar_t testLine[] = { 0xA2, 0xA3, 0x2014, 0x3044, 0x30FC, 0x4000, 0 };
55     const HANDLE conout = openConout();
56
57     char setFontCmd[1024];
58     for (int h = 1; h <= 100; ++h) {
59         sprintf(setFontCmd, ".\\SetFont.exe %s -h %d && cls", setFontArgs, h);
60         system(setFontCmd);
61
62         CONSOLE_FONT_INFOEX infoex = {};
63         infoex.cbSize = sizeof(infoex);
64         BOOL success = GetCurrentConsoleFontEx(conout, FALSE, &infoex);
65         ASSERT(success && "GetCurrentConsoleFontEx failed");
66
67         DWORD actual = 0;
68         success = WriteConsoleW(conout, testLine, wcslen(testLine), &actual, nullptr);
69         ASSERT(success && actual == wcslen(testLine));
70
71         std::vector<CHAR_INFO> readBuf(14);
72         const SMALL_RECT readRegion = {0, 0, static_cast<short>(readBuf.size() - 1), 0};
73         SMALL_RECT readRegion2 = readRegion;
74         success = ReadConsoleOutputW(
75             conout, readBuf.data(), 
76             {static_cast<short>(readBuf.size()), 1}, 
77             {0, 0},
78             &readRegion2);
79         ASSERT(success && !memcmp(&readRegion, &readRegion2, sizeof(readRegion)));
80
81         const auto widths = condense(readBuf);
82         std::string widthsStr;
83         for (bool width : widths) {
84             widthsStr.append(width ? "F" : "H");
85         }
86         char size[16];
87         sprintf(size, "%d,%d", infoex.dwFontSize.X, infoex.dwFontSize.Y);
88         const char *status = "";
89         if (widthsStr == "HHFFFF") {
90             status = "GOOD";
91         } else if (widthsStr == "HHHFFF") {
92             status = "OK";
93         } else {
94             status = "BAD";
95         }
96         trace("Size %3d: %-7s %-4s (%s)", h, size, status, widthsStr.c_str());
97     }
98     sprintf(setFontCmd, ".\\SetFont.exe %s -h 14", setFontArgs);
99     system(setFontCmd);
100 }