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