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