6 #include "../src/shared/OsModule.h"
7 #include "../src/shared/StringUtil.h"
10 #include "../src/shared/StringUtil.cc"
12 #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0]))
14 // Some of these types and functions are missing from the MinGW headers.
15 // Others are undocumented.
17 struct AGENT_CONSOLE_FONT_INFO {
22 struct AGENT_CONSOLE_FONT_INFOEX {
28 WCHAR FaceName[LF_FACESIZE];
31 // undocumented XP API
32 typedef BOOL WINAPI SetConsoleFont_t(
36 // undocumented XP API
37 typedef DWORD WINAPI GetNumberOfConsoleFonts_t();
40 typedef BOOL WINAPI GetCurrentConsoleFont_t(
43 AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont);
46 typedef COORD WINAPI GetConsoleFontSize_t(
47 HANDLE hConsoleOutput,
51 typedef BOOL WINAPI GetCurrentConsoleFontEx_t(
52 HANDLE hConsoleOutput,
54 AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
57 typedef BOOL WINAPI SetCurrentConsoleFontEx_t(
58 HANDLE hConsoleOutput,
60 AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
62 #define GET_MODULE_PROC(mod, funcName) \
63 m_##funcName = reinterpret_cast<funcName##_t*>((mod).proc(#funcName)); \
65 #define DEFINE_ACCESSOR(funcName) \
66 funcName##_t &funcName() const { \
68 return *m_##funcName; \
73 XPFontAPI() : m_kernel32(L"kernel32.dll") {
74 GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont);
75 GET_MODULE_PROC(m_kernel32, GetConsoleFontSize);
79 return m_GetCurrentConsoleFont != NULL &&
80 m_GetConsoleFontSize != NULL;
83 DEFINE_ACCESSOR(GetCurrentConsoleFont)
84 DEFINE_ACCESSOR(GetConsoleFontSize)
88 GetCurrentConsoleFont_t *m_GetCurrentConsoleFont;
89 GetConsoleFontSize_t *m_GetConsoleFontSize;
92 class UndocumentedXPFontAPI : public XPFontAPI {
94 UndocumentedXPFontAPI() : m_kernel32(L"kernel32.dll") {
95 GET_MODULE_PROC(m_kernel32, SetConsoleFont);
96 GET_MODULE_PROC(m_kernel32, GetNumberOfConsoleFonts);
100 return this->XPFontAPI::valid() &&
101 m_SetConsoleFont != NULL &&
102 m_GetNumberOfConsoleFonts != NULL;
105 DEFINE_ACCESSOR(SetConsoleFont)
106 DEFINE_ACCESSOR(GetNumberOfConsoleFonts)
110 SetConsoleFont_t *m_SetConsoleFont;
111 GetNumberOfConsoleFonts_t *m_GetNumberOfConsoleFonts;
114 class VistaFontAPI : public XPFontAPI {
116 VistaFontAPI() : m_kernel32(L"kernel32.dll") {
117 GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx);
118 GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx);
122 return this->XPFontAPI::valid() &&
123 m_GetCurrentConsoleFontEx != NULL &&
124 m_SetCurrentConsoleFontEx != NULL;
127 DEFINE_ACCESSOR(GetCurrentConsoleFontEx)
128 DEFINE_ACCESSOR(SetCurrentConsoleFontEx)
132 GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx;
133 SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx;
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) {
144 ret.push_back(std::make_pair(i, size));
149 static void dumpFontTable(HANDLE conout) {
150 const int kMaxCount = 1000;
153 printf("dumpFontTable: cannot dump font table -- missing APIs\n");
156 std::vector<std::pair<DWORD, COORD> > table =
157 readFontTable(api, conout, kMaxCount);
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));
166 for (size_t i = first; i <= last; ++i) {
170 winpty_snprintf(tmp, " %2dx%-2d",
171 table[i].second.X, table[i].second.Y);
174 printf("%s\n", line.c_str());
177 if (table.size() == kMaxCount) {
178 printf("... stopped reading at %d fonts ...\n", kMaxCount);
182 static std::string stringToCodePoints(const std::wstring &str) {
183 std::string ret = "(";
184 for (size_t i = 0; i < str.size(); ++i) {
186 winpty_snprintf(tmp, "%X", str[i]);
187 if (ret.size() > 1) {
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());
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");
215 dumpFontInfoEx(infoex);
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");
224 printf("nFont=%u dwFontSize=(%d,%d)\n",
225 static_cast<unsigned>(info.nFont),
226 info.dwFontSize.X, info.dwFontSize.Y);
229 static void dumpFontAndTable(HANDLE conout) {
232 printf("maxWnd=0: "); dumpVistaFont(vista, conout, FALSE);
233 printf("maxWnd=1: "); dumpVistaFont(vista, conout, TRUE);
234 dumpFontTable(conout);
237 UndocumentedXPFontAPI xp;
239 printf("maxWnd=0: "); dumpXPFont(xp, conout, FALSE);
240 printf("maxWnd=1: "); dumpXPFont(xp, conout, TRUE);
241 dumpFontTable(conout);
244 printf("setSmallFont: neither Vista nor XP APIs detected -- giving up\n");
245 dumpFontTable(conout);
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;
255 printf("GetNumberOfConsoleFonts returned %u\n", xp.GetNumberOfConsoleFonts()());
257 printf("The GetNumberOfConsoleFonts API was missing\n");
259 printf("CP=%u OutputCP=%u\n", GetConsoleCP(), GetConsoleOutputCP());