Sync with trunk r63383 .
[reactos.git] / dll / cpl / console / font.c
1 /*
2 * PROJECT: ReactOS Console Configuration DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/console/font.c
5 * PURPOSE: Font dialog
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 #include "console.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15
16 //
17 // Some temporary code for future reference...
18 //
19 #if 0
20 /*
21 * This code comes from PuTTY
22 */
23 {
24 CHOOSEFONT cf;
25 LOGFONT lf;
26 HDC hdc;
27 FontSpec *fs = (FontSpec *)c->data;
28
29 hdc = GetDC(0);
30 lf.lfHeight = -MulDiv(fs->height,
31 GetDeviceCaps(hdc, LOGPIXELSY), 72);
32 ReleaseDC(0, hdc);
33 lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
34 lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
35 lf.lfWeight = (fs->isbold ? FW_BOLD : 0);
36 lf.lfCharSet = fs->charset;
37 lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
38 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
39 lf.lfQuality = DEFAULT_QUALITY;
40 lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
41 strncpy(lf.lfFaceName, fs->name,
42 sizeof(lf.lfFaceName) - 1);
43 lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
44
45 cf.lStructSize = sizeof(cf);
46 cf.hwndOwner = dp->hwnd;
47 cf.lpLogFont = &lf;
48 cf.Flags = (dp->fixed_pitch_fonts ? CF_FIXEDPITCHONLY : 0) |
49 CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
50
51 if (ChooseFont(&cf)) {
52 fs = fontspec_new(lf.lfFaceName, (lf.lfWeight == FW_BOLD),
53 cf.iPointSize / 10, lf.lfCharSet);
54 dlg_fontsel_set(ctrl, dp, fs);
55 fontspec_free(fs);
56
57 ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
58 }
59 }
60
61 /*
62 * This code is from consrv.
63 */
64 {
65 if (!GetTextMetricsW(drawItem->hDC, &Metrics))
66 {
67 DPRINT1("PaintText: GetTextMetrics failed\n");
68 SelectObject(drawItem->hDC, OldFont);
69 DeleteObject(Font);
70 return;
71 }
72 GuiData->CharWidth = Metrics.tmMaxCharWidth;
73 GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
74
75 /* Measure real char width more precisely if possible. */
76 if (GetTextExtentPoint32W(drawItem->hDC, L"R", 1, &CharSize))
77 GuiData->CharWidth = CharSize.cx;
78 }
79 #endif
80
81
82 BOOL CALLBACK
83 EnumFontFamExProc(PLOGFONTW lplf,
84 PNEWTEXTMETRICW lpntm,
85 DWORD FontType,
86 LPARAM lParam)
87 {
88 HWND hwndCombo = (HWND)lParam;
89 LPWSTR pszName = lplf->lfFaceName;
90
91 BOOL fFixed;
92 BOOL fTrueType;
93
94 /* Record the font's attributes (Fixedwidth and Truetype) */
95 fFixed = ((lplf->lfPitchAndFamily & 0x03) == FIXED_PITCH);
96 fTrueType = (lplf->lfOutPrecision == OUT_STROKE_PRECIS) ? TRUE : FALSE;
97
98 /*
99 * According to: http://support.microsoft.com/kb/247815
100 * the criteria for console-eligible fonts are:
101 * - The font must be a fixed-pitch font.
102 * - The font cannot be an italic font.
103 * - The font cannot have a negative A or C space.
104 * - If it is a TrueType font, it must be FF_MODERN.
105 * - If it is not a TrueType font, it must be OEM_CHARSET.
106 *
107 * Non documented: vertical fonts are forbidden (their name start with a '@').
108 *
109 * Additional criteria for Asian installations:
110 * - If it is not a TrueType font, the face name must be "Terminal".
111 * - If it is an Asian TrueType font, it must also be an Asian character set.
112 *
113 * To install additional TrueType fonts to be available for the console,
114 * add entries of type REG_SZ named "0", "00" etc... in:
115 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont
116 * The names of the fonts listed there should match those in:
117 * HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts
118 */
119
120 /*
121 * In ReactOS, we relax some criteria:
122 * - We allow fixed-pitch FF_MODERN (Monospace) TrueType fonts
123 * that can be italic and have negative A or C space.
124 * - If it is not a TrueType font, it can be from another character set
125 * than OEM_CHARSET.
126 * - We do not support Asian criteria at the moment.
127 * - We do not look into the magic registry key mentioned above.
128 */
129
130 /* Reject variable width fonts */
131 if (((lplf->lfPitchAndFamily & 0x03) != FIXED_PITCH)
132 #if 0 /* Reject italic and TrueType fonts with negative A or C space */
133 || (lplf->lfItalic)
134 || !(lpntm->ntmFlags & NTM_NONNEGATIVE_AC)
135 #endif
136 )
137 {
138 DPRINT1("Font '%S' rejected because it%s (lfPitchAndFamily = %d).\n",
139 pszName, !(lplf->lfPitchAndFamily & FIXED_PITCH) ? "'s not FIXED_PITCH" : (!(lpntm->ntmFlags & NTM_NONNEGATIVE_AC) ? " has negative A or C space" : " is broken"),
140 lplf->lfPitchAndFamily);
141 return TRUE;
142 }
143
144 /* Reject TrueType fonts that are not FF_MODERN */
145 if ((FontType == TRUETYPE_FONTTYPE) && ((lplf->lfPitchAndFamily & 0xF0) != FF_MODERN))
146 {
147 DPRINT1("TrueType font '%S' rejected because it's not FF_MODERN (lfPitchAndFamily = %d)\n", pszName, lplf->lfPitchAndFamily);
148 return TRUE;
149 }
150
151 /* Reject non-TrueType fonts that are not OEM */
152 #if 0
153 if ((FontType != TRUETYPE_FONTTYPE) && (lplf->lfCharSet != OEM_CHARSET))
154 {
155 DPRINT1("Non-TrueType font '%S' rejected because it's not OEM_CHARSET %d\n", pszName, lplf->lfCharSet);
156 return TRUE;
157 }
158 #else // Improved criterium
159 if ((FontType != TRUETYPE_FONTTYPE) &&
160 ((lplf->lfCharSet != ANSI_CHARSET) && (lplf->lfCharSet != DEFAULT_CHARSET) && (lplf->lfCharSet != OEM_CHARSET)))
161 {
162 DPRINT1("Non-TrueType font '%S' rejected because it's not ANSI_CHARSET or DEFAULT_CHARSET or OEM_CHARSET (lfCharSet = %d)\n", pszName, lplf->lfCharSet);
163 return TRUE;
164 }
165 #endif
166
167 /* Reject fonts that are vertical (tategaki) */
168 if (pszName[0] == L'@')
169 {
170 DPRINT1("Font '%S' rejected because it's vertical\n", pszName);
171 return TRUE;
172 }
173
174 #if 0 // For Asian installations only
175 /* Reject non-TrueType fonts that are not Terminal */
176 if ((FontType != TRUETYPE_FONTTYPE) && (wcscmp(pszName, L"Terminal") != 0))
177 {
178 DPRINT1("Non-TrueType font '%S' rejected because it's not Terminal\n", pszName);
179 return TRUE;
180 }
181
182 // TODO: Asian TrueType font must also be an Asian character set.
183 #endif
184
185 /* Make sure the font doesn't already exist in the list */
186 if (SendMessageW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)pszName) == LB_ERR)
187 {
188 /* Add the font */
189 INT idx = (INT)SendMessageW(hwndCombo, LB_ADDSTRING, 0, (LPARAM)pszName);
190
191 DPRINT1("Add font '%S' (lfPitchAndFamily = %d)\n", pszName, lplf->lfPitchAndFamily);
192
193 /* Store this information in the list-item's userdata area */
194 SendMessageW(hwndCombo, LB_SETITEMDATA, idx, MAKEWPARAM(fFixed, fTrueType));
195 }
196
197 return TRUE;
198 }
199
200 INT_PTR
201 CALLBACK
202 FontProc(HWND hwndDlg,
203 UINT uMsg,
204 WPARAM wParam,
205 LPARAM lParam)
206 {
207 PCONSOLE_PROPS pConInfo = (PCONSOLE_PROPS)GetWindowLongPtr(hwndDlg, DWLP_USER);
208 PGUI_CONSOLE_INFO GuiInfo = (pConInfo ? pConInfo->TerminalInfo.TermInfo : NULL);
209
210 UNREFERENCED_PARAMETER(wParam);
211
212 switch (uMsg)
213 {
214 case WM_INITDIALOG:
215 {
216 HDC hDC;
217 HWND hwndCombo;
218 LOGFONTW lf;
219 INT idx;
220
221 pConInfo = (PCONSOLE_PROPS)((LPPROPSHEETPAGE)lParam)->lParam;
222 GuiInfo = pConInfo->TerminalInfo.TermInfo;
223 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pConInfo);
224
225 ZeroMemory(&lf, sizeof(lf));
226 lf.lfCharSet = DEFAULT_CHARSET; // OEM_CHARSET;
227 // lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
228 // lf.lfFaceName = L"";
229
230 hDC = GetDC(NULL);
231 hwndCombo = GetDlgItem(hwndDlg, IDC_LBOX_FONTTYPE);
232 EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontFamExProc, (LPARAM)hwndCombo, 0);
233 ReleaseDC(NULL, hDC);
234
235 DPRINT1("GuiInfo->FaceName = '%S'\n", GuiInfo->FaceName);
236 idx = (INT)SendMessageW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)GuiInfo->FaceName);
237 if (idx != LB_ERR)
238 {
239 SendMessageW(hwndCombo, LB_SETCURSEL, (WPARAM)idx, 0);
240 }
241
242 return TRUE;
243 }
244
245 case WM_DRAWITEM:
246 {
247 LPDRAWITEMSTRUCT drawItem = (LPDRAWITEMSTRUCT)lParam;
248
249 if (drawItem->CtlID == IDC_STATIC_FONT_WINDOW_PREVIEW)
250 {
251 PaintConsole(drawItem, pConInfo);
252 }
253 else if (drawItem->CtlID == IDC_STATIC_SELECT_FONT_PREVIEW)
254 {
255 PaintText(drawItem, pConInfo, Screen);
256 }
257 return TRUE;
258 }
259
260 default:
261 break;
262 }
263
264 return FALSE;
265 }