[WINSRV] Fix 64 bit issues
[reactos.git] / win32ss / user / winsrv / concfg / font.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/concfg/font.c
5 * PURPOSE: Console Fonts Management
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include "precomp.h"
13 #include <winuser.h>
14
15 #include "settings.h"
16 #include "font.h"
17 // #include "concfg.h"
18
19 #define NDEBUG
20 #include <debug.h>
21
22
23 /* FUNCTIONS ******************************************************************/
24
25 /* Retrieves the character set associated with a given code page */
26 BYTE
27 CodePageToCharSet(
28 IN UINT CodePage)
29 {
30 CHARSETINFO CharInfo;
31 if (TranslateCharsetInfo(UlongToPtr(CodePage), &CharInfo, TCI_SRCCODEPAGE))
32 return CharInfo.ciCharset;
33 else
34 return DEFAULT_CHARSET;
35 }
36
37 HFONT
38 CreateConsoleFontEx(
39 IN LONG Height,
40 IN LONG Width OPTIONAL,
41 IN OUT LPWSTR FaceName, // Points to a WCHAR array of LF_FACESIZE elements
42 IN ULONG FontFamily,
43 IN ULONG FontWeight,
44 IN UINT CodePage)
45 {
46 LOGFONTW lf;
47
48 RtlZeroMemory(&lf, sizeof(lf));
49
50 lf.lfHeight = Height;
51 lf.lfWidth = Width;
52
53 lf.lfEscapement = 0;
54 lf.lfOrientation = 0; // TA_BASELINE; // TA_RTLREADING; when the console supports RTL?
55 // lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = FALSE;
56 lf.lfWeight = FontWeight;
57 lf.lfCharSet = CodePageToCharSet(CodePage);
58 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
59 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
60 lf.lfQuality = DEFAULT_QUALITY;
61 lf.lfPitchAndFamily = (BYTE)(FIXED_PITCH | FontFamily);
62
63 if (!IsValidConsoleFont(FaceName, CodePage))
64 StringCchCopyW(FaceName, LF_FACESIZE, L"Terminal");
65
66 StringCchCopyNW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName),
67 FaceName, LF_FACESIZE);
68
69 return CreateFontIndirectW(&lf);
70 }
71
72 HFONT
73 CreateConsoleFont2(
74 IN LONG Height,
75 IN LONG Width OPTIONAL,
76 IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
77 {
78 return CreateConsoleFontEx(Height,
79 Width,
80 ConsoleInfo->FaceName,
81 ConsoleInfo->FontFamily,
82 ConsoleInfo->FontWeight,
83 ConsoleInfo->CodePage);
84 }
85
86 HFONT
87 CreateConsoleFont(
88 IN OUT PCONSOLE_STATE_INFO ConsoleInfo)
89 {
90 /*
91 * Format:
92 * Width = FontSize.X = LOWORD(FontSize);
93 * Height = FontSize.Y = HIWORD(FontSize);
94 */
95 /* NOTE: FontSize is always in cell height/width units (pixels) */
96 return CreateConsoleFontEx((LONG)(ULONG)ConsoleInfo->FontSize.Y,
97 (LONG)(ULONG)ConsoleInfo->FontSize.X,
98 ConsoleInfo->FaceName,
99 ConsoleInfo->FontFamily,
100 ConsoleInfo->FontWeight,
101 ConsoleInfo->CodePage);
102 }
103
104 BOOL
105 GetFontCellSize(
106 IN HDC hDC OPTIONAL,
107 IN HFONT hFont,
108 OUT PUINT Height,
109 OUT PUINT Width)
110 {
111 BOOL Success = FALSE;
112 HDC hOrgDC = hDC;
113 HFONT hOldFont;
114 // LONG LogSize, PointSize;
115 LONG CharWidth, CharHeight;
116 TEXTMETRICW tm;
117 // SIZE CharSize;
118
119 if (!hDC)
120 hDC = GetDC(NULL);
121
122 hOldFont = SelectObject(hDC, hFont);
123 if (hOldFont == NULL)
124 {
125 DPRINT1("GetFontCellSize: SelectObject failed\n");
126 goto Quit;
127 }
128
129 /*
130 * See also: Display_SetTypeFace in applications/fontview/display.c
131 */
132
133 /*
134 * Note that the method with GetObjectW just returns
135 * the original parameters with which the font was created.
136 */
137 if (!GetTextMetricsW(hDC, &tm))
138 {
139 DPRINT1("GetFontCellSize: GetTextMetrics failed\n");
140 goto Cleanup;
141 }
142
143 CharHeight = tm.tmHeight + tm.tmExternalLeading;
144
145 #if 0
146 /* Measure real char width more precisely if possible */
147 if (GetTextExtentPoint32W(hDC, L"R", 1, &CharSize))
148 CharWidth = CharSize.cx;
149 #else
150 CharWidth = tm.tmAveCharWidth; // tm.tmMaxCharWidth;
151 #endif
152
153 #if 0
154 /*** Logical to Point size ***/
155 LogSize = tm.tmHeight - tm.tmInternalLeading;
156 PointSize = MulDiv(LogSize, 72, GetDeviceCaps(hDC, LOGPIXELSY));
157 /*****************************/
158 #endif
159
160 *Height = (UINT)CharHeight;
161 *Width = (UINT)CharWidth;
162 Success = TRUE;
163
164 Cleanup:
165 SelectObject(hDC, hOldFont);
166 Quit:
167 if (!hOrgDC)
168 ReleaseDC(NULL, hDC);
169
170 return Success;
171 }
172
173 BOOL
174 IsValidConsoleFont2(
175 IN PLOGFONTW lplf,
176 IN PNEWTEXTMETRICW lpntm,
177 IN DWORD FontType,
178 IN UINT CodePage)
179 {
180 LPCWSTR FaceName = lplf->lfFaceName;
181
182 /* Record the font's attributes (Fixedwidth and Truetype) */
183 // BOOL fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
184 // BOOL fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS);
185
186 /*
187 * According to: http://support.microsoft.com/kb/247815
188 * the criteria for console-eligible fonts are:
189 * - The font must be a fixed-pitch font.
190 * - The font cannot be an italic font.
191 * - The font cannot have a negative A or C space.
192 * - If it is a TrueType font, it must be FF_MODERN.
193 * - If it is not a TrueType font, it must be OEM_CHARSET.
194 *
195 * Non documented: vertical fonts are forbidden (their name start with a '@').
196 *
197 * Additional criteria for Asian installations:
198 * - If it is not a TrueType font, the face name must be "Terminal".
199 * - If it is an Asian TrueType font, it must also be an Asian character set.
200 *
201 * To install additional TrueType fonts to be available for the console,
202 * add entries of type REG_SZ named "0", "00" etc... in:
203 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
204 * The names of the fonts listed there should match those in:
205 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
206 */
207
208 /*
209 * In ReactOS we relax some of the criteria:
210 * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
211 * that can be italic or have negative A or C space.
212 * - If it is not a TrueType font, it can be from another character set
213 * than OEM_CHARSET.
214 * - We do not look into the magic registry key mentioned above.
215 */
216
217 /* Reject variable width fonts */
218 if (((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
219 #if 0 /* Reject italic and TrueType fonts with negative A or C space */
220 || (lplf->lfItalic)
221 || !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
222 #endif
223 )
224 {
225 DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
226 FaceName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH"
227 : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space"
228 : " is broken"),
229 lplf->lfPitchAndFamily);
230 return FALSE;
231 }
232
233 /* Reject TrueType fonts that are not FF_MODERN */
234 if ((FontType == TRUETYPE_FONTTYPE) && ((lplf->lfPitchAndFamily & 0xF0) != FF_MODERN))
235 {
236 DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n",
237 FaceName, lplf->lfPitchAndFamily);
238 return FALSE;
239 }
240
241 /* Is the current code page Chinese, Japanese or Korean? */
242 if (IsCJKCodePage(CodePage))
243 {
244 /* It's Asian */
245 if (FontType == TRUETYPE_FONTTYPE)
246 {
247 if (lplf->lfCharSet != CodePageToCharSet(CodePage))
248 {
249 DPRINT1("TrueType font '%S' rejected because it's not user Asian charset (lfCharSet = %d)\n",
250 FaceName, lplf->lfCharSet);
251 return FALSE;
252 }
253 }
254 else
255 {
256 /* Reject non-TrueType fonts that are not Terminal */
257 if (wcscmp(FaceName, L"Terminal") != 0)
258 {
259 DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", FaceName);
260 return FALSE;
261 }
262 }
263 }
264 else
265 {
266 /* Not CJK */
267 if ((FontType != TRUETYPE_FONTTYPE) &&
268 (lplf->lfCharSet != ANSI_CHARSET) &&
269 (lplf->lfCharSet != DEFAULT_CHARSET) &&
270 (lplf->lfCharSet != OEM_CHARSET))
271 {
272 DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n",
273 FaceName, lplf->lfCharSet);
274 return FALSE;
275 }
276 }
277
278 /* Reject fonts that are vertical (tategaki) */
279 if (FaceName[0] == L'@')
280 {
281 DPRINT1("Font '%S' rejected because it's vertical\n", FaceName);
282 return FALSE;
283 }
284
285 /* All good */
286 return TRUE;
287 }
288
289 typedef struct _IS_VALID_CONSOLE_FONT_PARAM
290 {
291 BOOL IsValidFont;
292 UINT CodePage;
293 } IS_VALID_CONSOLE_FONT_PARAM, *PIS_VALID_CONSOLE_FONT_PARAM;
294
295 static BOOL CALLBACK
296 IsValidConsoleFontProc(
297 IN PLOGFONTW lplf,
298 IN PNEWTEXTMETRICW lpntm,
299 IN DWORD FontType,
300 IN LPARAM lParam)
301 {
302 PIS_VALID_CONSOLE_FONT_PARAM Param = (PIS_VALID_CONSOLE_FONT_PARAM)lParam;
303 Param->IsValidFont = IsValidConsoleFont2(lplf, lpntm, FontType, Param->CodePage);
304
305 /* Stop the enumeration now */
306 return FALSE;
307 }
308
309 BOOL
310 IsValidConsoleFont(
311 IN LPCWSTR FaceName,
312 IN UINT CodePage)
313 {
314 IS_VALID_CONSOLE_FONT_PARAM Param;
315 HDC hDC;
316 LOGFONTW lf;
317
318 Param.IsValidFont = FALSE;
319 Param.CodePage = CodePage;
320
321 RtlZeroMemory(&lf, sizeof(lf));
322 lf.lfCharSet = DEFAULT_CHARSET; // CodePageToCharSet(CodePage);
323 // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
324 StringCchCopyW(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), FaceName);
325
326 hDC = GetDC(NULL);
327 EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)IsValidConsoleFontProc, (LPARAM)&Param, 0);
328 ReleaseDC(NULL, hDC);
329
330 return Param.IsValidFont;
331 }
332
333 /* EOF */