Removed a few dependencies on kernel32 functions.
[wine] / dlls / commdlg / fontdlg.c
1 /*
2  * COMMDLG - Font Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  */
7
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "windef.h"
13 #include "winbase.h"
14 #include "wingdi.h"
15 #include "wine/winbase16.h"
16 #include "wine/winuser16.h"
17 #include "wine/winestring.h"
18 #include "ldt.h"
19 #include "heap.h"
20 #include "commdlg.h"
21 #include "dialog.h"
22 #include "dlgs.h"
23 #include "module.h"
24 #include "debugtools.h"
25 #include "font.h"
26 #include "winproc.h"
27 #include "cderr.h"
28
29 DEFAULT_DEBUG_CHANNEL(commdlg);
30
31 #include "cdlg.h"
32
33 static HBITMAP16 hBitmapTT = 0; 
34
35
36 LRESULT WINAPI FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
37                                   LPARAM lParam);
38 LRESULT WINAPI FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
39                                   LPARAM lParam);
40 LRESULT WINAPI FormatCharDlgProc16(HWND16 hDlg, UINT16 message, WPARAM16 wParam,
41                                    LPARAM lParam);
42
43 static void CFn_CHOOSEFONT16to32A(LPCHOOSEFONT16 chf16, LPCHOOSEFONTA chf32a)
44 {
45   chf32a->lStructSize=sizeof(CHOOSEFONTA);
46   chf32a->hwndOwner=chf16->hwndOwner;
47   chf32a->hDC=chf16->hDC;
48   chf32a->iPointSize=chf16->iPointSize;
49   chf32a->Flags=chf16->Flags;
50   chf32a->rgbColors=chf16->rgbColors;
51   chf32a->lCustData=chf16->lCustData;
52   chf32a->lpfnHook=NULL;
53   chf32a->lpTemplateName=PTR_SEG_TO_LIN(chf16->lpTemplateName);
54   chf32a->hInstance=chf16->hInstance;
55   chf32a->lpszStyle=PTR_SEG_TO_LIN(chf16->lpszStyle);
56   chf32a->nFontType=chf16->nFontType;
57   chf32a->nSizeMax=chf16->nSizeMax;
58   chf32a->nSizeMin=chf16->nSizeMin;
59   FONT_LogFont16To32A(PTR_SEG_TO_LIN(chf16->lpLogFont), chf32a->lpLogFont);
60 }
61
62
63 /***********************************************************************
64  *                        ChooseFont16   (COMMDLG.15)     
65  */
66 BOOL16 WINAPI ChooseFont16(LPCHOOSEFONT16 lpChFont)
67 {
68     HINSTANCE16 hInst;
69     HANDLE16 hDlgTmpl16 = 0, hResource16 = 0;
70     HGLOBAL16 hGlobal16 = 0;
71     BOOL16 bRet = FALSE;
72     LPCVOID template;
73     FARPROC16 ptr;
74     CHOOSEFONTA cf32a;
75     LOGFONTA lf32a;
76     SEGPTR lpTemplateName;
77     
78     cf32a.lpLogFont=&lf32a;
79     CFn_CHOOSEFONT16to32A(lpChFont, &cf32a);
80
81     TRACE("ChooseFont\n");
82     if (!lpChFont) return FALSE;    
83
84     if (lpChFont->Flags & CF_ENABLETEMPLATEHANDLE)
85     {
86         if (!(template = LockResource16( lpChFont->hInstance )))
87         {
88             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
89             return FALSE;
90         }
91     }
92     else if (lpChFont->Flags & CF_ENABLETEMPLATE)
93     {
94         HANDLE16 hResInfo;
95         if (!(hResInfo = FindResource16( lpChFont->hInstance,
96                                          lpChFont->lpTemplateName,
97                                          RT_DIALOG16)))
98         {
99             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
100             return FALSE;
101         }
102         if (!(hDlgTmpl16 = LoadResource16( lpChFont->hInstance, hResInfo )) ||
103             !(template = LockResource16( hDlgTmpl16 )))
104         {
105             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
106             return FALSE;
107         }
108     }
109     else
110     {
111         HANDLE hResInfo, hDlgTmpl32;
112         LPCVOID template32;
113         DWORD size;
114         if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "CHOOSE_FONT", RT_DIALOGA)))
115         {
116             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
117             return FALSE;
118         }
119         if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo)) ||
120             !(template32 = LockResource(hDlgTmpl32)))
121         {
122             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
123             return FALSE;
124         }
125         size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
126         hGlobal16 = GlobalAlloc16(0, size);
127         if (!hGlobal16)
128         {
129             COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
130             ERR("alloc failure for %ld bytes\n", size);
131             return FALSE;
132         }
133         template = GlobalLock16(hGlobal16);
134         if (!template)
135         {
136             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
137             ERR("global lock failure for %x handle\n", hGlobal16);
138             GlobalFree16(hGlobal16);
139             return FALSE;
140         }
141         ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
142         hDlgTmpl16 = hGlobal16;         
143
144     }
145
146     /* lpTemplateName is not used in the dialog */
147     lpTemplateName=lpChFont->lpTemplateName;
148     lpChFont->lpTemplateName=(SEGPTR)&cf32a;
149
150     ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (SEGPTR) 16);
151     hInst = GetWindowLongA(lpChFont->hwndOwner, GWL_HINSTANCE);
152     bRet = DialogBoxIndirectParam16(hInst, hDlgTmpl16, lpChFont->hwndOwner,
153                      (DLGPROC16) ptr, (DWORD)lpChFont);
154     if (hResource16) FreeResource16(hDlgTmpl16);
155     if (hGlobal16)
156     {
157         GlobalUnlock16(hGlobal16);
158         GlobalFree16(hGlobal16);
159     }
160     lpChFont->lpTemplateName=lpTemplateName;
161     FONT_LogFont32ATo16(cf32a.lpLogFont,
162         (LPLOGFONT16)(PTR_SEG_TO_LIN(lpChFont->lpLogFont)));
163     return bRet;
164 }
165
166
167 /***********************************************************************
168  *           ChooseFontA   (COMDLG32.3)
169  */
170 BOOL WINAPI ChooseFontA(LPCHOOSEFONTA lpChFont)
171 {
172   LPCVOID template;
173   HANDLE hResInfo, hDlgTmpl;
174
175   if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "CHOOSE_FONT", RT_DIALOGA)))
176   {
177     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
178     return FALSE;
179   }
180   if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
181       !(template = LockResource( hDlgTmpl )))
182   {
183     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
184     return FALSE;
185   }
186
187   if (lpChFont->Flags & (CF_SELECTSCRIPT | CF_NOVERTFONTS | CF_ENABLETEMPLATE |
188     CF_ENABLETEMPLATEHANDLE)) FIXME(": unimplemented flag (ignored)\n");
189   return DialogBoxIndirectParamA(COMMDLG_hInstance32, template, 
190             lpChFont->hwndOwner, (DLGPROC)FormatCharDlgProcA, (LPARAM)lpChFont );
191 }
192
193 /***********************************************************************
194  *           ChooseFontW   (COMDLG32.4)
195  */
196 BOOL WINAPI ChooseFontW(LPCHOOSEFONTW lpChFont)
197 {
198   BOOL bRet=FALSE;
199   CHOOSEFONTA cf32a;
200   LOGFONTA lf32a;
201   LPCVOID template;
202   HANDLE hResInfo, hDlgTmpl;
203
204   if (!(hResInfo = FindResourceA(COMMDLG_hInstance32, "CHOOSE_FONT", RT_DIALOGA)))
205   {
206     COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
207     return FALSE;
208   }
209   if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
210       !(template = LockResource( hDlgTmpl )))
211   {
212     COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
213     return FALSE;
214   }
215
216   if (lpChFont->Flags & (CF_SELECTSCRIPT | CF_NOVERTFONTS | CF_ENABLETEMPLATE |
217     CF_ENABLETEMPLATEHANDLE)) FIXME(": unimplemented flag (ignored)\n");
218   memcpy(&cf32a, lpChFont, sizeof(cf32a));
219   memcpy(&lf32a, lpChFont->lpLogFont, sizeof(LOGFONTA));
220   lstrcpynWtoA(lf32a.lfFaceName, lpChFont->lpLogFont->lfFaceName, LF_FACESIZE);
221   cf32a.lpLogFont=&lf32a;
222   cf32a.lpszStyle=HEAP_strdupWtoA(GetProcessHeap(), 0, lpChFont->lpszStyle);
223   lpChFont->lpTemplateName=(LPWSTR)&cf32a;
224   bRet = DialogBoxIndirectParamW(COMMDLG_hInstance32, template, 
225             lpChFont->hwndOwner, (DLGPROC)FormatCharDlgProcW, (LPARAM)lpChFont );
226   HeapFree(GetProcessHeap(), 0, cf32a.lpszStyle);
227   lpChFont->lpTemplateName=(LPWSTR)cf32a.lpTemplateName;
228   memcpy(lpChFont->lpLogFont, &lf32a, sizeof(CHOOSEFONTA));
229   lstrcpynAtoW(lpChFont->lpLogFont->lfFaceName, lf32a.lfFaceName, LF_FACESIZE);
230   return bRet;
231 }
232
233
234 #define TEXT_EXTRAS 4
235 #define TEXT_COLORS 16
236
237 static const COLORREF textcolors[TEXT_COLORS]=
238 {
239  0x00000000L,0x00000080L,0x00008000L,0x00008080L,
240  0x00800000L,0x00800080L,0x00808000L,0x00808080L,
241  0x00c0c0c0L,0x000000ffL,0x0000ff00L,0x0000ffffL,
242  0x00ff0000L,0x00ff00ffL,0x00ffff00L,0x00FFFFFFL
243 };
244
245 /***********************************************************************
246  *                          CFn_HookCallChk                 [internal]
247  */
248 static BOOL CFn_HookCallChk(LPCHOOSEFONT16 lpcf)
249 {
250  if (lpcf)
251   if(lpcf->Flags & CF_ENABLEHOOK)
252    if (lpcf->lpfnHook)
253     return TRUE;
254  return FALSE;
255 }
256
257 /***********************************************************************
258  *                          CFn_HookCallChk32                 [internal]
259  */
260 static BOOL CFn_HookCallChk32(LPCHOOSEFONTA lpcf)
261 {
262  if (lpcf)
263   if(lpcf->Flags & CF_ENABLEHOOK)
264    if (lpcf->lpfnHook)
265     return TRUE;
266  return FALSE;
267 }
268
269
270 /*************************************************************************
271  *              AddFontFamily                               [internal]
272  */
273 static INT AddFontFamily(LPLOGFONTA lplf, UINT nFontType, 
274                            LPCHOOSEFONTA lpcf, HWND hwnd)
275 {
276   int i;
277   WORD w;
278
279   TRACE("font=%s (nFontType=%d)\n", lplf->lfFaceName,nFontType);
280
281   if (lpcf->Flags & CF_FIXEDPITCHONLY)
282    if (!(lplf->lfPitchAndFamily & FIXED_PITCH))
283      return 1;
284   if (lpcf->Flags & CF_ANSIONLY)
285    if (lplf->lfCharSet != ANSI_CHARSET)
286      return 1;
287   if (lpcf->Flags & CF_TTONLY)
288    if (!(nFontType & TRUETYPE_FONTTYPE))
289      return 1;   
290
291   i=SendMessageA(hwnd, CB_ADDSTRING, 0, (LPARAM)lplf->lfFaceName);
292   if (i!=CB_ERR)
293   {
294     w=(lplf->lfCharSet << 8) | lplf->lfPitchAndFamily;
295     SendMessageA(hwnd, CB_SETITEMDATA, i, MAKELONG(nFontType,w));
296     return 1 ;        /* store some important font information */
297   }
298   else
299     return 0;
300 }
301
302 typedef struct
303 {
304   HWND hWnd1;
305   HWND hWnd2;
306   LPCHOOSEFONTA lpcf32a;
307 } CFn_ENUMSTRUCT, *LPCFn_ENUMSTRUCT;
308
309 /*************************************************************************
310  *              FontFamilyEnumProc32                           [internal]
311  */
312 static INT WINAPI FontFamilyEnumProc(LPENUMLOGFONTA lpEnumLogFont, 
313           LPNEWTEXTMETRICA metrics, UINT nFontType, LPARAM lParam)
314 {
315   LPCFn_ENUMSTRUCT e;
316   e=(LPCFn_ENUMSTRUCT)lParam;
317   return AddFontFamily(&lpEnumLogFont->elfLogFont, nFontType, e->lpcf32a, e->hWnd1);
318 }
319
320 /***********************************************************************
321  *                FontFamilyEnumProc16                     (COMMDLG.19)
322  */
323 INT16 WINAPI FontFamilyEnumProc16( SEGPTR logfont, SEGPTR metrics,
324                                    UINT16 nFontType, LPARAM lParam )
325 {
326   HWND16 hwnd=LOWORD(lParam);
327   HWND hDlg=GetParent(hwnd);
328   LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); 
329   LOGFONT16 *lplf = (LOGFONT16 *)PTR_SEG_TO_LIN( logfont );
330   LOGFONTA lf32a;
331   FONT_LogFont16To32A(lplf, &lf32a);
332   return AddFontFamily(&lf32a, nFontType, (LPCHOOSEFONTA)lpcf->lpTemplateName,
333                        hwnd);
334 }
335
336 /*************************************************************************
337  *              SetFontStylesToCombo2                           [internal]
338  *
339  * Fill font style information into combobox  (without using font.c directly)
340  */
341 static int SetFontStylesToCombo2(HWND hwnd, HDC hdc, LPLOGFONTA lplf)
342 {
343    #define FSTYLES 4
344    struct FONTSTYLE
345           { int italic; 
346             int weight;
347             char stname[20]; };
348    static struct FONTSTYLE fontstyles[FSTYLES]={ 
349           { 0,FW_NORMAL,"Regular"},{0,FW_BOLD,"Bold"},
350           { 1,FW_NORMAL,"Italic"}, {1,FW_BOLD,"Bold Italic"}};
351    HFONT hf;
352    TEXTMETRICA tm;
353    int i,j;
354
355    for (i=0;i<FSTYLES;i++)
356    {
357      lplf->lfItalic=fontstyles[i].italic;
358      lplf->lfWeight=fontstyles[i].weight;
359      hf=CreateFontIndirectA(lplf);
360      hf=SelectObject(hdc,hf);
361      GetTextMetricsA(hdc,&tm);
362      hf=SelectObject(hdc,hf);
363      DeleteObject(hf);
364
365      if (tm.tmWeight==fontstyles[i].weight &&
366          tm.tmItalic==fontstyles[i].italic)    /* font successful created ? */
367      {
368        char *str = SEGPTR_STRDUP(fontstyles[i].stname);
369        j=SendMessage16(hwnd,CB_ADDSTRING16,0,(LPARAM)SEGPTR_GET(str) );
370        SEGPTR_FREE(str);
371        if (j==CB_ERR) return 1;
372        j=SendMessage16(hwnd, CB_SETITEMDATA16, j, 
373                                  MAKELONG(fontstyles[i].weight,fontstyles[i].italic));
374        if (j==CB_ERR) return 1;                                 
375      }
376    }  
377   return 0;
378 }
379
380 /*************************************************************************
381  *              AddFontSizeToCombo3                           [internal]
382  */
383 static int AddFontSizeToCombo3(HWND hwnd, UINT h, LPCHOOSEFONTA lpcf)
384 {
385     int j;
386     char buffer[20];
387
388     if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
389         ((lpcf->Flags & CF_LIMITSIZE) && (h >= lpcf->nSizeMin) && (h <= lpcf->nSizeMax)))
390     {
391         sprintf(buffer, "%2d", h);
392         j=SendMessageA(hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)buffer);
393         if (j==CB_ERR)
394         {
395             j=SendMessageA(hwnd, CB_ADDSTRING, 0, (LPARAM)buffer);      
396             if (j!=CB_ERR) j = SendMessageA(hwnd, CB_SETITEMDATA, j, h); 
397             if (j==CB_ERR) return 1;
398         }
399     }
400     return 0;
401
402  
403 /*************************************************************************
404  *              SetFontSizesToCombo3                           [internal]
405  */
406 static int SetFontSizesToCombo3(HWND hwnd, LPCHOOSEFONTA lpcf)
407 {
408   static const int sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72,0};
409   int i;
410
411   for (i=0; sizes[i]; i++)
412     if (AddFontSizeToCombo3(hwnd, sizes[i], lpcf)) return 1;
413   return 0;
414 }
415
416 /***********************************************************************
417  *                 AddFontStyle                          [internal]
418  */
419 static INT AddFontStyle(LPLOGFONTA lplf, UINT nFontType, 
420     LPCHOOSEFONTA lpcf, HWND hcmb2, HWND hcmb3, HWND hDlg)
421 {
422   int i;
423   
424   TRACE("(nFontType=%d)\n",nFontType);
425   TRACE("  %s h=%ld w=%ld e=%ld o=%ld wg=%ld i=%d u=%d s=%d"
426                " ch=%d op=%d cp=%d q=%d pf=%xh\n",
427                lplf->lfFaceName,lplf->lfHeight,lplf->lfWidth,
428                lplf->lfEscapement,lplf->lfOrientation,
429                lplf->lfWeight,lplf->lfItalic,lplf->lfUnderline,
430                lplf->lfStrikeOut,lplf->lfCharSet, lplf->lfOutPrecision,
431                lplf->lfClipPrecision,lplf->lfQuality, lplf->lfPitchAndFamily);
432   if (nFontType & RASTER_FONTTYPE)
433   {
434     if (AddFontSizeToCombo3(hcmb3, lplf->lfHeight, lpcf)) return 0;
435   } else if (SetFontSizesToCombo3(hcmb3, lpcf)) return 0;
436
437   if (!SendMessageA(hcmb2, CB_GETCOUNT, 0, 0))
438   {
439        HDC hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
440        i=SetFontStylesToCombo2(hcmb2,hdc,lplf);
441        if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
442          ReleaseDC(hDlg,hdc);
443        if (i)
444         return 0;
445   }
446   return 1 ;
447
448 }    
449
450 /***********************************************************************
451  *                 FontStyleEnumProc16                     (COMMDLG.18)
452  */
453 INT16 WINAPI FontStyleEnumProc16( SEGPTR logfont, SEGPTR metrics,
454                                   UINT16 nFontType, LPARAM lParam )
455 {
456   HWND16 hcmb2=LOWORD(lParam);
457   HWND16 hcmb3=HIWORD(lParam);
458   HWND hDlg=GetParent(hcmb3);
459   LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); 
460   LOGFONT16 *lplf = (LOGFONT16 *)PTR_SEG_TO_LIN(logfont);
461   LOGFONTA lf32a;
462   FONT_LogFont16To32A(lplf, &lf32a);
463   return AddFontStyle(&lf32a, nFontType, (LPCHOOSEFONTA)lpcf->lpTemplateName,
464                       hcmb2, hcmb3, hDlg);
465 }
466
467 /***********************************************************************
468  *                 FontStyleEnumProc32                     [internal]
469  */
470 static INT WINAPI FontStyleEnumProc( LPENUMLOGFONTA lpFont, 
471           LPNEWTEXTMETRICA metrics, UINT nFontType, LPARAM lParam )
472 {
473   LPCFn_ENUMSTRUCT s=(LPCFn_ENUMSTRUCT)lParam;
474   HWND hcmb2=s->hWnd1;
475   HWND hcmb3=s->hWnd2;
476   HWND hDlg=GetParent(hcmb3);
477   return AddFontStyle(&lpFont->elfLogFont, nFontType, s->lpcf32a, hcmb2,
478                       hcmb3, hDlg);
479 }
480
481 /***********************************************************************
482  *           CFn_WMInitDialog                            [internal]
483  */
484 static LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam,
485                          LPCHOOSEFONTA lpcf)
486 {
487   HDC hdc;
488   int i,j,res,init=0;
489   long l;
490   LPLOGFONTA lpxx;
491   HCURSOR hcursor=SetCursor(LoadCursorA(0,IDC_WAITA));
492
493   SetWindowLongA(hDlg, DWL_USER, lParam); 
494   lpxx=lpcf->lpLogFont;
495   TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
496
497   if (lpcf->lStructSize != sizeof(CHOOSEFONTA))
498   {
499     ERR("structure size failure !!!\n");
500     EndDialog (hDlg, 0); 
501     return FALSE;
502   }
503   if (!hBitmapTT)
504     hBitmapTT = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_TRTYPE));
505
506   /* This font will be deleted by WM_COMMAND */
507   SendDlgItemMessageA(hDlg,stc6,WM_SETFONT,
508      CreateFontA(0, 0, 1, 1, 400, 0, 0, 0, 0, 0, 0, 0, 0, NULL),FALSE);
509                          
510   if (!(lpcf->Flags & CF_SHOWHELP) || !IsWindow(lpcf->hwndOwner))
511     ShowWindow(GetDlgItem(hDlg,pshHelp),SW_HIDE);
512   if (!(lpcf->Flags & CF_APPLY))
513     ShowWindow(GetDlgItem(hDlg,psh3),SW_HIDE);
514   if (lpcf->Flags & CF_EFFECTS)
515   {
516     for (res=1,i=0;res && i<TEXT_COLORS;i++)
517     {
518       /* FIXME: load color name from resource:  res=LoadString(...,i+....,buffer,.....); */
519       char name[20];
520       strcpy( name, "[color name]" );
521       j=SendDlgItemMessageA(hDlg, cmb4, CB_ADDSTRING, 0, (LPARAM)name);
522       SendDlgItemMessageA(hDlg, cmb4, CB_SETITEMDATA16, j, textcolors[j]);
523       /* look for a fitting value in color combobox */
524       if (textcolors[j]==lpcf->rgbColors)
525         SendDlgItemMessageA(hDlg,cmb4, CB_SETCURSEL,j,0);
526     }
527   }
528   else
529   {
530     ShowWindow(GetDlgItem(hDlg,cmb4),SW_HIDE);
531     ShowWindow(GetDlgItem(hDlg,chx1),SW_HIDE);
532     ShowWindow(GetDlgItem(hDlg,chx2),SW_HIDE);
533     ShowWindow(GetDlgItem(hDlg,grp1),SW_HIDE);
534     ShowWindow(GetDlgItem(hDlg,stc4),SW_HIDE);
535   }
536   hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
537   if (hdc)
538   {
539     CFn_ENUMSTRUCT s;
540     s.hWnd1=GetDlgItem(hDlg,cmb1);
541     s.lpcf32a=lpcf;
542     if (!EnumFontFamiliesA(hdc, NULL, FontFamilyEnumProc, (LPARAM)&s))
543       TRACE("EnumFontFamilies returns 0\n");
544     if (lpcf->Flags & CF_INITTOLOGFONTSTRUCT)
545     {
546       /* look for fitting font name in combobox1 */
547       j=SendDlgItemMessageA(hDlg,cmb1,CB_FINDSTRING,-1,(LONG)lpxx->lfFaceName);
548       if (j!=CB_ERR)
549       {
550         SendDlgItemMessageA(hDlg, cmb1, CB_SETCURSEL, j, 0);
551         SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE),
552                        GetDlgItem(hDlg,cmb1));
553         init=1;
554         /* look for fitting font style in combobox2 */
555         l=MAKELONG(lpxx->lfWeight > FW_MEDIUM ? FW_BOLD:FW_NORMAL,lpxx->lfItalic !=0);
556         for (i=0;i<TEXT_EXTRAS;i++)
557         {
558           if (l==SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0))
559             SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
560         }
561       
562         /* look for fitting font size in combobox3 */
563         j=SendDlgItemMessageA(hDlg, cmb3, CB_GETCOUNT, 0, 0);
564         for (i=0;i<j;i++)
565         {
566           if (lpxx->lfHeight==(int)SendDlgItemMessageA(hDlg,cmb3, CB_GETITEMDATA,i,0))
567             SendDlgItemMessageA(hDlg,cmb3,CB_SETCURSEL,i,0);
568         }
569       }
570     }
571     if (!init)
572     {
573       SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0);
574       SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE),
575                        GetDlgItem(hDlg,cmb1));
576     }    
577     if (lpcf->Flags & CF_USESTYLE && lpcf->lpszStyle)
578     {
579       j=SendDlgItemMessageA(hDlg,cmb2,CB_FINDSTRING,-1,(LONG)lpcf->lpszStyle);
580       if (j!=CB_ERR)
581       {
582         j=SendDlgItemMessageA(hDlg,cmb2,CB_SETCURSEL,j,0);
583         SendMessageA(hDlg,WM_COMMAND,cmb2,
584                        MAKELONG(GetDlgItem(hDlg,cmb2),CBN_SELCHANGE));
585       }
586     }
587   }
588   else
589   {
590     WARN("HDC failure !!!\n");
591     EndDialog (hDlg, 0); 
592     return FALSE;
593   }
594
595   if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
596     ReleaseDC(hDlg,hdc);
597   SetCursor(hcursor);   
598   return TRUE;
599 }
600
601
602 /***********************************************************************
603  *           CFn_WMMeasureItem                           [internal]
604  */
605 static LRESULT CFn_WMMeasureItem(HWND hDlg, WPARAM wParam, LPARAM lParam)
606 {
607   BITMAP bm;
608   LPMEASUREITEMSTRUCT lpmi=(LPMEASUREITEMSTRUCT)lParam;
609   if (!hBitmapTT)
610     hBitmapTT = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_TRTYPE));
611   GetObjectA( hBitmapTT, sizeof(bm), &bm );
612   lpmi->itemHeight=bm.bmHeight;
613   /* FIXME: use MAX of bm.bmHeight and tm.tmHeight .*/
614   return 0;
615 }
616
617
618 /***********************************************************************
619  *           CFn_WMDrawItem                              [internal]
620  */
621 static LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam)
622 {
623   HBRUSH hBrush;
624   char buffer[40];
625   BITMAP bm;
626   COLORREF cr, oldText=0, oldBk=0;
627   RECT rect;
628 #if 0  
629   HDC hMemDC;
630   int nFontType;
631   HBITMAP hBitmap; /* for later TT usage */
632 #endif  
633   LPDRAWITEMSTRUCT lpdi = (LPDRAWITEMSTRUCT)lParam;
634
635   if (lpdi->itemID == 0xFFFF)                   /* got no items */
636     DrawFocusRect(lpdi->hDC, &lpdi->rcItem);
637   else
638   {
639    if (lpdi->CtlType == ODT_COMBOBOX)
640    {
641      if (lpdi->itemState ==ODS_SELECTED)
642      {
643        hBrush=GetSysColorBrush(COLOR_HIGHLIGHT);
644        oldText=SetTextColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
645        oldBk=SetBkColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHT));
646      }  else
647      {
648        hBrush = SelectObject(lpdi->hDC, GetStockObject(LTGRAY_BRUSH));
649        SelectObject(lpdi->hDC, hBrush);
650      }
651      FillRect(lpdi->hDC, &lpdi->rcItem, hBrush);
652    }
653    else
654      return TRUE;       /* this should never happen */
655
656    rect=lpdi->rcItem;
657    switch (lpdi->CtlID)
658    {
659     case cmb1:  /* TRACE(commdlg,"WM_Drawitem cmb1\n"); */
660                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
661                                (LPARAM)buffer);           
662                 GetObjectA( hBitmapTT, sizeof(bm), &bm );
663                 TextOutA(lpdi->hDC, lpdi->rcItem.left + bm.bmWidth + 10,
664                            lpdi->rcItem.top, buffer, strlen(buffer));
665 #if 0
666                 nFontType = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
667                   /* FIXME: draw bitmap if truetype usage */
668                 if (nFontType&TRUETYPE_FONTTYPE)
669                 {
670                   hMemDC = CreateCompatibleDC(lpdi->hDC);
671                   hBitmap = SelectObject(hMemDC, hBitmapTT);
672                   BitBlt(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top,
673                            bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
674                   SelectObject(hMemDC, hBitmap);
675                   DeleteDC(hMemDC);
676                 }
677 #endif
678                 break;
679     case cmb2:
680     case cmb3:  /* TRACE(commdlg,"WM_DRAWITEN cmb2,cmb3\n"); */
681                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
682                                (LPARAM)buffer);
683                 TextOutA(lpdi->hDC, lpdi->rcItem.left,
684                            lpdi->rcItem.top, buffer, strlen(buffer));
685                 break;
686
687     case cmb4:  /* TRACE(commdlg,"WM_DRAWITEM cmb4 (=COLOR)\n"); */
688                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
689                                (LPARAM)buffer);
690                 TextOutA(lpdi->hDC, lpdi->rcItem.left +  25+5,
691                            lpdi->rcItem.top, buffer, strlen(buffer));
692                 cr = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
693                 hBrush = CreateSolidBrush(cr);
694                 if (hBrush)
695                 {
696                   hBrush = SelectObject (lpdi->hDC, hBrush) ;
697                   rect.right=rect.left+25;
698                   rect.top++;
699                   rect.left+=5;
700                   rect.bottom--;
701                   Rectangle( lpdi->hDC, rect.left, rect.top,
702                                rect.right, rect.bottom );
703                   DeleteObject( SelectObject (lpdi->hDC, hBrush)) ;
704                 }
705                 rect=lpdi->rcItem;
706                 rect.left+=25+5;
707                 break;
708
709     default:    return TRUE;    /* this should never happen */
710    }
711    if (lpdi->itemState == ODS_SELECTED)
712    {
713      SetTextColor(lpdi->hDC, oldText);
714      SetBkColor(lpdi->hDC, oldBk);
715    }
716  }
717  return TRUE;
718 }
719
720 /***********************************************************************
721  *           CFn_WMCtlColor                              [internal]
722  */
723 static LRESULT CFn_WMCtlColorStatic(HWND hDlg, WPARAM wParam, LPARAM lParam,
724                              LPCHOOSEFONTA lpcf)
725 {
726   if (lpcf->Flags & CF_EFFECTS)
727    if (GetDlgCtrlID(lParam)==stc6)
728    {
729      SetTextColor((HDC)wParam, lpcf->rgbColors);
730      return GetStockObject(WHITE_BRUSH);
731    }
732   return 0;
733 }
734
735 /***********************************************************************
736  *           CFn_WMCommand                               [internal]
737  */
738 static LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam,
739                       LPCHOOSEFONTA lpcf)
740 {
741   HFONT hFont;
742   int i,j;
743   long l;
744   HDC hdc;
745   LPLOGFONTA lpxx=lpcf->lpLogFont;
746   
747   TRACE("WM_COMMAND wParam=%08lX lParam=%08lX\n", (LONG)wParam, lParam);
748   switch (LOWORD(wParam))
749   {
750         case cmb1:if (HIWORD(wParam)==CBN_SELCHANGE)
751                   {
752                     hdc=(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
753                     if (hdc)
754                     {
755                       SendDlgItemMessageA(hDlg, cmb2, CB_RESETCONTENT16, 0, 0); 
756                       SendDlgItemMessageA(hDlg, cmb3, CB_RESETCONTENT16, 0, 0);
757                       i=SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL16, 0, 0);
758                       if (i!=CB_ERR)
759                       {
760                         HCURSOR hcursor=SetCursor(LoadCursorA(0,IDC_WAITA));
761                         CFn_ENUMSTRUCT s;
762                         char str[256];
763                         SendDlgItemMessageA(hDlg, cmb1, CB_GETLBTEXT, i,
764                                               (LPARAM)str);
765                         TRACE("WM_COMMAND/cmb1 =>%s\n",str);
766                         s.hWnd1=GetDlgItem(hDlg, cmb2);
767                         s.hWnd2=GetDlgItem(hDlg, cmb3);
768                         s.lpcf32a=lpcf;
769                         EnumFontFamiliesA(hdc, str, FontStyleEnumProc, (LPARAM)&s);
770                         SetCursor(hcursor);
771                       }
772                       if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
773                         ReleaseDC(hDlg,hdc);
774                     }
775                     else
776                     {
777                       WARN("HDC failure !!!\n");
778                       EndDialog (hDlg, 0); 
779                       return TRUE;
780                     }
781                   }
782         case chx1:
783         case chx2:
784         case cmb2:
785         case cmb3:if (HIWORD(wParam)==CBN_SELCHANGE || HIWORD(wParam)== BN_CLICKED )
786                   {
787                     char str[256];
788                     TRACE("WM_COMMAND/cmb2,3 =%08lX\n", lParam);
789                     i=SendDlgItemMessageA(hDlg,cmb1,CB_GETCURSEL,0,0);
790                     if (i==CB_ERR)
791                       i=GetDlgItemTextA( hDlg, cmb1, str, 256 );
792                     else
793                     {
794                       SendDlgItemMessageA(hDlg,cmb1,CB_GETLBTEXT,i,
795                                             (LPARAM)str);
796                       l=SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,i,0);
797                       j=HIWORD(l);
798                       lpcf->nFontType = LOWORD(l);
799                       /* FIXME:   lpcf->nFontType |= ....  SIMULATED_FONTTYPE and so */
800                       /* same value reported to the EnumFonts
801                        call back with the extra FONTTYPE_...  bits added */
802                       lpxx->lfPitchAndFamily=j&0xff;
803                       lpxx->lfCharSet=j>>8;
804                     }
805                     strcpy(lpxx->lfFaceName,str);
806                     i=SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
807                     if (i!=CB_ERR)
808                     {
809                       l=SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0);
810                       if (0!=(lpxx->lfItalic=HIWORD(l)))
811                         lpcf->nFontType |= ITALIC_FONTTYPE;
812                       if ((lpxx->lfWeight=LOWORD(l)) > FW_MEDIUM)
813                         lpcf->nFontType |= BOLD_FONTTYPE;
814                     }
815                     i=SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
816                     if (i!=CB_ERR)
817                       lpxx->lfHeight=-LOWORD(SendDlgItemMessageA(hDlg, cmb3, CB_GETITEMDATA, i, 0));
818                     else
819                       lpxx->lfHeight=0;
820                     lpxx->lfStrikeOut=IsDlgButtonChecked(hDlg,chx1);
821                     lpxx->lfUnderline=IsDlgButtonChecked(hDlg,chx2);
822                     lpxx->lfWidth=lpxx->lfOrientation=lpxx->lfEscapement=0;
823                     lpxx->lfOutPrecision=OUT_DEFAULT_PRECIS;
824                     lpxx->lfClipPrecision=CLIP_DEFAULT_PRECIS;
825                     lpxx->lfQuality=DEFAULT_QUALITY;
826                     lpcf->iPointSize= -10*lpxx->lfHeight;
827
828                     hFont=CreateFontIndirectA(lpxx);
829                     if (hFont)
830                     {
831                       HFONT oldFont=SendDlgItemMessageA(hDlg, stc6, 
832                           WM_GETFONT, 0, 0);
833                       SendDlgItemMessageA(hDlg,stc6,WM_SETFONT,hFont,TRUE);
834                       DeleteObject(oldFont);
835                     }
836                   }
837                   break;
838
839         case cmb4:i=SendDlgItemMessageA(hDlg, cmb4, CB_GETCURSEL, 0, 0);
840                   if (i!=CB_ERR)
841                   {
842                    lpcf->rgbColors=textcolors[i];
843                    InvalidateRect( GetDlgItem(hDlg,stc6), NULL, 0 );
844                   }
845                   break;
846         
847         case psh15:i=RegisterWindowMessageA( HELPMSGSTRING );
848                   if (lpcf->hwndOwner)
849                     SendMessageA(lpcf->hwndOwner, i, 0, (LPARAM)GetWindowLongA(hDlg, DWL_USER));
850 /*                if (CFn_HookCallChk(lpcf))
851                     CallWindowProc16(lpcf->lpfnHook,hDlg,WM_COMMAND,psh15,(LPARAM)lpcf);*/
852                   break;
853
854         case IDOK:if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
855                      ( (lpcf->Flags & CF_LIMITSIZE) && 
856                       (-lpxx->lfHeight >= lpcf->nSizeMin) && 
857                       (-lpxx->lfHeight <= lpcf->nSizeMax)))
858                      EndDialog(hDlg, TRUE);
859                   else
860                   {
861                    char buffer[80];
862                    sprintf(buffer,"Select a font size between %d and %d points.",
863                            lpcf->nSizeMin,lpcf->nSizeMax);
864                    MessageBoxA(hDlg, buffer, NULL, MB_OK);
865                   } 
866                   return(TRUE);
867         case IDCANCEL:EndDialog(hDlg, FALSE);
868                   return(TRUE);
869         }
870       return(FALSE);
871 }
872
873 static LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
874 {
875   DeleteObject(SendDlgItemMessageA(hwnd, stc6, WM_GETFONT, 0, 0));
876   return TRUE;
877 }
878
879
880 /***********************************************************************
881  *           FormatCharDlgProc16   (COMMDLG.16)
882              FIXME: 1. some strings are "hardcoded", but it's better load from sysres
883                     2. some CF_.. flags are not supported
884                     3. some TType extensions
885  */
886 LRESULT WINAPI FormatCharDlgProc16(HWND16 hDlg, UINT16 message, WPARAM16 wParam,
887                                    LPARAM lParam)
888 {
889   LPCHOOSEFONT16 lpcf;
890   LPCHOOSEFONTA lpcf32a;
891   UINT uMsg32;
892   WPARAM wParam32;
893   LRESULT res=0;  
894   if (message!=WM_INITDIALOG)
895   {
896    lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER);   
897    if (!lpcf)
898       return FALSE;
899    if (CFn_HookCallChk(lpcf))
900      res=CallWindowProc16((WNDPROC16)lpcf->lpfnHook,hDlg,message,wParam,lParam);
901    if (res)
902     return res;
903   }
904   else
905   {
906     lpcf=(LPCHOOSEFONT16)lParam;
907     lpcf32a=(LPCHOOSEFONTA)lpcf->lpTemplateName;
908     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf32a)) 
909     {
910       TRACE("CFn_WMInitDialog returned FALSE\n");
911       return FALSE;
912     }  
913     if (CFn_HookCallChk(lpcf))
914       return CallWindowProc16((WNDPROC16)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
915   }
916   WINPROC_MapMsg16To32A(message, wParam, &uMsg32, &wParam32, &lParam);
917   lpcf32a=(LPCHOOSEFONTA)lpcf->lpTemplateName;
918   switch (uMsg32)
919     {
920       case WM_MEASUREITEM:
921                         res=CFn_WMMeasureItem(hDlg, wParam32, lParam);
922                         break;
923       case WM_DRAWITEM:
924                         res=CFn_WMDrawItem(hDlg, wParam32, lParam);
925                         break;
926       case WM_CTLCOLORSTATIC:
927                         res=CFn_WMCtlColorStatic(hDlg, wParam32, lParam, lpcf32a);
928                         break;
929       case WM_COMMAND:
930                         res=CFn_WMCommand(hDlg, wParam32, lParam, lpcf32a);
931                         break;
932       case WM_DESTROY:
933                         res=CFn_WMDestroy(hDlg, wParam32, lParam);
934                         break;
935       case WM_CHOOSEFONT_GETLOGFONT: 
936                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
937                                       lParam);
938                          FIXME("current logfont back to caller\n");
939                         break;
940     }
941   WINPROC_UnmapMsg16To32A(hDlg,uMsg32, wParam32, lParam, res);    
942   return res;
943 }
944
945 /***********************************************************************
946  *           FormatCharDlgProcA   [internal]
947  */
948 LRESULT WINAPI FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
949                                     LPARAM lParam)
950 {
951   LPCHOOSEFONTA lpcf;
952   LRESULT res=FALSE;
953   if (uMsg!=WM_INITDIALOG)
954   {
955    lpcf=(LPCHOOSEFONTA)GetWindowLongA(hDlg, DWL_USER);   
956    if (!lpcf)
957      return FALSE;
958    if (CFn_HookCallChk32(lpcf))
959      res=CallWindowProcA((WNDPROC)lpcf->lpfnHook, hDlg, uMsg, wParam, lParam);
960    if (res)
961      return res;
962   }
963   else
964   {
965     lpcf=(LPCHOOSEFONTA)lParam;
966     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf)) 
967     {
968       TRACE("CFn_WMInitDialog returned FALSE\n");
969       return FALSE;
970     }  
971     if (CFn_HookCallChk32(lpcf))
972       return CallWindowProcA((WNDPROC)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
973   }
974   switch (uMsg)
975     {
976       case WM_MEASUREITEM:
977                         return CFn_WMMeasureItem(hDlg, wParam, lParam);
978       case WM_DRAWITEM:
979                         return CFn_WMDrawItem(hDlg, wParam, lParam);
980       case WM_CTLCOLORSTATIC:
981                         return CFn_WMCtlColorStatic(hDlg, wParam, lParam, lpcf);
982       case WM_COMMAND:
983                         return CFn_WMCommand(hDlg, wParam, lParam, lpcf);
984       case WM_DESTROY:
985                         return CFn_WMDestroy(hDlg, wParam, lParam);
986       case WM_CHOOSEFONT_GETLOGFONT:
987                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
988                                       lParam);
989                          FIXME("current logfont back to caller\n");
990                         break;
991     }
992   return res;
993 }
994
995 /***********************************************************************
996  *           FormatCharDlgProcW   [internal]
997  */
998 LRESULT WINAPI FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
999                                     LPARAM lParam)
1000 {
1001   LPCHOOSEFONTW lpcf32w;
1002   LPCHOOSEFONTA lpcf32a;
1003   LRESULT res=FALSE;
1004   if (uMsg!=WM_INITDIALOG)
1005   {
1006    lpcf32w=(LPCHOOSEFONTW)GetWindowLongA(hDlg, DWL_USER);   
1007    if (!lpcf32w)
1008      return FALSE;
1009    if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w))
1010      res=CallWindowProcW((WNDPROC)lpcf32w->lpfnHook, hDlg, uMsg, wParam, lParam);
1011    if (res)
1012      return res;
1013   }
1014   else
1015   {
1016     lpcf32w=(LPCHOOSEFONTW)lParam;
1017     lpcf32a=(LPCHOOSEFONTA)lpcf32w->lpTemplateName;
1018     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf32a)) 
1019     {
1020       TRACE("CFn_WMInitDialog returned FALSE\n");
1021       return FALSE;
1022     }  
1023     if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w))
1024       return CallWindowProcW((WNDPROC)lpcf32w->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
1025   }
1026   lpcf32a=(LPCHOOSEFONTA)lpcf32w->lpTemplateName;
1027   switch (uMsg)
1028     {
1029       case WM_MEASUREITEM:
1030                         return CFn_WMMeasureItem(hDlg, wParam, lParam);
1031       case WM_DRAWITEM:
1032                         return CFn_WMDrawItem(hDlg, wParam, lParam);
1033       case WM_CTLCOLORSTATIC:
1034                         return CFn_WMCtlColorStatic(hDlg, wParam, lParam, lpcf32a);
1035       case WM_COMMAND:
1036                         return CFn_WMCommand(hDlg, wParam, lParam, lpcf32a);
1037       case WM_DESTROY:
1038                         return CFn_WMDestroy(hDlg, wParam, lParam);
1039       case WM_CHOOSEFONT_GETLOGFONT: 
1040                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
1041                                       lParam);
1042                          FIXME("current logfont back to caller\n");
1043                         break;
1044     }
1045   return res;
1046 }
1047
1048