Release 990923.
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include "wine/winestring.h"
11 #include "font.h"
12 #include "heap.h"
13 #include "metafile.h"
14 #include "options.h"
15 #include "debugtools.h"
16 #include "winerror.h"
17 #include "dc.h"
18
19 DECLARE_DEBUG_CHANNEL(font)
20 DECLARE_DEBUG_CHANNEL(gdi)
21
22 #define ENUM_UNICODE    0x00000001
23
24 typedef struct
25 {
26   LPLOGFONT16           lpLogFontParam;
27   FONTENUMPROCEX16      lpEnumFunc;
28   LPARAM                lpData;
29
30   LPNEWTEXTMETRICEX16   lpTextMetric;
31   LPENUMLOGFONTEX16     lpLogFont;
32   SEGPTR                segTextMetric;
33   SEGPTR                segLogFont;
34 } fontEnum16;
35
36 typedef struct
37 {
38   LPLOGFONTW          lpLogFontParam;
39   FONTENUMPROCW       lpEnumFunc;
40   LPARAM                lpData;
41
42   LPNEWTEXTMETRICEXW  lpTextMetric;
43   LPENUMLOGFONTEXW    lpLogFont;
44   DWORD                 dwFlags;
45 } fontEnum32;
46  
47 /*
48  *  For TranslateCharsetInfo
49  */
50 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
51 #define MAXTCIINDEX 32
52 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
53   /* ANSI */
54   { ANSI_CHARSET, 1252, FS(0)},
55   { EASTEUROPE_CHARSET, 1250, FS(1)},
56   { RUSSIAN_CHARSET, 1251, FS(2)},
57   { GREEK_CHARSET, 1253, FS(3)},
58   { TURKISH_CHARSET, 1254, FS(4)},
59   { HEBREW_CHARSET, 1255, FS(5)},
60   { ARABIC_CHARSET, 1256, FS(6)},
61   { BALTIC_CHARSET, 1257, FS(7)},
62   /* reserved by ANSI */
63   { DEFAULT_CHARSET, 0, FS(0)},
64   { DEFAULT_CHARSET, 0, FS(0)},
65   { DEFAULT_CHARSET, 0, FS(0)},
66   { DEFAULT_CHARSET, 0, FS(0)},
67   { DEFAULT_CHARSET, 0, FS(0)},
68   { DEFAULT_CHARSET, 0, FS(0)},
69   { DEFAULT_CHARSET, 0, FS(0)},
70   { DEFAULT_CHARSET, 0, FS(0)},
71   /* ANSI and OEM */
72   { THAI_CHARSET,  874,  FS(16)},
73   { SHIFTJIS_CHARSET, 932, FS(17)},
74   { GB2312_CHARSET, 936, FS(18)},
75   { HANGEUL_CHARSET, 949, FS(19)},
76   { CHINESEBIG5_CHARSET, 950, FS(20)},
77   { JOHAB_CHARSET, 1361, FS(21)}, 
78   /* reserved for alternate ANSI and OEM */
79   { DEFAULT_CHARSET, 0, FS(0)},
80   { DEFAULT_CHARSET, 0, FS(0)},
81   { DEFAULT_CHARSET, 0, FS(0)},
82   { DEFAULT_CHARSET, 0, FS(0)},
83   { DEFAULT_CHARSET, 0, FS(0)},
84   { DEFAULT_CHARSET, 0, FS(0)},
85   { DEFAULT_CHARSET, 0, FS(0)},
86   { DEFAULT_CHARSET, 0, FS(0)},
87   /* reserved for system */
88   { DEFAULT_CHARSET, 0, FS(0)},
89   { DEFAULT_CHARSET, 0, FS(0)},
90 };
91
92 /***********************************************************************
93  *              LOGFONT conversion functions.
94  */
95 static void __logfont32to16( INT16* plf16, const INT* plf32 )
96 {
97     int  i;
98     for( i = 0; i < 5; i++ ) *plf16++ = *plf32++;
99    *((INT*)plf16)++ = *plf32++;
100    *((INT*)plf16)   = *plf32;
101 }
102
103 static void __logfont16to32( INT* plf32, const INT16* plf16 )
104 {
105     int i;
106     for( i = 0; i < 5; i++ ) *plf32++ = *plf16++;
107    *plf32++ = *((INT*)plf16)++;
108    *plf32   = *((INT*)plf16);
109 }
110
111 void FONT_LogFont32ATo16( const LOGFONTA* font32, LPLOGFONT16 font16 )
112 {
113   __logfont32to16( (INT16*)font16, (const INT*)font32 );
114     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
115 }
116
117 void FONT_LogFont32WTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
118 {
119   __logfont32to16( (INT16*)font16, (const INT*)font32 );
120     lstrcpynWtoA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
121 }
122
123 void FONT_LogFont16To32A( const LPLOGFONT16 font16, LPLOGFONTA font32 )
124 {
125   __logfont16to32( (INT*)font32, (const INT16*)font16 );
126     lstrcpynA( font32->lfFaceName, font16->lfFaceName, LF_FACESIZE );
127 }
128
129 void FONT_LogFont16To32W( const LPLOGFONT16 font16, LPLOGFONTW font32 )
130 {
131   __logfont16to32( (INT*)font32, (const INT16*)font16 );
132     lstrcpynAtoW( font32->lfFaceName, font16->lfFaceName, LF_FACESIZE );
133 }
134
135 /***********************************************************************
136  *              TEXTMETRIC conversion functions.
137  */
138 void FONT_TextMetric32Ato16(const LPTEXTMETRICA ptm32, LPTEXTMETRIC16 ptm16 )
139 {
140     ptm16->tmHeight = ptm32->tmHeight;
141     ptm16->tmAscent = ptm32->tmAscent;
142     ptm16->tmDescent = ptm32->tmDescent;
143     ptm16->tmInternalLeading = ptm32->tmInternalLeading;
144     ptm16->tmExternalLeading = ptm32->tmExternalLeading;
145     ptm16->tmAveCharWidth = ptm32->tmAveCharWidth;
146     ptm16->tmMaxCharWidth = ptm32->tmMaxCharWidth;
147     ptm16->tmWeight = ptm32->tmWeight;
148     ptm16->tmOverhang = ptm32->tmOverhang;
149     ptm16->tmDigitizedAspectX = ptm32->tmDigitizedAspectX;
150     ptm16->tmDigitizedAspectY = ptm32->tmDigitizedAspectY;
151     ptm16->tmFirstChar = ptm32->tmFirstChar;
152     ptm16->tmLastChar = ptm32->tmLastChar;
153     ptm16->tmDefaultChar = ptm32->tmDefaultChar;
154     ptm16->tmBreakChar = ptm32->tmBreakChar;
155     ptm16->tmItalic = ptm32->tmItalic;
156     ptm16->tmUnderlined = ptm32->tmUnderlined;
157     ptm16->tmStruckOut = ptm32->tmStruckOut;
158     ptm16->tmPitchAndFamily = ptm32->tmPitchAndFamily;
159     ptm16->tmCharSet = ptm32->tmCharSet;
160 }
161
162 void FONT_TextMetric32Wto16(const LPTEXTMETRICW ptm32, LPTEXTMETRIC16 ptm16 )
163 {
164     ptm16->tmHeight = ptm32->tmHeight;
165     ptm16->tmAscent = ptm32->tmAscent;
166     ptm16->tmDescent = ptm32->tmDescent;
167     ptm16->tmInternalLeading = ptm32->tmInternalLeading;
168     ptm16->tmExternalLeading = ptm32->tmExternalLeading;
169     ptm16->tmAveCharWidth = ptm32->tmAveCharWidth;
170     ptm16->tmMaxCharWidth = ptm32->tmMaxCharWidth;
171     ptm16->tmWeight = ptm32->tmWeight;
172     ptm16->tmOverhang = ptm32->tmOverhang;
173     ptm16->tmDigitizedAspectX = ptm32->tmDigitizedAspectX;
174     ptm16->tmDigitizedAspectY = ptm32->tmDigitizedAspectY;
175     ptm16->tmFirstChar = ptm32->tmFirstChar;
176     ptm16->tmLastChar = ptm32->tmLastChar;
177     ptm16->tmDefaultChar = ptm32->tmDefaultChar;
178     ptm16->tmBreakChar = ptm32->tmBreakChar;
179     ptm16->tmItalic = ptm32->tmItalic;
180     ptm16->tmUnderlined = ptm32->tmUnderlined;
181     ptm16->tmStruckOut = ptm32->tmStruckOut;
182     ptm16->tmPitchAndFamily = ptm32->tmPitchAndFamily;
183     ptm16->tmCharSet = ptm32->tmCharSet;
184 }
185
186 void FONT_TextMetric16to32A(const LPTEXTMETRIC16 ptm16, LPTEXTMETRICA ptm32 )
187 {
188     ptm32->tmHeight = ptm16->tmHeight;
189     ptm32->tmAscent = ptm16->tmAscent;
190     ptm32->tmDescent = ptm16->tmDescent;
191     ptm32->tmInternalLeading = ptm16->tmInternalLeading;
192     ptm32->tmExternalLeading = ptm16->tmExternalLeading;
193     ptm32->tmAveCharWidth = ptm16->tmAveCharWidth;
194     ptm32->tmMaxCharWidth = ptm16->tmMaxCharWidth;
195     ptm32->tmWeight = ptm16->tmWeight;
196     ptm32->tmOverhang = ptm16->tmOverhang;
197     ptm32->tmDigitizedAspectX = ptm16->tmDigitizedAspectX;
198     ptm32->tmDigitizedAspectY = ptm16->tmDigitizedAspectY;
199     ptm32->tmFirstChar = ptm16->tmFirstChar;
200     ptm32->tmLastChar = ptm16->tmLastChar;
201     ptm32->tmDefaultChar = ptm16->tmDefaultChar;
202     ptm32->tmBreakChar = ptm16->tmBreakChar;
203     ptm32->tmItalic = ptm16->tmItalic;
204     ptm32->tmUnderlined = ptm16->tmUnderlined;
205     ptm32->tmStruckOut = ptm16->tmStruckOut;
206     ptm32->tmPitchAndFamily = ptm16->tmPitchAndFamily;
207     ptm32->tmCharSet = ptm16->tmCharSet;
208 }
209
210 void FONT_TextMetric16to32W(const LPTEXTMETRIC16 ptm16, LPTEXTMETRICW ptm32 )
211 {
212     ptm32->tmHeight = ptm16->tmHeight;
213     ptm32->tmAscent = ptm16->tmAscent;
214     ptm32->tmDescent = ptm16->tmDescent;
215     ptm32->tmInternalLeading = ptm16->tmInternalLeading;
216     ptm32->tmExternalLeading = ptm16->tmExternalLeading;
217     ptm32->tmAveCharWidth = ptm16->tmAveCharWidth;
218     ptm32->tmMaxCharWidth = ptm16->tmMaxCharWidth;
219     ptm32->tmWeight = ptm16->tmWeight;
220     ptm32->tmOverhang = ptm16->tmOverhang;
221     ptm32->tmDigitizedAspectX = ptm16->tmDigitizedAspectX;
222     ptm32->tmDigitizedAspectY = ptm16->tmDigitizedAspectY;
223     ptm32->tmFirstChar = ptm16->tmFirstChar;
224     ptm32->tmLastChar = ptm16->tmLastChar;
225     ptm32->tmDefaultChar = ptm16->tmDefaultChar;
226     ptm32->tmBreakChar = ptm16->tmBreakChar;
227     ptm32->tmItalic = ptm16->tmItalic;
228     ptm32->tmUnderlined = ptm16->tmUnderlined;
229     ptm32->tmStruckOut = ptm16->tmStruckOut;
230     ptm32->tmPitchAndFamily = ptm16->tmPitchAndFamily;
231     ptm32->tmCharSet = ptm16->tmCharSet;
232 }
233
234 void FONT_TextMetric32Ato32W(const LPTEXTMETRICA ptm32A, LPTEXTMETRICW ptm32W )
235 {
236     ptm32W->tmHeight = ptm32A->tmHeight;
237     ptm32W->tmAscent = ptm32A->tmAscent;
238     ptm32W->tmDescent = ptm32A->tmDescent;
239     ptm32W->tmInternalLeading = ptm32A->tmInternalLeading;
240     ptm32W->tmExternalLeading = ptm32A->tmExternalLeading;
241     ptm32W->tmAveCharWidth = ptm32A->tmAveCharWidth;
242     ptm32W->tmMaxCharWidth = ptm32A->tmMaxCharWidth;
243     ptm32W->tmWeight = ptm32A->tmWeight;
244     ptm32W->tmOverhang = ptm32A->tmOverhang;
245     ptm32W->tmDigitizedAspectX = ptm32A->tmDigitizedAspectX;
246     ptm32W->tmDigitizedAspectY = ptm32A->tmDigitizedAspectY;
247     ptm32W->tmFirstChar = ptm32A->tmFirstChar;
248     ptm32W->tmLastChar = ptm32A->tmLastChar;
249     ptm32W->tmDefaultChar = ptm32A->tmDefaultChar;
250     ptm32W->tmBreakChar = ptm32A->tmBreakChar;
251     ptm32W->tmItalic = ptm32A->tmItalic;
252     ptm32W->tmUnderlined = ptm32A->tmUnderlined;
253     ptm32W->tmStruckOut = ptm32A->tmStruckOut;
254     ptm32W->tmPitchAndFamily = ptm32A->tmPitchAndFamily;
255     ptm32W->tmCharSet = ptm32A->tmCharSet;
256 }
257
258 /***********************************************************************
259  *           CreateFontIndirect16   (GDI.57)
260  */
261 HFONT16 WINAPI CreateFontIndirect16( const LOGFONT16 *font )
262 {
263     HFONT16 hFont = 0;
264
265     if (font)
266     {
267         hFont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
268         if( hFont )
269         {
270             FONTOBJ* fontPtr;
271             fontPtr = (FONTOBJ *) GDI_HEAP_LOCK( hFont );
272             memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
273
274             TRACE_(font)("(%i %i %i %i) '%s' %s %s => %04x\n",
275                                  font->lfHeight, font->lfWidth, 
276                                  font->lfEscapement, font->lfOrientation,
277                                  font->lfFaceName ? font->lfFaceName : "NULL",
278                                  font->lfWeight > 400 ? "Bold" : "",
279                                  font->lfItalic ? "Italic" : "",
280                                  hFont);
281
282             if (font->lfEscapement != font->lfOrientation) {
283               /* this should really depend on whether GM_ADVANCED is set */
284               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
285               WARN_(font)(
286        "orientation angle %f set to escapement angle %f for new font %04x\n", 
287            font->lfOrientation/10., font->lfEscapement/10., hFont);
288             }
289             GDI_HEAP_UNLOCK( hFont );
290         }
291     }
292     else WARN_(font)("(NULL) => NULL\n");
293
294     return hFont;
295 }
296
297 /***********************************************************************
298  *           CreateFontIndirectA   (GDI32.44)
299  */
300 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *font )
301 {
302     LOGFONT16 font16;
303
304     FONT_LogFont32ATo16( font, &font16 );
305     return CreateFontIndirect16( &font16 );
306 }
307
308 /***********************************************************************
309  *           CreateFontIndirectW   (GDI32.45)
310  */
311 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *font )
312 {
313     LOGFONT16 font16;
314
315     FONT_LogFont32WTo16( font, &font16 );
316     return CreateFontIndirect16( &font16 );
317 }
318
319 /***********************************************************************
320  *           CreateFont16    (GDI.56)
321  */
322 HFONT16 WINAPI CreateFont16(INT16 height, INT16 width, INT16 esc, INT16 orient,
323                             INT16 weight, BYTE italic, BYTE underline,
324                             BYTE strikeout, BYTE charset, BYTE outpres,
325                             BYTE clippres, BYTE quality, BYTE pitch,
326                             LPCSTR name )
327 {
328     LOGFONT16 logfont;
329
330     TRACE_(font)("('%s',%d,%d)\n",
331                  (name ? name : "(null)") , height, width);
332
333     logfont.lfHeight = height;
334     logfont.lfWidth = width;
335     logfont.lfEscapement = esc;
336     logfont.lfOrientation = orient;
337     logfont.lfWeight = weight;
338     logfont.lfItalic = italic;
339     logfont.lfUnderline = underline;
340     logfont.lfStrikeOut = strikeout;
341     logfont.lfCharSet = charset;
342     logfont.lfOutPrecision = outpres;
343     logfont.lfClipPrecision = clippres;
344     logfont.lfQuality = quality;
345     logfont.lfPitchAndFamily = pitch;
346    
347     if (name) 
348         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
349     else 
350         logfont.lfFaceName[0] = '\0';
351
352     return CreateFontIndirect16( &logfont );
353 }
354
355 /*************************************************************************
356  *           CreateFontA    (GDI32.43)
357  */
358 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
359                               INT orient, INT weight, DWORD italic,
360                               DWORD underline, DWORD strikeout, DWORD charset,
361                               DWORD outpres, DWORD clippres, DWORD quality,
362                               DWORD pitch, LPCSTR name )
363 {
364     return (HFONT)CreateFont16( height, width, esc, orient, weight, italic,
365                                   underline, strikeout, charset, outpres,
366                                   clippres, quality, pitch, name );
367 }
368
369 /*************************************************************************
370  *           CreateFontW    (GDI32.46)
371  */
372 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
373                               INT orient, INT weight, DWORD italic,
374                               DWORD underline, DWORD strikeout, DWORD charset,
375                               DWORD outpres, DWORD clippres, DWORD quality,
376                               DWORD pitch, LPCWSTR name )
377 {
378     LPSTR namea = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
379     HFONT ret = (HFONT)CreateFont16( height, width, esc, orient, weight,
380                                          italic, underline, strikeout, charset,
381                                          outpres, clippres, quality, pitch,
382                                          namea );
383     if (namea) HeapFree( GetProcessHeap(), 0, namea );
384     return ret;
385 }
386
387
388 /***********************************************************************
389  *           FONT_GetObject16
390  */
391 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
392 {
393     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
394     memcpy( buffer, &font->logfont, count );
395     return count;
396 }
397
398 /***********************************************************************
399  *           FONT_GetObjectA
400  */
401 INT FONT_GetObjectA( FONTOBJ *font, INT count, LPSTR buffer )
402 {
403     LOGFONTA fnt32;
404
405     FONT_LogFont16To32A( &font->logfont, &fnt32 );
406
407     if (count > sizeof(fnt32)) count = sizeof(fnt32);
408     memcpy( buffer, &fnt32, count );
409     return count;
410 }
411 /***********************************************************************
412  *           FONT_GetObjectW
413  */
414 INT FONT_GetObjectW( FONTOBJ *font, INT count, LPSTR buffer )
415 {
416     LOGFONTW fnt32;
417
418     FONT_LogFont16To32W( &font->logfont, &fnt32 );
419
420     if (count > sizeof(fnt32)) count = sizeof(fnt32);
421     memcpy( buffer, &fnt32, count );
422     return count;
423 }
424
425
426 /***********************************************************************
427  *              FONT_EnumInstance16
428  *
429  * Called by the device driver layer to pass font info
430  * down to the application.
431  */
432 static INT FONT_EnumInstance16( LPENUMLOGFONT16 plf, 
433                                   LPNEWTEXTMETRIC16 ptm, UINT16 fType, LPARAM lp )
434 {
435 #define pfe ((fontEnum16*)lp)
436     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
437         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
438     {
439         memcpy( pfe->lpLogFont, plf, sizeof(ENUMLOGFONT16) );
440         memcpy( pfe->lpTextMetric, ptm, sizeof(NEWTEXTMETRIC16) );
441
442         return pfe->lpEnumFunc( pfe->segLogFont, pfe->segTextMetric, fType, (LPARAM)(pfe->lpData) );
443     }
444 #undef pfe
445     return 1;
446 }
447
448 /***********************************************************************
449  *              FONT_EnumInstance
450  */
451 static INT FONT_EnumInstance( LPENUMLOGFONT16 plf,
452                                   LPNEWTEXTMETRIC16 ptm, UINT16 fType, LPARAM lp )
453 {
454     /* lfCharSet is at the same offset in both LOGFONT32A and LOGFONT32W */
455
456 #define pfe ((fontEnum32*)lp)
457     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
458         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
459     {
460         /* convert font metrics */
461
462         if( pfe->dwFlags & ENUM_UNICODE )
463         {
464             FONT_LogFont16To32W( &plf->elfLogFont, (LPLOGFONTW)(pfe->lpLogFont) );
465             FONT_TextMetric16to32W( (LPTEXTMETRIC16)ptm, (LPTEXTMETRICW)(pfe->lpTextMetric) );
466         }
467         else
468         {
469             FONT_LogFont16To32A( &plf->elfLogFont, (LPLOGFONTA)pfe->lpLogFont );
470             FONT_TextMetric16to32A( (LPTEXTMETRIC16)ptm, (LPTEXTMETRICA)pfe->lpTextMetric );
471         }
472
473         return pfe->lpEnumFunc( (LPENUMLOGFONTW)pfe->lpLogFont, 
474                                 (LPNEWTEXTMETRICW)pfe->lpTextMetric, fType, pfe->lpData );
475     }
476 #undef pfe
477     return 1;
478 }
479
480 /***********************************************************************
481  *              EnumFontFamiliesEx16    (GDI.613)
482  */
483 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
484                                    FONTENUMPROCEX16 efproc, LPARAM lParam,
485                                    DWORD dwFlags)
486 {
487     INT16       retVal = 0;
488     DC*         dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
489
490     if( dc && dc->funcs->pEnumDeviceFonts )
491     {
492         LPNEWTEXTMETRICEX16     lptm16 = SEGPTR_ALLOC( sizeof(NEWTEXTMETRICEX16) );
493         if( lptm16 )
494         {
495             LPENUMLOGFONTEX16   lplf16 = SEGPTR_ALLOC( sizeof(ENUMLOGFONTEX16) );
496             if( lplf16 )
497             {
498                 fontEnum16      fe16;
499
500                 fe16.lpLogFontParam = plf;
501                 fe16.lpEnumFunc = efproc;
502                 fe16.lpData = lParam;
503                 
504                 fe16.lpTextMetric = lptm16;
505                 fe16.lpLogFont = lplf16;
506                 fe16.segTextMetric = SEGPTR_GET(lptm16);
507                 fe16.segLogFont = SEGPTR_GET(lplf16);
508
509                 retVal = dc->funcs->pEnumDeviceFonts( dc, plf, FONT_EnumInstance16, (LPARAM)&fe16 );
510
511                 SEGPTR_FREE(lplf16);
512             }
513             SEGPTR_FREE(lptm16);
514         }
515     }
516     return retVal;
517 }
518
519 /***********************************************************************
520  *              FONT_EnumFontFamiliesEx
521  */
522 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc, 
523                                                    LPARAM lParam, DWORD dwUnicode)
524 {
525     DC*         dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
526
527     if( dc && dc->funcs->pEnumDeviceFonts )
528     {
529         LOGFONT16               lf16;
530         NEWTEXTMETRICEXW        tm32w;
531         ENUMLOGFONTEXW  lf32w;
532         fontEnum32              fe32;
533
534         fe32.lpLogFontParam = plf;
535         fe32.lpEnumFunc = efproc;
536         fe32.lpData = lParam;
537         
538         fe32.lpTextMetric = &tm32w;
539         fe32.lpLogFont = &lf32w;
540         fe32.dwFlags = dwUnicode;
541
542         /* the only difference between LOGFONT32A and LOGFONT32W is in the lfFaceName */
543
544         if( plf->lfFaceName[0] )
545         {
546             if( dwUnicode )
547                 lstrcpynWtoA( lf16.lfFaceName, plf->lfFaceName, LF_FACESIZE );
548             else
549                 lstrcpynA( lf16.lfFaceName, (LPCSTR)plf->lfFaceName, LF_FACESIZE );
550         }
551         else lf16.lfFaceName[0] = '\0';
552         lf16.lfCharSet = plf->lfCharSet;
553
554         return dc->funcs->pEnumDeviceFonts( dc, &lf16, FONT_EnumInstance, (LPARAM)&fe32 );
555     }
556     return 0;
557 }
558
559 /***********************************************************************
560  *              EnumFontFamiliesExW     (GDI32.82)
561  */
562 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
563                                     FONTENUMPROCEXW efproc, 
564                                     LPARAM lParam, DWORD dwFlags )
565 {
566     return  FONT_EnumFontFamiliesEx( hDC, plf, (FONTENUMPROCW)efproc, 
567                                                   lParam, ENUM_UNICODE );
568 }
569
570 /***********************************************************************
571  *              EnumFontFamiliesExA     (GDI32.81)
572  */
573 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
574                                     FONTENUMPROCEXA efproc, 
575                                     LPARAM lParam, DWORD dwFlags)
576 {
577     return  FONT_EnumFontFamiliesEx( hDC, (LPLOGFONTW)plf, 
578                                       (FONTENUMPROCW)efproc, lParam, 0);
579 }
580
581 /***********************************************************************
582  *              EnumFontFamilies16      (GDI.330)
583  */
584 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
585                                  FONTENUMPROC16 efproc, LPARAM lpData )
586 {
587     LOGFONT16   lf;
588
589     lf.lfCharSet = DEFAULT_CHARSET;
590     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
591     else lf.lfFaceName[0] = '\0';
592
593     return EnumFontFamiliesEx16( hDC, &lf, (FONTENUMPROCEX16)efproc, lpData, 0 );
594 }
595
596 /***********************************************************************
597  *              EnumFontFamiliesA       (GDI32.80)
598  */
599 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
600                                   FONTENUMPROCA efproc, LPARAM lpData )
601 {
602     LOGFONTA    lf;
603
604     lf.lfCharSet = DEFAULT_CHARSET;
605     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
606     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
607
608     return FONT_EnumFontFamiliesEx( hDC, (LPLOGFONTW)&lf, 
609                                            (FONTENUMPROCW)efproc, lpData, 0 );
610 }
611
612 /***********************************************************************
613  *              EnumFontFamiliesW       (GDI32.83)
614  */
615 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
616                                   FONTENUMPROCW efproc, LPARAM lpData )
617 {
618     LOGFONTW  lf;
619
620     lf.lfCharSet = DEFAULT_CHARSET;
621     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
622     else lf.lfFaceName[0] = 0;
623
624     return FONT_EnumFontFamiliesEx( hDC, &lf, efproc, lpData, ENUM_UNICODE );
625 }
626
627 /***********************************************************************
628  *              EnumFonts16             (GDI.70)
629  */
630 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
631                           LPARAM lpData )
632 {
633     return EnumFontFamilies16( hDC, lpName, (FONTENUMPROCEX16)efproc, lpData );
634 }
635
636 /***********************************************************************
637  *              EnumFontsA              (GDI32.84)
638  */
639 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
640                            LPARAM lpData )
641 {
642     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
643 }
644
645 /***********************************************************************
646  *              EnumFontsW              (GDI32.85)
647  */
648 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
649                            LPARAM lpData )
650 {
651     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
652 }
653
654
655 /***********************************************************************
656  *           GetTextCharacterExtra16    (GDI.89)
657  */
658 INT16 WINAPI GetTextCharacterExtra16( HDC16 hdc )
659 {
660     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
661     if (!dc) return 0;
662     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
663                  / dc->vportExtX );
664 }
665
666
667 /***********************************************************************
668  *           GetTextCharacterExtra    (GDI32.225)
669  */
670 INT WINAPI GetTextCharacterExtra( HDC hdc )
671 {
672     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
673     if (!dc) return 0;
674     return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
675                  / dc->vportExtX );
676 }
677
678
679 /***********************************************************************
680  *           SetTextCharacterExtra16    (GDI.8)
681  */
682 INT16 WINAPI SetTextCharacterExtra16( HDC16 hdc, INT16 extra )
683 {
684     return (INT16)SetTextCharacterExtra( hdc, extra );
685 }
686
687
688 /***********************************************************************
689  *           SetTextCharacterExtra    (GDI32.337)
690  */
691 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
692 {
693     INT prev;
694     DC * dc = DC_GetDCPtr( hdc );
695     if (!dc) return 0;
696     if (dc->funcs->pSetTextCharacterExtra)
697         return dc->funcs->pSetTextCharacterExtra( dc, extra );
698     extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
699     prev = dc->w.charExtra;
700     dc->w.charExtra = abs(extra);
701     return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
702 }
703
704
705 /***********************************************************************
706  *           SetTextJustification16    (GDI.10)
707  */
708 INT16 WINAPI SetTextJustification16( HDC16 hdc, INT16 extra, INT16 breaks )
709 {
710     return SetTextJustification( hdc, extra, breaks );
711 }
712
713
714 /***********************************************************************
715  *           SetTextJustification    (GDI32.339)
716  */
717 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
718 {
719     DC * dc = DC_GetDCPtr( hdc );
720     if (!dc) return 0;
721     if (dc->funcs->pSetTextJustification)
722         return dc->funcs->pSetTextJustification( dc, extra, breaks );
723
724     extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
725     if (!extra) breaks = 0;
726     dc->w.breakTotalExtra = extra;
727     dc->w.breakCount = breaks;
728     if (breaks)
729     {
730         dc->w.breakExtra = extra / breaks;
731         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
732     }
733     else
734     {
735         dc->w.breakExtra = 0;
736         dc->w.breakRem   = 0;
737     }
738     return 1;
739 }
740
741
742 /***********************************************************************
743  *           GetTextFace16    (GDI.92)
744  */
745 INT16 WINAPI GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
746 {
747         return GetTextFaceA(hdc,count,name);
748 }
749
750 /***********************************************************************
751  *           GetTextFaceA    (GDI32.234)
752  */
753 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
754 {
755     FONTOBJ *font;
756
757     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
758     if (!dc) return 0;
759     if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
760         return 0;
761     if (name) 
762         lstrcpynA( name, font->logfont.lfFaceName, count );
763     GDI_HEAP_UNLOCK( dc->w.hFont );
764     if (name)
765         return strlen(name);
766     else
767         return strlen(font->logfont.lfFaceName) + 1;
768 }
769
770 /***********************************************************************
771  *           GetTextFaceW    (GDI32.235)
772  */
773 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
774 {
775     LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
776     INT res = GetTextFaceA(hdc,count,nameA);
777     lstrcpyAtoW( name, nameA );
778     HeapFree( GetProcessHeap(), 0, nameA );
779     return res;
780 }
781
782
783 /***********************************************************************
784  *           GetTextExtent16    (GDI.91)
785  */
786 DWORD WINAPI GetTextExtent16( HDC16 hdc, LPCSTR str, INT16 count )
787 {
788     SIZE16 size;
789     if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
790     return MAKELONG( size.cx, size.cy );
791 }
792
793
794 /***********************************************************************
795  *           GetTextExtentPoint16    (GDI.471)
796  *
797  * FIXME: Should this have a bug for compatibility?
798  * Original Windows versions of GetTextExtentPoint{A,W} have documented
799  * bugs (-> MSDN KB q147647.txt).
800  */
801 BOOL16 WINAPI GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count,
802                                     LPSIZE16 size )
803 {
804     SIZE size32;
805     BOOL ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
806     CONV_SIZE32TO16( &size32, size );
807     return (BOOL16)ret;
808 }
809
810
811 /***********************************************************************
812  *           GetTextExtentPoint32A    (GDI32.230)
813  */
814 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
815                                      LPSIZE size )
816 {
817     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
818     if (!dc)
819     {
820         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
821             return FALSE;
822     }
823
824     if (!dc->funcs->pGetTextExtentPoint ||
825         !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
826         return FALSE;
827
828     TRACE_(font)("(%08x %s %d %p): returning %d,%d\n",
829                  hdc, debugstr_an (str, count), count,
830                  size, size->cx, size->cy );
831     return TRUE;
832 }
833
834
835 /***********************************************************************
836  * GetTextExtentPoint32W [GDI32.231]  Computes width/height for a string
837  *
838  * Computes width and height of the specified string.
839  *
840  * RETURNS
841  *    Success: TRUE
842  *    Failure: FALSE
843  */
844 BOOL WINAPI GetTextExtentPoint32W(
845     HDC hdc,     /* [in]  Handle of device context */
846     LPCWSTR str,   /* [in]  Address of text string */
847     INT count,   /* [in]  Number of characters in string */
848     LPSIZE size) /* [out] Address of structure for string size */
849 {
850     LPSTR p;
851     BOOL ret;
852
853   /* str may not be 0 terminated so we can't use HEAP_strdupWtoA.
854    * We allocate one more than we need so that lstrcpynWtoA can write a
855    * trailing 0 if it wants.
856    */
857
858     if(!count) count = lstrlenW(str);
859     p = HeapAlloc( GetProcessHeap(), 0, count+1 );
860     lstrcpynWtoA(p, str, count+1);
861     ret = GetTextExtentPoint32A( hdc, p, count, size );
862     HeapFree( GetProcessHeap(), 0, p );
863     return ret;
864 }
865
866
867 /***********************************************************************
868  *           GetTextExtentPointA    (GDI32.232)
869  */
870 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
871                                           LPSIZE size )
872 {
873     TRACE_(font)("not bug compatible.\n");
874     return GetTextExtentPoint32A( hdc, str, count, size );
875 }
876
877 /***********************************************************************
878  *           GetTextExtentPointW   (GDI32.233)
879  */
880 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
881                                           LPSIZE size )
882 {
883     TRACE_(font)("not bug compatible.\n");
884     return GetTextExtentPoint32W( hdc, str, count, size );
885 }
886
887
888 /***********************************************************************
889  *           GetTextExtentExPointA    (GDI32.228)
890  */
891 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
892                                        INT maxExt, LPINT lpnFit,
893                                        LPINT alpDx, LPSIZE size )
894 {
895     int index, nFit, extent;
896     SIZE tSize;
897     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
898
899     if (!dc)
900     {
901         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
902             return FALSE;
903     }
904     if (!dc->funcs->pGetTextExtentPoint) return FALSE;
905
906     size->cx = size->cy = nFit = extent = 0;
907     for(index = 0; index < count; index++)
908     {
909         if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
910         if( extent+tSize.cx < maxExt )
911         {
912             extent+=tSize.cx;
913             nFit++;
914             str++;
915             if( alpDx ) alpDx[index] = extent;
916             if( tSize.cy > size->cy ) size->cy = tSize.cy;
917         }
918         else break;
919     }
920     size->cx = extent;
921    *lpnFit = nFit;
922
923     TRACE_(font)("(%08x '%.*s' %d) returning %d %d %d\n",
924                hdc,count,str,maxExt,nFit, size->cx,size->cy);
925     return TRUE;
926 }
927
928
929 /***********************************************************************
930  *           GetTextExtentExPointW    (GDI32.229)
931  */
932
933 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
934                                        INT maxExt, LPINT lpnFit,
935                                        LPINT alpDx, LPSIZE size )
936 {
937     LPSTR p;
938     BOOL ret;
939
940   /* Docs say str should be 0 terminated here, but we'll use count just in case
941    */ 
942
943     if(!count) count = lstrlenW(str);
944     p = HeapAlloc( GetProcessHeap(), 0, count+1 );
945     lstrcpynWtoA(p, str, count+1);
946     ret = GetTextExtentExPointA( hdc, p, count, maxExt,
947                                         lpnFit, alpDx, size);
948     HeapFree( GetProcessHeap(), 0, p );
949     return ret;
950 }
951
952 /***********************************************************************
953  *           GetTextMetrics16    (GDI.93)
954  */
955 BOOL16 WINAPI GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
956 {
957     TEXTMETRICA tm32;
958
959     if (!GetTextMetricsA( (HDC)hdc, &tm32 )) return FALSE;
960     FONT_TextMetric32Ato16( &tm32, metrics );
961     return TRUE;
962 }
963
964
965 /***********************************************************************
966  *           GetTextMetricsA    (GDI32.236)
967  */
968 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
969 {
970     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
971     if (!dc)
972     {
973         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
974             return FALSE;
975     }
976
977     if (!dc->funcs->pGetTextMetrics ||
978         !dc->funcs->pGetTextMetrics( dc, metrics ))
979         return FALSE;
980
981     /* device layer returns values in device units
982      * therefore we have to convert them to logical */
983
984 #define WDPTOLP(x) ((x<0)?                                      \
985                 (-abs((x)*dc->wndExtX/dc->vportExtX)):          \
986                 (abs((x)*dc->wndExtX/dc->vportExtX)))
987 #define HDPTOLP(y) ((y<0)?                                      \
988                 (-abs((y)*dc->wndExtY/dc->vportExtY)):          \
989                 (abs((y)*dc->wndExtY/dc->vportExtY)))
990         
991     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
992     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
993     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
994     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
995     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
996     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
997     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
998     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
999
1000     TRACE_(font)("text metrics:\n"
1001     "    Weight = %03li\t FirstChar = %03i\t AveCharWidth = %li\n"
1002     "    Italic = % 3i\t LastChar = %03i\t\t MaxCharWidth = %li\n"
1003     "    UnderLined = %01i\t DefaultChar = %03i\t Overhang = %li\n"
1004     "    StruckOut = %01i\t BreakChar = %03i\t CharSet = %i\n"
1005     "    PitchAndFamily = %02x\n"
1006     "    --------------------\n"
1007     "    InternalLeading = %li\n"
1008     "    Ascent = %li\n"
1009     "    Descent = %li\n"
1010     "    Height = %li\n",
1011     metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1012     metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1013     metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1014     metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1015     metrics->tmPitchAndFamily,
1016     metrics->tmInternalLeading,
1017     metrics->tmAscent,
1018     metrics->tmDescent,
1019     metrics->tmHeight );
1020     return TRUE;
1021 }
1022
1023
1024 /***********************************************************************
1025  *           GetTextMetricsW    (GDI32.237)
1026  */
1027 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1028 {
1029     TEXTMETRICA tm;
1030     if (!GetTextMetricsA( (HDC16)hdc, &tm )) return FALSE;
1031     FONT_TextMetric32Ato32W( &tm, metrics );
1032     return TRUE;
1033 }
1034
1035
1036 /***********************************************************************
1037  * GetOutlineTextMetrics16 [GDI.308]  Gets metrics for TrueType fonts.
1038  *
1039  * NOTES
1040  *    lpOTM should be LPOUTLINETEXTMETRIC
1041  *
1042  * RETURNS
1043  *    Success: Non-zero or size of required buffer
1044  *    Failure: 0
1045  */
1046 UINT16 WINAPI GetOutlineTextMetrics16(
1047     HDC16 hdc,    /* [in]  Handle of device context */
1048     UINT16 cbData, /* [in]  Size of metric data array */
1049     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1050 {
1051     FIXME_(font)("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1052     return 0;
1053 }
1054
1055
1056 /***********************************************************************
1057  * GetOutlineTextMetricsA [GDI.207]  Gets metrics for TrueType fonts.
1058  *
1059  *
1060  * RETURNS
1061  *    Success: Non-zero or size of required buffer
1062  *    Failure: 0
1063  */
1064 UINT WINAPI GetOutlineTextMetricsA(
1065     HDC hdc,    /* [in]  Handle of device context */
1066     UINT cbData, /* [in]  Size of metric data array */
1067     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1068 {
1069
1070
1071     UINT rtn = FALSE;
1072     LPTEXTMETRICA lptxtMetr;
1073
1074
1075
1076     if (lpOTM == 0)
1077     {
1078         
1079         lpOTM = (LPOUTLINETEXTMETRICA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OUTLINETEXTMETRICA));
1080         rtn = sizeof(OUTLINETEXTMETRICA);
1081         cbData = rtn;
1082     } else
1083     {
1084         cbData = sizeof(*lpOTM);
1085         rtn = cbData;
1086     };
1087
1088     lpOTM->otmSize = cbData;
1089
1090     lptxtMetr =HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TEXTMETRICA));
1091     
1092     if (!GetTextMetricsA(hdc,lptxtMetr))
1093     {
1094         return 0;
1095     } else
1096     {
1097        memcpy(&(lpOTM->otmTextMetrics),lptxtMetr,sizeof(TEXTMETRICA));
1098     };
1099
1100     HeapFree(GetProcessHeap(),HEAP_ZERO_MEMORY,lptxtMetr);
1101     
1102     lpOTM->otmFilter = 0;
1103
1104     lpOTM->otmPanoseNumber.bFamilyType  = 0;
1105     lpOTM->otmPanoseNumber.bSerifStyle  = 0;
1106     lpOTM->otmPanoseNumber.bWeight      = 0;
1107     lpOTM->otmPanoseNumber.bProportion  = 0;
1108     lpOTM->otmPanoseNumber.bContrast    = 0;
1109     lpOTM->otmPanoseNumber.bStrokeVariation = 0;
1110     lpOTM->otmPanoseNumber.bArmStyle    = 0;
1111     lpOTM->otmPanoseNumber.bLetterform  = 0;
1112     lpOTM->otmPanoseNumber.bMidline     = 0;
1113     lpOTM->otmPanoseNumber.bXHeight     = 0;
1114
1115     lpOTM->otmfsSelection     = 0;
1116     lpOTM->otmfsType          = 0;
1117
1118     /*
1119      Further fill of the structure not implemented,
1120      Needs real values for the structure members
1121      */
1122     
1123     return rtn;
1124 }
1125
1126 /***********************************************************************
1127  *           GetOutlineTextMetricsW [GDI32.208]
1128  */
1129 UINT WINAPI GetOutlineTextMetricsW(
1130     HDC hdc,    /* [in]  Handle of device context */
1131     UINT cbData, /* [in]  Size of metric data array */
1132     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1133 {
1134     FIXME_(font)("(%d,%d,%p): stub\n", hdc, cbData, lpOTM);
1135     return 0; 
1136 }
1137
1138 /***********************************************************************
1139  *           GetCharWidth16    (GDI.350)
1140  */
1141 BOOL16 WINAPI GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1142                               LPINT16 buffer )
1143 {
1144     BOOL        retVal = FALSE;
1145
1146     if( firstChar != lastChar )
1147     {
1148         LPINT   buf32 = (LPINT)HeapAlloc(GetProcessHeap(), 0,
1149                                  sizeof(INT)*(1 + (lastChar - firstChar)));
1150         if( buf32 )
1151         {
1152             LPINT       obuf32 = buf32;
1153             int         i;
1154
1155             retVal = GetCharWidth32A(hdc, firstChar, lastChar, buf32);
1156             if (retVal)
1157             {
1158                 for (i = firstChar; i <= lastChar; i++)
1159                     *buffer++ = *buf32++;
1160             }
1161             HeapFree(GetProcessHeap(), 0, obuf32);
1162         }
1163     }
1164     else /* happens quite often to warrant a special treatment */
1165     {
1166         INT chWidth;
1167         retVal = GetCharWidth32A(hdc, firstChar, lastChar, &chWidth );
1168        *buffer = chWidth;
1169     }
1170     return retVal;
1171 }
1172
1173
1174 /***********************************************************************
1175  *           GetCharWidth32A    (GDI32.155)
1176  */
1177 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1178                                LPINT buffer )
1179 {
1180     UINT i, extra;
1181     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1182     if (!dc)
1183     {
1184         if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
1185             return FALSE;
1186     }
1187
1188     if (!dc->funcs->pGetCharWidth ||
1189         !dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
1190         return FALSE;
1191
1192     /* convert device units to logical */
1193
1194     extra = dc->vportExtX >> 1;
1195     for( i = firstChar; i <= lastChar; i++, buffer++ )
1196          *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1197
1198     return TRUE;
1199 }
1200
1201
1202 /***********************************************************************
1203  *           GetCharWidth32W    (GDI32.158)
1204  */
1205 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1206                                LPINT buffer )
1207 {
1208     return GetCharWidth32A( hdc, firstChar, lastChar, buffer );
1209 }
1210
1211
1212
1213 /* FIXME: all following APIs *******************************************
1214  *
1215  *
1216  *           SetMapperFlags16    (GDI.349)
1217  */
1218 DWORD WINAPI SetMapperFlags16( HDC16 hDC, DWORD dwFlag )
1219 {
1220     return SetMapperFlags( hDC, dwFlag );
1221 }
1222
1223
1224 /***********************************************************************
1225  *           SetMapperFlags    (GDI32.322)
1226  */
1227 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1228 {
1229     DC *dc = DC_GetDCPtr( hDC );
1230     DWORD ret = 0; 
1231     if(!dc) return 0;
1232     if(dc->funcs->pSetMapperFlags)
1233         ret = dc->funcs->pSetMapperFlags( dc, dwFlag );
1234     else
1235         FIXME_(font)("(0x%04x, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1236     GDI_HEAP_UNLOCK( hDC );
1237     return ret;
1238 }
1239
1240 /***********************************************************************
1241  *          GetAspectRatioFilterEx16  (GDI.486)
1242  */
1243 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1244 {
1245   FIXME_(font)("(%04x, %p): -- Empty Stub !\n",
1246                 hdc, pAspectRatio);
1247   return FALSE;
1248 }
1249
1250 /***********************************************************************
1251  *          GetAspectRatioFilterEx  (GDI32.142)
1252  */
1253 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1254 {
1255   FIXME_(font)("(%04x, %p): -- Empty Stub !\n",
1256         hdc, pAspectRatio);
1257   return FALSE;
1258 }
1259
1260 /***********************************************************************
1261  *           GetCharABCWidths16   (GDI.307)
1262  */
1263 BOOL16 WINAPI GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1264                                   LPABC16 abc )
1265 {
1266     ABC abc32;
1267     if (!GetCharABCWidthsA( hdc, firstChar, lastChar, &abc32 )) return FALSE;
1268     abc->abcA = abc32.abcA;
1269     abc->abcB = abc32.abcB;
1270     abc->abcC = abc32.abcC;
1271     return TRUE;
1272 }
1273
1274
1275 /***********************************************************************
1276  *           GetCharABCWidthsA   (GDI32.149)
1277  */
1278 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1279                                   LPABC abc )
1280 {
1281     return GetCharABCWidthsW( hdc, firstChar, lastChar, abc );
1282 }
1283
1284
1285 /******************************************************************************
1286  * GetCharABCWidthsW [GDI32.152]  Retrieves widths of characters in range
1287  *
1288  * PARAMS
1289  *    hdc       [I] Handle of device context
1290  *    firstChar [I] First character in range to query
1291  *    lastChar  [I] Last character in range to query
1292  *    abc       [O] Address of character-width structure
1293  *
1294  * NOTES
1295  *    Only works with TrueType fonts
1296  *
1297  * RETURNS
1298  *    Success: TRUE
1299  *    Failure: FALSE
1300  */
1301 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1302                                    LPABC abc )
1303 {
1304     /* No TrueType fonts in Wine so far */
1305     FIXME_(font)("(%04x,%04x,%04x,%p): stub\n", hdc, firstChar, lastChar, abc);
1306     return FALSE;
1307 }
1308
1309
1310 /***********************************************************************
1311  *           GetGlyphOutline16    (GDI.309)
1312  */
1313 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1314                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1315                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1316 {
1317     FIXME_(font)("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1318           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1319     return (DWORD)-1; /* failure */
1320 }
1321
1322
1323 /***********************************************************************
1324  *           GetGlyphOutlineA    (GDI32.186)
1325  */
1326 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1327                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1328                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1329 {
1330     FIXME_(font)("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1331           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1332     return (DWORD)-1; /* failure */
1333 }
1334
1335 /***********************************************************************
1336  *           GetGlyphOutlineW    (GDI32.187)
1337  */
1338 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1339                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1340                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1341 {
1342     FIXME_(font)("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1343           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1344     return (DWORD)-1; /* failure */
1345 }
1346
1347 /***********************************************************************
1348  *           CreateScalableFontResource16   (GDI.310)
1349  */
1350 BOOL16 WINAPI CreateScalableFontResource16( UINT16 fHidden,
1351                                             LPCSTR lpszResourceFile,
1352                                             LPCSTR fontFile, LPCSTR path )
1353 {
1354     return CreateScalableFontResourceA( fHidden, lpszResourceFile,
1355                                           fontFile, path );
1356 }
1357
1358 /***********************************************************************
1359  *           CreateScalableFontResourceA   (GDI32.62)
1360  */
1361 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1362                                              LPCSTR lpszResourceFile,
1363                                              LPCSTR lpszFontFile,
1364                                              LPCSTR lpszCurrentPath )
1365 {
1366     /* fHidden=1 - only visible for the calling app, read-only, not
1367      * enumbered with EnumFonts/EnumFontFamilies
1368      * lpszCurrentPath can be NULL
1369      */
1370     FIXME_(font)("(%ld,%s,%s,%s): stub\n",
1371           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1372     return FALSE; /* create failed */
1373 }
1374
1375 /***********************************************************************
1376  *           CreateScalableFontResourceW   (GDI32.63)
1377  */
1378 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1379                                              LPCWSTR lpszResourceFile,
1380                                              LPCWSTR lpszFontFile,
1381                                              LPCWSTR lpszCurrentPath )
1382 {
1383     FIXME_(font)("(%ld,%p,%p,%p): stub\n",
1384           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1385     return FALSE; /* create failed */
1386 }
1387
1388
1389 /*************************************************************************
1390  *             GetRasterizerCaps16   (GDI.313)
1391  */
1392 BOOL16 WINAPI GetRasterizerCaps16( LPRASTERIZER_STATUS lprs, UINT16 cbNumBytes)
1393 {
1394     return GetRasterizerCaps( lprs, cbNumBytes );
1395 }
1396
1397
1398 /*************************************************************************
1399  *             GetRasterizerCaps   (GDI32.216)
1400  */
1401 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1402 {
1403   lprs->nSize = sizeof(RASTERIZER_STATUS);
1404   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1405   lprs->nLanguageID = 0;
1406   return TRUE;
1407 }
1408
1409
1410 /*************************************************************************
1411  *             GetKerningPairs16   (GDI.332)
1412  */
1413 INT16 WINAPI GetKerningPairs16( HDC16 hDC, INT16 cPairs,
1414                                 LPKERNINGPAIR16 lpKerningPairs )
1415 {
1416     /* At this time kerning is ignored (set to 0) */
1417     int i;
1418     FIXME_(font)("(%x,%d,%p): almost empty stub!\n",
1419           hDC, cPairs, lpKerningPairs);
1420     for (i = 0; i < cPairs; i++) 
1421         lpKerningPairs[i].iKernAmount = 0;
1422     return 0;
1423 }
1424
1425
1426
1427 /*************************************************************************
1428  *             GetKerningPairsA   (GDI32.192)
1429  */
1430 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1431                                  LPKERNINGPAIR lpKerningPairs )
1432 {
1433     int i;
1434     FIXME_(font)("(%x,%ld,%p): almost empty stub!\n",
1435           hDC, cPairs, lpKerningPairs);
1436     for (i = 0; i < cPairs; i++) 
1437         lpKerningPairs[i].iKernAmount = 0;
1438     return 0;
1439 }
1440
1441
1442 /*************************************************************************
1443  *             GetKerningPairsW   (GDI32.193)
1444  */
1445 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1446                                  LPKERNINGPAIR lpKerningPairs )
1447 {
1448     return GetKerningPairsA( hDC, cPairs, lpKerningPairs );
1449 }
1450
1451 /*************************************************************************
1452  * TranslateCharsetInfo [GDI32.382]
1453  *
1454  * Fills a CHARSETINFO structure for a character set, code page, or
1455  * font. This allows making the correspondance between different labelings
1456  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges) 
1457  * of the same encoding.
1458  *
1459  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1460  * only one codepage should be set in *lpSrc.
1461  *
1462  * RETURNS
1463  *   TRUE on success, FALSE on failure.
1464  *
1465  */
1466 BOOL WINAPI TranslateCharsetInfo(
1467   LPDWORD lpSrc, /*
1468        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1469        if flags == TCI_SRCCHARSET: a character set value
1470        if flags == TCI_SRCCODEPAGE: a code page value
1471                  */
1472   LPCHARSETINFO lpCs, /* structure to receive charset information */
1473   DWORD flags /* determines interpretation of lpSrc */
1474 ) {
1475     int index = 0;
1476     switch (flags) {
1477     case TCI_SRCFONTSIG:
1478         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1479       break;
1480     case TCI_SRCCODEPAGE:
1481       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1482       break;
1483     case TCI_SRCCHARSET:
1484       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1485       break;
1486     default:
1487       return FALSE;
1488     }
1489     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1490     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1491     return TRUE;
1492 }
1493
1494 /*************************************************************************
1495  *             GetFontLanguageInfo   (GDI32.182)
1496  */
1497 DWORD WINAPI GetFontLanguageInfo(HDC hdc) {
1498         /* return value 0 is correct for most cases anyway */
1499         FIXME_(font)("(%x):stub!\n", hdc);
1500         return 0;
1501 }
1502
1503 /*************************************************************************
1504  *             GetFontLanguageInfo   (GDI.616)
1505  */
1506 DWORD WINAPI GetFontLanguageInfo16(HDC16 hdc) {
1507         /* return value 0 is correct for most cases anyway */
1508         FIXME_(font)("(%x):stub!\n",hdc);
1509         return 0;
1510 }
1511
1512 /*************************************************************************
1513  * GetFontData [GDI32.181] Retrieve data for TrueType font
1514  *
1515  * RETURNS
1516  *
1517  * success: Number of bytes returned 
1518  * failure: GDI_ERROR
1519  *
1520  * NOTES
1521  *
1522  * Calls SetLastError()  
1523  *
1524  * BUGS
1525  *
1526  * Unimplemented
1527  */
1528 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset, 
1529     LPVOID buffer, DWORD length)
1530 {
1531     FIXME_(font)("(%x,%ld,%ld,%p,%ld): stub\n", 
1532         hdc, table, offset, buffer, length);
1533     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1534     return GDI_ERROR;
1535 }
1536
1537 /*************************************************************************
1538  * GetCharacterPlacementA [GDI32.160]
1539  *
1540  * NOTES:
1541  *  the web browser control of ie4 calls this with dwFlags=0
1542  */
1543 DWORD WINAPI
1544 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1545                          INT nMaxExtent, GCP_RESULTSA *lpResults,
1546                          DWORD dwFlags)
1547 {
1548     DWORD ret=0;
1549     SIZE size;
1550
1551     TRACE_(font)("%s 0x%08x 0x%08x 0x%08lx:stub!\n",
1552       debugstr_a(lpString), uCount, nMaxExtent, dwFlags);
1553
1554     TRACE_(font)("lpOrder=%p lpDx=%p lpCaretPos=%p lpClass=%p lpOutString=%p lpGlyphs=%p\n",
1555       lpResults->lpOrder, lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1556       lpResults->lpOutString, lpResults->lpGlyphs);
1557
1558     if(dwFlags)                 FIXME_(font)("flags 0x%08lx ignored\n", dwFlags);
1559     if(lpResults->lpOrder)      FIXME_(font)("reordering not implemented\n");
1560     if(lpResults->lpCaretPos)   FIXME_(font)("caret positions not implemented\n");
1561     if(lpResults->lpClass)      FIXME_(font)("classes not implemented\n");
1562     if(lpResults->lpGlyphs)     FIXME_(font)("glyphs not implemented\n");
1563
1564     /* copy will do if the GCP_REORDER flag is not set */
1565     if(lpResults->lpOutString)
1566     {
1567       lstrcpynA(lpResults->lpOutString, lpString, uCount);
1568     }
1569
1570     if (lpResults->lpDx)
1571     {
1572       int i, c;
1573       for (i=0; i<uCount;i++)
1574       { 
1575         if (GetCharWidth32A(hdc, lpString[i], lpString[i], &c))
1576           lpResults->lpDx[i]= c;
1577       }
1578     }
1579
1580     if (GetTextExtentPoint32A(hdc, lpString, uCount, &size))
1581       ret = MAKELONG(size.cx, size.cy);
1582
1583     return ret;
1584 }
1585
1586 /*************************************************************************
1587  * GetCharacterPlacementW [GDI32.161]
1588  */
1589 DWORD WINAPI
1590 GetCharacterPlacementW(HDC hdc, LPCWSTR lpString, INT uCount,
1591                          INT nMaxExtent, GCP_RESULTSW *lpResults,
1592                          DWORD dwFlags)
1593 {
1594     /* return value 0 is correct for most cases anyway */
1595     FIXME_(font)(":stub!\n");
1596     return 0;
1597 }
1598
1599 /*************************************************************************
1600  *      GetCharABCWidthsFloatA [GDI32.150]
1601  */
1602 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
1603                                         LPABCFLOAT lpABCF)
1604 {
1605        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
1606        return 0;
1607 }
1608
1609 /*************************************************************************
1610  *      GetCharABCWidthsFloatW [GDI32.151]
1611  */
1612 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
1613                                         UINT iLastChar, LPABCFLOAT lpABCF)
1614 {
1615        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
1616        return 0;
1617 }
1618
1619 /*************************************************************************
1620  *      GetCharWidthFloatA [GDI32.156]
1621  */
1622 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
1623                                     UINT iLastChar, PFLOAT pxBuffer)
1624 {
1625        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
1626        return 0;
1627 }
1628
1629 /*************************************************************************
1630  *      GetCharWidthFloatW [GDI32.157]
1631  */
1632 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
1633                                     UINT iLastChar, PFLOAT pxBuffer)
1634 {
1635        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
1636        return 0;
1637 }
1638