xref: /reactos/dll/win32/comdlg32/fontdlg.c (revision cc439606)
1 /*
2  * COMMDLG - Font Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "commdlg.h"
33 #include "dlgs.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "wine/unicode.h"
37 #include "cderr.h"
38 #include "cdlg.h"
39 
40 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
41 
42 typedef struct
43 {
44   HWND hWnd1;
45   HWND hWnd2;
46   LPCHOOSEFONTW lpcf32w;
47   int  added;
48 } CFn_ENUMSTRUCT, *LPCFn_ENUMSTRUCT;
49 
50 
51 static const WCHAR strWineFontData[] = {'_','_','W','I','N','E','_','F','O','N','T','D','L','G','D','A','T','A',0};
52 static const WCHAR strWineFontData_a[] =
53                                {'_','_','W','I','N','E','_','F','O','N','T','D','L','G','D','A','T','A','_','A',0};
54 static const WCHAR chooseFontW[] = {'C','H','O','O','S','E','_','F','O','N','T',0};
55 static const WCHAR fontsizefmtW[] = {'%','d',0};
56 
57 /* image list with TrueType bitmaps and more */
58 static HIMAGELIST himlTT = 0;
59 #define TTBITMAP_XSIZE 20 /* x-size of the bitmaps */
60 
61 static INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
62 static INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
63 
64 /* There is a table here of all charsets, and the sample text for each.
65  * There is a second table that translates a charset into an index into
66  * the first table.
67  */
68 
69 #define CI(cs) ((IDS_CHARSET_##cs)-IDS_CHARSET_ANSI)
70 
71 
72 static const WCHAR stWestern[]={'A','a','B','b','Y','y','Z','z',0}; /* Western and default */
73 static const WCHAR stSymbol[]={'S','y','m','b','o','l',0}; /* Symbol */
74 static const WCHAR stShiftJis[]={'A','a',0x3042,0x3041,0x30a2,0x30a1,0x4e9c,0x5b87,0}; /* Shift JIS */
75 static const WCHAR stHangul[]={0xac00,0xb098,0xb2e4,'A','a','B','Y','y','Z','z',0}; /* Hangul */
76 static const WCHAR stGB2312[]={0x5fae,0x8f6f,0x4e2d,0x6587,0x8f6f,0x4ef6,0}; /* GB2312 */
77 static const WCHAR stBIG5[]={0x4e2d,0x6587,0x5b57,0x578b,0x7bc4,0x4f8b,0}; /* BIG5 */
78 static const WCHAR stGreek[]={'A','a','B','b',0x0391,0x03b1,0x0392,0x03b2,0}; /* Greek */
79 static const WCHAR stTurkish[]={'A','a','B','b',0x011e,0x011f,0x015e,0x015f,0}; /* Turkish */
80 static const WCHAR stHebrew[]={'A','a','B','b',0x05e0,0x05e1,0x05e9,0x05ea,0}; /* Hebrew */
81 static const WCHAR stArabic[]={'A','a','B','b',0x0627,0x0628,0x062c,0x062f,0x0647,0x0648,0x0632,0};/* Arabic */
82 static const WCHAR stBaltic[]={'A','a','B','b','Y','y','Z','z',0}; /* Baltic */
83 static const WCHAR stVietname[]={'A','a','B','b',0x01a0,0x01a1,0x01af,0x01b0,0}; /* Vietnamese */
84 static const WCHAR stCyrillic[]={'A','a','B','b',0x0411,0x0431,0x0424,0x0444,0}; /* Cyrillic */
85 static const WCHAR stEastEur[]={'A','a','B','b',0xc1,0xe1,0xd4,0xf4,0}; /* East European */
86 static const WCHAR stThai[]={'A','a','B','b',0x0e2d,0x0e31,0x0e01,0x0e29,0x0e23,0x0e44,0x0e17,0x0e22,0}; /* Thai */
87 static const WCHAR stJohab[]={0xac00,0xb098,0xb2e4,'A','a','B','Y','y','Z','z',0}; /* Johab */
88 static const WCHAR stMac[]={'A','a','B','b','Y','y','Z','z',0}; /* Mac */
89 static const WCHAR stOEM[]={'A','a','B','b',0xf8,0xf1,0xfd,0}; /* OEM */
90 /* the following character sets actually behave different (Win2K observation):
91  * the sample string is 'sticky': it uses the sample string of the previous
92  * selected character set. That behaviour looks like some default, which is
93  * not (yet) implemented. */
94 static const WCHAR stVISCII[]={'A','a','B','b',0}; /* VISCII */
95 static const WCHAR stTCVN[]={'A','a','B','b',0}; /* TCVN */
96 static const WCHAR stKOI8[]={'A','a','B','b',0}; /* KOI-8 */
97 static const WCHAR stIso88593[]={'A','a','B','b',0}; /* ISO-8859-3 */
98 static const WCHAR stIso88594[]={'A','a','B','b',0}; /* ISO-8859-4 */
99 static const WCHAR stIso885910[]={'A','a','B','b',0}; /* ISO-8859-10 */
100 static const WCHAR stCeltic[]={'A','a','B','b',0};/* Celtic */
101 
102 static const WCHAR * const sample_lang_text[]={
103     stWestern,stSymbol,stShiftJis,stHangul,stGB2312,
104     stBIG5,stGreek,stTurkish,stHebrew,stArabic,
105     stBaltic,stVietname,stCyrillic,stEastEur,stThai,
106     stJohab,stMac,stOEM,stVISCII,stTCVN,
107     stKOI8,stIso88593,stIso88594,stIso885910,stCeltic};
108 
109 
110 static const BYTE CHARSET_ORDER[256]={
111     CI(ANSI), 0, CI(SYMBOL), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CI(MAC), 0, 0,
116     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119     CI(JIS), CI(HANGUL), CI(JOHAB), 0, 0, 0, CI(GB2312), 0, CI(BIG5), 0, 0, 0, 0, 0, 0, 0,
120     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121     0, CI(GREEK), CI(TURKISH), CI(VIETNAMESE), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122     0, CI(HEBREW), CI(ARABIC), 0, 0, 0, 0, 0, 0, 0, CI(BALTIC), 0, 0, 0, 0, 0,
123     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CI(RUSSIAN), 0, 0, 0,
124     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CI(THAI), 0,
125     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CI(EE), 0,
126     CI(VISCII), CI(TCVN), CI(KOI8), CI(ISO3), CI(ISO4), CI(ISO10), CI(CELTIC), 0, 0, 0, 0, 0, 0, 0, 0, CI(OEM),
127 };
128 
129 static const struct {
130     DWORD       mask;
131     const char *name;
132 } cfflags[] = {
133 #define XX(x) { x, #x },
134     XX(CF_SCREENFONTS)
135     XX(CF_PRINTERFONTS)
136     XX(CF_SHOWHELP)
137     XX(CF_ENABLEHOOK)
138     XX(CF_ENABLETEMPLATE)
139     XX(CF_ENABLETEMPLATEHANDLE)
140     XX(CF_INITTOLOGFONTSTRUCT)
141     XX(CF_USESTYLE)
142     XX(CF_EFFECTS)
143     XX(CF_APPLY)
144     XX(CF_ANSIONLY)
145     XX(CF_NOVECTORFONTS)
146     XX(CF_NOSIMULATIONS)
147     XX(CF_LIMITSIZE)
148     XX(CF_FIXEDPITCHONLY)
149     XX(CF_WYSIWYG)
150     XX(CF_FORCEFONTEXIST)
151     XX(CF_SCALABLEONLY)
152     XX(CF_TTONLY)
153     XX(CF_NOFACESEL)
154     XX(CF_NOSTYLESEL)
155     XX(CF_NOSIZESEL)
156     XX(CF_SELECTSCRIPT)
157     XX(CF_NOSCRIPTSEL)
158     XX(CF_NOVERTFONTS)
159 #undef XX
160 };
161 
162 static void _dump_cf_flags(DWORD cflags)
163 {
164     unsigned int i;
165 
166     for (i = 0; i < ARRAY_SIZE(cfflags); i++)
167         if (cfflags[i].mask & cflags)
168             TRACE("%s|",cfflags[i].name);
169     TRACE("\n");
170 }
171 
172 /***********************************************************************
173  *           ChooseFontW   (COMDLG32.@)
174  *
175  * Create a font dialog box.
176  *
177  * PARAMS
178  *  lpChFont [I/O] in:  information to initialize the dialog box.
179  *                 out: User's color selection
180  *
181  * RETURNS
182  *  TRUE:  Ok button clicked.
183  *  FALSE: Cancel button clicked, or error.
184  */
185 BOOL WINAPI ChooseFontW(LPCHOOSEFONTW lpChFont)
186 {
187     LPCVOID template;
188     HRSRC hResInfo;
189     HINSTANCE hDlginst;
190     HGLOBAL hDlgTmpl;
191 
192     TRACE("(%p)\n", lpChFont);
193 
194     if ( (lpChFont->Flags&CF_ENABLETEMPLATEHANDLE)!=0 )
195     {
196         template=lpChFont->hInstance;
197     } else
198     {
199         if ( (lpChFont->Flags&CF_ENABLETEMPLATE)!=0 )
200         {
201             hDlginst=lpChFont->hInstance;
202             if( !(hResInfo = FindResourceW(hDlginst, lpChFont->lpTemplateName,
203                             (LPWSTR)RT_DIALOG)))
204             {
205                 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
206                 return FALSE;
207             }
208         } else
209         {
210             hDlginst=COMDLG32_hInstance;
211             if (!(hResInfo = FindResourceW(hDlginst, chooseFontW, (LPWSTR)RT_DIALOG)))
212             {
213                 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
214                 return FALSE;
215             }
216         }
217         if (!(hDlgTmpl = LoadResource(hDlginst, hResInfo )) ||
218                 !(template = LockResource( hDlgTmpl )))
219         {
220             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
221             return FALSE;
222         }
223     }
224     if (TRACE_ON(commdlg))
225         _dump_cf_flags(lpChFont->Flags);
226 
227     if (lpChFont->Flags & CF_SELECTSCRIPT)
228         FIXME(": unimplemented flag (ignored)\n");
229 
230     return DialogBoxIndirectParamW(COMDLG32_hInstance, template,
231             lpChFont->hwndOwner, FormatCharDlgProcW, (LPARAM)lpChFont );
232 }
233 
234 /***********************************************************************
235  *           ChooseFontA   (COMDLG32.@)
236  *
237  * See ChooseFontW.
238  */
239 BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont)
240 {
241     LPCVOID template;
242     HRSRC hResInfo;
243     HINSTANCE hDlginst;
244     HGLOBAL hDlgTmpl;
245 
246     TRACE("(%p)\n", lpChFont);
247 
248     if ( (lpChFont->Flags&CF_ENABLETEMPLATEHANDLE)!=0 )
249     {
250         template=lpChFont->hInstance;
251     } else
252     {
253         if ( (lpChFont->Flags&CF_ENABLETEMPLATE)!=0 )
254         {
255             hDlginst=lpChFont->hInstance;
256             if( !(hResInfo = FindResourceA(hDlginst, lpChFont->lpTemplateName,
257                             (LPSTR)RT_DIALOG)))
258             {
259                 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
260                 return FALSE;
261             }
262         } else
263         {
264             hDlginst=COMDLG32_hInstance;
265             if (!(hResInfo = FindResourceW(hDlginst, chooseFontW, (LPWSTR)RT_DIALOG)))
266             {
267                 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
268                 return FALSE;
269             }
270         }
271         if (!(hDlgTmpl = LoadResource(hDlginst, hResInfo )) ||
272                 !(template = LockResource( hDlgTmpl )))
273         {
274             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
275             return FALSE;
276         }
277     }
278     if (TRACE_ON(commdlg))
279         _dump_cf_flags(lpChFont->Flags);
280     if (lpChFont->Flags & CF_SELECTSCRIPT)
281         FIXME(": unimplemented flag (ignored)\n");
282 
283     return DialogBoxIndirectParamA(COMDLG32_hInstance, template,
284             lpChFont->hwndOwner, FormatCharDlgProcA, (LPARAM)lpChFont );
285 }
286 
287 #define TEXT_EXTRAS 4
288 #define TEXT_COLORS 16
289 
290 static const COLORREF textcolors[TEXT_COLORS]=
291 {
292     0x00000000L,0x00000080L,0x00008000L,0x00008080L,
293     0x00800000L,0x00800080L,0x00808000L,0x00808080L,
294     0x00c0c0c0L,0x000000ffL,0x0000ff00L,0x0000ffffL,
295     0x00ff0000L,0x00ff00ffL,0x00ffff00L,0x00FFFFFFL
296 };
297 
298 /***********************************************************************
299  *                          CFn_HookCallChk32                 [internal]
300  */
301 static BOOL CFn_HookCallChk32(const CHOOSEFONTW *lpcf)
302 {
303     if (lpcf)
304         if(lpcf->Flags & CF_ENABLEHOOK)
305             if (lpcf->lpfnHook)
306                 return TRUE;
307     return FALSE;
308 }
309 
310 /*************************************************************************
311  *              AddFontFamily                               [internal]
312  */
313 static INT AddFontFamily(const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *lpNTM,
314                          UINT nFontType, const CHOOSEFONTW *lpcf, HWND hwnd, LPCFn_ENUMSTRUCT e)
315 {
316     int i;
317     WORD w;
318     const LOGFONTW *lplf = &(lpElfex->elfLogFont);
319 
320     TRACE("font=%s (nFontType=%d)\n", debugstr_w(lplf->lfFaceName), nFontType);
321 
322     if (lpcf->Flags & CF_FIXEDPITCHONLY)
323         if (!(lplf->lfPitchAndFamily & FIXED_PITCH))
324             return 1;
325     if (lpcf->Flags & CF_ANSIONLY)
326         if (lplf->lfCharSet != ANSI_CHARSET)
327             return 1;
328     if (lpcf->Flags & CF_TTONLY)
329         if (!(nFontType & TRUETYPE_FONTTYPE))
330             return 1;
331     if (lpcf->Flags & CF_NOVERTFONTS)
332         if (lplf->lfFaceName[0] == '@')
333             return 1;
334 
335     if (e) e->added++;
336 
337     i=SendMessageW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)lplf->lfFaceName);
338     if (i == CB_ERR) {
339         i = SendMessageW(hwnd, CB_ADDSTRING, 0, (LPARAM)lplf->lfFaceName);
340         if( i != CB_ERR) {
341             /* store some important font information */
342             w = (lplf->lfPitchAndFamily) << 8 |
343                 (HIWORD(lpNTM->ntmTm.ntmFlags) & 0xff);
344             SendMessageW(hwnd, CB_SETITEMDATA, i, MAKELONG(nFontType,w));
345         }
346     }
347     return 1;
348 }
349 
350 /*************************************************************************
351  *              FontFamilyEnumProc32                           [internal]
352  */
353 static INT WINAPI FontFamilyEnumProc(const ENUMLOGFONTEXW *lpElfex,
354         const TEXTMETRICW *metrics, DWORD dwFontType, LPARAM lParam)
355 {
356     LPCFn_ENUMSTRUCT e;
357     e=(LPCFn_ENUMSTRUCT)lParam;
358     return AddFontFamily( lpElfex, (const NEWTEXTMETRICEXW *) metrics,
359             dwFontType, e->lpcf32w, e->hWnd1, e);
360 }
361 
362 /*************************************************************************
363  *              SetFontStylesToCombo2                           [internal]
364  *
365  * Fill font style information into combobox  (without using font.c directly)
366  */
367 static BOOL SetFontStylesToCombo2(HWND hwnd, HDC hdc, const LOGFONTW *lplf)
368 {
369 #define FSTYLES 4
370     struct FONTSTYLE
371     {
372         int italic;
373         int weight;
374         UINT resId;
375     };
376     static const struct FONTSTYLE fontstyles[FSTYLES]={
377         { 0, FW_NORMAL, IDS_FONT_REGULAR },
378         { 1, FW_NORMAL, IDS_FONT_ITALIC },
379         { 0, FW_BOLD,   IDS_FONT_BOLD },
380         { 1, FW_BOLD,   IDS_FONT_BOLD_ITALIC }
381     };
382     HFONT hf;
383     TEXTMETRICW tm;
384     int i,j;
385     LOGFONTW lf;
386 
387     lf = *lplf;
388 
389     for (i=0;i<FSTYLES;i++)
390     {
391         lf.lfItalic=fontstyles[i].italic;
392         lf.lfWeight=fontstyles[i].weight;
393         hf=CreateFontIndirectW(&lf);
394         hf=SelectObject(hdc,hf);
395         GetTextMetricsW(hdc,&tm);
396         hf=SelectObject(hdc,hf);
397         DeleteObject(hf);
398                 /* font successful created ? */
399         if (((fontstyles[i].weight == FW_NORMAL && tm.tmWeight <= FW_MEDIUM) ||
400              (fontstyles[i].weight == FW_BOLD && tm.tmWeight > FW_MEDIUM)) &&
401             ((tm.tmItalic != 0)==fontstyles[i].italic))
402         {
403             WCHAR name[64];
404             LoadStringW(COMDLG32_hInstance, fontstyles[i].resId, name, 64);
405             j=SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)name );
406             if (j==CB_ERR) return TRUE;
407             j=SendMessageW(hwnd, CB_SETITEMDATA, j,
408                            MAKELONG(tm.tmWeight,fontstyles[i].italic));
409             if (j==CB_ERR) return TRUE;
410         }
411     }
412     return FALSE;
413 }
414 
415 /*************************************************************************
416  *              AddFontSizeToCombo3                           [internal]
417  */
418 static BOOL AddFontSizeToCombo3(HWND hwnd, UINT h, const CHOOSEFONTW *lpcf)
419 {
420     int j;
421     WCHAR buffer[20];
422 
423     if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
424             ((lpcf->Flags & CF_LIMITSIZE) && (h >= lpcf->nSizeMin) && (h <= lpcf->nSizeMax)))
425     {
426         sprintfW(buffer, fontsizefmtW, h);
427         j=SendMessageW(hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)buffer);
428         if (j==CB_ERR)
429         {
430             j=SendMessageW(hwnd, CB_INSERTSTRING, -1, (LPARAM)buffer);
431             if (j!=CB_ERR) j = SendMessageW(hwnd, CB_SETITEMDATA, j, h);
432             if (j==CB_ERR) return TRUE;
433         }
434     }
435     return FALSE;
436 }
437 
438 /*************************************************************************
439  *              SetFontSizesToCombo3                           [internal]
440  */
441 static BOOL SetFontSizesToCombo3(HWND hwnd, const CHOOSEFONTW *lpcf)
442 {
443     static const BYTE sizes[]={6,7,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
444     unsigned int i;
445 
446     for (i = 0; i < ARRAY_SIZE(sizes); i++)
447         if (AddFontSizeToCombo3(hwnd, sizes[i], lpcf)) return TRUE;
448     return FALSE;
449 }
450 
451 /*************************************************************************
452  *              CFn_GetDC                           [internal]
453  */
454 static inline HDC CFn_GetDC(const CHOOSEFONTW *lpcf)
455 {
456     HDC ret = ((lpcf->Flags & CF_PRINTERFONTS) && lpcf->hDC) ?
457         lpcf->hDC :
458         GetDC(0);
459     if(!ret) ERR("HDC failure!!!\n");
460     return ret;
461 }
462 
463 /*************************************************************************
464  *              GetScreenDPI                           [internal]
465  */
466 static inline int GetScreenDPI(void)
467 {
468     HDC hdc;
469     int result;
470 
471     hdc = GetDC(0);
472     result = GetDeviceCaps(hdc, LOGPIXELSY);
473     ReleaseDC(0, hdc);
474 
475     return result;
476 }
477 
478 /*************************************************************************
479  *              CFn_ReleaseDC                           [internal]
480  */
481 static inline void CFn_ReleaseDC(const CHOOSEFONTW *lpcf, HDC hdc)
482 {
483         if(!((lpcf->Flags & CF_PRINTERFONTS) && lpcf->hDC))
484             ReleaseDC(0, hdc);
485 }
486 
487 /*************************************************************************
488  *              select_combo_item                           [internal]
489  */
490 static void select_combo_item( HWND dialog, int id, int sel )
491 {
492     HWND combo = GetDlgItem( dialog, id );
493     SendMessageW( combo, CB_SETCURSEL, sel, 0 );
494     SendMessageW( dialog, WM_COMMAND, MAKEWPARAM( id, CBN_SELCHANGE ), (LPARAM)combo );
495 }
496 
497 /***********************************************************************
498  *                 AddFontStyle                          [internal]
499  */
500 static INT AddFontStyle( const ENUMLOGFONTEXW *lpElfex, const NEWTEXTMETRICEXW *lpNTM,
501                          UINT nFontType, const CHOOSEFONTW *lpcf, HWND hcmb2, HWND hcmb3, HWND hDlg)
502 {
503     int i;
504     const LOGFONTW *lplf = &(lpElfex->elfLogFont);
505     HWND hcmb5;
506     HDC hdc;
507 
508     TRACE("(nFontType=%d)\n",nFontType);
509     TRACE("  %s h=%d w=%d e=%d o=%d wg=%d i=%d u=%d s=%d"
510             " ch=%d op=%d cp=%d q=%d pf=%xh\n",
511             debugstr_w(lplf->lfFaceName),lplf->lfHeight,lplf->lfWidth,
512             lplf->lfEscapement,lplf->lfOrientation,
513             lplf->lfWeight,lplf->lfItalic,lplf->lfUnderline,
514             lplf->lfStrikeOut,lplf->lfCharSet, lplf->lfOutPrecision,
515             lplf->lfClipPrecision,lplf->lfQuality, lplf->lfPitchAndFamily);
516     if (nFontType & RASTER_FONTTYPE)
517     {
518         INT points;
519         points = MulDiv( lpNTM->ntmTm.tmHeight - lpNTM->ntmTm.tmInternalLeading,
520                 72, GetScreenDPI());
521         if (AddFontSizeToCombo3(hcmb3, points, lpcf))
522             return 0;
523     } else if (SetFontSizesToCombo3(hcmb3, lpcf)) return 0;
524 
525     if (!SendMessageW(hcmb2, CB_GETCOUNT, 0, 0))
526     {
527         BOOL res;
528         if(!(hdc = CFn_GetDC(lpcf))) return 0;
529         res = SetFontStylesToCombo2(hcmb2,hdc,lplf);
530         CFn_ReleaseDC(lpcf, hdc);
531         if (res)
532             return 0;
533     }
534     if (!( hcmb5 = GetDlgItem(hDlg, cmb5))) return 1;
535     i = SendMessageW( hcmb5, CB_FINDSTRINGEXACT, 0,
536                 (LPARAM)lpElfex->elfScript);
537     if( i == CB_ERR) {
538         i = SendMessageW( hcmb5, CB_ADDSTRING, 0,
539                 (LPARAM)lpElfex->elfScript);
540         if( i != CB_ERR)
541             SendMessageW( hcmb5, CB_SETITEMDATA, i, lplf->lfCharSet);
542     }
543     return 1 ;
544 }
545 
546 static void CFn_FitFontSize( HWND hDlg, int points)
547 {
548     int i,n;
549 
550     /* look for fitting font size in combobox3 */
551     n=SendDlgItemMessageW(hDlg, cmb3, CB_GETCOUNT, 0, 0);
552     for (i=0;i<n;i++)
553     {
554         if (points == (int)SendDlgItemMessageW
555                 (hDlg,cmb3, CB_GETITEMDATA,i,0))
556         {
557             select_combo_item( hDlg, cmb3, i );
558             return;
559         }
560     }
561 
562     /* no default matching size, set text manually */
563     SetDlgItemInt(hDlg, cmb3, points, TRUE);
564 }
565 
566 static BOOL CFn_FitFontStyle( HWND hDlg, LONG packedstyle )
567 {
568     LONG id;
569     int i;
570     /* look for fitting font style in combobox2 */
571     for (i=0;i<TEXT_EXTRAS;i++)
572     {
573         id = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0);
574         if (packedstyle == id)
575         {
576             select_combo_item( hDlg, cmb2, i );
577             return TRUE;
578         }
579     }
580     return FALSE;
581 }
582 
583 
584 static BOOL CFn_FitCharSet( HWND hDlg, int charset )
585 {
586     int i,n,cs;
587     /* look for fitting char set in combobox5 */
588     n=SendDlgItemMessageW(hDlg, cmb5, CB_GETCOUNT, 0, 0);
589     for (i=0;i<n;i++)
590     {
591         cs =SendDlgItemMessageW(hDlg, cmb5, CB_GETITEMDATA, i, 0);
592         if (charset == cs)
593         {
594             select_combo_item( hDlg, cmb5, i );
595             return TRUE;
596         }
597     }
598     /* no charset fits: select the first one in the list */
599     select_combo_item( hDlg, cmb5, 0 );
600     return FALSE;
601 }
602 
603 /***********************************************************************
604  *                 FontStyleEnumProc32                     [internal]
605  */
606 static INT WINAPI FontStyleEnumProc( const ENUMLOGFONTEXW *lpElfex,
607         const TEXTMETRICW *metrics, DWORD dwFontType, LPARAM lParam )
608 {
609     LPCFn_ENUMSTRUCT s=(LPCFn_ENUMSTRUCT)lParam;
610     HWND hcmb2=s->hWnd1;
611     HWND hcmb3=s->hWnd2;
612     HWND hDlg=GetParent(hcmb3);
613     return AddFontStyle( lpElfex, (const NEWTEXTMETRICEXW *) metrics,
614                          dwFontType, s->lpcf32w, hcmb2, hcmb3, hDlg);
615 }
616 
617 /***********************************************************************
618  *           CFn_WMInitDialog                            [internal]
619  */
620 static LRESULT CFn_WMInitDialog(HWND hDlg, LPARAM lParam, LPCHOOSEFONTW lpcf)
621 {
622     HDC hdc;
623     int i,j;
624     BOOL init = FALSE;
625     long pstyle;
626     CFn_ENUMSTRUCT s;
627     LPLOGFONTW lpxx;
628     HCURSOR hcursor=SetCursor(LoadCursorW(0,(LPWSTR)IDC_WAIT));
629     static const WCHAR strColorName[] = {'[','c','o','l','o','r',' ','n','a','m','e',']',0};
630 
631     SetPropW(hDlg, strWineFontData, lpcf);
632     lpxx=lpcf->lpLogFont;
633     TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
634 
635     if (lpcf->lStructSize != sizeof(CHOOSEFONTW))
636     {
637         ERR("structure size failure!!!\n");
638         EndDialog (hDlg, 0);
639         return FALSE;
640     }
641     if (!himlTT)
642         himlTT = ImageList_LoadImageW( COMDLG32_hInstance, MAKEINTRESOURCEW(38),
643                 TTBITMAP_XSIZE, 0, CLR_DEFAULT, IMAGE_BITMAP, 0);
644 
645     /* Set effect flags */
646     if((lpcf->Flags & CF_EFFECTS) && (lpcf->Flags & CF_INITTOLOGFONTSTRUCT))
647     {
648         if(lpxx->lfUnderline)
649             CheckDlgButton(hDlg, chx2, TRUE);
650         if(lpxx->lfStrikeOut)
651             CheckDlgButton(hDlg, chx1, TRUE);
652     }
653 
654     if (!(lpcf->Flags & CF_SHOWHELP) || !IsWindow(lpcf->hwndOwner))
655         ShowWindow(GetDlgItem(hDlg,pshHelp),SW_HIDE);
656     if (!(lpcf->Flags & CF_APPLY))
657         ShowWindow(GetDlgItem(hDlg,psh3),SW_HIDE);
658     if (lpcf->Flags & CF_NOSCRIPTSEL)
659         EnableWindow(GetDlgItem(hDlg,cmb5),FALSE);
660     if (lpcf->Flags & CF_EFFECTS)
661     {
662         for (i=0;i<TEXT_COLORS;i++)
663         {
664             WCHAR name[30];
665 
666             if( LoadStringW(COMDLG32_hInstance, IDS_COLOR_BLACK+i, name,
667                         ARRAY_SIZE(name)) == 0 )
668             {
669                 memcpy(name, strColorName, sizeof(strColorName));
670             }
671             j=SendDlgItemMessageW(hDlg, cmb4, CB_ADDSTRING, 0, (LPARAM)name);
672             SendDlgItemMessageW(hDlg, cmb4, CB_SETITEMDATA, j, textcolors[i]);
673             /* look for a fitting value in color combobox */
674             if (textcolors[i]==lpcf->rgbColors)
675                 SendDlgItemMessageW(hDlg,cmb4, CB_SETCURSEL,j,0);
676         }
677     }
678     else
679     {
680         ShowWindow(GetDlgItem(hDlg,cmb4),SW_HIDE);
681         ShowWindow(GetDlgItem(hDlg,chx1),SW_HIDE);
682         ShowWindow(GetDlgItem(hDlg,chx2),SW_HIDE);
683         ShowWindow(GetDlgItem(hDlg,grp1),SW_HIDE);
684         ShowWindow(GetDlgItem(hDlg,stc4),SW_HIDE);
685     }
686     if(!(hdc = CFn_GetDC(lpcf)))
687     {
688         EndDialog (hDlg, 0);
689         return FALSE;
690     }
691     s.hWnd1=GetDlgItem(hDlg,cmb1);
692     s.lpcf32w=lpcf;
693     do {
694         LOGFONTW elf;
695         s.added = 0;
696         elf.lfCharSet = DEFAULT_CHARSET; /* enum all charsets */
697         elf.lfPitchAndFamily = 0;
698         elf.lfFaceName[0] = '\0'; /* enum all fonts */
699         if (!EnumFontFamiliesExW(hdc, &elf, (FONTENUMPROCW)FontFamilyEnumProc, (LPARAM)&s, 0))
700         {
701             TRACE("EnumFontFamiliesEx returns 0\n");
702             break;
703         }
704         if (s.added) break;
705         if (lpcf->Flags & CF_FIXEDPITCHONLY) {
706             FIXME("No font found with fixed pitch only, dropping flag.\n");
707             lpcf->Flags &= ~CF_FIXEDPITCHONLY;
708             continue;
709         }
710         if (lpcf->Flags & CF_TTONLY) {
711             FIXME("No font found with truetype only, dropping flag.\n");
712             lpcf->Flags &= ~CF_TTONLY;
713             continue;
714         }
715         break;
716     } while (1);
717 
718 
719     if (lpcf->Flags & CF_INITTOLOGFONTSTRUCT)
720     {
721         /* look for fitting font name in combobox1 */
722         j=SendDlgItemMessageW(hDlg,cmb1,CB_FINDSTRING,-1,(LPARAM)lpxx->lfFaceName);
723         if (j!=CB_ERR)
724         {
725             INT height = lpxx->lfHeight < 0 ? -lpxx->lfHeight :
726                 lpxx->lfHeight;
727             INT points;
728             int charset = lpxx->lfCharSet;
729             points = MulDiv( height, 72, GetScreenDPI());
730             pstyle = MAKELONG(lpxx->lfWeight > FW_MEDIUM ? FW_BOLD:
731                     FW_NORMAL,lpxx->lfItalic !=0);
732             select_combo_item( hDlg, cmb1, j );
733             init = TRUE;
734             /* look for fitting font style in combobox2 */
735             CFn_FitFontStyle(hDlg, pstyle);
736             /* look for fitting font size in combobox3 */
737             CFn_FitFontSize(hDlg, points);
738             CFn_FitCharSet( hDlg, charset );
739         }
740     }
741     if (!init)
742     {
743         select_combo_item( hDlg, cmb1, 0 );
744         select_combo_item( hDlg, cmb2, 0 );
745         select_combo_item( hDlg, cmb3, 0 );
746         select_combo_item( hDlg, cmb5, 0 );
747     }
748     /* limit text length user can type in as font size */
749     SendDlgItemMessageW(hDlg, cmb3, CB_LIMITTEXT, 5, 0);
750 
751     if ((lpcf->Flags & CF_USESTYLE) && lpcf->lpszStyle)
752     {
753         j=SendDlgItemMessageW(hDlg,cmb2,CB_FINDSTRING,-1,(LPARAM)lpcf->lpszStyle);
754         if (j!=CB_ERR) select_combo_item( hDlg, cmb2, j );
755     }
756     CFn_ReleaseDC(lpcf, hdc);
757     SetCursor(hcursor);
758     return TRUE;
759 }
760 
761 
762 /***********************************************************************
763  *           CFn_WMMeasureItem                           [internal]
764  */
765 static LRESULT CFn_WMMeasureItem(HWND hDlg, LPARAM lParam)
766 {
767     HDC hdc;
768     HFONT hfontprev;
769     TEXTMETRICW tm;
770     LPMEASUREITEMSTRUCT lpmi=(LPMEASUREITEMSTRUCT)lParam;
771     INT height = 0, cx;
772 
773     if (!himlTT)
774         himlTT = ImageList_LoadImageW( COMDLG32_hInstance, MAKEINTRESOURCEW(38),
775                 TTBITMAP_XSIZE, 0, CLR_DEFAULT, IMAGE_BITMAP, 0);
776     ImageList_GetIconSize( himlTT, &cx, &height);
777     lpmi->itemHeight = height + 2;
778     /* use MAX of bitmap height and tm.tmHeight .*/
779     hdc=GetDC(hDlg);
780     if(!hdc) return 0;
781     hfontprev = SelectObject( hdc, (HFONT)SendMessageW( hDlg, WM_GETFONT, 0, 0 ));
782     GetTextMetricsW(hdc, &tm);
783     if( tm.tmHeight > lpmi->itemHeight) lpmi->itemHeight = tm.tmHeight;
784     SelectObject(hdc, hfontprev);
785     ReleaseDC(hDlg, hdc);
786     return 0;
787 }
788 
789 
790 /***********************************************************************
791  *           CFn_WMDrawItem                              [internal]
792  */
793 static LRESULT CFn_WMDrawItem(LPARAM lParam)
794 {
795     HBRUSH hBrush;
796     WCHAR buffer[40];
797     COLORREF cr, oldText=0, oldBk=0;
798     RECT rect;
799     int nFontType;
800     int cx, cy, idx;
801     LPDRAWITEMSTRUCT lpdi = (LPDRAWITEMSTRUCT)lParam;
802 
803     if (lpdi->itemID == (UINT)-1)  /* got no items */
804         DrawFocusRect(lpdi->hDC, &lpdi->rcItem);
805     else
806     {
807         if (lpdi->CtlType == ODT_COMBOBOX)
808         {
809             if (lpdi->itemState & ODS_SELECTED)
810             {
811                 hBrush=GetSysColorBrush(COLOR_HIGHLIGHT);
812                 oldText=SetTextColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
813                 oldBk=SetBkColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHT));
814             }  else
815             {
816                 hBrush = SelectObject(lpdi->hDC, GetStockObject(LTGRAY_BRUSH));
817                 SelectObject(lpdi->hDC, hBrush);
818             }
819             FillRect(lpdi->hDC, &lpdi->rcItem, hBrush);
820         }
821         else
822             return TRUE;        /* this should never happen */
823 
824         rect=lpdi->rcItem;
825         switch (lpdi->CtlID)
826         {
827         case cmb1:
828             /* TRACE(commdlg,"WM_Drawitem cmb1\n"); */
829             ImageList_GetIconSize( himlTT, &cx, &cy);
830             SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
831                          (LPARAM)buffer);
832             TextOutW(lpdi->hDC, lpdi->rcItem.left + cx + 4,
833                      lpdi->rcItem.top, buffer, lstrlenW(buffer));
834             nFontType = SendMessageW(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
835             idx = -1;
836             if (nFontType & TRUETYPE_FONTTYPE) {
837                 idx = 0;  /* picture: TT */
838                 if( nFontType & NTM_TT_OPENTYPE)
839                     idx = 2; /* picture: O */
840             } else if( nFontType & NTM_PS_OPENTYPE)
841                 idx = 3; /* picture: O+ps */
842             else if( nFontType & NTM_TYPE1)
843                 idx = 4; /* picture: a */
844             else if( nFontType & DEVICE_FONTTYPE)
845                 idx = 1; /* picture: printer */
846             if( idx >= 0)
847                 ImageList_Draw( himlTT, idx, lpdi->hDC, lpdi->rcItem.left,
848                                 (lpdi->rcItem.top + lpdi->rcItem.bottom - cy) / 2, ILD_TRANSPARENT);
849             break;
850         case cmb2:
851         case cmb3:
852             /* TRACE(commdlg,"WM_DRAWITEN cmb2,cmb3\n"); */
853         case cmb5:
854             SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
855                          (LPARAM)buffer);
856             TextOutW(lpdi->hDC, lpdi->rcItem.left,
857                      lpdi->rcItem.top, buffer, lstrlenW(buffer));
858             break;
859 
860         case cmb4:
861             /* TRACE(commdlg,"WM_DRAWITEM cmb4 (=COLOR)\n"); */
862             SendMessageW(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
863                      (LPARAM)buffer);
864             TextOutW(lpdi->hDC, lpdi->rcItem.left +  25+5,
865                      lpdi->rcItem.top, buffer, lstrlenW(buffer));
866             cr = SendMessageW(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
867             hBrush = CreateSolidBrush(cr);
868             if (hBrush)
869             {
870                 hBrush = SelectObject (lpdi->hDC, hBrush) ;
871                 rect.right=rect.left+25;
872                 rect.top++;
873                 rect.left+=5;
874                 rect.bottom--;
875                 Rectangle( lpdi->hDC, rect.left, rect.top,
876                            rect.right, rect.bottom );
877                 DeleteObject( SelectObject (lpdi->hDC, hBrush)) ;
878             }
879             rect=lpdi->rcItem;
880             rect.left+=25+5;
881             break;
882 
883         default:
884             return TRUE;  /* this should never happen */
885         }
886         if (lpdi->itemState & ODS_SELECTED)
887         {
888             SetTextColor(lpdi->hDC, oldText);
889             SetBkColor(lpdi->hDC, oldBk);
890         }
891     }
892     return TRUE;
893 }
894 
895 static INT get_dialog_font_point_size(HWND hDlg, CHOOSEFONTW *cf)
896 {
897     BOOL invalid_size = FALSE;
898     INT i, size;
899 
900     i = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
901     if (i != CB_ERR)
902         size = LOWORD(SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA , i, 0));
903     else
904     {
905         WCHAR buffW[8], *endptrW;
906 
907         GetDlgItemTextW(hDlg, cmb3, buffW, ARRAY_SIZE(buffW));
908         size = strtolW(buffW, &endptrW, 10);
909         invalid_size = size == 0 && *endptrW;
910 
911         if (size == 0)
912             size = 10;
913     }
914 
915     cf->iPointSize = 10 * size;
916     cf->lpLogFont->lfHeight = -MulDiv(cf->iPointSize, GetScreenDPI(), 720);
917     return invalid_size ? -1 : size;
918 }
919 
920 /***********************************************************************
921  *           CFn_WMCommand                               [internal]
922  */
923 static LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam, LPCHOOSEFONTW lpcf)
924 {
925     int i;
926     long l;
927     HDC hdc;
928     BOOL cmb_selected_by_edit = FALSE;
929 
930     if (!lpcf) return FALSE;
931 
932     if(HIWORD(wParam) == CBN_EDITCHANGE)
933     {
934         int idx;
935         WCHAR str_edit[256], str_cmb[256];
936         int cmb = LOWORD(wParam);
937 
938         GetDlgItemTextW(hDlg, cmb, str_edit, ARRAY_SIZE(str_edit));
939         idx = SendDlgItemMessageW(hDlg, cmb, CB_FINDSTRING, -1, (LPARAM)str_edit);
940         if(idx != -1)
941         {
942             SendDlgItemMessageW(hDlg, cmb, CB_GETLBTEXT, idx, (LPARAM)str_cmb);
943 
944             /* Select listbox entry only if we have an exact match */
945             if(lstrcmpiW(str_edit, str_cmb) == 0)
946             {
947                  SendDlgItemMessageW(hDlg, cmb, CB_SETCURSEL, idx, 0);
948                  SendDlgItemMessageW(hDlg, cmb, CB_SETEDITSEL, 0, -1); /* Remove edit field selection */
949                  cmb_selected_by_edit = TRUE;
950             }
951         }
952     }
953 
954     TRACE("WM_COMMAND wParam=%08X lParam=%08lX\n", (LONG)wParam, lParam);
955     switch (LOWORD(wParam))
956     {
957     case cmb1:
958         if (HIWORD(wParam) == CBN_SELCHANGE || cmb_selected_by_edit)
959         {
960             INT pointsize; /* save current pointsize */
961             LONG pstyle;  /* save current style */
962             int charset;
963             int idx;
964             if(!(hdc = CFn_GetDC(lpcf)))
965             {
966                 EndDialog (hDlg, 0);
967                 return TRUE;
968             }
969             idx = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
970             pointsize = (int)SendDlgItemMessageW( hDlg, cmb3, CB_GETITEMDATA,
971                     idx, 0);
972             idx = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
973             pstyle = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, idx, 0);
974             idx = SendDlgItemMessageW(hDlg, cmb5, CB_GETCURSEL, 0, 0);
975             charset = SendDlgItemMessageW(hDlg, cmb5, CB_GETITEMDATA, idx, 0);
976 
977             SendDlgItemMessageW(hDlg, cmb2, CB_RESETCONTENT, 0, 0);
978             SendDlgItemMessageW(hDlg, cmb3, CB_RESETCONTENT, 0, 0);
979             SendDlgItemMessageW(hDlg, cmb5, CB_RESETCONTENT, 0, 0);
980             i=SendDlgItemMessageW(hDlg, cmb1, CB_GETCURSEL, 0, 0);
981             if (i!=CB_ERR)
982             {
983                 HCURSOR hcursor=SetCursor(LoadCursorW(0,(LPWSTR)IDC_WAIT));
984                 CFn_ENUMSTRUCT s;
985                 LOGFONTW enumlf;
986                 SendDlgItemMessageW(hDlg, cmb1, CB_GETLBTEXT, i,
987                                     (LPARAM)enumlf.lfFaceName);
988                 TRACE("WM_COMMAND/cmb1 =>%s\n", debugstr_w(enumlf.lfFaceName));
989                 s.hWnd1=GetDlgItem(hDlg, cmb2);
990                 s.hWnd2=GetDlgItem(hDlg, cmb3);
991                 s.lpcf32w=lpcf;
992                 enumlf.lfCharSet = DEFAULT_CHARSET; /* enum all charsets */
993                 enumlf.lfPitchAndFamily = 0;
994                 EnumFontFamiliesExW(hdc, &enumlf,
995                         (FONTENUMPROCW)FontStyleEnumProc, (LPARAM)&s, 0);
996                 CFn_FitFontStyle(hDlg, pstyle);
997                 if( pointsize != CB_ERR) CFn_FitFontSize(hDlg, pointsize);
998                 if( charset != CB_ERR) CFn_FitCharSet( hDlg, charset );
999                 SetCursor(hcursor);
1000             }
1001             CFn_ReleaseDC(lpcf, hdc);
1002         }
1003         break;
1004     case chx1:
1005     case chx2:
1006     case cmb2:
1007     case cmb3:
1008     case cmb5:
1009         if (HIWORD(wParam) == CBN_SELCHANGE || HIWORD(wParam) == BN_CLICKED || cmb_selected_by_edit)
1010         {
1011             WCHAR str[256];
1012             WINDOWINFO wininfo;
1013             LPLOGFONTW lpxx=lpcf->lpLogFont;
1014 
1015             TRACE("WM_COMMAND/cmb2,3 =%08lX\n", lParam);
1016 
1017             /* face name */
1018             i=SendDlgItemMessageW(hDlg,cmb1,CB_GETCURSEL,0,0);
1019             if (i==CB_ERR)
1020                 GetDlgItemTextW( hDlg, cmb1, str, ARRAY_SIZE(str));
1021             else
1022             {
1023                 SendDlgItemMessageW(hDlg,cmb1,CB_GETLBTEXT,i,
1024                                     (LPARAM)str);
1025                 l=SendDlgItemMessageW(hDlg,cmb1,CB_GETITEMDATA,i,0);
1026                 lpcf->nFontType = LOWORD(l);
1027                 /* FIXME:   lpcf->nFontType |= ....  SIMULATED_FONTTYPE and so */
1028                 /* same value reported to the EnumFonts
1029                    call back with the extra FONTTYPE_...  bits added */
1030                 lpxx->lfPitchAndFamily = HIWORD(l) >> 8;
1031             }
1032             lstrcpynW(lpxx->lfFaceName, str, ARRAY_SIZE(lpxx->lfFaceName));
1033 
1034             /* style */
1035             i=SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1036             if (i!=CB_ERR)
1037             {
1038                 l=SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0);
1039                 if (0!=(lpxx->lfItalic=HIWORD(l)))
1040                     lpcf->nFontType |= ITALIC_FONTTYPE;
1041                 if ((lpxx->lfWeight=LOWORD(l)) > FW_MEDIUM)
1042                     lpcf->nFontType |= BOLD_FONTTYPE;
1043             }
1044 
1045             /* size */
1046             get_dialog_font_point_size(hDlg, lpcf);
1047 
1048             /* charset */
1049             i=SendDlgItemMessageW(hDlg, cmb5, CB_GETCURSEL, 0, 0);
1050             if (i!=CB_ERR)
1051                 lpxx->lfCharSet=SendDlgItemMessageW(hDlg, cmb5, CB_GETITEMDATA, i, 0);
1052             else
1053                 lpxx->lfCharSet = DEFAULT_CHARSET;
1054             lpxx->lfStrikeOut=IsDlgButtonChecked(hDlg,chx1);
1055             lpxx->lfUnderline=IsDlgButtonChecked(hDlg,chx2);
1056             lpxx->lfWidth=lpxx->lfOrientation=lpxx->lfEscapement=0;
1057             lpxx->lfOutPrecision=OUT_DEFAULT_PRECIS;
1058             lpxx->lfClipPrecision=CLIP_DEFAULT_PRECIS;
1059             lpxx->lfQuality=DEFAULT_QUALITY;
1060 
1061             wininfo.cbSize=sizeof(wininfo);
1062 
1063             if( GetWindowInfo( GetDlgItem( hDlg, stc5), &wininfo ) )
1064             {
1065                 MapWindowPoints( 0, hDlg, (LPPOINT) &wininfo.rcWindow, 2);
1066                 InvalidateRect( hDlg, &wininfo.rcWindow, TRUE );
1067             }
1068         }
1069         break;
1070 
1071     case cmb4:
1072         i=SendDlgItemMessageW(hDlg, cmb4, CB_GETCURSEL, 0, 0);
1073         if (i!=CB_ERR)
1074         {
1075             WINDOWINFO wininfo;
1076 
1077             lpcf->rgbColors = SendDlgItemMessageW(hDlg, cmb4, CB_GETITEMDATA, i, 0);
1078             wininfo.cbSize=sizeof(wininfo);
1079 
1080             if( GetWindowInfo( GetDlgItem( hDlg, stc5), &wininfo ) )
1081             {
1082                 MapWindowPoints( 0, hDlg, (LPPOINT) &wininfo.rcWindow, 2);
1083                 InvalidateRect( hDlg, &wininfo.rcWindow, TRUE );
1084             }
1085         }
1086         break;
1087 
1088     case psh15:
1089         i=RegisterWindowMessageW( HELPMSGSTRINGW );
1090         if (lpcf->hwndOwner)
1091             SendMessageW(lpcf->hwndOwner, i, 0, (LPARAM)GetPropW(hDlg, strWineFontData));
1092         break;
1093 
1094     case IDOK:
1095     {
1096         WCHAR msgW[80];
1097         INT pointsize;
1098 
1099         pointsize = get_dialog_font_point_size(hDlg, lpcf);
1100         if (pointsize == -1)
1101         {
1102             LoadStringW(COMDLG32_hInstance, IDS_FONT_SIZE_INPUT, msgW, ARRAY_SIZE(msgW));
1103             MessageBoxW(hDlg, msgW, NULL, MB_OK | MB_ICONINFORMATION);
1104             return TRUE;
1105         }
1106 
1107         if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
1108               ( (lpcf->Flags & CF_LIMITSIZE) &&
1109                 (lpcf->iPointSize >= 10 * lpcf->nSizeMin) &&
1110                 (lpcf->iPointSize <= 10 * lpcf->nSizeMax)))
1111             EndDialog(hDlg, TRUE);
1112         else
1113         {
1114             WCHAR format[80];
1115             DWORD_PTR args[2];
1116             LoadStringW(COMDLG32_hInstance, IDS_FONT_SIZE, format, ARRAY_SIZE(format));
1117             args[0] = lpcf->nSizeMin;
1118             args[1] = lpcf->nSizeMax;
1119             FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
1120                            format, 0, 0, msgW, ARRAY_SIZE(msgW),
1121                            (__ms_va_list*)args);
1122             MessageBoxW(hDlg, msgW, NULL, MB_OK);
1123         }
1124         return(TRUE);
1125     }
1126     case IDCANCEL:
1127         EndDialog(hDlg, FALSE);
1128         return(TRUE);
1129     }
1130     return(FALSE);
1131 }
1132 
1133 static LRESULT CFn_WMDestroy(HWND hwnd, LPCHOOSEFONTW lpcfw)
1134 {
1135     LPCHOOSEFONTA lpcfa;
1136     LPSTR lpszStyle;
1137     LPLOGFONTA lpLogFonta;
1138     int len;
1139 
1140     if (!lpcfw) return FALSE;
1141 
1142     lpcfa = GetPropW(hwnd, strWineFontData_a);
1143     lpLogFonta = lpcfa->lpLogFont;
1144     lpszStyle = lpcfa->lpszStyle;
1145     memcpy(lpcfa, lpcfw, sizeof(CHOOSEFONTA));
1146     lpcfa->lpLogFont = lpLogFonta;
1147     lpcfa->lpszStyle = lpszStyle;
1148     memcpy(lpcfa->lpLogFont, lpcfw->lpLogFont, sizeof(LOGFONTA));
1149     WideCharToMultiByte(CP_ACP, 0, lpcfw->lpLogFont->lfFaceName,
1150                         LF_FACESIZE, lpcfa->lpLogFont->lfFaceName, LF_FACESIZE, 0, 0);
1151 
1152     if((lpcfw->Flags & CF_USESTYLE) && lpcfw->lpszStyle) {
1153         len = WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, NULL, 0, 0, 0);
1154         WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, lpcfa->lpszStyle, len, 0, 0);
1155         heap_free(lpcfw->lpszStyle);
1156     }
1157 
1158     heap_free(lpcfw->lpLogFont);
1159     heap_free(lpcfw);
1160     SetPropW(hwnd, strWineFontData, 0);
1161 
1162     return TRUE;
1163 }
1164 
1165 static LRESULT CFn_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam, const CHOOSEFONTW *lpcf)
1166 {
1167     WINDOWINFO info;
1168 
1169     if (!lpcf) return FALSE;
1170 
1171     info.cbSize=sizeof(info);
1172     if( GetWindowInfo( GetDlgItem( hDlg, stc5), &info ) )
1173     {
1174         PAINTSTRUCT ps;
1175         HDC hdc;
1176         HFONT hOrigFont;
1177         LOGFONTW lf = *(lpcf->lpLogFont);
1178 
1179         MapWindowPoints( 0, hDlg, (LPPOINT) &info.rcWindow, 2);
1180         hdc = BeginPaint( hDlg, &ps );
1181 
1182         TRACE("erase %d, rect=%s\n", ps.fErase, wine_dbgstr_rect(&ps.rcPaint));
1183 
1184         /* Paint frame */
1185         DrawEdge( hdc, &info.rcWindow, EDGE_SUNKEN, BF_RECT|BF_ADJUST );
1186 
1187         /* Draw the sample text itself */
1188         hOrigFont = SelectObject( hdc, CreateFontIndirectW( &lf ) );
1189         SetTextColor( hdc, lpcf->rgbColors );
1190 
1191         DrawTextW( hdc,
1192                 sample_lang_text[CHARSET_ORDER[lpcf->lpLogFont->lfCharSet]],
1193                 -1, &info.rcWindow, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
1194 
1195         DeleteObject(SelectObject( hdc, hOrigFont ));
1196         EndPaint( hDlg, &ps );
1197     }
1198     return FALSE;
1199 }
1200 
1201 /***********************************************************************
1202  *           FormatCharDlgProcA   [internal]
1203  */
1204 static INT_PTR CALLBACK FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1205 {
1206     LPCHOOSEFONTW lpcfw;
1207     LPCHOOSEFONTA lpcfa;
1208     INT_PTR res = FALSE;
1209     int len;
1210 
1211     if (uMsg!=WM_INITDIALOG) {
1212         lpcfw = GetPropW(hDlg, strWineFontData);
1213         if (lpcfw && CFn_HookCallChk32(lpcfw))
1214             res=CallWindowProcA((WNDPROC)lpcfw->lpfnHook, hDlg, uMsg, wParam, lParam);
1215         if (res)
1216             return res;
1217     } else {
1218         lpcfa=(LPCHOOSEFONTA)lParam;
1219         SetPropW(hDlg, strWineFontData_a, (HANDLE)lParam);
1220 
1221         lpcfw = heap_alloc(sizeof(*lpcfw));
1222         memcpy(lpcfw, lpcfa, sizeof(CHOOSEFONTA));
1223         lpcfw->lpLogFont = heap_alloc(sizeof(*lpcfw->lpLogFont));
1224         memcpy(lpcfw->lpLogFont, lpcfa->lpLogFont, sizeof(LOGFONTA));
1225         MultiByteToWideChar(CP_ACP, 0, lpcfa->lpLogFont->lfFaceName,
1226                             LF_FACESIZE, lpcfw->lpLogFont->lfFaceName, LF_FACESIZE);
1227 
1228         if((lpcfa->Flags & CF_USESTYLE) && lpcfa->lpszStyle)  {
1229             len = MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, NULL, 0);
1230             lpcfw->lpszStyle = heap_alloc(len * sizeof(WCHAR));
1231             MultiByteToWideChar(CP_ACP, 0, lpcfa->lpszStyle, -1, lpcfw->lpszStyle, len);
1232         }
1233 
1234         if (!CFn_WMInitDialog(hDlg, lParam, lpcfw))
1235         {
1236             TRACE("CFn_WMInitDialog returned FALSE\n");
1237             return FALSE;
1238         }
1239         if (CFn_HookCallChk32(lpcfw))
1240             return CallWindowProcA((WNDPROC)lpcfa->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
1241     }
1242     switch (uMsg)
1243     {
1244     case WM_MEASUREITEM:
1245         return CFn_WMMeasureItem(hDlg,lParam);
1246     case WM_DRAWITEM:
1247         return CFn_WMDrawItem(lParam);
1248     case WM_COMMAND:
1249         return CFn_WMCommand(hDlg, wParam, lParam, lpcfw);
1250     case WM_DESTROY:
1251         return CFn_WMDestroy(hDlg, lpcfw);
1252     case WM_CHOOSEFONT_GETLOGFONT:
1253     {
1254         LOGFONTA *logfont = (LOGFONTA *)lParam;
1255         TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam);
1256         memcpy( logfont, lpcfw->lpLogFont, FIELD_OFFSET( LOGFONTA, lfFaceName ));
1257         WideCharToMultiByte( CP_ACP, 0, lpcfw->lpLogFont->lfFaceName, LF_FACESIZE,
1258                              logfont->lfFaceName, LF_FACESIZE, NULL, NULL );
1259         break;
1260     }
1261     case WM_PAINT:
1262         return CFn_WMPaint(hDlg, wParam, lParam, lpcfw);
1263     }
1264     return res;
1265 }
1266 
1267 /***********************************************************************
1268  *           FormatCharDlgProcW   [internal]
1269  */
1270 static INT_PTR CALLBACK FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1271 {
1272     LPCHOOSEFONTW lpcf;
1273     INT_PTR res = FALSE;
1274 
1275     if (uMsg!=WM_INITDIALOG)
1276     {
1277         lpcf= GetPropW(hDlg, strWineFontData);
1278         if (lpcf && CFn_HookCallChk32(lpcf))
1279             res=CallWindowProcW((WNDPROC)lpcf->lpfnHook, hDlg, uMsg, wParam, lParam);
1280         if (res)
1281             return res;
1282     }
1283     else
1284     {
1285         lpcf=(LPCHOOSEFONTW)lParam;
1286         if (!CFn_WMInitDialog(hDlg, lParam, lpcf))
1287         {
1288             TRACE("CFn_WMInitDialog returned FALSE\n");
1289             return FALSE;
1290         }
1291         if (CFn_HookCallChk32(lpcf))
1292             return CallWindowProcW((WNDPROC)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
1293     }
1294     switch (uMsg)
1295     {
1296     case WM_MEASUREITEM:
1297         return CFn_WMMeasureItem(hDlg, lParam);
1298     case WM_DRAWITEM:
1299         return CFn_WMDrawItem(lParam);
1300     case WM_COMMAND:
1301         return CFn_WMCommand(hDlg, wParam, lParam, lpcf);
1302     case WM_DESTROY:
1303         return TRUE;
1304     case WM_CHOOSEFONT_GETLOGFONT:
1305         TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n", lParam);
1306         memcpy( (LOGFONTW *)lParam, lpcf->lpLogFont, sizeof(LOGFONTW) );
1307         break;
1308     case WM_PAINT:
1309         return CFn_WMPaint(hDlg, wParam, lParam, lpcf);
1310     }
1311     return res;
1312 }
1313