Replaced all lstr* calls from inside Wine code by their str* equivalent.
[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 "ldt.h"
18 #include "heap.h"
19 #include "commdlg.h"
20 #include "dialog.h"
21 #include "dlgs.h"
22 #include "module.h"
23 #include "debugtools.h"
24 #include "font.h"
25 #include "winproc.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(LPLOGFONTA 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(LPENUMLOGFONTA lpEnumLogFont, 
312           LPNEWTEXTMETRICA metrics, UINT nFontType, LPARAM lParam)
313 {
314   LPCFn_ENUMSTRUCT e;
315   e=(LPCFn_ENUMSTRUCT)lParam;
316   return AddFontFamily(&lpEnumLogFont->elfLogFont, nFontType, 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, LPLOGFONTA 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
354    for (i=0;i<FSTYLES;i++)
355    {
356      lplf->lfItalic=fontstyles[i].italic;
357      lplf->lfWeight=fontstyles[i].weight;
358      hf=CreateFontIndirectA(lplf);
359      hf=SelectObject(hdc,hf);
360      GetTextMetricsA(hdc,&tm);
361      hf=SelectObject(hdc,hf);
362      DeleteObject(hf);
363
364      if (tm.tmWeight==fontstyles[i].weight &&
365          tm.tmItalic==fontstyles[i].italic)    /* font successful created ? */
366      {
367        char *str = SEGPTR_STRDUP(fontstyles[i].stname);
368        j=SendMessage16(hwnd,CB_ADDSTRING16,0,(LPARAM)SEGPTR_GET(str) );
369        SEGPTR_FREE(str);
370        if (j==CB_ERR) return 1;
371        j=SendMessage16(hwnd, CB_SETITEMDATA16, j, 
372                                  MAKELONG(fontstyles[i].weight,fontstyles[i].italic));
373        if (j==CB_ERR) return 1;                                 
374      }
375    }  
376   return 0;
377 }
378
379 /*************************************************************************
380  *              AddFontSizeToCombo3                           [internal]
381  */
382 static int AddFontSizeToCombo3(HWND hwnd, UINT h, LPCHOOSEFONTA lpcf)
383 {
384     int j;
385     char buffer[20];
386
387     if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
388         ((lpcf->Flags & CF_LIMITSIZE) && (h >= lpcf->nSizeMin) && (h <= lpcf->nSizeMax)))
389     {
390         sprintf(buffer, "%2d", h);
391         j=SendMessageA(hwnd, CB_FINDSTRINGEXACT, -1, (LPARAM)buffer);
392         if (j==CB_ERR)
393         {
394             j=SendMessageA(hwnd, CB_ADDSTRING, 0, (LPARAM)buffer);      
395             if (j!=CB_ERR) j = SendMessageA(hwnd, CB_SETITEMDATA, j, h); 
396             if (j==CB_ERR) return 1;
397         }
398     }
399     return 0;
400
401  
402 /*************************************************************************
403  *              SetFontSizesToCombo3                           [internal]
404  */
405 static int SetFontSizesToCombo3(HWND hwnd, LPCHOOSEFONTA lpcf)
406 {
407   static const int sizes[]={8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72,0};
408   int i;
409
410   for (i=0; sizes[i]; i++)
411     if (AddFontSizeToCombo3(hwnd, sizes[i], lpcf)) return 1;
412   return 0;
413 }
414
415 /***********************************************************************
416  *                 AddFontStyle                          [internal]
417  */
418 static INT AddFontStyle(LPLOGFONTA lplf, UINT nFontType, 
419     LPCHOOSEFONTA lpcf, HWND hcmb2, HWND hcmb3, HWND hDlg)
420 {
421   int i;
422   
423   TRACE("(nFontType=%d)\n",nFontType);
424   TRACE("  %s h=%ld w=%ld e=%ld o=%ld wg=%ld i=%d u=%d s=%d"
425                " ch=%d op=%d cp=%d q=%d pf=%xh\n",
426                lplf->lfFaceName,lplf->lfHeight,lplf->lfWidth,
427                lplf->lfEscapement,lplf->lfOrientation,
428                lplf->lfWeight,lplf->lfItalic,lplf->lfUnderline,
429                lplf->lfStrikeOut,lplf->lfCharSet, lplf->lfOutPrecision,
430                lplf->lfClipPrecision,lplf->lfQuality, lplf->lfPitchAndFamily);
431   if (nFontType & RASTER_FONTTYPE)
432   {
433     if (AddFontSizeToCombo3(hcmb3, lplf->lfHeight, lpcf)) return 0;
434   } else if (SetFontSizesToCombo3(hcmb3, lpcf)) return 0;
435
436   if (!SendMessageA(hcmb2, CB_GETCOUNT, 0, 0))
437   {
438        HDC hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
439        i=SetFontStylesToCombo2(hcmb2,hdc,lplf);
440        if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
441          ReleaseDC(hDlg,hdc);
442        if (i)
443         return 0;
444   }
445   return 1 ;
446
447 }    
448
449 /***********************************************************************
450  *                 FontStyleEnumProc16                     (COMMDLG.18)
451  */
452 INT16 WINAPI FontStyleEnumProc16( SEGPTR logfont, SEGPTR metrics,
453                                   UINT16 nFontType, LPARAM lParam )
454 {
455   HWND16 hcmb2=LOWORD(lParam);
456   HWND16 hcmb3=HIWORD(lParam);
457   HWND hDlg=GetParent(hcmb3);
458   LPCHOOSEFONT16 lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER); 
459   LOGFONT16 *lplf = (LOGFONT16 *)PTR_SEG_TO_LIN(logfont);
460   LOGFONTA lf32a;
461   FONT_LogFont16To32A(lplf, &lf32a);
462   return AddFontStyle(&lf32a, nFontType, (LPCHOOSEFONTA)lpcf->lpTemplateName,
463                       hcmb2, hcmb3, hDlg);
464 }
465
466 /***********************************************************************
467  *                 FontStyleEnumProc32                     [internal]
468  */
469 static INT WINAPI FontStyleEnumProc( LPENUMLOGFONTA lpFont, 
470           LPNEWTEXTMETRICA metrics, UINT nFontType, LPARAM lParam )
471 {
472   LPCFn_ENUMSTRUCT s=(LPCFn_ENUMSTRUCT)lParam;
473   HWND hcmb2=s->hWnd1;
474   HWND hcmb3=s->hWnd2;
475   HWND hDlg=GetParent(hcmb3);
476   return AddFontStyle(&lpFont->elfLogFont, nFontType, s->lpcf32a, hcmb2,
477                       hcmb3, hDlg);
478 }
479
480 /***********************************************************************
481  *           CFn_WMInitDialog                            [internal]
482  */
483 static LRESULT CFn_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam,
484                          LPCHOOSEFONTA lpcf)
485 {
486   HDC hdc;
487   int i,j,res,init=0;
488   long l;
489   LPLOGFONTA lpxx;
490   HCURSOR hcursor=SetCursor(LoadCursorA(0,IDC_WAITA));
491
492   SetWindowLongA(hDlg, DWL_USER, lParam); 
493   lpxx=lpcf->lpLogFont;
494   TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
495
496   if (lpcf->lStructSize != sizeof(CHOOSEFONTA))
497   {
498     ERR("structure size failure !!!\n");
499     EndDialog (hDlg, 0); 
500     return FALSE;
501   }
502   if (!hBitmapTT)
503     hBitmapTT = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_TRTYPE));
504
505   /* This font will be deleted by WM_COMMAND */
506   SendDlgItemMessageA(hDlg,stc6,WM_SETFONT,
507      CreateFontA(0, 0, 1, 1, 400, 0, 0, 0, 0, 0, 0, 0, 0, NULL),FALSE);
508                          
509   if (!(lpcf->Flags & CF_SHOWHELP) || !IsWindow(lpcf->hwndOwner))
510     ShowWindow(GetDlgItem(hDlg,pshHelp),SW_HIDE);
511   if (!(lpcf->Flags & CF_APPLY))
512     ShowWindow(GetDlgItem(hDlg,psh3),SW_HIDE);
513   if (lpcf->Flags & CF_EFFECTS)
514   {
515     for (res=1,i=0;res && i<TEXT_COLORS;i++)
516     {
517       /* FIXME: load color name from resource:  res=LoadString(...,i+....,buffer,.....); */
518       char name[20];
519       strcpy( name, "[color name]" );
520       j=SendDlgItemMessageA(hDlg, cmb4, CB_ADDSTRING, 0, (LPARAM)name);
521       SendDlgItemMessageA(hDlg, cmb4, CB_SETITEMDATA16, j, textcolors[j]);
522       /* look for a fitting value in color combobox */
523       if (textcolors[j]==lpcf->rgbColors)
524         SendDlgItemMessageA(hDlg,cmb4, CB_SETCURSEL,j,0);
525     }
526   }
527   else
528   {
529     ShowWindow(GetDlgItem(hDlg,cmb4),SW_HIDE);
530     ShowWindow(GetDlgItem(hDlg,chx1),SW_HIDE);
531     ShowWindow(GetDlgItem(hDlg,chx2),SW_HIDE);
532     ShowWindow(GetDlgItem(hDlg,grp1),SW_HIDE);
533     ShowWindow(GetDlgItem(hDlg,stc4),SW_HIDE);
534   }
535   hdc= (lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
536   if (hdc)
537   {
538     CFn_ENUMSTRUCT s;
539     s.hWnd1=GetDlgItem(hDlg,cmb1);
540     s.lpcf32a=lpcf;
541     if (!EnumFontFamiliesA(hdc, NULL, FontFamilyEnumProc, (LPARAM)&s))
542       TRACE("EnumFontFamilies returns 0\n");
543     if (lpcf->Flags & CF_INITTOLOGFONTSTRUCT)
544     {
545       /* look for fitting font name in combobox1 */
546       j=SendDlgItemMessageA(hDlg,cmb1,CB_FINDSTRING,-1,(LONG)lpxx->lfFaceName);
547       if (j!=CB_ERR)
548       {
549         SendDlgItemMessageA(hDlg, cmb1, CB_SETCURSEL, j, 0);
550         SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE),
551                        GetDlgItem(hDlg,cmb1));
552         init=1;
553         /* look for fitting font style in combobox2 */
554         l=MAKELONG(lpxx->lfWeight > FW_MEDIUM ? FW_BOLD:FW_NORMAL,lpxx->lfItalic !=0);
555         for (i=0;i<TEXT_EXTRAS;i++)
556         {
557           if (l==SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0))
558             SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
559         }
560       
561         /* look for fitting font size in combobox3 */
562         j=SendDlgItemMessageA(hDlg, cmb3, CB_GETCOUNT, 0, 0);
563         for (i=0;i<j;i++)
564         {
565           if (lpxx->lfHeight==(int)SendDlgItemMessageA(hDlg,cmb3, CB_GETITEMDATA,i,0))
566             SendDlgItemMessageA(hDlg,cmb3,CB_SETCURSEL,i,0);
567         }
568       }
569     }
570     if (!init)
571     {
572       SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0);
573       SendMessageA(hDlg, WM_COMMAND, MAKEWPARAM(cmb1, CBN_SELCHANGE),
574                        GetDlgItem(hDlg,cmb1));
575     }    
576     if (lpcf->Flags & CF_USESTYLE && lpcf->lpszStyle)
577     {
578       j=SendDlgItemMessageA(hDlg,cmb2,CB_FINDSTRING,-1,(LONG)lpcf->lpszStyle);
579       if (j!=CB_ERR)
580       {
581         j=SendDlgItemMessageA(hDlg,cmb2,CB_SETCURSEL,j,0);
582         SendMessageA(hDlg,WM_COMMAND,cmb2,
583                        MAKELONG(GetDlgItem(hDlg,cmb2),CBN_SELCHANGE));
584       }
585     }
586   }
587   else
588   {
589     WARN("HDC failure !!!\n");
590     EndDialog (hDlg, 0); 
591     return FALSE;
592   }
593
594   if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
595     ReleaseDC(hDlg,hdc);
596   SetCursor(hcursor);   
597   return TRUE;
598 }
599
600
601 /***********************************************************************
602  *           CFn_WMMeasureItem                           [internal]
603  */
604 static LRESULT CFn_WMMeasureItem(HWND hDlg, WPARAM wParam, LPARAM lParam)
605 {
606   BITMAP bm;
607   LPMEASUREITEMSTRUCT lpmi=(LPMEASUREITEMSTRUCT)lParam;
608   if (!hBitmapTT)
609     hBitmapTT = LoadBitmapA(0, MAKEINTRESOURCEA(OBM_TRTYPE));
610   GetObjectA( hBitmapTT, sizeof(bm), &bm );
611   lpmi->itemHeight=bm.bmHeight;
612   /* FIXME: use MAX of bm.bmHeight and tm.tmHeight .*/
613   return 0;
614 }
615
616
617 /***********************************************************************
618  *           CFn_WMDrawItem                              [internal]
619  */
620 static LRESULT CFn_WMDrawItem(HWND hDlg, WPARAM wParam, LPARAM lParam)
621 {
622   HBRUSH hBrush;
623   char buffer[40];
624   BITMAP bm;
625   COLORREF cr, oldText=0, oldBk=0;
626   RECT rect;
627 #if 0  
628   HDC hMemDC;
629   int nFontType;
630   HBITMAP hBitmap; /* for later TT usage */
631 #endif  
632   LPDRAWITEMSTRUCT lpdi = (LPDRAWITEMSTRUCT)lParam;
633
634   if (lpdi->itemID == 0xFFFF)                   /* got no items */
635     DrawFocusRect(lpdi->hDC, &lpdi->rcItem);
636   else
637   {
638    if (lpdi->CtlType == ODT_COMBOBOX)
639    {
640      if (lpdi->itemState ==ODS_SELECTED)
641      {
642        hBrush=GetSysColorBrush(COLOR_HIGHLIGHT);
643        oldText=SetTextColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
644        oldBk=SetBkColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHT));
645      }  else
646      {
647        hBrush = SelectObject(lpdi->hDC, GetStockObject(LTGRAY_BRUSH));
648        SelectObject(lpdi->hDC, hBrush);
649      }
650      FillRect(lpdi->hDC, &lpdi->rcItem, hBrush);
651    }
652    else
653      return TRUE;       /* this should never happen */
654
655    rect=lpdi->rcItem;
656    switch (lpdi->CtlID)
657    {
658     case cmb1:  /* TRACE(commdlg,"WM_Drawitem cmb1\n"); */
659                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
660                                (LPARAM)buffer);           
661                 GetObjectA( hBitmapTT, sizeof(bm), &bm );
662                 TextOutA(lpdi->hDC, lpdi->rcItem.left + bm.bmWidth + 10,
663                            lpdi->rcItem.top, buffer, strlen(buffer));
664 #if 0
665                 nFontType = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
666                   /* FIXME: draw bitmap if truetype usage */
667                 if (nFontType&TRUETYPE_FONTTYPE)
668                 {
669                   hMemDC = CreateCompatibleDC(lpdi->hDC);
670                   hBitmap = SelectObject(hMemDC, hBitmapTT);
671                   BitBlt(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top,
672                            bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
673                   SelectObject(hMemDC, hBitmap);
674                   DeleteDC(hMemDC);
675                 }
676 #endif
677                 break;
678     case cmb2:
679     case cmb3:  /* TRACE(commdlg,"WM_DRAWITEN cmb2,cmb3\n"); */
680                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
681                                (LPARAM)buffer);
682                 TextOutA(lpdi->hDC, lpdi->rcItem.left,
683                            lpdi->rcItem.top, buffer, strlen(buffer));
684                 break;
685
686     case cmb4:  /* TRACE(commdlg,"WM_DRAWITEM cmb4 (=COLOR)\n"); */
687                 SendMessageA(lpdi->hwndItem, CB_GETLBTEXT, lpdi->itemID,
688                                (LPARAM)buffer);
689                 TextOutA(lpdi->hDC, lpdi->rcItem.left +  25+5,
690                            lpdi->rcItem.top, buffer, strlen(buffer));
691                 cr = SendMessageA(lpdi->hwndItem, CB_GETITEMDATA, lpdi->itemID,0L);
692                 hBrush = CreateSolidBrush(cr);
693                 if (hBrush)
694                 {
695                   hBrush = SelectObject (lpdi->hDC, hBrush) ;
696                   rect.right=rect.left+25;
697                   rect.top++;
698                   rect.left+=5;
699                   rect.bottom--;
700                   Rectangle( lpdi->hDC, rect.left, rect.top,
701                                rect.right, rect.bottom );
702                   DeleteObject( SelectObject (lpdi->hDC, hBrush)) ;
703                 }
704                 rect=lpdi->rcItem;
705                 rect.left+=25+5;
706                 break;
707
708     default:    return TRUE;    /* this should never happen */
709    }
710    if (lpdi->itemState == ODS_SELECTED)
711    {
712      SetTextColor(lpdi->hDC, oldText);
713      SetBkColor(lpdi->hDC, oldBk);
714    }
715  }
716  return TRUE;
717 }
718
719 /***********************************************************************
720  *           CFn_WMCtlColor                              [internal]
721  */
722 static LRESULT CFn_WMCtlColorStatic(HWND hDlg, WPARAM wParam, LPARAM lParam,
723                              LPCHOOSEFONTA lpcf)
724 {
725   if (lpcf->Flags & CF_EFFECTS)
726    if (GetDlgCtrlID(lParam)==stc6)
727    {
728      SetTextColor((HDC)wParam, lpcf->rgbColors);
729      return GetStockObject(WHITE_BRUSH);
730    }
731   return 0;
732 }
733
734 /***********************************************************************
735  *           CFn_WMCommand                               [internal]
736  */
737 static LRESULT CFn_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam,
738                       LPCHOOSEFONTA lpcf)
739 {
740   HFONT hFont;
741   int i,j;
742   long l;
743   HDC hdc;
744   LPLOGFONTA lpxx=lpcf->lpLogFont;
745   
746   TRACE("WM_COMMAND wParam=%08lX lParam=%08lX\n", (LONG)wParam, lParam);
747   switch (LOWORD(wParam))
748   {
749         case cmb1:if (HIWORD(wParam)==CBN_SELCHANGE)
750                   {
751                     hdc=(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC) ? lpcf->hDC : GetDC(hDlg);
752                     if (hdc)
753                     {
754                       SendDlgItemMessageA(hDlg, cmb2, CB_RESETCONTENT16, 0, 0); 
755                       SendDlgItemMessageA(hDlg, cmb3, CB_RESETCONTENT16, 0, 0);
756                       i=SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL16, 0, 0);
757                       if (i!=CB_ERR)
758                       {
759                         HCURSOR hcursor=SetCursor(LoadCursorA(0,IDC_WAITA));
760                         CFn_ENUMSTRUCT s;
761                         char str[256];
762                         SendDlgItemMessageA(hDlg, cmb1, CB_GETLBTEXT, i,
763                                               (LPARAM)str);
764                         TRACE("WM_COMMAND/cmb1 =>%s\n",str);
765                         s.hWnd1=GetDlgItem(hDlg, cmb2);
766                         s.hWnd2=GetDlgItem(hDlg, cmb3);
767                         s.lpcf32a=lpcf;
768                         EnumFontFamiliesA(hdc, str, FontStyleEnumProc, (LPARAM)&s);
769                         SetCursor(hcursor);
770                       }
771                       if (!(lpcf->Flags & CF_PRINTERFONTS && lpcf->hDC))
772                         ReleaseDC(hDlg,hdc);
773                     }
774                     else
775                     {
776                       WARN("HDC failure !!!\n");
777                       EndDialog (hDlg, 0); 
778                       return TRUE;
779                     }
780                   }
781         case chx1:
782         case chx2:
783         case cmb2:
784         case cmb3:if (HIWORD(wParam)==CBN_SELCHANGE || HIWORD(wParam)== BN_CLICKED )
785                   {
786                     char str[256];
787                     TRACE("WM_COMMAND/cmb2,3 =%08lX\n", lParam);
788                     i=SendDlgItemMessageA(hDlg,cmb1,CB_GETCURSEL,0,0);
789                     if (i==CB_ERR)
790                       i=GetDlgItemTextA( hDlg, cmb1, str, 256 );
791                     else
792                     {
793                       SendDlgItemMessageA(hDlg,cmb1,CB_GETLBTEXT,i,
794                                             (LPARAM)str);
795                       l=SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,i,0);
796                       j=HIWORD(l);
797                       lpcf->nFontType = LOWORD(l);
798                       /* FIXME:   lpcf->nFontType |= ....  SIMULATED_FONTTYPE and so */
799                       /* same value reported to the EnumFonts
800                        call back with the extra FONTTYPE_...  bits added */
801                       lpxx->lfPitchAndFamily=j&0xff;
802                       lpxx->lfCharSet=j>>8;
803                     }
804                     strcpy(lpxx->lfFaceName,str);
805                     i=SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
806                     if (i!=CB_ERR)
807                     {
808                       l=SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0);
809                       if (0!=(lpxx->lfItalic=HIWORD(l)))
810                         lpcf->nFontType |= ITALIC_FONTTYPE;
811                       if ((lpxx->lfWeight=LOWORD(l)) > FW_MEDIUM)
812                         lpcf->nFontType |= BOLD_FONTTYPE;
813                     }
814                     i=SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
815                     if (i!=CB_ERR)
816                       lpxx->lfHeight=-LOWORD(SendDlgItemMessageA(hDlg, cmb3, CB_GETITEMDATA, i, 0));
817                     else
818                       lpxx->lfHeight=0;
819                     lpxx->lfStrikeOut=IsDlgButtonChecked(hDlg,chx1);
820                     lpxx->lfUnderline=IsDlgButtonChecked(hDlg,chx2);
821                     lpxx->lfWidth=lpxx->lfOrientation=lpxx->lfEscapement=0;
822                     lpxx->lfOutPrecision=OUT_DEFAULT_PRECIS;
823                     lpxx->lfClipPrecision=CLIP_DEFAULT_PRECIS;
824                     lpxx->lfQuality=DEFAULT_QUALITY;
825                     lpcf->iPointSize= -10*lpxx->lfHeight;
826
827                     hFont=CreateFontIndirectA(lpxx);
828                     if (hFont)
829                     {
830                       HFONT oldFont=SendDlgItemMessageA(hDlg, stc6, 
831                           WM_GETFONT, 0, 0);
832                       SendDlgItemMessageA(hDlg,stc6,WM_SETFONT,hFont,TRUE);
833                       DeleteObject(oldFont);
834                     }
835                   }
836                   break;
837
838         case cmb4:i=SendDlgItemMessageA(hDlg, cmb4, CB_GETCURSEL, 0, 0);
839                   if (i!=CB_ERR)
840                   {
841                    lpcf->rgbColors=textcolors[i];
842                    InvalidateRect( GetDlgItem(hDlg,stc6), NULL, 0 );
843                   }
844                   break;
845         
846         case psh15:i=RegisterWindowMessageA( HELPMSGSTRING );
847                   if (lpcf->hwndOwner)
848                     SendMessageA(lpcf->hwndOwner, i, 0, (LPARAM)GetWindowLongA(hDlg, DWL_USER));
849 /*                if (CFn_HookCallChk(lpcf))
850                     CallWindowProc16(lpcf->lpfnHook,hDlg,WM_COMMAND,psh15,(LPARAM)lpcf);*/
851                   break;
852
853         case IDOK:if (  (!(lpcf->Flags & CF_LIMITSIZE))  ||
854                      ( (lpcf->Flags & CF_LIMITSIZE) && 
855                       (-lpxx->lfHeight >= lpcf->nSizeMin) && 
856                       (-lpxx->lfHeight <= lpcf->nSizeMax)))
857                      EndDialog(hDlg, TRUE);
858                   else
859                   {
860                    char buffer[80];
861                    sprintf(buffer,"Select a font size between %d and %d points.",
862                            lpcf->nSizeMin,lpcf->nSizeMax);
863                    MessageBoxA(hDlg, buffer, NULL, MB_OK);
864                   } 
865                   return(TRUE);
866         case IDCANCEL:EndDialog(hDlg, FALSE);
867                   return(TRUE);
868         }
869       return(FALSE);
870 }
871
872 static LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
873 {
874   DeleteObject(SendDlgItemMessageA(hwnd, stc6, WM_GETFONT, 0, 0));
875   return TRUE;
876 }
877
878
879 /***********************************************************************
880  *           FormatCharDlgProc16   (COMMDLG.16)
881              FIXME: 1. some strings are "hardcoded", but it's better load from sysres
882                     2. some CF_.. flags are not supported
883                     3. some TType extensions
884  */
885 LRESULT WINAPI FormatCharDlgProc16(HWND16 hDlg, UINT16 message, WPARAM16 wParam,
886                                    LPARAM lParam)
887 {
888   LPCHOOSEFONT16 lpcf;
889   LPCHOOSEFONTA lpcf32a;
890   UINT uMsg32;
891   WPARAM wParam32;
892   LRESULT res=0;  
893   if (message!=WM_INITDIALOG)
894   {
895    lpcf=(LPCHOOSEFONT16)GetWindowLongA(hDlg, DWL_USER);   
896    if (!lpcf)
897       return FALSE;
898    if (CFn_HookCallChk(lpcf))
899      res=CallWindowProc16((WNDPROC16)lpcf->lpfnHook,hDlg,message,wParam,lParam);
900    if (res)
901     return res;
902   }
903   else
904   {
905     lpcf=(LPCHOOSEFONT16)lParam;
906     lpcf32a=(LPCHOOSEFONTA)lpcf->lpTemplateName;
907     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf32a)) 
908     {
909       TRACE("CFn_WMInitDialog returned FALSE\n");
910       return FALSE;
911     }  
912     if (CFn_HookCallChk(lpcf))
913       return CallWindowProc16((WNDPROC16)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
914   }
915   WINPROC_MapMsg16To32A(message, wParam, &uMsg32, &wParam32, &lParam);
916   lpcf32a=(LPCHOOSEFONTA)lpcf->lpTemplateName;
917   switch (uMsg32)
918     {
919       case WM_MEASUREITEM:
920                         res=CFn_WMMeasureItem(hDlg, wParam32, lParam);
921                         break;
922       case WM_DRAWITEM:
923                         res=CFn_WMDrawItem(hDlg, wParam32, lParam);
924                         break;
925       case WM_CTLCOLORSTATIC:
926                         res=CFn_WMCtlColorStatic(hDlg, wParam32, lParam, lpcf32a);
927                         break;
928       case WM_COMMAND:
929                         res=CFn_WMCommand(hDlg, wParam32, lParam, lpcf32a);
930                         break;
931       case WM_DESTROY:
932                         res=CFn_WMDestroy(hDlg, wParam32, lParam);
933                         break;
934       case WM_CHOOSEFONT_GETLOGFONT: 
935                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
936                                       lParam);
937                          FIXME("current logfont back to caller\n");
938                         break;
939     }
940   WINPROC_UnmapMsg16To32A(hDlg,uMsg32, wParam32, lParam, res);    
941   return res;
942 }
943
944 /***********************************************************************
945  *           FormatCharDlgProcA   [internal]
946  */
947 LRESULT WINAPI FormatCharDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
948                                     LPARAM lParam)
949 {
950   LPCHOOSEFONTA lpcf;
951   LRESULT res=FALSE;
952   if (uMsg!=WM_INITDIALOG)
953   {
954    lpcf=(LPCHOOSEFONTA)GetWindowLongA(hDlg, DWL_USER);   
955    if (!lpcf)
956      return FALSE;
957    if (CFn_HookCallChk32(lpcf))
958      res=CallWindowProcA((WNDPROC)lpcf->lpfnHook, hDlg, uMsg, wParam, lParam);
959    if (res)
960      return res;
961   }
962   else
963   {
964     lpcf=(LPCHOOSEFONTA)lParam;
965     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf)) 
966     {
967       TRACE("CFn_WMInitDialog returned FALSE\n");
968       return FALSE;
969     }  
970     if (CFn_HookCallChk32(lpcf))
971       return CallWindowProcA((WNDPROC)lpcf->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
972   }
973   switch (uMsg)
974     {
975       case WM_MEASUREITEM:
976                         return CFn_WMMeasureItem(hDlg, wParam, lParam);
977       case WM_DRAWITEM:
978                         return CFn_WMDrawItem(hDlg, wParam, lParam);
979       case WM_CTLCOLORSTATIC:
980                         return CFn_WMCtlColorStatic(hDlg, wParam, lParam, lpcf);
981       case WM_COMMAND:
982                         return CFn_WMCommand(hDlg, wParam, lParam, lpcf);
983       case WM_DESTROY:
984                         return CFn_WMDestroy(hDlg, wParam, lParam);
985       case WM_CHOOSEFONT_GETLOGFONT:
986                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
987                                       lParam);
988                          FIXME("current logfont back to caller\n");
989                         break;
990     }
991   return res;
992 }
993
994 /***********************************************************************
995  *           FormatCharDlgProcW   [internal]
996  */
997 LRESULT WINAPI FormatCharDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
998                                     LPARAM lParam)
999 {
1000   LPCHOOSEFONTW lpcf32w;
1001   LPCHOOSEFONTA lpcf32a;
1002   LRESULT res=FALSE;
1003   if (uMsg!=WM_INITDIALOG)
1004   {
1005    lpcf32w=(LPCHOOSEFONTW)GetWindowLongA(hDlg, DWL_USER);   
1006    if (!lpcf32w)
1007      return FALSE;
1008    if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w))
1009      res=CallWindowProcW((WNDPROC)lpcf32w->lpfnHook, hDlg, uMsg, wParam, lParam);
1010    if (res)
1011      return res;
1012   }
1013   else
1014   {
1015     lpcf32w=(LPCHOOSEFONTW)lParam;
1016     lpcf32a=(LPCHOOSEFONTA)lpcf32w->lpTemplateName;
1017     if (!CFn_WMInitDialog(hDlg, wParam, lParam, lpcf32a)) 
1018     {
1019       TRACE("CFn_WMInitDialog returned FALSE\n");
1020       return FALSE;
1021     }  
1022     if (CFn_HookCallChk32((LPCHOOSEFONTA)lpcf32w))
1023       return CallWindowProcW((WNDPROC)lpcf32w->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
1024   }
1025   lpcf32a=(LPCHOOSEFONTA)lpcf32w->lpTemplateName;
1026   switch (uMsg)
1027     {
1028       case WM_MEASUREITEM:
1029                         return CFn_WMMeasureItem(hDlg, wParam, lParam);
1030       case WM_DRAWITEM:
1031                         return CFn_WMDrawItem(hDlg, wParam, lParam);
1032       case WM_CTLCOLORSTATIC:
1033                         return CFn_WMCtlColorStatic(hDlg, wParam, lParam, lpcf32a);
1034       case WM_COMMAND:
1035                         return CFn_WMCommand(hDlg, wParam, lParam, lpcf32a);
1036       case WM_DESTROY:
1037                         return CFn_WMDestroy(hDlg, wParam, lParam);
1038       case WM_CHOOSEFONT_GETLOGFONT: 
1039                          TRACE("WM_CHOOSEFONT_GETLOGFONT lParam=%08lX\n",
1040                                       lParam);
1041                          FIXME("current logfont back to caller\n");
1042                         break;
1043     }
1044   return res;
1045 }
1046
1047