installed pty
[VSoRC/.git] / node_modules / node-pty / deps / winpty / misc / GetFont.cc
1 #include <windows.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <wchar.h>
5
6 #include "../src/shared/OsModule.h"
7 #include "../src/shared/StringUtil.h"
8
9 #include "TestUtil.cc"
10 #include "../src/shared/StringUtil.cc"
11
12 #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0]))
13
14 // Some of these types and functions are missing from the MinGW headers.
15 // Others are undocumented.
16
17 struct AGENT_CONSOLE_FONT_INFO {
18     DWORD nFont;
19     COORD dwFontSize;
20 };
21
22 struct AGENT_CONSOLE_FONT_INFOEX {
23     ULONG cbSize;
24     DWORD nFont;
25     COORD dwFontSize;
26     UINT FontFamily;
27     UINT FontWeight;
28     WCHAR FaceName[LF_FACESIZE];
29 };
30
31 // undocumented XP API
32 typedef BOOL WINAPI SetConsoleFont_t(
33             HANDLE hOutput,
34             DWORD dwFontIndex);
35
36 // undocumented XP API
37 typedef DWORD WINAPI GetNumberOfConsoleFonts_t();
38
39 // XP and up
40 typedef BOOL WINAPI GetCurrentConsoleFont_t(
41             HANDLE hOutput,
42             BOOL bMaximumWindow,
43             AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont);
44
45 // XP and up
46 typedef COORD WINAPI GetConsoleFontSize_t(
47             HANDLE hConsoleOutput,
48             DWORD nFont);
49
50 // Vista and up
51 typedef BOOL WINAPI GetCurrentConsoleFontEx_t(
52             HANDLE hConsoleOutput,
53             BOOL bMaximumWindow,
54             AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
55
56 // Vista and up
57 typedef BOOL WINAPI SetCurrentConsoleFontEx_t(
58             HANDLE hConsoleOutput,
59             BOOL bMaximumWindow,
60             AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
61
62 #define GET_MODULE_PROC(mod, funcName) \
63     m_##funcName = reinterpret_cast<funcName##_t*>((mod).proc(#funcName)); \
64
65 #define DEFINE_ACCESSOR(funcName) \
66     funcName##_t &funcName() const { \
67         ASSERT(valid()); \
68         return *m_##funcName; \
69     }
70
71 class XPFontAPI {
72 public:
73     XPFontAPI() : m_kernel32(L"kernel32.dll") {
74         GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont);
75         GET_MODULE_PROC(m_kernel32, GetConsoleFontSize);
76     }
77
78     bool valid() const {
79         return m_GetCurrentConsoleFont != NULL &&
80             m_GetConsoleFontSize != NULL;
81     }
82
83     DEFINE_ACCESSOR(GetCurrentConsoleFont)
84     DEFINE_ACCESSOR(GetConsoleFontSize)
85
86 private:
87     OsModule m_kernel32;
88     GetCurrentConsoleFont_t *m_GetCurrentConsoleFont;
89     GetConsoleFontSize_t *m_GetConsoleFontSize;
90 };
91
92 class UndocumentedXPFontAPI : public XPFontAPI {
93 public:
94     UndocumentedXPFontAPI() : m_kernel32(L"kernel32.dll") {
95         GET_MODULE_PROC(m_kernel32, SetConsoleFont);
96         GET_MODULE_PROC(m_kernel32, GetNumberOfConsoleFonts);
97     }
98
99     bool valid() const {
100         return this->XPFontAPI::valid() &&
101             m_SetConsoleFont != NULL &&
102             m_GetNumberOfConsoleFonts != NULL;
103     }
104
105     DEFINE_ACCESSOR(SetConsoleFont)
106     DEFINE_ACCESSOR(GetNumberOfConsoleFonts)
107
108 private:
109     OsModule m_kernel32;
110     SetConsoleFont_t *m_SetConsoleFont;
111     GetNumberOfConsoleFonts_t *m_GetNumberOfConsoleFonts;
112 };
113
114 class VistaFontAPI : public XPFontAPI {
115 public:
116     VistaFontAPI() : m_kernel32(L"kernel32.dll") {
117         GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx);
118         GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx);
119     }
120
121     bool valid() const {
122         return this->XPFontAPI::valid() &&
123             m_GetCurrentConsoleFontEx != NULL &&
124             m_SetCurrentConsoleFontEx != NULL;
125     }
126
127     DEFINE_ACCESSOR(GetCurrentConsoleFontEx)
128     DEFINE_ACCESSOR(SetCurrentConsoleFontEx)
129
130 private:
131     OsModule m_kernel32;
132     GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx;
133     SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx;
134 };
135
136 static std::vector<std::pair<DWORD, COORD> > readFontTable(
137         XPFontAPI &api, HANDLE conout, DWORD maxCount) {
138     std::vector<std::pair<DWORD, COORD> > ret;
139     for (DWORD i = 0; i < maxCount; ++i) {
140         COORD size = api.GetConsoleFontSize()(conout, i);
141         if (size.X == 0 && size.Y == 0) {
142             break;
143         }
144         ret.push_back(std::make_pair(i, size));
145     }
146     return ret;
147 }
148
149 static void dumpFontTable(HANDLE conout) {
150     const int kMaxCount = 1000;
151     XPFontAPI api;
152     if (!api.valid()) {
153         printf("dumpFontTable: cannot dump font table -- missing APIs\n");
154         return;
155     }
156     std::vector<std::pair<DWORD, COORD> > table =
157         readFontTable(api, conout, kMaxCount);
158     std::string line;
159     char tmp[128];
160     size_t first = 0;
161     while (first < table.size()) {
162         size_t last = std::min(table.size() - 1, first + 10 - 1);
163         winpty_snprintf(tmp, "%02u-%02u:",
164             static_cast<unsigned>(first), static_cast<unsigned>(last));
165         line = tmp;
166         for (size_t i = first; i <= last; ++i) {
167             if (i % 10 == 5) {
168                 line += "  - ";
169             }
170             winpty_snprintf(tmp, " %2dx%-2d",
171                 table[i].second.X, table[i].second.Y);
172             line += tmp;
173         }
174         printf("%s\n", line.c_str());
175         first = last + 1;
176     }
177     if (table.size() == kMaxCount) {
178         printf("... stopped reading at %d fonts ...\n", kMaxCount);
179     }
180 }
181
182 static std::string stringToCodePoints(const std::wstring &str) {
183     std::string ret = "(";
184     for (size_t i = 0; i < str.size(); ++i) {
185         char tmp[32];
186         winpty_snprintf(tmp, "%X", str[i]);
187         if (ret.size() > 1) {
188             ret.push_back(' ');
189         }
190         ret += tmp;
191     }
192     ret.push_back(')');
193     return ret;
194 }
195
196 static void dumpFontInfoEx(
197         const AGENT_CONSOLE_FONT_INFOEX &infoex) {
198     std::wstring faceName(infoex.FaceName,
199         winpty_wcsnlen(infoex.FaceName, COUNT_OF(infoex.FaceName)));
200     cprintf(L"nFont=%u dwFontSize=(%d,%d) "
201         "FontFamily=0x%x FontWeight=%u FaceName=%ls %hs\n",
202         static_cast<unsigned>(infoex.nFont),
203         infoex.dwFontSize.X, infoex.dwFontSize.Y,
204         infoex.FontFamily, infoex.FontWeight, faceName.c_str(),
205         stringToCodePoints(faceName).c_str());
206 }
207
208 static void dumpVistaFont(VistaFontAPI &api, HANDLE conout, BOOL maxWindow) {
209     AGENT_CONSOLE_FONT_INFOEX infoex = {0};
210     infoex.cbSize = sizeof(infoex);
211     if (!api.GetCurrentConsoleFontEx()(conout, maxWindow, &infoex)) {
212         printf("GetCurrentConsoleFontEx call failed\n");
213         return;
214     }
215     dumpFontInfoEx(infoex);
216 }
217
218 static void dumpXPFont(XPFontAPI &api, HANDLE conout, BOOL maxWindow) {
219     AGENT_CONSOLE_FONT_INFO info = {0};
220     if (!api.GetCurrentConsoleFont()(conout, maxWindow, &info)) {
221         printf("GetCurrentConsoleFont call failed\n");
222         return;
223     }
224     printf("nFont=%u dwFontSize=(%d,%d)\n",
225         static_cast<unsigned>(info.nFont),
226         info.dwFontSize.X, info.dwFontSize.Y);
227 }
228
229 static void dumpFontAndTable(HANDLE conout) {
230     VistaFontAPI vista;
231     if (vista.valid()) {
232         printf("maxWnd=0: "); dumpVistaFont(vista, conout, FALSE);
233         printf("maxWnd=1: "); dumpVistaFont(vista, conout, TRUE);
234         dumpFontTable(conout);
235         return;
236     }
237     UndocumentedXPFontAPI xp;
238     if (xp.valid()) {
239         printf("maxWnd=0: "); dumpXPFont(xp, conout, FALSE);
240         printf("maxWnd=1: "); dumpXPFont(xp, conout, TRUE);
241         dumpFontTable(conout);
242         return;
243     }
244     printf("setSmallFont: neither Vista nor XP APIs detected -- giving up\n");
245     dumpFontTable(conout);
246 }
247
248 int main() {
249     const HANDLE conout = openConout();
250     const COORD largest = GetLargestConsoleWindowSize(conout);
251     printf("largestConsoleWindowSize=(%d,%d)\n", largest.X, largest.Y);
252     dumpFontAndTable(conout);
253     UndocumentedXPFontAPI xp;
254     if (xp.valid()) {
255         printf("GetNumberOfConsoleFonts returned %u\n", xp.GetNumberOfConsoleFonts()());
256     } else {
257         printf("The GetNumberOfConsoleFonts API was missing\n");
258     }
259     printf("CP=%u OutputCP=%u\n", GetConsoleCP(), GetConsoleOutputCP());
260     return 0;
261 }